Imported Upstream version 5.3.3 60/94760/1 upstream/5.3.3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 05:27:09 +0000 (14:27 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 05:27:09 +0000 (14:27 +0900)
Change-Id: I59dadecaff3d1e7c294e9dff914881dc75da9d60
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
70 files changed:
Makefile
README
doc/contents.html
doc/index.css [new file with mode: 0644]
doc/lua.1
doc/lua.css
doc/manual.css
doc/manual.html
doc/readme.html
src/Makefile
src/lapi.c
src/lapi.h
src/lauxlib.c
src/lauxlib.h
src/lbaselib.c
src/lbitlib.c
src/lcode.c
src/lcode.h
src/lcorolib.c
src/lctype.c
src/lctype.h
src/ldblib.c
src/ldebug.c
src/ldebug.h
src/ldo.c
src/ldo.h
src/ldump.c
src/lfunc.c
src/lfunc.h
src/lgc.c
src/lgc.h
src/linit.c
src/liolib.c
src/llex.c
src/llex.h
src/llimits.h
src/lmathlib.c
src/lmem.c
src/lmem.h
src/loadlib.c
src/lobject.c
src/lobject.h
src/lopcodes.c
src/lopcodes.h
src/loslib.c
src/lparser.c
src/lparser.h
src/lprefix.h [new file with mode: 0644]
src/lstate.c
src/lstate.h
src/lstring.c
src/lstring.h
src/lstrlib.c
src/ltable.c
src/ltable.h
src/ltablib.c
src/ltm.c
src/ltm.h
src/lua.c
src/lua.h
src/luac.c
src/luaconf.h
src/lualib.h
src/lundump.c
src/lundump.h
src/lutf8lib.c [new file with mode: 0644]
src/lvm.c
src/lvm.h
src/lzio.c
src/lzio.h

index b2a62cf..c795dd7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@ RM= rm -f
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
 # Convenience platforms targets.
-PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
 
 # What to install.
 TO_BIN= lua luac
@@ -45,8 +45,8 @@ TO_LIB= liblua.a
 TO_MAN= lua.1 luac.1
 
 # Lua version and release.
-V= 5.2
-R= $V.4
+V= 5.3
+R= $V.3
 
 # Targets start here.
 all:   $(PLAT)
diff --git a/README b/README
index 710e3ee..e84d9ac 100644 (file)
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 
-This is Lua 5.2.4, released on 25 Feb 2015.
+This is Lua 5.3.3, released on 30 May 2016.
 
 For installation instructions, license details, and
 further information about Lua, see doc/readme.html.
index 9d5202f..ca0f568 100644 (file)
@@ -1,44 +1,44 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML>
 <HEAD>
-<TITLE>Lua 5.2 Reference Manual - contents</TITLE>
+<TITLE>Lua 5.3 Reference Manual - contents</TITLE>
 <LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
+<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 ;
-}
-</STYLE>
 </HEAD>
 
 <BODY>
 
-<HR>
 <H1>
-<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="" BORDER=0></A>
-Lua 5.2 Reference Manual
+<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>
 &middot;
 <A HREF="#contents">contents</A>
 &middot;
 <A HREF="#index">index</A>
-<HR>
+&middot;
+<A HREF="http://www.lua.org/manual/">other versions</A>
+</DIV>
+
+<P>
 <SMALL>
-Copyright &copy; 2011&ndash;2015 Lua.org, PUC-Rio.
+Copyright &copy; 2015&ndash;2016 Lua.org, PUC-Rio.
 Freely available under the terms of the
 <A HREF="http://www.lua.org/license.html">Lua license</A>.
 </SMALL>
 
 <H2><A NAME="contents">Contents</A></H2>
-<UL style="padding: 0">
+<UL CLASS="contents menubar">
 <LI><A HREF="manual.html">1 &ndash; Introduction</A>
 <P>
 <LI><A HREF="manual.html#2">2 &ndash; Basic Concepts</A>
@@ -72,15 +72,16 @@ Freely available under the terms of the
 <LI><A HREF="manual.html#3.4">3.4 &ndash; Expressions</A>
 <UL>
 <LI><A HREF="manual.html#3.4.1">3.4.1 &ndash; Arithmetic Operators</A>
-<LI><A HREF="manual.html#3.4.2">3.4.2 &ndash; Coercion</A>
-<LI><A HREF="manual.html#3.4.3">3.4.3 &ndash; Relational Operators</A>
-<LI><A HREF="manual.html#3.4.4">3.4.4 &ndash; Logical Operators</A>
-<LI><A HREF="manual.html#3.4.5">3.4.5 &ndash; Concatenation</A>
-<LI><A HREF="manual.html#3.4.6">3.4.6 &ndash; The Length Operator</A>
-<LI><A HREF="manual.html#3.4.7">3.4.7 &ndash; Precedence</A>
-<LI><A HREF="manual.html#3.4.8">3.4.8 &ndash; Table Constructors</A>
-<LI><A HREF="manual.html#3.4.9">3.4.9 &ndash; Function Calls</A>
-<LI><A HREF="manual.html#3.4.10">3.4.10 &ndash; Function Definitions</A>
+<LI><A HREF="manual.html#3.4.2">3.4.2 &ndash; Bitwise Operators</A>
+<LI><A HREF="manual.html#3.4.3">3.4.3 &ndash; Coercions and Conversions</A>
+<LI><A HREF="manual.html#3.4.4">3.4.4 &ndash; Relational Operators</A>
+<LI><A HREF="manual.html#3.4.5">3.4.5 &ndash; Logical Operators</A>
+<LI><A HREF="manual.html#3.4.6">3.4.6 &ndash; Concatenation</A>
+<LI><A HREF="manual.html#3.4.7">3.4.7 &ndash; The Length Operator</A>
+<LI><A HREF="manual.html#3.4.8">3.4.8 &ndash; Precedence</A>
+<LI><A HREF="manual.html#3.4.9">3.4.9 &ndash; Table Constructors</A>
+<LI><A HREF="manual.html#3.4.10">3.4.10 &ndash; Function Calls</A>
+<LI><A HREF="manual.html#3.4.11">3.4.11 &ndash; Function Definitions</A>
 </UL>
 <LI><A HREF="manual.html#3.5">3.5 &ndash; Visibility Rules</A>
 </UL>
@@ -111,10 +112,11 @@ Freely available under the terms of the
 <LI><A HREF="manual.html#6.4">6.4 &ndash; String Manipulation</A>
 <UL>
 <LI><A HREF="manual.html#6.4.1">6.4.1 &ndash; Patterns</A>
+<LI><A HREF="manual.html#6.4.2">6.4.2 &ndash; Format Strings for Pack and Unpack</A>
 </UL>
-<LI><A HREF="manual.html#6.5">6.5 &ndash; Table Manipulation</A>
-<LI><A HREF="manual.html#6.6">6.6 &ndash; Mathematical Functions</A>
-<LI><A HREF="manual.html#6.7">6.7 &ndash; Bitwise Operations</A>
+<LI><A HREF="manual.html#6.5">6.5 &ndash; UTF-8 Support</A>
+<LI><A HREF="manual.html#6.6">6.6 &ndash; Table Manipulation</A>
+<LI><A HREF="manual.html#6.7">6.7 &ndash; Mathematical Functions</A>
 <LI><A HREF="manual.html#6.8">6.8 &ndash; Input and Output Facilities</A>
 <LI><A HREF="manual.html#6.9">6.9 &ndash; Operating System Facilities</A>
 <LI><A HREF="manual.html#6.10">6.10 &ndash; The Debug Library</A>
@@ -133,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>
@@ -167,23 +168,9 @@ Freely available under the terms of the
 <A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
 
 <P>
-<A HREF="manual.html#6.7">bit32</A><BR>
-<A HREF="manual.html#pdf-bit32.arshift">bit32.arshift</A><BR>
-<A HREF="manual.html#pdf-bit32.band">bit32.band</A><BR>
-<A HREF="manual.html#pdf-bit32.bnot">bit32.bnot</A><BR>
-<A HREF="manual.html#pdf-bit32.bor">bit32.bor</A><BR>
-<A HREF="manual.html#pdf-bit32.btest">bit32.btest</A><BR>
-<A HREF="manual.html#pdf-bit32.bxor">bit32.bxor</A><BR>
-<A HREF="manual.html#pdf-bit32.extract">bit32.extract</A><BR>
-<A HREF="manual.html#pdf-bit32.lrotate">bit32.lrotate</A><BR>
-<A HREF="manual.html#pdf-bit32.lshift">bit32.lshift</A><BR>
-<A HREF="manual.html#pdf-bit32.replace">bit32.replace</A><BR>
-<A HREF="manual.html#pdf-bit32.rrotate">bit32.rrotate</A><BR>
-<A HREF="manual.html#pdf-bit32.rshift">bit32.rshift</A><BR>
-
-<P>
 <A HREF="manual.html#6.2">coroutine</A><BR>
 <A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
+<A HREF="manual.html#pdf-coroutine.isyieldable">coroutine.isyieldable</A><BR>
 <A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
 <A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
 <A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
@@ -193,18 +180,18 @@ Freely available under the terms of the
 <P>
 <A HREF="manual.html#6.10">debug</A><BR>
 <A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
-<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
 <A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
 <A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
 <A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
 <A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
 <A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
 <A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
-<A HREF="manual.html#pdf-debug.setuservalue">debug.setuservalue</A><BR>
+<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
 <A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
 <A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
 <A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
 <A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
+<A HREF="manual.html#pdf-debug.setuservalue">debug.setuservalue</A><BR>
 <A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
 <A HREF="manual.html#pdf-debug.upvalueid">debug.upvalueid</A><BR>
 <A HREF="manual.html#pdf-debug.upvaluejoin">debug.upvaluejoin</A><BR>
@@ -225,6 +212,7 @@ Freely available under the terms of the
 <A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
 <A HREF="manual.html#pdf-io.type">io.type</A><BR>
 <A HREF="manual.html#pdf-io.write">io.write</A><BR>
+
 <A HREF="manual.html#pdf-file:close">file:close</A><BR>
 <A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
 <A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
@@ -237,36 +225,34 @@ Freely available under the terms of the
 <TD>
 <H3>&nbsp;</H3>
 <P>
-<A HREF="manual.html#6.6">math</A><BR>
+<A HREF="manual.html#6.7">math</A><BR>
 <A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
 <A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
 <A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
 <A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
-<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR>
 <A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
 <A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
-<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR>
 <A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
 <A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
 <A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
 <A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
-<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
 <A HREF="manual.html#pdf-math.huge">math.huge</A><BR>
-<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
 <A HREF="manual.html#pdf-math.log">math.log</A><BR>
 <A HREF="manual.html#pdf-math.max">math.max</A><BR>
+<A HREF="manual.html#pdf-math.maxinteger">math.maxinteger</A><BR>
 <A HREF="manual.html#pdf-math.min">math.min</A><BR>
+<A HREF="manual.html#pdf-math.mininteger">math.mininteger</A><BR>
 <A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
 <A HREF="manual.html#pdf-math.pi">math.pi</A><BR>
-<A HREF="manual.html#pdf-math.pow">math.pow</A><BR>
 <A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
 <A HREF="manual.html#pdf-math.random">math.random</A><BR>
 <A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
 <A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
-<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR>
 <A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
 <A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
-<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR>
+<A HREF="manual.html#pdf-math.tointeger">math.tointeger</A><BR>
+<A HREF="manual.html#pdf-math.type">math.type</A><BR>
+<A HREF="manual.html#pdf-math.ult">math.ult</A><BR>
 
 <P>
 <A HREF="manual.html#6.9">os</A><BR>
@@ -305,37 +291,53 @@ Freely available under the terms of the
 <A HREF="manual.html#pdf-string.len">string.len</A><BR>
 <A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
 <A HREF="manual.html#pdf-string.match">string.match</A><BR>
+<A HREF="manual.html#pdf-string.pack">string.pack</A><BR>
+<A HREF="manual.html#pdf-string.packsize">string.packsize</A><BR>
 <A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
 <A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
 <A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
+<A HREF="manual.html#pdf-string.unpack">string.unpack</A><BR>
 <A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
 
 <P>
-<A HREF="manual.html#6.5">table</A><BR>
+<A HREF="manual.html#6.6">table</A><BR>
 <A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
 <A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
+<A HREF="manual.html#pdf-table.move">table.move</A><BR>
 <A HREF="manual.html#pdf-table.pack">table.pack</A><BR>
 <A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
 <A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
 <A HREF="manual.html#pdf-table.unpack">table.unpack</A><BR>
 
+<P>
+<A HREF="manual.html#6.5">utf8</A><BR>
+<A HREF="manual.html#pdf-utf8.char">utf8.char</A><BR>
+<A HREF="manual.html#pdf-utf8.charpattern">utf8.charpattern</A><BR>
+<A HREF="manual.html#pdf-utf8.codepoint">utf8.codepoint</A><BR>
+<A HREF="manual.html#pdf-utf8.codes">utf8.codes</A><BR>
+<A HREF="manual.html#pdf-utf8.len">utf8.len</A><BR>
+<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_2">LUA_CPATH_5_2</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>
-<A HREF="manual.html#pdf-LUA_INIT_5_2">LUA_INIT_5_2</A><BR>
+<A HREF="manual.html#pdf-LUA_INIT_5_3">LUA_INIT_5_3</A><BR>
 <A HREF="manual.html#pdf-LUA_PATH">LUA_PATH</A><BR>
-<A HREF="manual.html#pdf-LUA_PATH_5_2">LUA_PATH_5_2</A><BR>
+<A HREF="manual.html#pdf-LUA_PATH_5_3">LUA_PATH_5_3</A><BR>
 
 </TD>
 <TD>
-<H3>C API</H3>
+<H3><A NAME="api">C API</A></H3>
 <P>
 <A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
 <A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
 <A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
 <A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
 <A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
+<A HREF="manual.html#lua_KContext">lua_KContext</A><BR>
+<A HREF="manual.html#lua_KFunction">lua_KFunction</A><BR>
 <A HREF="manual.html#lua_Number">lua_Number</A><BR>
 <A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
 <A HREF="manual.html#lua_State">lua_State</A><BR>
@@ -358,12 +360,13 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_error">lua_error</A><BR>
 <A HREF="manual.html#lua_gc">lua_gc</A><BR>
 <A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
-<A HREF="manual.html#lua_getctx">lua_getctx</A><BR>
+<A HREF="manual.html#lua_getextraspace">lua_getextraspace</A><BR>
 <A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
 <A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
 <A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
 <A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
 <A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
+<A HREF="manual.html#lua_geti">lua_geti</A><BR>
 <A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
 <A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
 <A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
@@ -376,6 +379,7 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
 <A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
 <A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
+<A HREF="manual.html#lua_isinteger">lua_isinteger</A><BR>
 <A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
 <A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
 <A HREF="manual.html#lua_isnone">lua_isnone</A><BR>
@@ -385,6 +389,7 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_istable">lua_istable</A><BR>
 <A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
 <A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
+<A HREF="manual.html#lua_isyieldable">lua_isyieldable</A><BR>
 <A HREF="manual.html#lua_len">lua_len</A><BR>
 <A HREF="manual.html#lua_load">lua_load</A><BR>
 <A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
@@ -392,6 +397,7 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
 <A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR>
 <A HREF="manual.html#lua_next">lua_next</A><BR>
+<A HREF="manual.html#lua_numbertointeger">lua_numbertointeger</A><BR>
 <A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
 <A HREF="manual.html#lua_pcallk">lua_pcallk</A><BR>
 <A HREF="manual.html#lua_pop">lua_pop</A><BR>
@@ -408,7 +414,6 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
 <A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
 <A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
-<A HREF="manual.html#lua_pushunsigned">lua_pushunsigned</A><BR>
 <A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
 <A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
 <A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
@@ -423,10 +428,12 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_remove">lua_remove</A><BR>
 <A HREF="manual.html#lua_replace">lua_replace</A><BR>
 <A HREF="manual.html#lua_resume">lua_resume</A><BR>
+<A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
 <A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
 <A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
 <A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
 <A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
+<A HREF="manual.html#lua_seti">lua_seti</A><BR>
 <A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
 <A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
 <A HREF="manual.html#lua_settable">lua_settable</A><BR>
@@ -434,6 +441,7 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
 <A HREF="manual.html#lua_setuservalue">lua_setuservalue</A><BR>
 <A HREF="manual.html#lua_status">lua_status</A><BR>
+<A HREF="manual.html#lua_stringtonumber">lua_stringtonumber</A><BR>
 <A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
 <A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
 <A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
@@ -444,8 +452,6 @@ Freely available under the terms of the
 <A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
 <A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
 <A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
-<A HREF="manual.html#lua_tounsigned">lua_tounsigned</A><BR>
-<A HREF="manual.html#lua_tounsignedx">lua_tounsignedx</A><BR>
 <A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
 <A HREF="manual.html#lua_type">lua_type</A><BR>
 <A HREF="manual.html#lua_typename">lua_typename</A><BR>
@@ -459,10 +465,11 @@ Freely available under the terms of the
 
 </TD>
 <TD>
-<H3>auxiliary library</H3>
+<H3><A NAME="auxlib">auxiliary library</A></H3>
 <P>
 <A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
 <A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
+<A HREF="manual.html#luaL_Stream">luaL_Stream</A><BR>
 
 <P>
 <A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
@@ -476,9 +483,7 @@ Freely available under the terms of the
 <A HREF="manual.html#luaL_buffinitsize">luaL_buffinitsize</A><BR>
 <A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
 <A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
-<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR>
 <A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
-<A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR>
 <A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
 <A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
 <A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
@@ -486,7 +491,6 @@ Freely available under the terms of the
 <A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
 <A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
 <A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
-<A HREF="manual.html#luaL_checkunsigned">luaL_checkunsigned</A><BR>
 <A HREF="manual.html#luaL_checkversion">luaL_checkversion</A><BR>
 <A HREF="manual.html#luaL_dofile">luaL_dofile</A><BR>
 <A HREF="manual.html#luaL_dostring">luaL_dostring</A><BR>
@@ -508,13 +512,10 @@ Freely available under the terms of the
 <A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
 <A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
 <A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
-<A HREF="manual.html#luaL_optint">luaL_optint</A><BR>
 <A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
-<A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR>
 <A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
 <A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
 <A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
-<A HREF="manual.html#luaL_optunsigned">luaL_optunsigned</A><BR>
 <A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
 <A HREF="manual.html#luaL_prepbuffsize">luaL_prepbuffsize</A><BR>
 <A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
@@ -533,7 +534,6 @@ Freely available under the terms of the
 <H3><A NAME="library">standard library</A></H3>
 <P>
 <A HREF="manual.html#pdf-luaopen_base">luaopen_base</A><BR>
-<A HREF="manual.html#pdf-luaopen_bit32">luaopen_bit32</A><BR>
 <A HREF="manual.html#pdf-luaopen_coroutine">luaopen_coroutine</A><BR>
 <A HREF="manual.html#pdf-luaopen_debug">luaopen_debug</A><BR>
 <A HREF="manual.html#pdf-luaopen_io">luaopen_io</A><BR>
@@ -542,8 +542,10 @@ Freely available under the terms of the
 <A HREF="manual.html#pdf-luaopen_package">luaopen_package</A><BR>
 <A HREF="manual.html#pdf-luaopen_string">luaopen_string</A><BR>
 <A HREF="manual.html#pdf-luaopen_table">luaopen_table</A><BR>
+<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>
@@ -559,18 +561,27 @@ Freely available under the terms of the
 <A HREF="manual.html#pdf-LUA_MASKCOUNT">LUA_MASKCOUNT</A><BR>
 <A HREF="manual.html#pdf-LUA_MASKLINE">LUA_MASKLINE</A><BR>
 <A HREF="manual.html#pdf-LUA_MASKRET">LUA_MASKRET</A><BR>
+<A HREF="manual.html#pdf-LUA_MAXINTEGER">LUA_MAXINTEGER</A><BR>
+<A HREF="manual.html#pdf-LUA_MININTEGER">LUA_MININTEGER</A><BR>
 <A HREF="manual.html#pdf-LUA_MINSTACK">LUA_MINSTACK</A><BR>
 <A HREF="manual.html#pdf-LUA_MULTRET">LUA_MULTRET</A><BR>
 <A HREF="manual.html#pdf-LUA_NOREF">LUA_NOREF</A><BR>
 <A HREF="manual.html#pdf-LUA_OK">LUA_OK</A><BR>
 <A HREF="manual.html#pdf-LUA_OPADD">LUA_OPADD</A><BR>
+<A HREF="manual.html#pdf-LUA_OPBAND">LUA_OPBAND</A><BR>
+<A HREF="manual.html#pdf-LUA_OPBNOT">LUA_OPBNOT</A><BR>
+<A HREF="manual.html#pdf-LUA_OPBOR">LUA_OPBOR</A><BR>
+<A HREF="manual.html#pdf-LUA_OPBXOR">LUA_OPBXOR</A><BR>
 <A HREF="manual.html#pdf-LUA_OPDIV">LUA_OPDIV</A><BR>
 <A HREF="manual.html#pdf-LUA_OPEQ">LUA_OPEQ</A><BR>
+<A HREF="manual.html#pdf-LUA_OPIDIV">LUA_OPIDIV</A><BR>
 <A HREF="manual.html#pdf-LUA_OPLE">LUA_OPLE</A><BR>
 <A HREF="manual.html#pdf-LUA_OPLT">LUA_OPLT</A><BR>
 <A HREF="manual.html#pdf-LUA_OPMOD">LUA_OPMOD</A><BR>
 <A HREF="manual.html#pdf-LUA_OPMUL">LUA_OPMUL</A><BR>
 <A HREF="manual.html#pdf-LUA_OPPOW">LUA_OPPOW</A><BR>
+<A HREF="manual.html#pdf-LUA_OPSHL">LUA_OPSHL</A><BR>
+<A HREF="manual.html#pdf-LUA_OPSHR">LUA_OPSHR</A><BR>
 <A HREF="manual.html#pdf-LUA_OPSUB">LUA_OPSUB</A><BR>
 <A HREF="manual.html#pdf-LUA_OPUNM">LUA_OPUNM</A><BR>
 <A HREF="manual.html#pdf-LUA_REFNIL">LUA_REFNIL</A><BR>
@@ -595,13 +606,12 @@ Freely available under the terms of the
 </TR>
 </TABLE>
 
-<HR>
-<SMALL CLASS="footer">
+<P CLASS="footer">
 Last update:
-Mon Feb 23 22:24:36 BRT 2015
-</SMALL>
+Thu Jan 14 10:14:28 BRST 2016
+</P>
 <!--
-Last change: revised for Lua 5.2.4
+Last change: revised for Lua 5.3.3
 -->
 
 </BODY>
diff --git a/doc/index.css b/doc/index.css
new file mode 100644 (file)
index 0000000..c961835
--- /dev/null
@@ -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% ;
+}
index 1dbf043..411531b 100644 (file)
--- a/doc/lua.1
+++ b/doc/lua.1
@@ -1,5 +1,4 @@
-.\" $Id: lua.man,v 1.13 2011/11/16 17:16:53 lhf Exp $
-.TH LUA 1 "$Date: 2011/11/16 17:16:53 $"
+.TH LUA 1 "$Date: 2014/12/10 15:55:45 $"
 .SH NAME
 lua \- Lua interpreter
 .SH SYNOPSIS
@@ -50,22 +49,18 @@ In interactive mode,
 prompts the user,
 reads lines from the standard input,
 and executes them as they are read.
+If the line contains an expression or list of expressions,
+then the line is evaluated and the results are printed.
 If a line does not contain a complete statement,
 then a secondary prompt is displayed and
 lines are read until a complete statement is formed or
 a syntax error is found.
-If a line starts with
-.BR '=' ,
-then
-.B lua
-evaluates and displays
-the values of the expressions in the remainder of the line.
 .LP
 At the very start,
 before even handling the command line,
 .B lua
 checks the contents of the environment variables
-.B LUA_INIT_5_2
+.B LUA_INIT_5_3
 or
 .BR LUA_INIT ,
 in that order.
index 5dc9a8b..5bedf7e 100644 (file)
@@ -3,57 +3,51 @@ 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 ;
+       color: #000080 ;
        border-radius: 4px ;
 }
 
@@ -61,32 +55,44 @@ 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 {
        color: gray ;
        font-size: x-small ;
+       text-transform: lowercase ;
 }
 
 input[type=text] {
@@ -104,3 +110,55 @@ 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 ;
+}
+
+table.book {
+       border: none ;
+       border-spacing: 0 ;
+       border-collapse: collapse ;
+}
+
+table.book td {
+       padding: 0 ;
+       vertical-align: top ;
+}
+
+table.book td.cover {
+       padding-right: 1em ;
+}
+
+table.book img {
+       border: solid #000080 1px ;
+}
+
+table.book span {
+       font-size: small ;
+       text-align: left ;
+       display: block ;
+       margin-top: 0.25em ;
+}
+
+img {
+       background-color: white ;
+}
index ca613cd..aa0e677 100644 (file)
@@ -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 ;
 }
index 0a95e9e..5fb26b2 100644 (file)
@@ -1,39 +1,41 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-
-<head>
-<title>Lua 5.2 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>
-Lua 5.2 Reference Manual
-</h1>
+<H1>
+<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua"></A>
+Lua 5.3 Reference Manual
+</H1>
 
+<P>
 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
-<p>
-<small>
-Copyright &copy; 2011&ndash;2015 Lua.org, PUC-Rio.
+
+<P>
+<SMALL>
+Copyright &copy; 2015&ndash;2016 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>
+&middot;
+<A HREF="contents.html#index">index</A>
 &middot;
-<a href="contents.html#index">index</A>
+<A HREF="http://www.lua.org/manual/">other versions</A>
+</DIV>
 
 <!-- ====================================================================== -->
 <p>
 
-<!-- $Id: manual.of,v 1.104 2013/06/01 00:13:11 roberto Exp $ -->
+<!-- $Id: manual.of,v 1.162 2016/05/30 15:57:03 roberto Exp $ -->
 
 
 
@@ -41,30 +43,47 @@ Freely available under the terms of the
 <h1>1 &ndash; <a name="1">Introduction</a></h1>
 
 <p>
-Lua is an extension programming language designed to support
-general procedural programming with data description
-facilities.
-It also offers good support for object-oriented programming,
-functional programming, and data-driven programming.
-Lua is intended to be used as a powerful, lightweight,
-embeddable scripting language for any program that needs one.
+Lua is a powerful, efficient, lightweight, embeddable scripting language.
+It supports procedural programming,
+object-oriented programming, functional programming,
+data-driven programming, and data description.
+
+
+<p>
+Lua combines simple procedural syntax with powerful data description
+constructs based on associative arrays and extensible semantics.
+Lua is dynamically typed,
+runs by interpreting bytecode with a register-based
+virtual machine,
+and has automatic memory management with
+incremental garbage collection,
+making it ideal for configuration, scripting,
+and rapid prototyping.
+
+
+<p>
 Lua is implemented as a library, written in <em>clean C</em>,
 the common subset of Standard&nbsp;C and C++.
+The Lua distribution includes a host program called <code>lua</code>,
+which uses the Lua library to offer a complete,
+standalone Lua interpreter,
+for interactive or batch use.
+Lua is intended to be used both as a powerful, lightweight,
+embeddable scripting language for any program that needs one,
+and as a powerful but lightweight and efficient stand-alone language.
 
 
 <p>
-Being an extension language, Lua has no notion of a "main" program:
-it only works <em>embedded</em> in a host client,
+As an extension language, Lua has no notion of a "main" program:
+it works <em>embedded</em> in a host client,
 called the <em>embedding program</em> or simply the <em>host</em>.
+(Frequently, this host is the stand-alone <code>lua</code> program.)
 The host program can invoke functions to execute a piece of Lua code,
 can write and read Lua variables,
 and can register C&nbsp;functions to be called by Lua code.
 Through the use of C&nbsp;functions, Lua can be augmented to cope with
 a wide range of different domains,
 thus creating customized programming languages sharing a syntactical framework.
-The Lua distribution includes a sample host program called <code>lua</code>,
-which uses the Lua library to offer a complete, standalone Lua interpreter,
-for interactive or batch use.
 
 
 <p>
@@ -113,40 +132,57 @@ 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 real (double-precision floating-point) numbers.
-Operations on numbers follow the same rules of
-the underlying C&nbsp;implementation,
-which, in turn, usually follows the IEEE 754 standard.
-(It is easy to build Lua interpreters that use other
-internal representations for numbers,
-such as single-precision floats or long integers;
-see file <code>luaconf.h</code>.)
-<em>String</em> represents immutable sequences of bytes.
+The type <em>number</em> represents both
+integer numbers and real (floating-point) numbers.
+The type <em>string</em> represents immutable sequences of bytes.
 
 Lua is 8-bit clean:
 strings can contain any 8-bit value,
 including embedded zeros ('<code>\0</code>').
+Lua is also encoding-agnostic;
+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">&sect;3.4.3</a>).
+Therefore,
+the programmer may choose to mostly ignore the difference
+between integers and floats
+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
+is particularly attractive
+for small machines and embedded systems.
+(See macro <code>LUA_32BITS</code> in file <code>luaconf.h</code>.)
 
 
 <p>
 Lua can call (and manipulate) functions written in Lua and
-functions written in C
-(see <a href="#3.4.9">&sect;3.4.9</a>).
+functions written in C (see <a href="#3.4.10">&sect;3.4.10</a>).
+Both are represented by the type <em>function</em>.
 
 
 <p>
 The type <em>userdata</em> is provided to allow arbitrary C&nbsp;data to
 be stored in Lua variables.
-A userdata value is a pointer to a block of raw memory.
+A userdata value represents a block of raw memory.
 There are two kinds of userdata:
-full userdata, where the block of memory is managed by Lua,
-and light userdata, where the block of memory is managed by the host.
+<em>full userdata</em>,
+which is an object with a block of memory managed by Lua,
+and <em>light userdata</em>,
+which is simply a C&nbsp;pointer value.
 Userdata has no predefined operations in Lua,
 except assignment and identity test.
 By using <em>metatables</em>,
@@ -160,17 +196,17 @@ This guarantees the integrity of data owned by the host program.
 <p>
 The type <em>thread</em> represents independent threads of execution
 and it is used to implement coroutines (see <a href="#2.6">&sect;2.6</a>).
-Do not confuse Lua threads with operating-system threads.
+Lua threads are not related to operating-system threads.
 Lua supports coroutines on all systems,
-even those that do not support threads.
+even those that do not support threads natively.
 
 
 <p>
 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>, a special numeric value used to represent
-undefined or unrepresentable results, such as <code>0/0</code>).
+but with any Lua value except <b>nil</b> and NaN.
+(<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.
@@ -179,21 +215,21 @@ an associated value <b>nil</b>.
 
 
 <p>
-Tables are the sole data structuring mechanism in Lua;
+Tables are the sole data-structuring mechanism in Lua;
 they can be used to represent ordinary arrays, sequences,
 symbol tables, sets, records, graphs, trees, etc.
 To represent records, Lua uses the field name as an index.
 The language supports this representation by
 providing <code>a.name</code> as syntactic sugar for <code>a["name"]</code>.
 There are several convenient ways to create tables in Lua
-(see <a href="#3.4.8">&sect;3.4.8</a>).
+(see <a href="#3.4.9">&sect;3.4.9</a>).
 
 
 <p>
 We use the term <em>sequence</em> to denote a table where
-the set of all positive numeric keys is equal to <em>{1..n}</em>
-for some integer <em>n</em>,
-which is called the length of the sequence (see <a href="#3.4.6">&sect;3.4.6</a>).
+the set of all positive numeric keys is equal to {1..<em>n</em>}
+for some non-negative integer <em>n</em>,
+which is called the length of the sequence (see <a href="#3.4.7">&sect;3.4.7</a>).
 
 
 <p>
@@ -202,7 +238,7 @@ the values of table fields can be of any type.
 In particular,
 because functions are first-class values,
 table fields can contain functions.
-Thus tables can also carry <em>methods</em> (see <a href="#3.4.10">&sect;3.4.10</a>).
+Thus tables can also carry <em>methods</em> (see <a href="#3.4.11">&sect;3.4.11</a>).
 
 
 <p>
@@ -212,6 +248,18 @@ The expressions <code>a[i]</code> and <code>a[j]</code>
 denote the same table element
 if and only if <code>i</code> and <code>j</code> are raw equal
 (that is, equal without metamethods).
+In particular, floats with integral values
+are equal to their respective integers
+(e.g., <code>1.0 == 1</code>).
+To avoid ambiguities,
+any float with integral value used as a key
+is converted to its respective integer.
+For instance, if you write <code>a[2.0] = true</code>,
+the actual key inserted into the table will be the
+integer <code>2</code>.
+(On the other hand,
+2 and "<code>2</code>" are different Lua values and therefore
+denote different table entries.)
 
 
 <p>
@@ -235,20 +283,21 @@ of a given value (see <a href="#6.1">&sect;6.1</a>).
 
 <p>
 As will be discussed in <a href="#3.2">&sect;3.2</a> and <a href="#3.3.3">&sect;3.3.3</a>,
-any reference to a global name <code>var</code> is syntactically translated
-to <code>_ENV.var</code>.
+any reference to a free name
+(that is, a name not bound to any declaration) <code>var</code>
+is syntactically translated to <code>_ENV.var</code>.
 Moreover, every chunk is compiled in the scope of
-an external local variable called <code>_ENV</code> (see <a href="#3.3.2">&sect;3.3.2</a>),
-so <code>_ENV</code> itself is never a global name in a chunk.
+an external local variable named <code>_ENV</code> (see <a href="#3.3.2">&sect;3.3.2</a>),
+so <code>_ENV</code> itself is never a free name in a chunk.
 
 
 <p>
 Despite the existence of this external <code>_ENV</code> variable and
-the translation of global names,
+the translation of free names,
 <code>_ENV</code> is a completely regular name.
 In particular,
 you can define new variables and parameters with that name.
-Each reference to a global name uses the <code>_ENV</code> that is
+Each reference to a free name uses the <code>_ENV</code> that is
 visible at that point in the program,
 following the usual visibility rules of Lua (see <a href="#3.5">&sect;3.5</a>).
 
@@ -260,34 +309,25 @@ Any table used as the value of <code>_ENV</code> is called an <em>environment</e
 <p>
 Lua keeps a distinguished environment called the <em>global environment</em>.
 This value is kept at a special index in the C registry (see <a href="#4.5">&sect;4.5</a>).
-In Lua, the variable <a href="#pdf-_G"><code>_G</code></a> is initialized with this same value.
+In Lua, the global variable <a href="#pdf-_G"><code>_G</code></a> is initialized with this same value.
+(<a href="#pdf-_G"><code>_G</code></a> is never used internally.)
 
 
 <p>
-When Lua compiles a chunk,
-it initializes the value of its <code>_ENV</code> upvalue
-with the global environment (see <a href="#pdf-load"><code>load</code></a>).
+When Lua loads a chunk,
+the default value for its <code>_ENV</code> upvalue
+is the global environment (see <a href="#pdf-load"><code>load</code></a>).
 Therefore, by default,
-global variables in Lua code refer to entries in the global environment.
+free names in Lua code refer to entries in the global environment
+(and, therefore, they are also called <em>global variables</em>).
 Moreover, all standard libraries are loaded in the global environment
-and several functions there operate on that environment.
+and some functions there operate on that environment.
 You can use <a href="#pdf-load"><code>load</code></a> (or <a href="#pdf-loadfile"><code>loadfile</code></a>)
 to load a chunk with a different environment.
 (In C, you have to load the chunk and then change the value
 of its first upvalue.)
 
 
-<p>
-If you change the global environment in the registry
-(through C code or the debug library),
-all chunks loaded after the change will get the new environment.
-Previously loaded chunks are not affected, however,
-as each has its own reference to the environment in its <code>_ENV</code> variable.
-Moreover, the variable <a href="#pdf-_G"><code>_G</code></a>
-(which is stored in the original global environment)
-is never updated by Lua.
-
-
 
 
 
@@ -296,7 +336,9 @@ is never updated by Lua.
 <p>
 Because Lua is an embedded extension language,
 all Lua actions start from C&nbsp;code in the host program
-calling a function from the Lua library (see <a href="#lua_pcall"><code>lua_pcall</code></a>).
+calling a function from the Lua library.
+(When you use Lua standalone,
+the <code>lua</code> application is the host program.)
 Whenever an error occurs during
 the compilation or execution of a Lua chunk,
 control returns to the host,
@@ -316,24 +358,26 @@ to call a given function in <em>protected mode</em>.
 Whenever there is an error,
 an <em>error object</em> (also called an <em>error message</em>)
 is propagated with information about the error.
-Lua itself only generates errors where the error object is a string,
+Lua itself only generates errors whose error object is a string,
 but programs may generate errors with
-any value for the error object.
+any value as the error object.
+It is up to the Lua program or its host to handle such error objects.
 
 
 <p>
 When you use <a href="#pdf-xpcall"><code>xpcall</code></a> or <a href="#lua_pcall"><code>lua_pcall</code></a>,
 you may give a <em>message handler</em>
 to be called in case of errors.
-This function is called with the original error message
-and returns a new error message.
+This function is called with the original error object
+and returns a new error object.
 It is called before the error unwinds the stack,
 so that it can gather more information about the error,
 for instance by inspecting the stack and creating a stack traceback.
 This message handler is still protected by the protected call;
 so, an error inside the message handler
 will call the message handler again.
-If this loop goes on, Lua breaks it and returns an appropriate message.
+If this loop goes on for too long,
+Lua breaks it and returns an appropriate message.
 
 
 
@@ -355,23 +399,30 @@ Lua calls this function to perform the addition.
 
 
 <p>
-The keys in a metatable are derived from the <em>event</em> names;
+The key for each event in a metatable is a string
+with the event name prefixed by two underscores;
 the corresponding values are called <em>metamethods</em>.
-In the previous example, the event is <code>"add"</code>
+In the previous example, the key is "<code>__add</code>"
 and the metamethod is the function that performs the addition.
 
 
 <p>
 You can query the metatable of any value
 using the <a href="#pdf-getmetatable"><code>getmetatable</code></a> function.
+Lua queries metamethods in metatables using a raw access (see <a href="#pdf-rawget"><code>rawget</code></a>).
+So, to retrieve the metamethod for event <code>ev</code> in object <code>o</code>,
+Lua does the equivalent to the following code:
 
+<pre>
+     rawget(getmetatable(<em>o</em>) or {}, "__<em>ev</em>")
+</pre>
 
 <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
-(except by using the debug library);
-you must use the C&nbsp;API for that.
+You cannot change the metatable of other types from Lua code
+(except by using the debug library (<a href="#6.10">&sect;6.10</a>));
+you should use the C&nbsp;API for that.
 
 
 <p>
@@ -385,382 +436,249 @@ but the string library sets a metatable for the string type (see <a href="#6.4">
 
 
 <p>
-A metatable controls how an object behaves in arithmetic operations,
-order comparisons, concatenation, length operation, and indexing.
+A metatable controls how an object behaves in
+arithmetic operations, bitwise operations,
+order comparisons, concatenation, length operation, calls, and indexing.
 A metatable also can define a function to be called
-when a userdata or a table is garbage collected.
-When Lua performs one of these operations over a value,
-it checks whether this value has a metatable with the corresponding event.
-If so, the value associated with that key (the metamethod)
-controls how Lua will perform the operation.
+when a userdata or a table is garbage collected (<a href="#2.5">&sect;2.5</a>).
 
 
 <p>
-Metatables control the operations listed next.
-Each operation is identified by its corresponding name.
-The key for each operation is a string with its name prefixed by
-two underscores, '<code>__</code>';
-for instance, the key for operation "add" is the
-string "<code>__add</code>".
-
-
-<p>
-The semantics of these operations is better explained by a Lua function
-describing how the interpreter executes the operation.
-The code shown here in Lua is only illustrative;
-the real behavior is hard coded in the interpreter
-and it is much more efficient than this simulation.
-All functions used in these descriptions
-(<a href="#pdf-rawget"><code>rawget</code></a>, <a href="#pdf-tonumber"><code>tonumber</code></a>, etc.)
-are described in <a href="#6.1">&sect;6.1</a>.
-In particular, to retrieve the metamethod of a given object,
-we use the expression
-
-<pre>
-     metatable(obj)[event]
-</pre><p>
-This should be read as
-
-<pre>
-     rawget(getmetatable(obj) or {}, event)
-</pre><p>
-This means that the access to a metamethod does not invoke other metamethods,
-and access to objects with no metatables does not fail
-(it simply results in <b>nil</b>).
+For the unary operators (negation, length, and bitwise NOT),
+the metamethod is computed and called with a dummy second operand,
+equal to the first one.
+This extra operand is only to simplify Lua's internals
+(by making these operators behave like a binary operation)
+and may be removed in future versions.
+(For most uses this extra operand is irrelevant.)
 
 
 <p>
-For the unary <code>-</code> and <code>#</code> operators,
-the metamethod is called with a dummy second argument.
-This extra argument is only to simplify Lua's internals;
-it may be removed in future versions and therefore it is not present
-in the following code.
-(For most uses this extra argument is irrelevant.)
+A detailed list of events controlled by metatables is given next.
+Each operation is identified by its corresponding key.
 
 
 
 <ul>
 
-<li><b>"add": </b>
-the <code>+</code> operation.
-
-
-
-<p>
-The function <code>getbinhandler</code> below defines how Lua chooses a handler
-for a binary operation.
-First, Lua tries the first operand.
-If its type does not define a handler for the operation,
-then Lua tries the second operand.
-
-<pre>
-     function getbinhandler (op1, op2, event)
-       return metatable(op1)[event] or metatable(op2)[event]
-     end
-</pre><p>
-By using this function,
-the behavior of the <code>op1 + op2</code> is
-
-<pre>
-     function add_event (op1, op2)
-       local o1, o2 = tonumber(op1), tonumber(op2)
-       if o1 and o2 then  -- both operands are numeric?
-         return o1 + o2   -- '+' here is the primitive 'add'
-       else  -- at least one of the operands is not numeric
-         local h = getbinhandler(op1, op2, "__add")
-         if h then
-           -- call the handler with both operands
-           return (h(op1, op2))
-         else  -- no handler available: default behavior
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
+<li><b><code>__add</code>: </b>
+the addition (<code>+</code>) operation.
+If any operand for an addition is not a number
+(nor a string coercible to a number),
+Lua will try to call a metamethod.
+First, Lua will check the first operand (even if it is valid).
+If that operand does not define a metamethod for <code>__add</code>,
+then Lua will check the second operand.
+If Lua can find a metamethod,
+it calls the metamethod with the two operands as arguments,
+and the result of the call
+(adjusted to one value)
+is the result of the operation.
+Otherwise,
+it raises an error.
 </li>
 
-<li><b>"sub": </b>
-the <code>-</code> operation.
-
-Behavior similar to the "add" operation.
+<li><b><code>__sub</code>: </b>
+the subtraction (<code>-</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"mul": </b>
-the <code>*</code> operation.
-
-Behavior similar to the "add" operation.
+<li><b><code>__mul</code>: </b>
+the multiplication (<code>*</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"div": </b>
-the <code>/</code> operation.
-
-Behavior similar to the "add" operation.
+<li><b><code>__div</code>: </b>
+the division (<code>/</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"mod": </b>
-the <code>%</code> operation.
-
-Behavior similar to the "add" operation,
-with the operation
-<code>o1 - floor(o1/o2)*o2</code> as the primitive operation.
+<li><b><code>__mod</code>: </b>
+the modulo (<code>%</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"pow": </b>
-the <code>^</code> (exponentiation) operation.
-
-Behavior similar to the "add" operation,
-with the function <code>pow</code> (from the C&nbsp;math library)
-as the primitive operation.
+<li><b><code>__pow</code>: </b>
+the exponentiation (<code>^</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"unm": </b>
-the unary <code>-</code> operation.
-
-
-<pre>
-     function unm_event (op)
-       local o = tonumber(op)
-       if o then  -- operand is numeric?
-         return -o  -- '-' here is the primitive 'unm'
-       else  -- the operand is not numeric.
-         -- Try to get a handler from the operand
-         local h = metatable(op).__unm
-         if h then
-           -- call the handler with the operand
-           return (h(op))
-         else  -- no handler available: default behavior
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
+<li><b><code>__unm</code>: </b>
+the negation (unary <code>-</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"concat": </b>
-the <code>..</code> (concatenation) operation.
-
-
-<pre>
-     function concat_event (op1, op2)
-       if (type(op1) == "string" or type(op1) == "number") and
-          (type(op2) == "string" or type(op2) == "number") then
-         return op1 .. op2  -- primitive string concatenation
-       else
-         local h = getbinhandler(op1, op2, "__concat")
-         if h then
-           return (h(op1, op2))
-         else
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
+<li><b><code>__idiv</code>: </b>
+the floor division (<code>//</code>) operation.
+Behavior similar to the addition operation.
 </li>
 
-<li><b>"len": </b>
-the <code>#</code> operation.
-
-
-<pre>
-     function len_event (op)
-       if type(op) == "string" then
-         return strlen(op)      -- primitive string length
-       else
-         local h = metatable(op).__len
-         if h then
-           return (h(op))       -- call handler with the operand
-         elseif type(op) == "table" then
-           return #op              -- primitive table length
-         else  -- no handler available: error
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
-See <a href="#3.4.6">&sect;3.4.6</a> for a description of the length of a table.
+<li><b><code>__band</code>: </b>
+the bitwise AND (<code>&amp;</code>) operation.
+Behavior similar to the addition operation,
+except that Lua will try a metamethod
+if any operand is neither an integer
+nor a value coercible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>).
 </li>
 
-<li><b>"eq": </b>
-the <code>==</code> operation.
-
-The function <code>getequalhandler</code> defines how Lua chooses a metamethod
-for equality.
-A metamethod is selected only when both values
-being compared have the same type
-and the same metamethod for the selected operation,
-and the values are either tables or full userdata.
-
-<pre>
-     function getequalhandler (op1, op2)
-       if type(op1) ~= type(op2) or
-          (type(op1) ~= "table" and type(op1) ~= "userdata") then
-         return nil     -- different values
-       end
-       local mm1 = metatable(op1).__eq
-       local mm2 = metatable(op2).__eq
-       if mm1 == mm2 then return mm1 else return nil end
-     end
-</pre><p>
-The "eq" event is defined as follows:
+<li><b><code>__bor</code>: </b>
+the bitwise OR (<code>|</code>) operation.
+Behavior similar to the bitwise AND operation.
+</li>
 
-<pre>
-     function eq_event (op1, op2)
-       if op1 == op2 then   -- primitive equal?
-         return true   -- values are equal
-       end
-       -- try metamethod
-       local h = getequalhandler(op1, op2)
-       if h then
-         return not not h(op1, op2)
-       else
-         return false
-       end
-     end
-</pre><p>
-Note that the result is always a boolean.
+<li><b><code>__bxor</code>: </b>
+the bitwise exclusive OR (binary <code>~</code>) operation.
+Behavior similar to the bitwise AND operation.
 </li>
 
-<li><b>"lt": </b>
-the <code>&lt;</code> operation.
+<li><b><code>__bnot</code>: </b>
+the bitwise NOT (unary <code>~</code>) operation.
+Behavior similar to the bitwise AND operation.
+</li>
 
+<li><b><code>__shl</code>: </b>
+the bitwise left shift (<code>&lt;&lt;</code>) operation.
+Behavior similar to the bitwise AND operation.
+</li>
 
-<pre>
-     function lt_event (op1, op2)
-       if type(op1) == "number" and type(op2) == "number" then
-         return op1 &lt; op2   -- numeric comparison
-       elseif type(op1) == "string" and type(op2) == "string" then
-         return op1 &lt; op2   -- lexicographic comparison
-       else
-         local h = getbinhandler(op1, op2, "__lt")
-         if h then
-           return not not h(op1, op2)
-         else
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
-Note that the result is always a boolean.
+<li><b><code>__shr</code>: </b>
+the bitwise right shift (<code>&gt;&gt;</code>) operation.
+Behavior similar to the bitwise AND operation.
 </li>
 
-<li><b>"le": </b>
-the <code>&lt;=</code> operation.
+<li><b><code>__concat</code>: </b>
+the concatenation (<code>..</code>) operation.
+Behavior similar to the addition operation,
+except that Lua will try a metamethod
+if any operand is neither a string nor a number
+(which is always coercible to a string).
+</li>
 
+<li><b><code>__len</code>: </b>
+the length (<code>#</code>) operation.
+If the object is not a string,
+Lua will try its metamethod.
+If there is a metamethod,
+Lua calls it with the object as argument,
+and the result of the call
+(always adjusted to one value)
+is the result of the operation.
+If there is no metamethod but the object is a table,
+then Lua uses the table length operation (see <a href="#3.4.7">&sect;3.4.7</a>).
+Otherwise, Lua raises an error.
+</li>
 
-<pre>
-     function le_event (op1, op2)
-       if type(op1) == "number" and type(op2) == "number" then
-         return op1 &lt;= op2   -- numeric comparison
-       elseif type(op1) == "string" and type(op2) == "string" then
-         return op1 &lt;= op2   -- lexicographic comparison
-       else
-         local h = getbinhandler(op1, op2, "__le")
-         if h then
-           return not not h(op1, op2)
-         else
-           h = getbinhandler(op1, op2, "__lt")
-           if h then
-             return not h(op2, op1)
-           else
-             error(&middot;&middot;&middot;)
-           end
-         end
-       end
-     end
-</pre><p>
-Note that, in the absence of a "le" metamethod,
-Lua tries the "lt", assuming that <code>a &lt;= b</code> is
-equivalent to <code>not (b &lt; a)</code>.
+<li><b><code>__eq</code>: </b>
+the equal (<code>==</code>) operation.
+Behavior similar to the addition operation,
+except that Lua will try a metamethod only when the values
+being compared are either both tables or both full userdata
+and they are not primitively equal.
+The result of the call is always converted to a boolean.
+</li>
 
+<li><b><code>__lt</code>: </b>
+the less than (<code>&lt;</code>) operation.
+Behavior similar to the addition operation,
+except that Lua will try a metamethod only when the values
+being compared are neither both numbers nor both strings.
+The result of the call is always converted to a boolean.
+</li>
 
-<p>
+<li><b><code>__le</code>: </b>
+the less equal (<code>&lt;=</code>) operation.
+Unlike other operations,
+the less-equal operation can use two different events.
+First, Lua looks for the <code>__le</code> metamethod in both operands,
+like in the less than operation.
+If it cannot find such a metamethod,
+then it will try the <code>__lt</code> metamethod,
+assuming that <code>a &lt;= b</code> is equivalent to <code>not (b &lt; 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>
+<li><b><code>__index</code>: </b>
 The indexing access <code>table[key]</code>.
-Note that the metamethod is tried only
+This event happens when <code>table</code> is not a table or
 when <code>key</code> is not present in <code>table</code>.
-(When <code>table</code> is not a table,
-no key is ever present,
-so the metamethod is always tried.)
+The metamethod is looked up in <code>table</code>.
 
 
-<pre>
-     function gettable_event (table, key)
-       local h
-       if type(table) == "table" then
-         local v = rawget(table, key)
-         -- if key is present, return raw value
-         if v ~= nil then return v end
-         h = metatable(table).__index
-         if h == nil then return nil end
-       else
-         h = metatable(table).__index
-         if h == nil then
-           error(&middot;&middot;&middot;)
-         end
-       end
-       if type(h) == "function" then
-         return (h(table, key))     -- call the handler
-       else return h[key]           -- or repeat operation on it
-       end
-     end
-</pre><p>
+<p>
+Despite the name,
+the metamethod for this event can be either a function or a table.
+If it is a function,
+it is called with <code>table</code> and <code>key</code> as arguments,
+and the result of the call
+(adjusted to one value)
+is the result of the operation.
+If it is a table,
+the final result is the result of indexing this table with <code>key</code>.
+(This indexing is regular, not raw,
+and therefore can trigger another metamethod.)
 </li>
 
-<li><b>"newindex": </b>
+<li><b><code>__newindex</code>: </b>
 The indexing assignment <code>table[key] = value</code>.
-Note that the metamethod is tried only
+Like the index event,
+this event happens when <code>table</code> is not a table or
 when <code>key</code> is not present in <code>table</code>.
+The metamethod is looked up in <code>table</code>.
 
 
-<pre>
-     function settable_event (table, key, value)
-       local h
-       if type(table) == "table" then
-         local v = rawget(table, key)
-         -- if key is present, do raw assignment
-         if v ~= nil then rawset(table, key, value); return end
-         h = metatable(table).__newindex
-         if h == nil then rawset(table, key, value); return end
-       else
-         h = metatable(table).__newindex
-         if h == nil then
-           error(&middot;&middot;&middot;)
-         end
-       end
-       if type(h) == "function" then
-         h(table, key,value)           -- call the handler
-       else h[key] = value             -- or repeat operation on it
-       end
-     end
-</pre><p>
-</li>
+<p>
+Like with indexing,
+the metamethod for this event can be either a function or a table.
+If it is a function,
+it is called with <code>table</code>, <code>key</code>, and <code>value</code> as arguments.
+If it is a table,
+Lua does an indexing assignment to this table with the same key and value.
+(This assignment is regular, not raw,
+and therefore can trigger another metamethod.)
 
-<li><b>"call": </b>
-called when Lua calls a value.
 
+<p>
+Whenever there is a <code>__newindex</code> metamethod,
+Lua does not perform the primitive assignment.
+(If necessary,
+the metamethod itself can call <a href="#pdf-rawset"><code>rawset</code></a>
+to do the assignment.)
+</li>
 
-<pre>
-     function function_event (func, ...)
-       if type(func) == "function" then
-         return func(...)   -- primitive call
-       else
-         local h = metatable(func).__call
-         if h then
-           return h(func, ...)
-         else
-           error(&middot;&middot;&middot;)
-         end
-       end
-     end
-</pre><p>
+<li><b><code>__call</code>: </b>
+The call operation <code>func(args)</code>.
+This event happens when Lua tries to call a non-function value
+(that is, <code>func</code> is not a function).
+The metamethod is looked up in <code>func</code>.
+If present,
+the metamethod is called with <code>func</code> as its first argument,
+followed by the arguments of the original call (<code>args</code>).
+All results of the call
+are the result of the operation.
+(This is the only metamethod that allows multiple results.)
 </li>
 
 </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">&sect;2.5.1</a>).
+
+
+<p>
+Because metatables are regular tables,
+they can contain arbitrary fields,
+not only the event names defined above.
+Some functions in the standard library
+(e.g., <a href="#pdf-tostring"><code>tostring</code></a>)
+use other fields in metatables for their own purposes.
+
+
 
 
 
@@ -769,8 +687,8 @@ called when Lua calls a value.
 <p>
 Lua performs automatic memory management.
 This means that
-you have to worry neither about allocating memory for new objects
-nor about freeing it when the objects are no longer needed.
+you do not have to worry about allocating memory for new objects
+or freeing it when the objects are no longer needed.
 Lua manages memory automatically by running
 a <em>garbage collector</em> to collect all <em>dead objects</em>
 (that is, objects that are no longer accessible from Lua).
@@ -803,7 +721,8 @@ controls the relative speed of the collector relative to
 memory allocation.
 Larger values make the collector more aggressive but also increase
 the size of each incremental step.
-Values smaller than 100 make the collector too slow and
+You should not use values smaller than 100,
+because they make the collector too slow and
 can result in the collector never finishing a cycle.
 The default is 200,
 which means that the collector runs at "twice"
@@ -828,21 +747,6 @@ You can also use these functions to control
 the collector directly (e.g., stop and restart it).
 
 
-<p>
-As an experimental feature in Lua 5.2,
-you can change the collector's operation mode
-from incremental to <em>generational</em>.
-A <em>generational collector</em> assumes that most objects die young,
-and therefore it traverses only young (recently created) objects.
-This behavior can reduce the time used by the collector,
-but also increases memory usage (as old dead objects may accumulate).
-To mitigate this second problem,
-from time to time the generational collector performs a full collection.
-Remember that this is an experimental feature;
-you are welcome to try it,
-but check your gains.
-
-
 
 <h3>2.5.1 &ndash; <a name="2.5.1">Garbage-Collection Metamethods</a></h3>
 
@@ -866,8 +770,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 is marked,
-you can freely change the <code>__gc</code> field of its metatable.
 
 
 <p>
@@ -875,22 +777,19 @@ When a marked object becomes garbage,
 it is not collected immediately by the garbage collector.
 Instead, Lua puts it in a list.
 After the collection,
-Lua does the equivalent of the following function
-for each object in that list:
+Lua goes through that list.
+For each object in the list,
+it checks the object's <code>__gc</code> metamethod:
+If it is a function,
+Lua calls it with the object as its single argument;
+if the metamethod is not a function,
+Lua simply ignores it.
 
-<pre>
-     function gc_event (obj)
-       local h = metatable(obj).__gc
-       if type(h) == "function" then
-         h(obj)
-       end
-     end
-</pre>
 
 <p>
 At the end of each garbage-collection cycle,
 the finalizers for objects are called in
-the reverse order that they were marked for collection,
+the reverse order that the objects were marked for finalization,
 among those collected in that cycle;
 that is, the first finalizer to be called is the one associated
 with the object marked last in the program.
@@ -900,24 +799,27 @@ the execution of the regular code.
 
 <p>
 Because the object being collected must still be used by the finalizer,
-it (and other objects accessible only through it)
+that object (and other objects accessible only through it)
 must be <em>resurrected</em> by Lua.
 Usually, this resurrection is transient,
 and the object memory is freed in the next garbage-collection cycle.
 However, if the finalizer stores the object in some global place
 (e.g., a global variable),
-then there is a permanent resurrection.
+then the resurrection is permanent.
+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 when it becomes completely inaccessible;
-its finalizer will never be called twice.
+the object memory is freed only in a GC cycle where
+the object is unreachable and not marked for finalization.
 
 
 <p>
 When you close a state (see <a href="#lua_close"><code>lua_close</code></a>),
 Lua calls the finalizers of all objects marked for finalization,
 following the reverse order that they were marked.
-If any finalizer marks new objects for collection during that phase,
-these new objects will not be finalized.
+If any finalizer marks objects for collection during that phase,
+these marks have no effect.
 
 
 
@@ -936,8 +838,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,
@@ -974,7 +876,7 @@ are removed from weak tables.
 Values, such as numbers and light C functions,
 are not subject to garbage collection,
 and therefore are not removed from weak tables
-(unless its associated value is collected).
+(unless their associated values are collected).
 Although strings are subject to garbage collection,
 they do not have an explicit construction,
 and therefore are not removed from weak tables.
@@ -1027,10 +929,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.
-Extra arguments passed to <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> are passed on
-to the coroutine 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 that function.
 After the coroutine starts running,
 it runs until it terminates or <em>yields</em>.
 
@@ -1040,10 +942,11 @@ A coroutine can terminate its execution in two ways:
 normally, when its main function returns
 (explicitly or implicitly, after the last instruction);
 and abnormally, if there is an unprotected error.
-In the first case, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>,
+In case of normal termination,
+<a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>true</b>,
 plus any values returned by the coroutine main function.
 In case of errors, <a href="#pdf-coroutine.resume"><code>coroutine.resume</code></a> returns <b>false</b>
-plus an error message.
+plus an error object.
 
 
 <p>
@@ -1159,7 +1062,8 @@ except as delimiters between names and keywords.
 (also called <em>identifiers</em>)
 in Lua can be any string of letters,
 digits, and underscores,
-not beginning with a digit.
+not beginning with a digit and
+not being a reserved word.
 Identifiers are used to name variables, table fields, and labels.
 
 
@@ -1179,9 +1083,10 @@ and cannot be used as names:
 Lua is a case-sensitive language:
 <code>and</code> is a reserved word, but <code>And</code> and <code>AND</code>
 are two different, valid names.
-As a convention, names starting with an underscore followed by
-uppercase letters (such as <a href="#pdf-_VERSION"><code>_VERSION</code></a>)
-are reserved for variables used by Lua.
+As a convention,
+programs should avoid creating 
+names that start with an underscore followed by
+one or more uppercase letters (such as <a href="#pdf-_VERSION"><code>_VERSION</code></a>).
 
 
 <p>
@@ -1189,6 +1094,7 @@ The following strings denote other tokens:
 
 <pre>
      +     -     *     /     %     ^     #
+     &amp;     ~     |     &lt;&lt;    &gt;&gt;    //
      ==    ~=    &lt;=    &gt;=    &lt;     &gt;     =
      (     )     {     }     [     ]     ::
      ;     :     ,     .     ..    ...
@@ -1219,15 +1125,26 @@ into the string contents.
 
 
 <p>
-A byte in a literal string can also be specified by its numerical value.
-This can be done with the escape sequence <code>\x<em>XX</em></code>,
+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 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,
 or with the escape sequence <code>\<em>ddd</em></code>,
 where <em>ddd</em> is a sequence of up to three decimal digits.
-(Note that if a decimal escape is to be followed by a digit,
+(Note that if a decimal escape sequence is to be followed by a digit,
 it must be expressed using exactly three digits.)
-Strings in Lua can contain any 8-bit value, including embedded zeros,
-which can be specified as '<code>\0</code>'.
+
+
+<p>
+The UTF-8 encoding of a Unicode character
+can be inserted in a literal string with
+the escape sequence <code>\u{<em>XXX</em>}</code>
+(note the mandatory enclosing brackets),
+where <em>XXX</em> is a sequence of one or more hexadecimal digits
+representing the character code point.
 
 
 <p>
@@ -1236,14 +1153,15 @@ enclosed by <em>long brackets</em>.
 We define an <em>opening long bracket of level <em>n</em></em> as an opening
 square bracket followed by <em>n</em> equal signs followed by another
 opening square bracket.
-So, an opening long bracket of level&nbsp;0 is written as <code>[[</code>,
-an opening long bracket of level&nbsp;1 is written as <code>[=[</code>,
+So, an opening long bracket of level&nbsp;0 is written as <code>[[</code>, 
+an opening long bracket of level&nbsp;1 is written as <code>[=[</code>, 
 and so on.
 A <em>closing long bracket</em> is defined similarly;
-for instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.
+for instance,
+a closing long bracket of level&nbsp;4 is written as  <code>]====]</code>.
 A <em>long literal</em> starts with an opening long bracket of any level and
 ends at the first closing long bracket of the same level.
-It can contain any text except a closing bracket of the proper level.
+It can contain any text except a closing bracket of the same level.
 Literals in this bracketed form can run for several lines,
 do not interpret any escape sequences,
 and ignore long brackets of any other level.
@@ -1261,7 +1179,7 @@ and the system file functions may have problems with
 some control characters.
 So, it is safer to represent
 non-text data as a quoted literal with
-explicit escape sequences for non-text characters.
+explicit escape sequences for the non-text characters.
 
 
 <p>
@@ -1285,7 +1203,8 @@ the five literal strings below denote the same string:
 </pre>
 
 <p>
-A <em>numerical constant</em> can be written with an optional fractional part
+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>'.
 Lua also accepts hexadecimal constants,
@@ -1293,11 +1212,21 @@ which start with <code>0x</code> or <code>0X</code>.
 Hexadecimal constants also accept an optional fractional part
 plus an optional binary exponent,
 marked by a letter '<code>p</code>' or '<code>P</code>'.
-Examples of valid numerical constants are
+A numeric constant with a radix point or an exponent 
+denotes a float;
+otherwise,
+if its value fits in an integer,
+it denotes an integer.
+Examples of valid integer constants are
+
+<pre>
+     3   345   0xff   0xBEBADA
+</pre><p>
+Examples of valid float constants are
 
 <pre>
-     3     3.0     3.1416     314.16e-2     0.31416E1
-     0xff  0x0.1E  0xA23p-4   0X1.921FB54442D18P+1
+     3.0     3.1416     314.16e-2     0.31416E1     34e1
+     0x0.1E  0xA23p-4   0X1.921FB54442D18P+1
 </pre>
 
 <p>
@@ -1466,7 +1395,7 @@ a chunk is simply a block:
 <p>
 Lua handles a chunk as the body of an anonymous function
 with a variable number of arguments
-(see <a href="#3.4.10">&sect;3.4.10</a>).
+(see <a href="#3.4.11">&sect;3.4.11</a>).
 As such, chunks can define local variables,
 receive arguments, and return values.
 Moreover, such anonymous function is compiled as in the
@@ -1478,17 +1407,17 @@ even if it does not use that variable.
 <p>
 A chunk can be stored in a file or in a string inside the host program.
 To execute a chunk,
-Lua first precompiles the chunk into instructions for a virtual machine,
-and then it executes the compiled code
+Lua first <em>loads</em> it,
+precompiling the chunk's code into instructions for a virtual machine,
+and then Lua executes the compiled code
 with an interpreter for the virtual machine.
 
 
 <p>
 Chunks can also be precompiled into binary form;
-see program <code>luac</code> for details.
+see program <code>luac</code> and function <a href="#pdf-string.dump"><code>string.dump</code></a> for details.
 Programs in source and compiled forms are interchangeable;
-Lua automatically detects the file type and acts accordingly.
-
+Lua automatically detects the file type and acts accordingly (see <a href="#pdf-load"><code>load</code></a>).
 
 
 
@@ -1527,7 +1456,7 @@ before the adjustment
 
 <p>
 The assignment statement first evaluates all its expressions
-and only then are the assignments performed.
+and only then the assignments are performed.
 Thus the code
 
 <pre>
@@ -1563,7 +1492,7 @@ We use it here only for explanatory purposes.)
 
 
 <p>
-An assignment to a global variable <code>x = val</code>
+An assignment to a global name <code>x = val</code>
 is equivalent to the assignment
 <code>_ENV.x = val</code> (see <a href="#2.2">&sect;2.2</a>).
 
@@ -1644,7 +1573,8 @@ A <b>break</b> ends the innermost enclosing loop.
 
 <p>
 The <b>return</b> statement is used to return values
-from a function or a chunk (which is a function in disguise).
+from a function or a chunk
+(which is an anonymous function).
 
 Functions can return more than one value,
 so the syntax for the <b>return</b> statement is
@@ -1670,11 +1600,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:
 
@@ -1695,13 +1625,19 @@ is equivalent to the code:
      do
        local <em>var</em>, <em>limit</em>, <em>step</em> = tonumber(<em>e1</em>), tonumber(<em>e2</em>), tonumber(<em>e3</em>)
        if not (<em>var</em> and <em>limit</em> and <em>step</em>) then error() end
-       while (<em>step</em> &gt; 0 and <em>var</em> &lt;= <em>limit</em>) or (<em>step</em> &lt;= 0 and <em>var</em> &gt;= <em>limit</em>) do
+       <em>var</em> = <em>var</em> - <em>step</em>
+       while true do
+         <em>var</em> = <em>var</em> + <em>step</em>
+         if (<em>step</em> &gt;= 0 and <em>var</em> &gt; <em>limit</em>) or (<em>step</em> &lt; 0 and <em>var</em> &lt; <em>limit</em>) then
+           break
+         end
          local v = <em>var</em>
          <em>block</em>
-         <em>var</em> = <em>var</em> + <em>step</em>
        end
      end
-</pre><p>
+</pre>
+
+<p>
 Note the following:
 
 <ul>
@@ -1723,14 +1659,13 @@ then a step of&nbsp;1 is used.
 </li>
 
 <li>
-You can use <b>break</b> to exit a <b>for</b> loop.
+You can use <b>break</b> and <b>goto</b> to exit a <b>for</b> loop.
 </li>
 
 <li>
-The loop variable <code>v</code> is local to the loop;
-you cannot use its value after the <b>for</b> ends or is broken.
-If you need this value,
-assign it to another variable before breaking or exiting the loop.
+The loop variable <code>v</code> is local to the loop body.
+If you need its value after the loop,
+assign it to another variable before exiting the loop.
 </li>
 
 </ul>
@@ -1804,7 +1739,7 @@ function calls can be executed as statements:
        stat ::= functioncall
 </pre><p>
 In this case, all returned values are thrown away.
-Function calls are explained in <a href="#3.4.9">&sect;3.4.9</a>.
+Function calls are explained in <a href="#3.4.10">&sect;3.4.10</a>.
 
 
 
@@ -1844,8 +1779,8 @@ The basic expressions in Lua are the following:
 <pre>
        exp ::= prefixexp
        exp ::= <b>nil</b> | <b>false</b> | <b>true</b>
-       exp ::= Number
-       exp ::= String
+       exp ::= Numeral
+       exp ::= LiteralString
        exp ::= functiondef
        exp ::= tableconstructor
        exp ::= &lsquo;<b>...</b>&rsquo;
@@ -1855,24 +1790,26 @@ The basic expressions in Lua are the following:
 </pre>
 
 <p>
-Numbers and literal strings are explained in <a href="#3.1">&sect;3.1</a>;
+Numerals and literal strings are explained in <a href="#3.1">&sect;3.1</a>;
 variables are explained in <a href="#3.2">&sect;3.2</a>;
-function definitions are explained in <a href="#3.4.10">&sect;3.4.10</a>;
-function calls are explained in <a href="#3.4.9">&sect;3.4.9</a>;
-table constructors are explained in <a href="#3.4.8">&sect;3.4.8</a>.
+function definitions are explained in <a href="#3.4.11">&sect;3.4.11</a>;
+function calls are explained in <a href="#3.4.10">&sect;3.4.10</a>;
+table constructors are explained in <a href="#3.4.9">&sect;3.4.9</a>.
 Vararg expressions,
 denoted by three dots ('<code>...</code>'), can only be used when
 directly inside a vararg function;
-they are explained in <a href="#3.4.10">&sect;3.4.10</a>.
+they are explained in <a href="#3.4.11">&sect;3.4.11</a>.
 
 
 <p>
 Binary operators comprise arithmetic operators (see <a href="#3.4.1">&sect;3.4.1</a>),
-relational operators (see <a href="#3.4.3">&sect;3.4.3</a>), logical operators (see <a href="#3.4.4">&sect;3.4.4</a>),
-and the concatenation operator (see <a href="#3.4.5">&sect;3.4.5</a>).
+bitwise operators (see <a href="#3.4.2">&sect;3.4.2</a>),
+relational operators (see <a href="#3.4.4">&sect;3.4.4</a>), logical operators (see <a href="#3.4.5">&sect;3.4.5</a>),
+and the concatenation operator (see <a href="#3.4.6">&sect;3.4.6</a>).
 Unary operators comprise the unary minus (see <a href="#3.4.1">&sect;3.4.1</a>),
-the unary <b>not</b> (see <a href="#3.4.4">&sect;3.4.4</a>),
-and the unary <em>length operator</em> (see <a href="#3.4.6">&sect;3.4.6</a>).
+the unary bitwise NOT (see <a href="#3.4.2">&sect;3.4.2</a>),
+the unary logical <b>not</b> (see <a href="#3.4.5">&sect;3.4.5</a>),
+and the unary <em>length operator</em> (see <a href="#3.4.7">&sect;3.4.7</a>).
 
 
 <p>
@@ -1923,38 +1860,152 @@ or <b>nil</b> if <code>f</code> does not return any values.)
 
 
 <h3>3.4.1 &ndash; <a name="3.4.1">Arithmetic Operators</a></h3><p>
-Lua supports the usual arithmetic operators:
-the binary <code>+</code> (addition),
-<code>-</code> (subtraction), <code>*</code> (multiplication),
-<code>/</code> (division), <code>%</code> (modulo), and <code>^</code> (exponentiation);
-and unary <code>-</code> (mathematical negation).
-If the operands are numbers, or strings that can be converted to
-numbers (see <a href="#3.4.2">&sect;3.4.2</a>),
-then all operations have the usual meaning.
-Exponentiation works for any exponent.
-For instance, <code>x^(-0.5)</code> computes the inverse of the square root of <code>x</code>.
-Modulo is defined as
+Lua supports the following arithmetic operators:
 
-<pre>
-     a % b == a - math.floor(a/b)*b
-</pre><p>
-That is, it is the remainder of a division that rounds
-the quotient towards minus infinity.
+<ul>
+<li><b><code>+</code>: </b>addition</li>
+<li><b><code>-</code>: </b>subtraction</li>
+<li><b><code>*</code>: </b>multiplication</li>
+<li><b><code>/</code>: </b>float division</li>
+<li><b><code>//</code>: </b>floor division</li>
+<li><b><code>%</code>: </b>modulo</li>
+<li><b><code>^</code>: </b>exponentiation</li>
+<li><b><code>-</code>: </b>unary minus</li>
+</ul>
+
+<p>
+With the exception of exponentiation and float division,
+the arithmetic operators work as follows:
+If both operands are integers,
+the operation is performed over integers and the result is an integer.
+Otherwise, if both operands are numbers
+or strings that can be converted to
+numbers (see <a href="#3.4.3">&sect;3.4.3</a>),
+then they are converted to floats,
+the operation is performed following the usual rules
+for floating-point arithmetic
+(usually the IEEE 754 standard),
+and the result is a float.
+
+
+<p>
+Exponentiation and float division (<code>/</code>)
+always convert their operands to floats
+and the result is always a float.
+Exponentiation uses the ISO&nbsp;C function <code>pow</code>,
+so that it works for non-integer exponents too.
 
 
+<p>
+Floor division (<code>//</code>) is a division 
+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 infinity (floor division).
 
-<h3>3.4.2 &ndash; <a name="3.4.2">Coercion</a></h3>
 
 <p>
-Lua provides automatic conversion between
-string and number values at run time.
-Any arithmetic operation applied to a string tries to convert
-this string to a number, following the rules of the Lua lexer.
-(The string may have leading and trailing spaces and a sign.)
-Conversely, whenever a number is used where a string is expected,
-the number is converted to a string, in a reasonable format.
+In case of overflows in integer arithmetic,
+all operations <em>wrap around</em>,
+according to the usual rules of two-complement arithmetic.
+(In other words,
+they return the unique representable integer
+that is equal modulo <em>2<sup>64</sup></em> to the mathematical result.)
+
+
+
+<h3>3.4.2 &ndash; <a name="3.4.2">Bitwise Operators</a></h3><p>
+Lua supports the following bitwise operators:
+
+<ul>
+<li><b><code>&amp;</code>: </b>bitwise AND</li>
+<li><b><code>&#124;</code>: </b>bitwise OR</li>
+<li><b><code>~</code>: </b>bitwise exclusive OR</li>
+<li><b><code>&gt;&gt;</code>: </b>right shift</li>
+<li><b><code>&lt;&lt;</code>: </b>left shift</li>
+<li><b><code>~</code>: </b>unary bitwise NOT</li>
+</ul>
+
+<p>
+All bitwise operations convert its operands to integers
+(see <a href="#3.4.3">&sect;3.4.3</a>),
+operate on all bits of those integers,
+and result in an integer.
+
+
+<p>
+Both right and left shifts fill the vacant bits with zeros.
+Negative displacements shift to the other direction;
+displacements with absolute values equal to or higher than
+the number of bits in an integer
+result in zero (as all bits are shifted out).
+
+
+
+
+
+<h3>3.4.3 &ndash; <a name="3.4.3">Coercions and Conversions</a></h3><p>
+Lua provides some automatic conversions between some
+types and representations at run time.
+Bitwise operators always convert float operands to integers.
+Exponentiation and float division
+always convert integer operands to floats.
+All other arithmetic operations applied to mixed numbers
+(integers and floats) convert the integer operand to a float;
+this is called the <em>usual rule</em>.
+The C API also converts both integers to floats and
+floats to integers, as needed.
+Moreover, string concatenation accepts numbers as arguments,
+besides strings. 
+
+
+<p>
+Lua also converts strings to numbers,
+whenever a number is expected.
+
+
+<p>
+In a conversion from integer to float,
+if the integer value has an exact representation as a float,
+that is the result.
+Otherwise,
+the conversion gets the nearest higher or
+the nearest lower representable value.
+This kind of conversion never fails.
+
+
+<p>
+The conversion from float to integer
+checks whether the float has an exact representation as an integer
+(that is, the float has an integral value and
+it is in the range of integer representation).
+If it does, that representation is the result.
+Otherwise, the conversion fails.
+
+
+<p>
+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 (float or integer)
+is converted to the type (float or integer) required by the context
+(e.g., the operation that forced the conversion).
+
+
+<p>
+All conversions from strings to numbers 
+accept both a dot and the current locale mark
+as the radix character.
+(The Lua lexer, however, accepts only a dot.)
+
+
+<p>
+The conversion from numbers to strings uses a
+non-specified human-readable format.
 For complete control over how numbers are converted to strings,
 use the <code>format</code> function from the string library
 (see <a href="#pdf-string.format"><code>string.format</code></a>).
@@ -1963,12 +2014,17 @@ use the <code>format</code> function from the string library
 
 
 
-<h3>3.4.3 &ndash; <a name="3.4.3">Relational Operators</a></h3><p>
-The relational operators in Lua are
+<h3>3.4.4 &ndash; <a name="3.4.4">Relational Operators</a></h3><p>
+Lua supports the following relational operators:
 
-<pre>
-     ==    ~=    &lt;     &gt;     &lt;=    &gt;=
-</pre><p>
+<ul>
+<li><b><code>==</code>: </b>equality</li>
+<li><b><code>~=</code>: </b>inequality</li>
+<li><b><code>&lt;</code>: </b>less than</li>
+<li><b><code>&gt;</code>: </b>greater than</li>
+<li><b><code>&lt;=</code>: </b>less or equal</li>
+<li><b><code>&gt;=</code>: </b>greater or equal</li>
+</ul><p>
 These operators always result in <b>false</b> or <b>true</b>.
 
 
@@ -1976,7 +2032,11 @@ These operators always result in <b>false</b> or <b>true</b>.
 Equality (<code>==</code>) first compares the type of its operands.
 If the types are different, then the result is <b>false</b>.
 Otherwise, the values of the operands are compared.
-Numbers and strings are compared in the usual way.
+Strings are compared in the obvious way.
+Numbers are equal if they denote the same mathematical value.
+
+
+<p>
 Tables, userdata, and threads
 are compared by reference:
 two objects are considered equal only if they are the same object.
@@ -1994,8 +2054,8 @@ by using the "eq" metamethod (see <a href="#2.4">&sect;2.4</a>).
 
 
 <p>
-The conversion rules of <a href="#3.4.2">&sect;3.4.2</a>
-do not apply to equality comparisons.
+Equality comparisons do not convert strings to numbers
+or vice versa.
 Thus, <code>"0"==0</code> evaluates to <b>false</b>,
 and <code>t[0]</code> and <code>t["0"]</code> denote different
 entries in a table.
@@ -2007,7 +2067,9 @@ The operator <code>~=</code> is exactly the negation of equality (<code>==</code
 
 <p>
 The order operators work as follows.
-If both arguments are numbers, then they are compared as such.
+If both arguments are numbers,
+then they are compared 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"
@@ -2016,10 +2078,16 @@ A comparison <code>a &gt; b</code> is translated to <code>b &lt; a</code>
 and <code>a &gt;= b</code> is translated to <code>b &lt;= a</code>.
 
 
+<p>
+Following the IEEE 754 standard,
+NaN is considered neither smaller than,
+nor equal to, nor greater than any value (including itself).
+
+
 
 
 
-<h3>3.4.4 &ndash; <a name="3.4.4">Logical Operators</a></h3><p>
+<h3>3.4.5 &ndash; <a name="3.4.5">Logical Operators</a></h3><p>
 The logical operators in Lua are
 <b>and</b>, <b>or</b>, and <b>not</b>.
 Like the control structures (see <a href="#3.3.4">&sect;3.3.4</a>),
@@ -2035,7 +2103,7 @@ otherwise, <b>and</b> returns its second argument.
 The disjunction operator <b>or</b> returns its first argument
 if this value is different from <b>nil</b> and <b>false</b>;
 otherwise, <b>or</b> returns its second argument.
-Both <b>and</b> and <b>or</b> use short-cut evaluation;
+Both <b>and</b> and <b>or</b> use short-circuit evaluation;
 that is,
 the second operand is evaluated only if necessary.
 Here are some examples:
@@ -2057,18 +2125,18 @@ Here are some examples:
 
 
 
-<h3>3.4.5 &ndash; <a name="3.4.5">Concatenation</a></h3><p>
+<h3>3.4.6 &ndash; <a name="3.4.6">Concatenation</a></h3><p>
 The string concatenation operator in Lua is
 denoted by two dots ('<code>..</code>').
 If both operands are strings or numbers, then they are converted to
-strings according to the rules mentioned in <a href="#3.4.2">&sect;3.4.2</a>.
+strings according to the rules described in <a href="#3.4.3">&sect;3.4.3</a>.
 Otherwise, the <code>__concat</code> metamethod is called (see <a href="#2.4">&sect;2.4</a>).
 
 
 
 
 
-<h3>3.4.6 &ndash; <a name="3.4.6">The Length Operator</a></h3>
+<h3>3.4.7 &ndash; <a name="3.4.7">The Length Operator</a></h3>
 
 <p>
 The length operator is denoted by the unary prefix operator <code>#</code>.
@@ -2106,7 +2174,7 @@ with whether a table is a sequence.
 
 
 
-<h3>3.4.7 &ndash; <a name="3.4.7">Precedence</a></h3><p>
+<h3>3.4.8 &ndash; <a name="3.4.8">Precedence</a></h3><p>
 Operator precedence in Lua follows the table below,
 from lower to higher priority:
 
@@ -2114,10 +2182,14 @@ from lower to higher priority:
      or
      and
      &lt;     &gt;     &lt;=    &gt;=    ~=    ==
+     |
+     ~
+     &amp;
+     &lt;&lt;    &gt;&gt;
      ..
      +     -
-     *     /     %
-     not   #     - (unary)
+     *     /     //    %
+     unary operators (not   #     -     ~)
      ^
 </pre><p>
 As usual,
@@ -2130,7 +2202,7 @@ All other binary operators are left associative.
 
 
 
-<h3>3.4.8 &ndash; <a name="3.4.8">Table Constructors</a></h3><p>
+<h3>3.4.9 &ndash; <a name="3.4.9">Table Constructors</a></h3><p>
 Table constructors are expressions that create tables.
 Every time a constructor is evaluated, a new table is created.
 A constructor can be used to create an empty table
@@ -2150,7 +2222,7 @@ with key <code>exp1</code> and value <code>exp2</code>.
 A field of the form <code>name = exp</code> is equivalent to
 <code>["name"] = exp</code>.
 Finally, fields of the form <code>exp</code> are equivalent to
-<code>[i] = exp</code>, where <code>i</code> are consecutive numerical integers,
+<code>[i] = exp</code>, where <code>i</code> are consecutive integers
 starting with 1.
 Fields in the other formats do not affect this counting.
 For example,
@@ -2175,10 +2247,15 @@ is equivalent to
 </pre>
 
 <p>
+The order of the assignments in a constructor is undefined.
+(This order would be relevant only when there are repeated keys.)
+
+
+<p>
 If the last field in the list has the form <code>exp</code>
 and the expression is a function call or a vararg expression,
 then all values returned by this expression enter the list consecutively
-(see <a href="#3.4.9">&sect;3.4.9</a>).
+(see <a href="#3.4.10">&sect;3.4.10</a>).
 
 
 <p>
@@ -2189,7 +2266,7 @@ as a convenience for machine-generated code.
 
 
 
-<h3>3.4.9 &ndash; <a name="3.4.9">Function Calls</a></h3><p>
+<h3>3.4.10 &ndash; <a name="3.4.10">Function Calls</a></h3><p>
 A function call in Lua has the following syntax:
 
 <pre>
@@ -2224,7 +2301,7 @@ Arguments have the following syntax:
 <pre>
        args ::= &lsquo;<b>(</b>&rsquo; [explist] &lsquo;<b>)</b>&rsquo;
        args ::= tableconstructor
-       args ::= String
+       args ::= LiteralString
 </pre><p>
 All argument expressions are evaluated before the call.
 A call of the form <code>f{<em>fields</em>}</code> is
@@ -2264,7 +2341,7 @@ So, none of the following examples are tail calls:
 
 
 
-<h3>3.4.10 &ndash; <a name="3.4.10">Function Definitions</a></h3>
+<h3>3.4.11 &ndash; <a name="3.4.11">Function Definitions</a></h3>
 
 <p>
 The syntax for function definition is
@@ -2555,12 +2632,13 @@ you are responsible for ensuring consistency.
 In particular,
 <em>you are responsible for controlling stack overflow</em>.
 You can use the function <a href="#lua_checkstack"><code>lua_checkstack</code></a>
-to ensure that the stack has extra slots when pushing new elements.
+to ensure that the stack has enough space for pushing new elements.
 
 
 <p>
 Whenever Lua calls C,
-it ensures that the stack has at least <a name="pdf-LUA_MINSTACK"><code>LUA_MINSTACK</code></a> extra slots.
+it ensures that the stack has space for
+at least <a name="pdf-LUA_MINSTACK"><code>LUA_MINSTACK</code></a> extra slots.
 <code>LUA_MINSTACK</code> is defined as 20,
 so that usually you do not have to worry about stack space
 unless your code has loops pushing elements onto the stack.
@@ -2569,7 +2647,7 @@ unless your code has loops pushing elements onto the stack.
 <p>
 When you call a Lua function
 without a fixed number of results (see <a href="#lua_call"><code>lua_call</code></a>),
-Lua ensures that the stack has enough size for all results,
+Lua ensures that the stack has enough space for all results,
 but it does not ensure any extra space.
 So, before pushing anything in the stack after such a call
 you should use <a href="#lua_checkstack"><code>lua_checkstack</code></a>.
@@ -2587,29 +2665,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&nbsp;1 and the stack top
-(<code>1 &le; abs(index) &le; 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&nbsp;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&nbsp;1 and the stack top
+(<code>1 &le; abs(index) &le; top</code>)
+
+plus <em>pseudo-indices</em>,
+which represent some positions that are accessible to C&nbsp;code
+but that are not in the stack.
+Pseudo-indices are used to access the registry (see <a href="#4.5">&sect;4.5</a>)
 and the upvalues of a C&nbsp;function (see <a href="#4.4">&sect;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.
@@ -2652,11 +2723,13 @@ Whenever a C&nbsp;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
-current function (but not greater than 256),
+current function
+(but not greater than 256,
+which is one plus the maximum number of upvalues in a closure),
 produces an acceptable but invalid index.
 
 
@@ -2670,25 +2743,24 @@ Lua provides a <em>registry</em>,
 a predefined table that can be used by any C&nbsp;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&nbsp;library can store data into this table,
-but it should take care to choose keys
+but it must take care to choose keys
 that are different from those used
 by other libraries, to avoid collisions.
 Typically, you should use as key a string containing your library name,
 or a light userdata with the address of a C&nbsp;object in your code,
 or any Lua object created by your code.
-As with global names,
+As with variable names,
 string keys starting with an underscore followed by
 uppercase letters are reserved for Lua.
 
 
 <p>
-The integer keys in the registry are used by the reference mechanism,
-implemented by the auxiliary library,
+The integer keys in the registry are used
+by the reference mechanism (see <a href="#luaL_ref"><code>luaL_ref</code></a>)
 and by some predefined values.
-Therefore, integer keys should not be used for other purposes.
+Therefore, integer keys must not be used for other purposes.
 
 
 <p>
@@ -2716,8 +2788,8 @@ the global environment.
 
 <p>
 Internally, Lua uses the C <code>longjmp</code> facility to handle errors.
-(You can also choose to use exceptions if you compile Lua as C++;
-search for <code>LUAI_THROW</code> in the source code.)
+(Lua will use exceptions if you compile it as C++;
+search for <code>LUAI_THROW</code> in the source code for details.)
 When Lua faces any error
 (such as a memory allocation error, type errors, syntax errors,
 and runtime errors)
@@ -2740,21 +2812,21 @@ never returning
 
 <p>
 The panic function runs as if it were a message handler (see <a href="#2.3">&sect;2.3</a>);
-in particular, the error message is at the top of the stack.
-However, there is no guarantees about stack space.
+in particular, the error object is at the top of the stack.
+However, there is no guarantee about stack space.
 To push anything on the stack,
-the panic function should first check the available space (see <a href="#4.2">&sect;4.2</a>).
+the panic function must first check the available space (see <a href="#4.2">&sect;4.2</a>).
 
 
 <p>
-Most functions in the API can throw an error,
+Most functions in the API can raise an error,
 for instance due to a memory allocation error.
 The documentation for each function indicates whether
-it can throw errors.
+it can raise errors.
 
 
 <p>
-Inside a C&nbsp;function you can throw an error by calling <a href="#lua_error"><code>lua_error</code></a>.
+Inside a C&nbsp;function you can raise an error by calling <a href="#lua_error"><code>lua_error</code></a>.
 
 
 
@@ -2764,7 +2836,7 @@ Inside a C&nbsp;function you can throw an error by calling <a href="#lua_error">
 
 <p>
 Internally, Lua uses the C <code>longjmp</code> facility to yield a coroutine.
-Therefore, if a function <code>foo</code> calls an API function
+Therefore, if a function <code>foo</code> calls an API function
 and this API function yields
 (directly or indirectly by calling another function that yields),
 Lua cannot return to <code>foo</code> any more,
@@ -2777,7 +2849,7 @@ Lua raises an error whenever it tries to yield across an API call,
 except for three functions:
 <a href="#lua_yieldk"><code>lua_yieldk</code></a>, <a href="#lua_callk"><code>lua_callk</code></a>, and <a href="#lua_pcallk"><code>lua_pcallk</code></a>.
 All those functions receive a <em>continuation function</em>
-(as a parameter called <code>k</code>) to continue execution after a yield.
+(as a parameter named <code>k</code>) to continue execution after a yield.
 
 
 <p>
@@ -2807,6 +2879,81 @@ of the original function.
 
 
 <p>
+As an illustration, consider the following function:
+
+<pre>
+     int original_function (lua_State *L) {
+       ...     /* code 1 */
+       status = lua_pcall(L, n, m, h);  /* calls Lua */
+       ...     /* code 2 */
+     }
+</pre><p>
+Now we want to allow
+the Lua code being run by <a href="#lua_pcall"><code>lua_pcall</code></a> to yield.
+First, we can rewrite our function like here:
+
+<pre>
+     int k (lua_State *L, int status, lua_KContext ctx) {
+       ...  /* code 2 */
+     }
+     
+     int original_function (lua_State *L) {
+       ...     /* code 1 */
+       return k(L, lua_pcall(L, n, m, h), ctx);
+     }
+</pre><p>
+In the above code,
+the new function <code>k</code> is a
+<em>continuation function</em> (with type <a href="#lua_KFunction"><code>lua_KFunction</code></a>),
+which should do all the work that the original function
+was doing after calling <a href="#lua_pcall"><code>lua_pcall</code></a>.
+Now, we must inform Lua that it must call <code>k</code> if the Lua code
+being executed by <a href="#lua_pcall"><code>lua_pcall</code></a> gets interrupted in some way
+(errors or yielding),
+so we rewrite the code as here,
+replacing <a href="#lua_pcall"><code>lua_pcall</code></a> by <a href="#lua_pcallk"><code>lua_pcallk</code></a>:
+
+<pre>
+     int original_function (lua_State *L) {
+       ...     /* code 1 */
+       return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
+     }
+</pre><p>
+Note the external, explicit call to the continuation:
+Lua will call the continuation only if needed, that is,
+in case of errors or resuming after a yield.
+If the called function returns normally without ever yielding,
+<a href="#lua_pcallk"><code>lua_pcallk</code></a> (and <a href="#lua_callk"><code>lua_callk</code></a>) will also return normally.
+(Of course, instead of calling the continuation in that case,
+you can do the equivalent work directly inside the original function.)
+
+
+<p>
+Besides the Lua state,
+the continuation function has two other parameters:
+the final status of the call plus the context value (<code>ctx</code>) that
+was passed originally to <a href="#lua_pcallk"><code>lua_pcallk</code></a>.
+(Lua does not use this context value;
+it only passes this value from the original function to the
+continuation function.)
+For <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
+the status is the same value that would be returned by <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
+except that it is <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when being executed after a yield
+(instead of <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>).
+For <a href="#lua_yieldk"><code>lua_yieldk</code></a> and <a href="#lua_callk"><code>lua_callk</code></a>,
+the status is always <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> when Lua calls the continuation.
+(For these two functions,
+Lua will not call the continuation in case of errors,
+because they do not handle errors.)
+Similarly, when using <a href="#lua_callk"><code>lua_callk</code></a>,
+you should call the continuation function
+with <a href="#pdf-LUA_OK"><code>LUA_OK</code></a> as the status.
+(For <a href="#lua_yieldk"><code>lua_yieldk</code></a>, there is not much point in calling
+directly the continuation function,
+because <a href="#lua_yieldk"><code>lua_yieldk</code></a> usually does not return.)
+
+
+<p>
 Lua treats the continuation function as if it were the original function.
 The continuation function receives the same Lua stack
 from the original function,
@@ -2819,11 +2966,6 @@ Whatever it returns is handled by Lua as if it were the return
 of the original function.
 
 
-<p>
-The only difference in the Lua state between the original function
-and its continuation is the result of a call to <a href="#lua_getctx"><code>lua_getctx</code></a>.
-
-
 
 
 
@@ -2850,10 +2992,14 @@ we cannot know how many elements the function pops/pushes
 by looking only at its arguments
 (e.g., they may depend on what is on the stack).
 The third field, <code>x</code>,
-tells whether the function may throw errors:
-'<code>-</code>' means the function never throws any error;
-'<code>e</code>' means the function may throw errors;
-'<code>v</code>' means the function may throw an error on purpose.
+tells whether the function may raise errors:
+'<code>-</code>' means the function never raises any error;
+'<code>m</code>' means the function may raise out-of-memory errors
+and errors running a <code>__gc</code> metamethod;
+'<code>e</code>' means the function may raise any errors
+(it can run arbitrary Lua code,
+either directly or through metamethods);
+'<code>v</code>' means the function may raise an error on purpose.
 
 
 
@@ -2862,7 +3008,8 @@ tells whether the function may throw 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).
 
 
@@ -2885,7 +3032,7 @@ Its arguments are
 <code>ptr</code>, a pointer to the block being allocated/reallocated/freed;
 <code>osize</code>, the original size of the block or some code about what
 is being allocated;
-<code>nsize</code>, the new size of the block.
+and <code>nsize</code>, the new size of the block.
 
 
 <p>
@@ -2911,13 +3058,13 @@ Lua assumes the following behavior from the allocator function:
 
 <p>
 When <code>nsize</code> is zero,
-the allocator should behave like <code>free</code>
+the allocator must behave like <code>free</code>
 and return <code>NULL</code>.
 
 
 <p>
 When <code>nsize</code> is not zero,
-the allocator should behave like <code>realloc</code>.
+the allocator must behave like <code>realloc</code>.
 The allocator returns <code>NULL</code>
 if and only if it cannot fulfill the request.
 Lua assumes that the allocator never fails when
@@ -2942,7 +3089,7 @@ It is used in the auxiliary library by <a href="#luaL_newstate"><code>luaL_newst
 </pre><p>
 Note that Standard&nbsp;C ensures
 that <code>free(NULL)</code> has no effect and that
-<code>realloc(NULL, size)</code> is equivalent to <code>malloc(size)</code>.
+<code>realloc(NULL,size)</code> is equivalent to <code>malloc(size)</code>.
 This code assumes that <code>realloc</code> does not fail when shrinking a block.
 (Although Standard&nbsp;C does not ensure this behavior,
 it seems to be a safe assumption.)
@@ -2956,8 +3103,8 @@ it seems to be a safe assumption.)
 <pre>void lua_arith (lua_State *L, int op);</pre>
 
 <p>
-Performs an arithmetic operation over the two values
-(or one, in the case of negation)
+Performs an arithmetic or bitwise operation over the two values
+(or one, in the case of negations)
 at the top of the stack,
 with the value at the top being the second operand,
 pops these values, and pushes the result of the operation.
@@ -2973,10 +3120,17 @@ The value of <code>op</code> must be one of the following constants:
 <li><b><a name="pdf-LUA_OPADD"><code>LUA_OPADD</code></a>: </b> performs addition (<code>+</code>)</li>
 <li><b><a name="pdf-LUA_OPSUB"><code>LUA_OPSUB</code></a>: </b> performs subtraction (<code>-</code>)</li>
 <li><b><a name="pdf-LUA_OPMUL"><code>LUA_OPMUL</code></a>: </b> performs multiplication (<code>*</code>)</li>
-<li><b><a name="pdf-LUA_OPDIV"><code>LUA_OPDIV</code></a>: </b> performs division (<code>/</code>)</li>
+<li><b><a name="pdf-LUA_OPDIV"><code>LUA_OPDIV</code></a>: </b> performs float division (<code>/</code>)</li>
+<li><b><a name="pdf-LUA_OPIDIV"><code>LUA_OPIDIV</code></a>: </b> performs floor division (<code>//</code>)</li>
 <li><b><a name="pdf-LUA_OPMOD"><code>LUA_OPMOD</code></a>: </b> performs modulo (<code>%</code>)</li>
 <li><b><a name="pdf-LUA_OPPOW"><code>LUA_OPPOW</code></a>: </b> performs exponentiation (<code>^</code>)</li>
 <li><b><a name="pdf-LUA_OPUNM"><code>LUA_OPUNM</code></a>: </b> performs mathematical negation (unary <code>-</code>)</li>
+<li><b><a name="pdf-LUA_OPBNOT"><code>LUA_OPBNOT</code></a>: </b> performs bitwise NOT (<code>~</code>)</li>
+<li><b><a name="pdf-LUA_OPBAND"><code>LUA_OPBAND</code></a>: </b> performs bitwise AND (<code>&amp;</code>)</li>
+<li><b><a name="pdf-LUA_OPBOR"><code>LUA_OPBOR</code></a>: </b> performs bitwise OR (<code>|</code>)</li>
+<li><b><a name="pdf-LUA_OPBXOR"><code>LUA_OPBXOR</code></a>: </b> performs bitwise exclusive OR (<code>~</code>)</li>
+<li><b><a name="pdf-LUA_OPSHL"><code>LUA_OPSHL</code></a>: </b> performs left shift (<code>&lt;&lt;</code>)</li>
+<li><b><a name="pdf-LUA_OPSHR"><code>LUA_OPSHR</code></a>: </b> performs right shift (<code>&gt;&gt;</code>)</li>
 
 </ul>
 
@@ -3016,7 +3170,8 @@ The function results are pushed onto the stack when the function returns.
 The number of results is adjusted to <code>nresults</code>,
 unless <code>nresults</code> is <a name="pdf-LUA_MULTRET"><code>LUA_MULTRET</code></a>.
 In this case, all results from the function are pushed.
-Lua takes care that the returned values fit into the stack space.
+Lua takes care that the returned values fit into the stack space,
+but it does not ensure any extra space in the stack.
 The function results are pushed onto the stack in direct order
 (the first result is pushed first),
 so that after the call the last result is on the top of the stack.
@@ -3038,7 +3193,7 @@ Here it is in&nbsp;C:
 
 <pre>
      lua_getglobal(L, "f");                  /* function to be called */
-     lua_pushstring(L, "how");                        /* 1st argument */
+     lua_pushliteral(L, "how");                       /* 1st argument */
      lua_getglobal(L, "t");                    /* table to be indexed */
      lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
      lua_remove(L, -2);                  /* remove 't' from the stack */
@@ -3046,7 +3201,7 @@ Here it is in&nbsp;C:
      lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
      lua_setglobal(L, "a");                         /* set global 'a' */
 </pre><p>
-Note that the code above is "balanced":
+Note that the code above is <em>balanced</em>:
 at its end, the stack is back to its original configuration.
 This is considered good programming practice.
 
@@ -3056,8 +3211,11 @@ This is considered good programming practice.
 
 <hr><h3><a name="lua_callk"><code>lua_callk</code></a></h3><p>
 <span class="apii">[-(nargs + 1), +nresults, <em>e</em>]</span>
-<pre>void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
-                lua_CFunction k);</pre>
+<pre>void lua_callk (lua_State *L,
+                int nargs,
+                int nresults,
+                lua_KContext ctx,
+                lua_KFunction k);</pre>
 
 <p>
 This function behaves exactly like <a href="#lua_call"><code>lua_call</code></a>,
@@ -3095,16 +3253,16 @@ many results.
 
 <p>
 As an example, the following function receives a variable number
-of numerical arguments and returns their average and sum:
+of numeric arguments and returns their average and their sum:
 
 <pre>
      static int foo (lua_State *L) {
        int n = lua_gettop(L);    /* number of arguments */
-       lua_Number sum = 0;
+       lua_Number sum = 0.0;
        int i;
        for (i = 1; i &lt;= n; i++) {
          if (!lua_isnumber(L, i)) {
-           lua_pushstring(L, "incorrect argument");
+           lua_pushliteral(L, "incorrect argument");
            lua_error(L);
          }
          sum += lua_tonumber(L, i);
@@ -3120,16 +3278,18 @@ of numerical arguments and returns their average and sum:
 
 <hr><h3><a name="lua_checkstack"><code>lua_checkstack</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>int lua_checkstack (lua_State *L, int extra);</pre>
+<pre>int lua_checkstack (lua_State *L, int n);</pre>
 
 <p>
-Ensures that there are at least <code>extra</code> free stack slots in the stack.
+Ensures that the stack has space for at least <code>n</code> extra slots
+(that is, that you can safely push up to <code>n</code> values into it).
 It returns false if it cannot fulfill the request,
-because it would cause the stack to be larger than a fixed maximum size
-(typically at least a few thousand elements) or
-because it cannot allocate memory for the new stack size.
+either because it would cause the stack
+to be larger than a fixed maximum size
+(typically at least several thousand elements) or
+because it cannot allocate memory for the extra space.
 This function never shrinks the stack;
-if the stack is already larger than the new size,
+if the stack already has space for the extra slots,
 it is left unchanged.
 
 
@@ -3148,7 +3308,7 @@ On several platforms, you may not need to call this function,
 because all resources are naturally released when the host program ends.
 On the other hand, long-running programs that create multiple states,
 such as daemons or web servers,
-might need to close states as soon as they are not needed.
+will probably need to close states as soon as they are not needed.
 
 
 
@@ -3165,7 +3325,7 @@ when compared with the value at index <code>index2</code>,
 following the semantics of the corresponding Lua operator
 (that is, it may call metamethods).
 Otherwise returns&nbsp;0.
-Also returns&nbsp;0 if any of the indices is non valid.
+Also returns&nbsp;0 if any of the indices is not valid.
 
 
 <p>
@@ -3193,7 +3353,7 @@ If <code>n</code>&nbsp;is&nbsp;1, the result is the single value on the stack
 (that is, the function does nothing);
 if <code>n</code> is 0, the result is the empty string.
 Concatenation is performed following the usual semantics of Lua
-(see <a href="#3.4.5">&sect;3.4.5</a>).
+(see <a href="#3.4.6">&sect;3.4.6</a>).
 
 
 
@@ -3204,17 +3364,17 @@ Concatenation is performed following the usual semantics of Lua
 <pre>void lua_copy (lua_State *L, int fromidx, int toidx);</pre>
 
 <p>
-Moves the element at index <code>fromidx</code>
-into the valid index <code>toidx</code>
-without shifting any element
-(therefore replacing the value at that position).
+Copies the element at index <code>fromidx</code>
+into the valid index <code>toidx</code>,
+replacing the value at that position.
+Values at other positions are not affected.
 
 
 
 
 
 <hr><h3><a name="lua_createtable"><code>lua_createtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void lua_createtable (lua_State *L, int narr, int nrec);</pre>
 
 <p>
@@ -3224,7 +3384,7 @@ will have as a sequence;
 parameter <code>nrec</code> is a hint for how many other elements
 the table will have.
 Lua may use these hints to preallocate memory for the new table.
-This pre-allocation is useful for performance when you know in advance
+This preallocation is useful for performance when you know in advance
 how many elements the table will have.
 Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</code></a>.
 
@@ -3233,8 +3393,11 @@ Otherwise you can use the function <a href="#lua_newtable"><code>lua_newtable</c
 
 
 <hr><h3><a name="lua_dump"><code>lua_dump</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
-<pre>int lua_dump (lua_State *L, lua_Writer writer, void *data);</pre>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>int lua_dump (lua_State *L,
+                        lua_Writer writer,
+                        void *data,
+                        int strip);</pre>
 
 <p>
 Dumps a function as a binary chunk.
@@ -3249,6 +3412,13 @@ to write them.
 
 
 <p>
+If <code>strip</code> is true,
+the binary representation may not include all debug information
+about the function,
+to save space.
+
+
+<p>
 The value returned is the error code returned by the last
 call to the writer;
 0&nbsp;means no errors.
@@ -3266,9 +3436,8 @@ This function does not pop the Lua function from the stack.
 <pre>int lua_error (lua_State *L);</pre>
 
 <p>
-Generates a Lua error.
-The error message (which can actually be a Lua value of any type)
-must be on the stack top.
+Generates a Lua error,
+using the value at the top of the stack as the error object.
 This function does a long jump,
 and therefore never returns
 (see <a href="#luaL_error"><code>luaL_error</code></a>).
@@ -3278,7 +3447,7 @@ and therefore never returns
 
 
 <hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>m</em>]</span>
 <pre>int lua_gc (lua_State *L, int what, int data);</pre>
 
 <p>
@@ -3314,24 +3483,18 @@ memory in use by Lua by 1024.
 
 <li><b><code>LUA_GCSTEP</code>: </b>
 performs an incremental step of garbage collection.
-The step "size" is controlled by <code>data</code>
-(larger values mean more steps) in a non-specified way.
-If you want to control the step size
-you must experimentally tune the value of <code>data</code>.
-The function returns 1 if the step finished a
-garbage-collection cycle.
 </li>
 
 <li><b><code>LUA_GCSETPAUSE</code>: </b>
 sets <code>data</code> as the new value
-for the <em>pause</em> of the collector (see <a href="#2.5">&sect;2.5</a>).
-The function returns the previous value of the pause.
+for the <em>pause</em> of the collector (see <a href="#2.5">&sect;2.5</a>)
+and returns the previous value of the pause.
 </li>
 
 <li><b><code>LUA_GCSETSTEPMUL</code>: </b>
 sets <code>data</code> as the new value for the <em>step multiplier</em> of
-the collector (see <a href="#2.5">&sect;2.5</a>).
-The function returns the previous value of the step multiplier.
+the collector (see <a href="#2.5">&sect;2.5</a>)
+and returns the previous value of the step multiplier.
 </li>
 
 <li><b><code>LUA_GCISRUNNING</code>: </b>
@@ -3339,16 +3502,6 @@ returns a boolean that tells whether the collector is running
 (i.e., not stopped).
 </li>
 
-<li><b><code>LUA_GCGEN</code>: </b>
-changes the collector to generational mode
-(see <a href="#2.5">&sect;2.5</a>).
-</li>
-
-<li><b><code>LUA_GCINC</code>: </b>
-changes the collector to incremental mode.
-This is the default mode.
-</li>
-
 </ul>
 
 <p>
@@ -3366,68 +3519,80 @@ see <a href="#pdf-collectgarbage"><code>collectgarbage</code></a>.
 <p>
 Returns the memory-allocation function of a given state.
 If <code>ud</code> is not <code>NULL</code>, Lua stores in <code>*ud</code> the
-opaque pointer passed to <a href="#lua_newstate"><code>lua_newstate</code></a>.
+opaque pointer given when the memory-allocator function was set.
+
+
+
 
 
+<hr><h3><a name="lua_getfield"><code>lua_getfield</code></a></h3><p>
+<span class="apii">[-0, +1, <em>e</em>]</span>
+<pre>int lua_getfield (lua_State *L, int index, const char *k);</pre>
+
+<p>
+Pushes onto the stack the value <code>t[k]</code>,
+where <code>t</code> is the value at the given index.
+As in Lua, this function may trigger a metamethod
+for the "index" event (see <a href="#2.4">&sect;2.4</a>).
+
+
+<p>
+Returns the type of the pushed value.
+
 
 
 
-<hr><h3><a name="lua_getctx"><code>lua_getctx</code></a></h3><p>
+
+<hr><h3><a name="lua_getextraspace"><code>lua_getextraspace</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>int lua_getctx (lua_State *L, int *ctx);</pre>
+<pre>void *lua_getextraspace (lua_State *L);</pre>
 
 <p>
-This function is called by a continuation function (see <a href="#4.7">&sect;4.7</a>)
-to retrieve the status of the thread and a context information.
+Returns a pointer to a raw memory area associated with the
+given Lua state.
+The application can use this area for any purpose;
+Lua does not use it for anything.
 
 
 <p>
-When called in the original function,
-<a href="#lua_getctx"><code>lua_getctx</code></a> always returns <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>
-and does not change the value of its argument <code>ctx</code>.
-When called inside a continuation function,
-<a href="#lua_getctx"><code>lua_getctx</code></a> returns <a href="#pdf-LUA_YIELD"><code>LUA_YIELD</code></a> and sets
-the value of <code>ctx</code> to be the context information
-(the value passed as the <code>ctx</code> argument
-to the callee together with the continuation function).
+Each new thread has this area initialized with a copy
+of the area of the main thread.
 
 
 <p>
-When the callee is <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
-Lua may also call its continuation function
-to handle errors during the call.
-That is, upon an error in the function called by <a href="#lua_pcallk"><code>lua_pcallk</code></a>,
-Lua may not return to the original function
-but instead may call the continuation function.
-In that case, a call to <a href="#lua_getctx"><code>lua_getctx</code></a> will return the error code
-(the value that would be returned by <a href="#lua_pcallk"><code>lua_pcallk</code></a>);
-the value of <code>ctx</code> will be set to the context information,
-as in the case of a yield.
+By default, this area has the size of a pointer to void,
+but you can recompile Lua with a different size for this area.
+(See <code>LUA_EXTRASPACE</code> in <code>luaconf.h</code>.)
 
 
 
 
 
-<hr><h3><a name="lua_getfield"><code>lua_getfield</code></a></h3><p>
+<hr><h3><a name="lua_getglobal"><code>lua_getglobal</code></a></h3><p>
 <span class="apii">[-0, +1, <em>e</em>]</span>
-<pre>void lua_getfield (lua_State *L, int index, const char *k);</pre>
+<pre>int lua_getglobal (lua_State *L, const char *name);</pre>
 
 <p>
-Pushes onto the stack the value <code>t[k]</code>,
-where <code>t</code> is the value at the given index.
-As in Lua, this function may trigger a metamethod
-for the "index" event (see <a href="#2.4">&sect;2.4</a>).
+Pushes onto the stack the value of the global <code>name</code>.
+Returns the type of that value.
 
 
 
 
 
-<hr><h3><a name="lua_getglobal"><code>lua_getglobal</code></a></h3><p>
+<hr><h3><a name="lua_geti"><code>lua_geti</code></a></h3><p>
 <span class="apii">[-0, +1, <em>e</em>]</span>
-<pre>void lua_getglobal (lua_State *L, const char *name);</pre>
+<pre>int lua_geti (lua_State *L, int index, lua_Integer i);</pre>
 
 <p>
-Pushes onto the stack the value of the global <code>name</code>.
+Pushes onto the stack the value <code>t[i]</code>,
+where <code>t</code> is the value at the given index.
+As in Lua, this function may trigger a metamethod
+for the "index" event (see <a href="#2.4">&sect;2.4</a>).
+
+
+<p>
+Returns the type of the pushed value.
 
 
 
@@ -3438,8 +3603,9 @@ Pushes onto the stack the value of the global <code>name</code>.
 <pre>int lua_getmetatable (lua_State *L, int index);</pre>
 
 <p>
-Pushes onto the stack the metatable of the value at the given index.
-If the value does not have a metatable,
+If the value at the given index has a metatable,
+the function pushes that metatable onto the stack and returns&nbsp;1.
+Otherwise,
 the function returns&nbsp;0 and pushes nothing on the stack.
 
 
@@ -3448,7 +3614,7 @@ the function returns&nbsp;0 and pushes nothing on the stack.
 
 <hr><h3><a name="lua_gettable"><code>lua_gettable</code></a></h3><p>
 <span class="apii">[-1, +1, <em>e</em>]</span>
-<pre>void lua_gettable (lua_State *L, int index);</pre>
+<pre>int lua_gettable (lua_State *L, int index);</pre>
 
 <p>
 Pushes onto the stack the value <code>t[k]</code>,
@@ -3457,12 +3623,16 @@ and <code>k</code> is the value at the top of the stack.
 
 
 <p>
-This function pops the key from the stack
-(putting the resulting value in its place).
+This function pops the key from the stack,
+pushing the resulting value in its place.
 As in Lua, this function may trigger a metamethod
 for the "index" event (see <a href="#2.4">&sect;2.4</a>).
 
 
+<p>
+Returns the type of the pushed value.
+
+
 
 
 
@@ -3473,8 +3643,8 @@ for the "index" event (see <a href="#2.4">&sect;2.4</a>).
 <p>
 Returns the index of the top element in the stack.
 Because indices start at&nbsp;1,
-this result is equal to the number of elements in the stack
-(and so 0&nbsp;means an empty stack).
+this result is equal to the number of elements in the stack;
+in particular, 0&nbsp;means an empty stack.
 
 
 
@@ -3482,12 +3652,15 @@ this result is equal to the number of elements in the stack
 
 <hr><h3><a name="lua_getuservalue"><code>lua_getuservalue</code></a></h3><p>
 <span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_getuservalue (lua_State *L, int index);</pre>
+<pre>int lua_getuservalue (lua_State *L, int index);</pre>
 
 <p>
 Pushes onto the stack the Lua value associated with the userdata
 at the given index.
-This Lua value must be a table or <b>nil</b>.
+
+
+<p>
+Returns the type of the pushed value.
 
 
 
@@ -3508,16 +3681,24 @@ because a pseudo-index is not an actual stack position.
 
 
 <hr><h3><a name="lua_Integer"><code>lua_Integer</code></a></h3>
-<pre>typedef ptrdiff_t lua_Integer;</pre>
+<pre>typedef ... lua_Integer;</pre>
+
+<p>
+The type of integers in Lua.
+
 
 <p>
-The type used by the Lua API to represent signed integral values.
+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_TYPE</code> in <code>luaconf.h</code>.)
 
 
 <p>
-By default it is a <code>ptrdiff_t</code>,
-which is usually the largest signed integral type the machine handles
-"comfortably".
+Lua also defines the constants
+<a name="pdf-LUA_MININTEGER"><code>LUA_MININTEGER</code></a> and <a name="pdf-LUA_MAXINTEGER"><code>LUA_MAXINTEGER</code></a>,
+with the minimum and the maximum values that fit in this type.
 
 
 
@@ -3559,6 +3740,19 @@ Returns 1 if the value at the given index is a function
 
 
 
+<hr><h3><a name="lua_isinteger"><code>lua_isinteger</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>int lua_isinteger (lua_State *L, int index);</pre>
+
+<p>
+Returns 1 if the value at the given index is an integer
+(that is, the value is a number and is represented as an integer),
+and 0&nbsp;otherwise.
+
+
+
+
+
 <hr><h3><a name="lua_islightuserdata"><code>lua_islightuserdata</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>int lua_islightuserdata (lua_State *L, int index);</pre>
@@ -3670,13 +3864,51 @@ Returns 1 if the value at the given index is a userdata
 
 
 
+<hr><h3><a name="lua_isyieldable"><code>lua_isyieldable</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>int lua_isyieldable (lua_State *L);</pre>
+
+<p>
+Returns 1 if the given coroutine can yield,
+and 0&nbsp;otherwise.
+
+
+
+
+
+<hr><h3><a name="lua_KContext"><code>lua_KContext</code></a></h3>
+<pre>typedef ... lua_KContext;</pre>
+
+<p>
+The type for continuation-function contexts.
+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.
+Otherwise, it is defined as <code>ptrdiff_t</code>.
+
+
+
+
+
+<hr><h3><a name="lua_KFunction"><code>lua_KFunction</code></a></h3>
+<pre>typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);</pre>
+
+<p>
+Type for continuation functions (see <a href="#4.7">&sect;4.7</a>).
+
+
+
+
+
 <hr><h3><a name="lua_len"><code>lua_len</code></a></h3><p>
 <span class="apii">[-0, +1, <em>e</em>]</span>
 <pre>void lua_len (lua_State *L, int index);</pre>
 
 <p>
-Returns the "length" of the value at the given index;
-it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">&sect;3.4.6</a>).
+Returns the length of the value at the given index.
+It is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.7">&sect;3.4.7</a>) and
+may trigger a metamethod for the "length" event (see <a href="#2.4">&sect;2.4</a>).
 The result is pushed on the stack.
 
 
@@ -3688,11 +3920,11 @@ The result is pushed on the stack.
 <pre>int lua_load (lua_State *L,
               lua_Reader reader,
               void *data,
-              const char *source,
+              const char *chunkname,
               const char *mode);</pre>
 
 <p>
-Loads a Lua chunk (without running it).
+Loads a Lua chunk without running it.
 If there are no errors,
 <code>lua_load</code> pushes the compiled chunk as a Lua
 function on top of the stack.
@@ -3710,7 +3942,7 @@ The return values of <code>lua_load</code> are:
 syntax error during precompilation;</li>
 
 <li><b><a href="#pdf-LUA_ERRMEM"><code>LUA_ERRMEM</code></a>: </b>
-memory allocation error;</li>
+memory allocation (out-of-memory) error;</li>
 
 <li><b><a href="#pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
 error while running a <code>__gc</code> metamethod.
@@ -3727,7 +3959,7 @@ The <code>data</code> argument is an opaque value passed to the reader function.
 
 
 <p>
-The <code>source</code> argument gives a name to the chunk,
+The <code>chunkname</code> argument gives a name to the chunk,
 which is used for error messages and in debug information (see <a href="#4.9">&sect;4.9</a>).
 
 
@@ -3741,16 +3973,17 @@ a <code>NULL</code> value is equivalent to the string "<code>bt</code>".
 
 <p>
 <code>lua_load</code> uses the stack internally,
-so the reader function should always leave the stack
+so the reader function must always leave the stack
 unmodified when returning.
 
 
 <p>
-If the resulting function has one upvalue,
-this upvalue is set to the value of the global environment
+If the resulting function has upvalues,
+its first upvalue is set to the value of the global environment
 stored at index <code>LUA_RIDX_GLOBALS</code> in the registry (see <a href="#4.5">&sect;4.5</a>).
 When loading main chunks,
 this upvalue will be the <code>_ENV</code> variable (see <a href="#2.2">&sect;2.2</a>).
+Other upvalues are initialized with <b>nil</b>.
 
 
 
@@ -3762,7 +3995,7 @@ this upvalue will be the <code>_ENV</code> variable (see <a href="#2.2">&sect;2.
 
 <p>
 Creates a new thread running in a new, independent state.
-Returns <code>NULL</code> if cannot create the thread or the state
+Returns <code>NULL</code> if it cannot create the thread or the state
 (due to lack of memory).
 The argument <code>f</code> is the allocator function;
 Lua does all memory allocation for this state through this function.
@@ -3774,7 +4007,7 @@ passes to the allocator in every call.
 
 
 <hr><h3><a name="lua_newtable"><code>lua_newtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void lua_newtable (lua_State *L);</pre>
 
 <p>
@@ -3786,7 +4019,7 @@ It is equivalent to <code>lua_createtable(L, 0, 0)</code>.
 
 
 <hr><h3><a name="lua_newthread"><code>lua_newthread</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>lua_State *lua_newthread (lua_State *L);</pre>
 
 <p>
@@ -3807,7 +4040,7 @@ like any Lua object.
 
 
 <hr><h3><a name="lua_newuserdata"><code>lua_newuserdata</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void *lua_newuserdata (lua_State *L, size_t size);</pre>
 
 <p>
@@ -3866,13 +4099,38 @@ 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.
+
+
+<p>
+By default this type is double,
+but that can be changed to a single float or a long double.
+(See <code>LUA_FLOAT_TYPE</code> in <code>luaconf.h</code>.)
+
+
+
+
+
+<hr><h3><a name="lua_numbertointeger"><code>lua_numbertointeger</code></a></h3>
+<pre>int lua_numbertointeger (lua_Number n, lua_Integer *p);</pre>
 
 <p>
-The type of numbers in Lua.
-By default, it is double, but that can be changed in <code>luaconf.h</code>.
-Through this configuration file you can change
-Lua to operate with another type for numbers (e.g., float or long).
+Converts a Lua float to a Lua integer.
+This macro assumes that <code>n</code> has an integral value.
+If that value is within the range of Lua integers,
+it is converted to an integer and assigned to <code>*p</code>.
+The macro results in a boolean indicating whether the
+conversion was successful.
+(Note that this range test can be tricky to do
+correctly without this macro,
+due to roundings.)
+
+
+<p>
+This macro may evaluate its arguments more than once.
 
 
 
@@ -3893,7 +4151,7 @@ If there are no errors during the call,
 <a href="#lua_pcall"><code>lua_pcall</code></a> behaves exactly like <a href="#lua_call"><code>lua_call</code></a>.
 However, if there is any error,
 <a href="#lua_pcall"><code>lua_pcall</code></a> catches it,
-pushes a single value on the stack (the error message),
+pushes a single value on the stack (the error object),
 and returns an error code.
 Like <a href="#lua_call"><code>lua_call</code></a>,
 <a href="#lua_pcall"><code>lua_pcall</code></a> always removes the function
@@ -3902,26 +4160,26 @@ and its arguments from the stack.
 
 <p>
 If <code>msgh</code> is 0,
-then the error message returned on the stack
-is exactly the original error message.
+then the error object returned on the stack
+is exactly the original error object.
 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
+this function will be called with the error object
+and its return value will be the object
 returned on the stack by <a href="#lua_pcall"><code>lua_pcall</code></a>.
 
 
 <p>
 Typically, the message handler is used to add more debug
-information to the error message, such as a stack traceback.
+information to the error object, such as a stack traceback.
 Such information cannot be gathered after the return of <a href="#lua_pcall"><code>lua_pcall</code></a>,
 since by then the stack has unwound.
 
 
 <p>
-The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns one of the following codes
+The <a href="#lua_pcall"><code>lua_pcall</code></a> function returns one of the following constants
 (defined in <code>lua.h</code>):
 
 <ul>
@@ -3944,8 +4202,7 @@ error while running the message handler.
 
 <li><b><a name="pdf-LUA_ERRGCMM"><code>LUA_ERRGCMM</code></a>: </b>
 error while running a <code>__gc</code> metamethod.
-(This error typically has no relation with the function being called.
-It is generated by the garbage collector.)
+(This error typically has no relation with the function being called.)
 </li>
 
 </ul>
@@ -3958,9 +4215,9 @@ It is generated by the garbage collector.)
 <pre>int lua_pcallk (lua_State *L,
                 int nargs,
                 int nresults,
-                int errfunc,
-                int ctx,
-                lua_CFunction k);</pre>
+                int msgh,
+                lua_KContext ctx,
+                lua_KFunction k);</pre>
 
 <p>
 This function behaves exactly like <a href="#lua_pcall"><code>lua_pcall</code></a>,
@@ -3993,7 +4250,7 @@ Pushes a boolean value with value <code>b</code> onto the stack.
 
 
 <hr><h3><a name="lua_pushcclosure"><code>lua_pushcclosure</code></a></h3><p>
-<span class="apii">[-n, +1, <em>e</em>]</span>
+<span class="apii">[-n, +1, <em>m</em>]</span>
 <pre>void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);</pre>
 
 <p>
@@ -4006,11 +4263,11 @@ it is possible to associate some values with it,
 thus creating a C&nbsp;closure (see <a href="#4.4">&sect;4.4</a>);
 these values are then accessible to the function whenever it is called.
 To associate values with a C&nbsp;function,
-first these values should be pushed onto the stack
+first these values must be pushed onto the stack
 (when there are multiple values, the first value is pushed first).
 Then <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a>
 is called to create and push the C&nbsp;function onto the stack,
-with the argument <code>n</code> telling how many values should be
+with the argument <code>n</code> telling how many values will be
 associated with the function.
 <a href="#lua_pushcclosure"><code>lua_pushcclosure</code></a> also pops these values from the stack.
 
@@ -4023,7 +4280,7 @@ The maximum value for <code>n</code> is 255.
 When <code>n</code> is zero,
 this function creates a <em>light C function</em>,
 which is just a pointer to the C&nbsp;function.
-In that case, it never throws a memory error.
+In that case, it never raises a memory error.
 
 
 
@@ -4041,20 +4298,11 @@ when called, invokes the corresponding C&nbsp;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.
-
-
 
 
 
@@ -4080,16 +4328,24 @@ the result is a Lua string and Lua takes care of memory allocation
 The conversion specifiers are quite restricted.
 There are no flags, widths, or precisions.
 The conversion specifiers can only be
-'<code>%%</code>' (inserts a '<code>%</code>' in the string),
+'<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>%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>), and
-'<code>%c</code>' (inserts an <code>int</code> as a byte).
+'<code>%d</code>' (inserts an <code>int</code>),
+'<code>%c</code>' (inserts an <code>int</code> as a one-byte character), and
+'<code>%U</code>' (inserts a <code>long int</code> as a UTF-8 byte sequence).
 </li>
 
 </ul>
 
+<p>
+Unlike other push functions,
+this function checks for the stack space it needs,
+including the slot for its result.
+
+
 
 
 
@@ -4109,7 +4365,7 @@ Pushes the global environment onto the stack.
 <pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre>
 
 <p>
-Pushes a number with value <code>n</code> onto the stack.
+Pushes an integer with value <code>n</code> onto the stack.
 
 
 
@@ -4137,20 +4393,19 @@ light userdata with the same C&nbsp;address.
 
 
 <hr><h3><a name="lua_pushliteral"><code>lua_pushliteral</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <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.
 
 
 
 
 
 <hr><h3><a name="lua_pushlstring"><code>lua_pushlstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>const char *lua_pushlstring (lua_State *L, const char *s, size_t len);</pre>
 
 <p>
@@ -4186,14 +4441,14 @@ Pushes a nil value onto the stack.
 <pre>void lua_pushnumber (lua_State *L, lua_Number n);</pre>
 
 <p>
-Pushes a number with value <code>n</code> onto the stack.
+Pushes a float with value <code>n</code> onto the stack.
 
 
 
 
 
 <hr><h3><a name="lua_pushstring"><code>lua_pushstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>const char *lua_pushstring (lua_State *L, const char *s);</pre>
 
 <p>
@@ -4227,17 +4482,6 @@ Returns 1 if this thread is the main thread of its state.
 
 
 
-<hr><h3><a name="lua_pushunsigned"><code>lua_pushunsigned</code></a></h3><p>
-<span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_pushunsigned (lua_State *L, lua_Unsigned n);</pre>
-
-<p>
-Pushes a number with value <code>n</code> onto the stack.
-
-
-
-
-
 <hr><h3><a name="lua_pushvalue"><code>lua_pushvalue</code></a></h3><p>
 <span class="apii">[-0, +1, &ndash;]</span>
 <pre>void lua_pushvalue (lua_State *L, int index);</pre>
@@ -4251,7 +4495,7 @@ onto the stack.
 
 
 <hr><h3><a name="lua_pushvfstring"><code>lua_pushvfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>const char *lua_pushvfstring (lua_State *L,
                               const char *fmt,
                               va_list argp);</pre>
@@ -4271,9 +4515,9 @@ instead of a variable number of arguments.
 <p>
 Returns 1 if the two values in indices <code>index1</code> and
 <code>index2</code> are primitively equal
-(that is, without calling metamethods).
+(that is, without calling the <code>__eq</code> metamethod).
 Otherwise returns&nbsp;0.
-Also returns&nbsp;0 if any of the indices are non valid.
+Also returns&nbsp;0 if any of the indices are not valid.
 
 
 
@@ -4281,7 +4525,7 @@ Also returns&nbsp;0 if any of the indices are non valid.
 
 <hr><h3><a name="lua_rawget"><code>lua_rawget</code></a></h3><p>
 <span class="apii">[-1, +1, &ndash;]</span>
-<pre>void lua_rawget (lua_State *L, int index);</pre>
+<pre>int lua_rawget (lua_State *L, int index);</pre>
 
 <p>
 Similar to <a href="#lua_gettable"><code>lua_gettable</code></a>, but does a raw access
@@ -4293,13 +4537,17 @@ Similar to <a href="#lua_gettable"><code>lua_gettable</code></a>, but does a raw
 
 <hr><h3><a name="lua_rawgeti"><code>lua_rawgeti</code></a></h3><p>
 <span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_rawgeti (lua_State *L, int index, int n);</pre>
+<pre>int lua_rawgeti (lua_State *L, int index, lua_Integer n);</pre>
 
 <p>
 Pushes onto the stack the value <code>t[n]</code>,
 where <code>t</code> is the table at the given index.
-The access is raw;
-that is, it does not invoke metamethods.
+The access is raw,
+that is, it does not invoke the <code>__index</code> metamethod.
+
+
+<p>
+Returns the type of the pushed value.
 
 
 
@@ -4307,14 +4555,18 @@ that is, it does not invoke metamethods.
 
 <hr><h3><a name="lua_rawgetp"><code>lua_rawgetp</code></a></h3><p>
 <span class="apii">[-0, +1, &ndash;]</span>
-<pre>void lua_rawgetp (lua_State *L, int index, const void *p);</pre>
+<pre>int lua_rawgetp (lua_State *L, int index, const void *p);</pre>
 
 <p>
 Pushes onto the stack the value <code>t[k]</code>,
 where <code>t</code> is the table at the given index and
 <code>k</code> is the pointer <code>p</code> represented as a light userdata.
 The access is raw;
-that is, it does not invoke metamethods.
+that is, it does not invoke the <code>__index</code> metamethod.
+
+
+<p>
+Returns the type of the pushed value.
 
 
 
@@ -4338,7 +4590,7 @@ for other values, it is&nbsp;0.
 
 
 <hr><h3><a name="lua_rawset"><code>lua_rawset</code></a></h3><p>
-<span class="apii">[-2, +0, <em>e</em>]</span>
+<span class="apii">[-2, +0, <em>m</em>]</span>
 <pre>void lua_rawset (lua_State *L, int index);</pre>
 
 <p>
@@ -4350,39 +4602,39 @@ Similar to <a href="#lua_settable"><code>lua_settable</code></a>, but does a raw
 
 
 <hr><h3><a name="lua_rawseti"><code>lua_rawseti</code></a></h3><p>
-<span class="apii">[-1, +0, <em>e</em>]</span>
-<pre>void lua_rawseti (lua_State *L, int index, int n);</pre>
+<span class="apii">[-1, +0, <em>m</em>]</span>
+<pre>void lua_rawseti (lua_State *L, int index, lua_Integer i);</pre>
 
 <p>
-Does the equivalent of <code>t[n] = v</code>,
+Does the equivalent of <code>t[i] = v</code>,
 where <code>t</code> is the table at the given index
 and <code>v</code> is the value at the top of the stack.
 
 
 <p>
 This function pops the value from the stack.
-The assignment is raw;
-that is, it does not invoke metamethods.
+The assignment is raw,
+that is, it does not invoke the <code>__newindex</code> metamethod.
 
 
 
 
 
 <hr><h3><a name="lua_rawsetp"><code>lua_rawsetp</code></a></h3><p>
-<span class="apii">[-1, +0, <em>e</em>]</span>
+<span class="apii">[-1, +0, <em>m</em>]</span>
 <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.
 
 
 <p>
 This function pops the value from the stack.
-The assignment is raw;
-that is, it does not invoke metamethods.
+The assignment is raw,
+that is, it does not invoke <code>__newindex</code> metamethod.
 
 
 
@@ -4447,7 +4699,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.
 
 
@@ -4459,7 +4711,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>
@@ -4481,7 +4733,7 @@ or an error code in case of errors (see <a href="#lua_pcall"><code>lua_pcall</co
 In case of errors,
 the stack is not unwound,
 so you can use the debug API over it.
-The error message is on the top of the stack.
+The error object is on the top of the stack.
 
 
 <p>
@@ -4501,6 +4753,26 @@ this parameter can be <code>NULL</code>.
 
 
 
+<hr><h3><a name="lua_rotate"><code>lua_rotate</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_rotate (lua_State *L, int idx, int n);</pre>
+
+<p>
+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.
+
+
+
+
+
 <hr><h3><a name="lua_setallocf"><code>lua_setallocf</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);</pre>
@@ -4544,6 +4816,25 @@ sets it as the new value of global <code>name</code>.
 
 
 
+<hr><h3><a name="lua_seti"><code>lua_seti</code></a></h3><p>
+<span class="apii">[-1, +0, <em>e</em>]</span>
+<pre>void lua_seti (lua_State *L, int index, lua_Integer n);</pre>
+
+<p>
+Does the equivalent to <code>t[n] = v</code>,
+where <code>t</code> is the value at the given index
+and <code>v</code> is the value at the top of the stack.
+
+
+<p>
+This function pops the value from the stack.
+As in Lua, this function may trigger a metamethod
+for the "newindex" event (see <a href="#2.4">&sect;2.4</a>).
+
+
+
+
+
 <hr><h3><a name="lua_setmetatable"><code>lua_setmetatable</code></a></h3><p>
 <span class="apii">[-1, +0, &ndash;]</span>
 <pre>void lua_setmetatable (lua_State *L, int index);</pre>
@@ -4596,7 +4887,7 @@ If <code>index</code> is&nbsp;0, then all stack elements are removed.
 <pre>void lua_setuservalue (lua_State *L, int index);</pre>
 
 <p>
-Pops a table or <b>nil</b> from the stack and sets it as
+Pops a value from the stack and sets it as
 the new value associated to the userdata at the given index.
 
 
@@ -4648,6 +4939,27 @@ You can resume threads with status <a href="#pdf-LUA_OK"><code>LUA_OK</code></a>
 
 
 
+<hr><h3><a name="lua_stringtonumber"><code>lua_stringtonumber</code></a></h3><p>
+<span class="apii">[-0, +1, &ndash;]</span>
+<pre>size_t lua_stringtonumber (lua_State *L, const char *s);</pre>
+
+<p>
+Converts the zero-terminated string <code>s</code> to a number,
+pushes that number into the stack,
+and returns the total size of the string,
+that is, its length plus one.
+The conversion can result in an integer or a float,
+according to the lexical conventions of Lua (see <a href="#3.1">&sect;3.1</a>).
+The string may have leading and trailing spaces and a sign.
+If the string is not a valid numeral,
+returns 0 and pushes nothing.
+(Note that the result can be used as a boolean,
+true if the conversion succeeds.)
+
+
+
+
+
 <hr><h3><a name="lua_toboolean"><code>lua_toboolean</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>int lua_toboolean (lua_State *L, int index);</pre>
@@ -4697,17 +5009,12 @@ Equivalent to <a href="#lua_tointegerx"><code>lua_tointegerx</code></a> with <co
 <p>
 Converts the Lua value at the given index
 to the signed integral type <a href="#lua_Integer"><code>lua_Integer</code></a>.
-The Lua value must be a number or a string convertible to a number
-(see <a href="#3.4.2">&sect;3.4.2</a>);
+The Lua value must be an integer,
+or a number or string convertible to an integer (see <a href="#3.4.3">&sect;3.4.3</a>);
 otherwise, <code>lua_tointegerx</code> returns&nbsp;0.
 
 
 <p>
-If the number is not an integer,
-it is truncated in some non-specified way.
-
-
-<p>
 If <code>isnum</code> is not <code>NULL</code>,
 its referent is assigned a boolean value that
 indicates whether the operation succeeded.
@@ -4717,13 +5024,13 @@ indicates whether the operation succeeded.
 
 
 <hr><h3><a name="lua_tolstring"><code>lua_tolstring</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>m</em>]</span>
 <pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre>
 
 <p>
 Converts the Lua value at the given index to a C&nbsp;string.
 If <code>len</code> is not <code>NULL</code>,
-it also sets <code>*len</code> with the string length.
+it sets <code>*len</code> with the string length.
 The Lua value must be a string or a number;
 otherwise, the function returns <code>NULL</code>.
 If the value is a number,
@@ -4734,14 +5041,17 @@ when <code>lua_tolstring</code> is applied to keys during a table traversal.)
 
 
 <p>
-<code>lua_tolstring</code> returns a fully aligned pointer
+<code>lua_tolstring</code> returns a pointer
 to a string inside the Lua state.
 This string always has a zero ('<code>\0</code>')
 after its last character (as in&nbsp;C),
 but can contain other zeros in its body.
+
+
+<p>
 Because Lua has garbage collection,
 there is no guarantee that the pointer returned by <code>lua_tolstring</code>
-will be valid after the corresponding value is removed from the stack.
+will be valid after the corresponding Lua value is removed from the stack.
 
 
 
@@ -4766,7 +5076,7 @@ Equivalent to <a href="#lua_tonumberx"><code>lua_tonumberx</code></a> with <code
 Converts the Lua value at the given index
 to the C&nbsp;type <a href="#lua_Number"><code>lua_Number</code></a> (see <a href="#lua_Number"><code>lua_Number</code></a>).
 The Lua value must be a number or a string convertible to a number
-(see <a href="#3.4.2">&sect;3.4.2</a>);
+(see <a href="#3.4.3">&sect;3.4.3</a>);
 otherwise, <a href="#lua_tonumberx"><code>lua_tonumberx</code></a> returns&nbsp;0.
 
 
@@ -4793,14 +5103,14 @@ 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.
 
 
 
 
 
 <hr><h3><a name="lua_tostring"><code>lua_tostring</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>m</em>]</span>
 <pre>const char *lua_tostring (lua_State *L, int index);</pre>
 
 <p>
@@ -4824,46 +5134,6 @@ otherwise, the function returns <code>NULL</code>.
 
 
 
-<hr><h3><a name="lua_tounsigned"><code>lua_tounsigned</code></a></h3><p>
-<span class="apii">[-0, +0, &ndash;]</span>
-<pre>lua_Unsigned lua_tounsigned (lua_State *L, int index);</pre>
-
-<p>
-Equivalent to <a href="#lua_tounsignedx"><code>lua_tounsignedx</code></a> with <code>isnum</code> equal to <code>NULL</code>.
-
-
-
-
-
-<hr><h3><a name="lua_tounsignedx"><code>lua_tounsignedx</code></a></h3><p>
-<span class="apii">[-0, +0, &ndash;]</span>
-<pre>lua_Unsigned lua_tounsignedx (lua_State *L, int index, int *isnum);</pre>
-
-<p>
-Converts the Lua value at the given index
-to the unsigned integral type <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
-The Lua value must be a number or a string convertible to a number
-(see <a href="#3.4.2">&sect;3.4.2</a>);
-otherwise, <code>lua_tounsignedx</code> returns&nbsp;0.
-
-
-<p>
-If the number is not an integer,
-it is truncated in some non-specified way.
-If the number is outside the range of representable values,
-it is normalized to the remainder of its division by
-one more than the maximum representable value.
-
-
-<p>
-If <code>isnum</code> is not <code>NULL</code>,
-its referent is assigned a boolean value that
-indicates whether the operation succeeded.
-
-
-
-
-
 <hr><h3><a name="lua_touserdata"><code>lua_touserdata</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
 <pre>void *lua_touserdata (lua_State *L, int index);</pre>
@@ -4888,7 +5158,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>,
@@ -4916,16 +5186,10 @@ which must be one the values returned by <a href="#lua_type"><code>lua_type</cod
 
 
 <hr><h3><a name="lua_Unsigned"><code>lua_Unsigned</code></a></h3>
-<pre>typedef unsigned long lua_Unsigned;</pre>
-
-<p>
-The type used by the Lua API to represent unsigned integral values.
-It must have at least 32 bits.
-
+<pre>typedef ... lua_Unsigned;</pre>
 
 <p>
-By default it is an <code>unsigned int</code> or an <code>unsigned long</code>,
-whichever can hold 32-bit values.
+The unsigned version of <a href="#lua_Integer"><code>lua_Integer</code></a>.
 
 
 
@@ -4944,11 +5208,13 @@ the running function (see <a href="#4.4">&sect;4.4</a>).
 
 
 <hr><h3><a name="lua_version"><code>lua_version</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
+<span class="apii">[-0, +0, &ndash;]</span>
 <pre>const lua_Number *lua_version (lua_State *L);</pre>
 
 <p>
-Returns the address of the version number stored in the Lua core.
+Returns the address of the version number
+(a C static variable)
+stored in the Lua core.
 When called with a valid <a href="#lua_State"><code>lua_State</code></a>,
 returns the address of the version used to create that state.
 When called with <code>NULL</code>,
@@ -5000,14 +5266,14 @@ and pushes them onto the stack <code>to</code>.
 
 
 <hr><h3><a name="lua_yield"><code>lua_yield</code></a></h3><p>
-<span class="apii">[-?, +?, &ndash;]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
 <pre>int lua_yield (lua_State *L, int nresults);</pre>
 
 <p>
 This function is equivalent to <a href="#lua_yieldk"><code>lua_yieldk</code></a>,
 but it has no continuation (see <a href="#4.7">&sect;4.7</a>).
 Therefore, when the thread resumes,
-it returns to the function that called
+it continues the function that called
 the function calling <code>lua_yield</code>.
 
 
@@ -5015,25 +5281,22 @@ the function calling <code>lua_yield</code>.
 
 
 <hr><h3><a name="lua_yieldk"><code>lua_yieldk</code></a></h3><p>
-<span class="apii">[-?, +?, &ndash;]</span>
-<pre>int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k);</pre>
+<span class="apii">[-?, +?, <em>e</em>]</span>
+<pre>int lua_yieldk (lua_State *L,
+                int nresults,
+                lua_KContext ctx,
+                lua_KFunction k);</pre>
 
 <p>
-Yields a coroutine.
+Yields a coroutine (thread).
 
 
 <p>
-This function should only be called as the
-return expression of a C&nbsp;function, as follows:
-
-<pre>
-     return lua_yieldk (L, n, i, k);
-</pre><p>
-When a C&nbsp;function calls <a href="#lua_yieldk"><code>lua_yieldk</code></a> in that way,
+When a C&nbsp;function calls <a href="#lua_yieldk"><code>lua_yieldk</code></a>,
 the running coroutine suspends its execution,
 and the call to <a href="#lua_resume"><code>lua_resume</code></a> that started this coroutine returns.
 The parameter <code>nresults</code> is the number of values from the stack
-that are passed as results to <a href="#lua_resume"><code>lua_resume</code></a>.
+that will be passed as results to <a href="#lua_resume"><code>lua_resume</code></a>.
 
 
 <p>
@@ -5042,11 +5305,34 @@ Lua calls the given continuation function <code>k</code> to continue
 the execution of the C function that yielded (see <a href="#4.7">&sect;4.7</a>).
 This continuation function receives the same stack
 from the previous function,
-with the results removed and
+with the <code>n</code> results removed and
 replaced by the arguments passed to <a href="#lua_resume"><code>lua_resume</code></a>.
 Moreover,
-the continuation function may access the value <code>ctx</code>
-by calling <a href="#lua_getctx"><code>lua_getctx</code></a>.
+the continuation function receives the value <code>ctx</code>
+that was passed to <a href="#lua_yieldk"><code>lua_yieldk</code></a>.
+
+
+<p>
+Usually, this function does not return;
+when the coroutine eventually resumes,
+it continues executing the continuation function.
+However, there is one special case,
+which is when this function is called
+from inside a line or a count hook (see <a href="#4.9">&sect;4.9</a>).
+In that case, <code>lua_yieldk</code> should be called with no continuation
+(probably in the form of <a href="#lua_yield"><code>lua_yield</code></a>) and no results,
+and the hook should return immediately after the call.
+Lua will yield and,
+when the coroutine resumes again,
+it will continue the normal execution
+of the (Lua) function that triggered the hook.
+
+
+<p>
+This function can raise an error if it is called from a thread
+with a pending C call with no continuation function,
+or it is called from a thread that is not running inside a resume
+(e.g., the main thread).
 
 
 
@@ -5100,7 +5386,7 @@ The fields of <a href="#lua_Debug"><code>lua_Debug</code></a> have the following
 <ul>
 
 <li><b><code>source</code>: </b>
-the source of the chunk that created the function.
+the name of the chunk that created the function.
 If <code>source</code> starts with a '<code>@</code>',
 it means that the function was defined in a file where
 the file name follows the '<code>@</code>'.
@@ -5279,6 +5565,11 @@ numbers of the lines that are valid on the function.
 (A <em>valid line</em> is a line with some associated code,
 that is, a line where you can put a break point.
 Non-valid lines include empty lines and comments.)
+
+
+<p>
+If this option is given together with option '<code>f</code>',
+its table is pushed after the function.
 </li>
 
 </ul>
@@ -5293,7 +5584,7 @@ This function returns 0 on error
 
 <hr><h3><a name="lua_getlocal"><code>lua_getlocal</code></a></h3><p>
 <span class="apii">[-0, +(0|1), &ndash;]</span>
-<pre>const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);</pre>
+<pre>const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);</pre>
 
 <p>
 Gets information about a local variable of
@@ -5316,7 +5607,7 @@ and returns its name.
 
 
 <p>
-In the second case, <code>ar</code> should be <code>NULL</code> and the function
+In the second case, <code>ar</code> must be <code>NULL</code> and the function
 to be inspected must be at the top of the stack.
 In this case, only parameters of Lua functions are visible
 (as there is no information about what variables are active)
@@ -5360,24 +5651,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&nbsp;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.
 
 
 
@@ -5422,10 +5715,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).
 
 
 
@@ -5433,7 +5726,7 @@ calling <a href="#lua_yield"><code>lua_yield</code></a> with <code>nresults</cod
 
 <hr><h3><a name="lua_sethook"><code>lua_sethook</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>
+<pre>void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>
 
 <p>
 Sets the debugging hook function.
@@ -5442,7 +5735,7 @@ Sets the debugging hook function.
 <p>
 Argument <code>f</code> is the hook function.
 <code>mask</code> specifies on which events the hook will be called:
-it is formed by a bitwise or of the constants
+it is formed by a bitwise OR of the constants
 <a name="pdf-LUA_MASKCALL"><code>LUA_MASKCALL</code></a>,
 <a name="pdf-LUA_MASKRET"><code>LUA_MASKRET</code></a>,
 <a name="pdf-LUA_MASKLINE"><code>LUA_MASKLINE</code></a>,
@@ -5486,13 +5779,11 @@ A hook is disabled by setting <code>mask</code> to zero.
 
 <hr><h3><a name="lua_setlocal"><code>lua_setlocal</code></a></h3><p>
 <span class="apii">[-(0|1), +0, &ndash;]</span>
-<pre>const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);</pre>
+<pre>const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);</pre>
 
 <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.
 
@@ -5503,6 +5794,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>.
+
+
 
 
 
@@ -5515,13 +5810,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>.
 
 
 
@@ -5532,11 +5829,8 @@ when the index is greater than the number of upvalues.
 <pre>void *lua_upvalueid (lua_State *L, int funcindex, int n);</pre>
 
 <p>
-Returns an unique identifier for the upvalue numbered <code>n</code>
+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>
@@ -5547,6 +5841,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.
+
+
 
 
 
@@ -5609,7 +5908,7 @@ you should not use these functions for other stack values.
 
 <p>
 Functions called <code>luaL_check*</code>
-always throw an error if the check is not satisfied.
+always raise an error if the check is not satisfied.
 
 
 
@@ -5622,7 +5921,7 @@ in alphabetical order.
 
 
 <hr><h3><a name="luaL_addchar"><code>luaL_addchar</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>void luaL_addchar (luaL_Buffer *B, char c);</pre>
 
 <p>
@@ -5634,7 +5933,7 @@ Adds the byte <code>c</code> to the buffer <code>B</code>
 
 
 <hr><h3><a name="luaL_addlstring"><code>luaL_addlstring</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);</pre>
 
 <p>
@@ -5648,7 +5947,7 @@ The string can contain embedded zeros.
 
 
 <hr><h3><a name="luaL_addsize"><code>luaL_addsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, &ndash;]</span>
 <pre>void luaL_addsize (luaL_Buffer *B, size_t n);</pre>
 
 <p>
@@ -5661,21 +5960,20 @@ buffer area (see <a href="#luaL_prepbuffer"><code>luaL_prepbuffer</code></a>).
 
 
 <hr><h3><a name="luaL_addstring"><code>luaL_addstring</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>void luaL_addstring (luaL_Buffer *B, const char *s);</pre>
 
 <p>
 Adds the zero-terminated string pointed to by <code>s</code>
 to the buffer <code>B</code>
 (see <a href="#luaL_Buffer"><code>luaL_Buffer</code></a>).
-The string cannot contain embedded zeros.
 
 
 
 
 
 <hr><h3><a name="luaL_addvalue"><code>luaL_addvalue</code></a></h3><p>
-<span class="apii">[-1, +?, <em>e</em>]</span>
+<span class="apii">[-1, +?, <em>m</em>]</span>
 <pre>void luaL_addvalue (luaL_Buffer *B);</pre>
 
 <p>
@@ -5703,7 +6001,7 @@ which is the value to be added to the buffer.
 
 <p>
 Checks whether <code>cond</code> is true.
-If not, raises an error with a standard message.
+If it is not, raises an error with a standard message (see <a href="#luaL_argerror"><code>luaL_argerror</code></a>).
 
 
 
@@ -5714,14 +6012,15 @@ If not, raises an error with a standard message.
 <pre>int luaL_argerror (lua_State *L, int arg, const char *extramsg);</pre>
 
 <p>
-Raises an error with a standard message
-that includes <code>extramsg</code> as a comment.
+Raises an error reporting a problem with argument <code>arg</code>
+of the C function that called it,
+using a standard message
+that includes <code>extramsg</code> as a comment:
 
-
-<p>
-This function never returns,
-but it is an idiom to use it in C&nbsp;functions
-as <code>return luaL_argerror(<em>args</em>)</code>.
+<pre>
+     bad argument #<em>arg</em> to '<em>funcname</em>' (<em>extramsg</em>)
+</pre><p>
+This function never returns.
 
 
 
@@ -5812,7 +6111,7 @@ the buffer must be declared as a variable
 
 
 <hr><h3><a name="luaL_buffinitsize"><code>luaL_buffinitsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -5856,37 +6155,14 @@ of any type (including <b>nil</b>) at position <code>arg</code>.
 
 
 
-<hr><h3><a name="luaL_checkint"><code>luaL_checkint</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_checkint (lua_State *L, int arg);</pre>
-
-<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to an <code>int</code>.
-
-
-
-
-
 <hr><h3><a name="luaL_checkinteger"><code>luaL_checkinteger</code></a></h3><p>
 <span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>lua_Integer luaL_checkinteger (lua_State *L, int arg);</pre>
 
 <p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
-
-
-
-
-
-<hr><h3><a name="luaL_checklong"><code>luaL_checklong</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_checklong (lua_State *L, int arg);</pre>
-
-<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <code>long</code>.
+Checks whether the function argument <code>arg</code> is an integer
+(or can be converted to an integer)
+and returns this integer cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
 
 
 
@@ -6010,20 +6286,8 @@ returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata
 
 
 
-<hr><h3><a name="luaL_checkunsigned"><code>luaL_checkunsigned</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);</pre>
-
-<p>
-Checks whether the function argument <code>arg</code> is a number
-and returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
-
-
-
-
-
 <hr><h3><a name="luaL_checkversion"><code>luaL_checkversion</code></a></h3><p>
-<span class="apii">[-0, +0, &ndash;]</span>
+<span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>void luaL_checkversion (lua_State *L);</pre>
 
 <p>
@@ -6098,7 +6362,7 @@ as <code>return luaL_error(<em>args</em>)</code>.
 
 
 <hr><h3><a name="luaL_execresult"><code>luaL_execresult</code></a></h3><p>
-<span class="apii">[-0, +3, <em>e</em>]</span>
+<span class="apii">[-0, +3, <em>m</em>]</span>
 <pre>int luaL_execresult (lua_State *L, int stat);</pre>
 
 <p>
@@ -6111,7 +6375,7 @@ process-related functions in the standard library
 
 
 <hr><h3><a name="luaL_fileresult"><code>luaL_fileresult</code></a></h3><p>
-<span class="apii">[-0, +(1|3), <em>e</em>]</span>
+<span class="apii">[-0, +(1|3), <em>m</em>]</span>
 <pre>int luaL_fileresult (lua_State *L, int stat, const char *fname);</pre>
 
 <p>
@@ -6124,27 +6388,29 @@ file-related functions in the standard library
 
 
 <hr><h3><a name="luaL_getmetafield"><code>luaL_getmetafield</code></a></h3><p>
-<span class="apii">[-0, +(0|1), <em>e</em>]</span>
+<span class="apii">[-0, +(0|1), <em>m</em>]</span>
 <pre>int luaL_getmetafield (lua_State *L, int obj, const char *e);</pre>
 
 <p>
 Pushes onto the stack the field <code>e</code> from the metatable
-of the object at index <code>obj</code>.
+of the object at index <code>obj</code> and returns the type of pushed value.
 If the object does not have a metatable,
 or if the metatable does not have this field,
-returns false and pushes nothing.
+pushes nothing and returns <code>LUA_TNIL</code>.
 
 
 
 
 
 <hr><h3><a name="luaL_getmetatable"><code>luaL_getmetatable</code></a></h3><p>
-<span class="apii">[-0, +1, &ndash;]</span>
-<pre>void luaL_getmetatable (lua_State *L, const char *tname);</pre>
+<span class="apii">[-0, +1, <em>m</em>]</span>
+<pre>int luaL_getmetatable (lua_State *L, const char *tname);</pre>
 
 <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>).
+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.
 
 
 
@@ -6167,7 +6433,7 @@ and false if it creates a new table.
 
 
 <hr><h3><a name="luaL_gsub"><code>luaL_gsub</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>const char *luaL_gsub (lua_State *L,
                        const char *s,
                        const char *p,
@@ -6185,13 +6451,13 @@ Pushes the resulting string on the stack and returns it.
 
 <hr><h3><a name="luaL_len"><code>luaL_len</code></a></h3><p>
 <span class="apii">[-0, +0, <em>e</em>]</span>
-<pre>int luaL_len (lua_State *L, int index);</pre>
+<pre>lua_Integer luaL_len (lua_State *L, int index);</pre>
 
 <p>
 Returns the "length" of the value at the given index
 as a number;
-it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">&sect;3.4.6</a>).
-Raises an error if the result of the operation is not a number.
+it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.7">&sect;3.4.7</a>).
+Raises an error if the result of the operation is not an integer.
 (This case only can happen through metamethods.)
 
 
@@ -6237,7 +6503,7 @@ The string <code>mode</code> works as in function <a href="#lua_load"><code>lua_
 
 
 <hr><h3><a name="luaL_loadfile"><code>luaL_loadfile</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>int luaL_loadfile (lua_State *L, const char *filename);</pre>
 
 <p>
@@ -6248,7 +6514,7 @@ Equivalent to <a href="#luaL_loadfilex"><code>luaL_loadfilex</code></a> with <co
 
 
 <hr><h3><a name="luaL_loadfilex"><code>luaL_loadfilex</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>int luaL_loadfilex (lua_State *L, const char *filename,
                                             const char *mode);</pre>
 
@@ -6302,23 +6568,29 @@ it does not run it.
 
 
 <hr><h3><a name="luaL_newlib"><code>luaL_newlib</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
-<pre>void luaL_newlib (lua_State *L, const luaL_Reg *l);</pre>
+<span class="apii">[-0, +1, <em>m</em>]</span>
+<pre>void luaL_newlib (lua_State *L, const luaL_Reg l[]);</pre>
 
 <p>
 Creates a new table and registers there
 the functions in list <code>l</code>.
+
+
+<p>
 It is implemented as the following macro:
 
 <pre>
      (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
-</pre>
+</pre><p>
+The array <code>l</code> must be the actual array,
+not a pointer to it.
+
 
 
 
 
 <hr><h3><a name="luaL_newlibtable"><code>luaL_newlibtable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);</pre>
 
 <p>
@@ -6339,7 +6611,7 @@ not a pointer to it.
 
 
 <hr><h3><a name="luaL_newmetatable"><code>luaL_newmetatable</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>int luaL_newmetatable (lua_State *L, const char *tname);</pre>
 
 <p>
@@ -6347,8 +6619,10 @@ If the registry already has the key <code>tname</code>,
 returns 0.
 Otherwise,
 creates a new table to be used as a metatable for userdata,
-adds it to the registry with key <code>tname</code>,
+adds to this new table the pair <code>__name = tname</code>,
+adds to the registry the pair <code>[tname] = new table</code>,
 and returns 1.
+(The entry <code>__name</code> is used by some error-reporting functions.)
 
 
 <p>
@@ -6391,16 +6665,22 @@ Opens all standard Lua libraries into the given state.
 
 
 
-<hr><h3><a name="luaL_optint"><code>luaL_optint</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_optint (lua_State *L, int arg, int d);</pre>
+<hr><h3><a name="luaL_opt"><code>luaL_opt</code></a></h3><p>
+<span class="apii">[-0, +0, <em>e</em>]</span>
+<pre>T luaL_opt (L, func, arg, dflt);</pre>
 
 <p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to an <code>int</code>.
-If this argument is absent or is <b>nil</b>,
-returns <code>d</code>.
-Otherwise, raises an error.
+This macro is defined as follows:
+
+<pre>
+     (lua_isnoneornil(L,(arg)) ? (dflt) : func(L,(arg)))
+</pre><p>
+In words, if the argument <code>arg</code> is nil or absent,
+the macro results in the default <code>dflt</code>.
+Otherwise, it results in the result of calling <code>func</code>
+with the state <code>L</code> and the argument index <code>arg</code> as
+parameters.
+Note that it evaluates the expression <code>dflt</code> only if needed.
 
 
 
@@ -6413,23 +6693,9 @@ Otherwise, raises an error.
                              lua_Integer d);</pre>
 
 <p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
-If this argument is absent or is <b>nil</b>,
-returns <code>d</code>.
-Otherwise, raises an error.
-
-
-
-
-
-<hr><h3><a name="luaL_optlong"><code>luaL_optlong</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_optlong (lua_State *L, int arg, long d);</pre>
-
-<p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to a <code>long</code>.
+If the function argument <code>arg</code> is an integer
+(or convertible to an integer),
+returns this integer.
 If this argument is absent or is <b>nil</b>,
 returns <code>d</code>.
 Otherwise, raises an error.
@@ -6456,6 +6722,9 @@ Otherwise, raises an error.
 <p>
 If <code>l</code> is not <code>NULL</code>,
 fills the position <code>*l</code> with the result's length.
+If the result is <code>NULL</code>
+(only possible when returning <code>d</code> and <code>d == NULL</code>),
+its length is considered zero.
 
 
 
@@ -6493,25 +6762,8 @@ Otherwise, raises an error.
 
 
 
-<hr><h3><a name="luaL_optunsigned"><code>luaL_optunsigned</code></a></h3><p>
-<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Unsigned luaL_optunsigned (lua_State *L,
-                               int arg,
-                               lua_Unsigned u);</pre>
-
-<p>
-If the function argument <code>arg</code> is a number,
-returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
-If this argument is absent or is <b>nil</b>,
-returns <code>u</code>.
-Otherwise, raises an error.
-
-
-
-
-
 <hr><h3><a name="luaL_prepbuffer"><code>luaL_prepbuffer</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>char *luaL_prepbuffer (luaL_Buffer *B);</pre>
 
 <p>
@@ -6523,7 +6775,7 @@ with the predefined size <a name="pdf-LUAL_BUFFERSIZE"><code>LUAL_BUFFERSIZE</co
 
 
 <hr><h3><a name="luaL_prepbuffsize"><code>luaL_prepbuffsize</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>m</em>]</span>
 <pre>char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -6539,7 +6791,7 @@ it to the buffer.
 
 
 <hr><h3><a name="luaL_pushresult"><code>luaL_pushresult</code></a></h3><p>
-<span class="apii">[-?, +1, <em>e</em>]</span>
+<span class="apii">[-?, +1, <em>m</em>]</span>
 <pre>void luaL_pushresult (luaL_Buffer *B);</pre>
 
 <p>
@@ -6551,7 +6803,7 @@ the top of the stack.
 
 
 <hr><h3><a name="luaL_pushresultsize"><code>luaL_pushresultsize</code></a></h3><p>
-<span class="apii">[-?, +1, <em>e</em>]</span>
+<span class="apii">[-?, +1, <em>m</em>]</span>
 <pre>void luaL_pushresultsize (luaL_Buffer *B, size_t sz);</pre>
 
 <p>
@@ -6562,7 +6814,7 @@ Equivalent to the sequence <a href="#luaL_addsize"><code>luaL_addsize</code></a>
 
 
 <hr><h3><a name="luaL_ref"><code>luaL_ref</code></a></h3><p>
-<span class="apii">[-1, +0, <em>e</em>]</span>
+<span class="apii">[-1, +0, <em>m</em>]</span>
 <pre>int luaL_ref (lua_State *L, int t);</pre>
 
 <p>
@@ -6601,7 +6853,7 @@ Type for arrays of functions to be registered by
 <a href="#luaL_setfuncs"><code>luaL_setfuncs</code></a>.
 <code>name</code> is the function name and <code>func</code> is a pointer to
 the function.
-Any array of <a href="#luaL_Reg"><code>luaL_Reg</code></a> must end with an sentinel entry
+Any array of <a href="#luaL_Reg"><code>luaL_Reg</code></a> must end with a sentinel entry
 in which both <code>name</code> and <code>func</code> are <code>NULL</code>.
 
 
@@ -6614,25 +6866,26 @@ in which both <code>name</code> and <code>func</code> are <code>NULL</code>.
                     lua_CFunction openf, int glb);</pre>
 
 <p>
-Calls function <code>openf</code> with string <code>modname</code> as an argument
+If <code>modname</code> is not already present in <a href="#pdf-package.loaded"><code>package.loaded</code></a>,
+calls function <code>openf</code> with string <code>modname</code> as an argument
 and sets the call result in <code>package.loaded[modname]</code>,
 as if that function has been called through <a href="#pdf-require"><code>require</code></a>.
 
 
 <p>
 If <code>glb</code> is true,
-also stores the result into global <code>modname</code>.
+also stores the module into global <code>modname</code>.
 
 
 <p>
-Leaves a copy of that result on the stack.
+Leaves a copy of the module on the stack.
 
 
 
 
 
 <hr><h3><a name="luaL_setfuncs"><code>luaL_setfuncs</code></a></h3><p>
-<span class="apii">[-nup, +0, <em>e</em>]</span>
+<span class="apii">[-nup, +0, <em>m</em>]</span>
 <pre>void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);</pre>
 
 <p>
@@ -6665,14 +6918,52 @@ in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code>
 
 
 
+<hr><h3><a name="luaL_Stream"><code>luaL_Stream</code></a></h3>
+<pre>typedef struct luaL_Stream {
+  FILE *f;
+  lua_CFunction closef;
+} luaL_Stream;</pre>
+
+<p>
+The standard representation for file handles,
+which is used by the standard I/O library.
+
+
+<p>
+A file handle is implemented as a full userdata,
+with a metatable called <code>LUA_FILEHANDLE</code>
+(where <code>LUA_FILEHANDLE</code> is a macro with the actual metatable's name).
+The metatable is created by the I/O library
+(see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>).
+
+
+<p>
+This userdata must start with the structure <code>luaL_Stream</code>;
+it can contain other data after this initial structure.
+Field <code>f</code> points to the corresponding C stream
+(or it can be <code>NULL</code> to indicate an incompletely created handle).
+Field <code>closef</code> points to a Lua function
+that will be called to close the stream
+when the handle is closed or collected;
+this function receives the file handle as its sole argument and
+must return either <b>true</b> (in case of success)
+or <b>nil</b> plus an error message (in case of error).
+Once Lua calls this field,
+it changes the field value to <code>NULL</code>
+to signal that the handle is closed.
+
+
+
+
+
 <hr><h3><a name="luaL_testudata"><code>luaL_testudata</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>m</em>]</span>
 <pre>void *luaL_testudata (lua_State *L, int arg, const char *tname);</pre>
 
 <p>
 This function works like <a href="#luaL_checkudata"><code>luaL_checkudata</code></a>,
 except that, when the test fails,
-it returns <code>NULL</code> instead of throwing an error.
+it returns <code>NULL</code> instead of raising an error.
 
 
 
@@ -6692,7 +6983,7 @@ the function also sets <code>*len</code> with the string length.
 
 
 <p>
-If the value has a metatable with a <code>"__tostring"</code> field,
+If the value has a metatable with a <code>__tostring</code> field,
 then <code>luaL_tolstring</code> calls the corresponding metamethod
 with the value as argument,
 and uses the result of the call as its result.
@@ -6702,7 +6993,7 @@ and uses the result of the call as its result.
 
 
 <hr><h3><a name="luaL_traceback"><code>luaL_traceback</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                      int level);</pre>
 
@@ -6749,7 +7040,7 @@ If <code>ref</code> is <a href="#pdf-LUA_NOREF"><code>LUA_NOREF</code></a> or <a
 
 
 <hr><h3><a name="luaL_where"><code>luaL_where</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>m</em>]</span>
 <pre>void luaL_where (lua_State *L, int lvl);</pre>
 
 <p>
@@ -6802,11 +7093,11 @@ Currently, Lua has the following standard libraries:
 
 <li>string manipulation (<a href="#6.4">&sect;6.4</a>);</li>
 
-<li>table manipulation (<a href="#6.5">&sect;6.5</a>);</li>
+<li>basic UTF-8 support (<a href="#6.5">&sect;6.5</a>);</li>
 
-<li>mathematical functions (<a href="#6.6">&sect;6.6</a>) (sin, log, etc.);</li>
+<li>table manipulation (<a href="#6.6">&sect;6.6</a>);</li>
 
-<li>bitwise operations (<a href="#6.7">&sect;6.7</a>);</li>
+<li>mathematical functions (<a href="#6.7">&sect;6.7</a>) (sin, log, etc.);</li>
 
 <li>input and output (<a href="#6.8">&sect;6.8</a>);</li>
 
@@ -6831,11 +7122,11 @@ the host program can open them individually by using
 <a name="pdf-luaopen_package"><code>luaopen_package</code></a> (for the package library),
 <a name="pdf-luaopen_coroutine"><code>luaopen_coroutine</code></a> (for the coroutine library),
 <a name="pdf-luaopen_string"><code>luaopen_string</code></a> (for the string library),
+<a name="pdf-luaopen_utf8"><code>luaopen_utf8</code></a> (for the UTF8 library),
 <a name="pdf-luaopen_table"><code>luaopen_table</code></a> (for the table library),
 <a name="pdf-luaopen_math"><code>luaopen_math</code></a> (for the mathematical library),
-<a name="pdf-luaopen_bit32"><code>luaopen_bit32</code></a> (for the bit library),
 <a name="pdf-luaopen_io"><code>luaopen_io</code></a> (for the I/O library),
-<a name="pdf-luaopen_os"><code>luaopen_os</code></a> (for the Operating System library),
+<a name="pdf-luaopen_os"><code>luaopen_os</code></a> (for the operating system library),
 and <a name="pdf-luaopen_debug"><code>luaopen_debug</code></a> (for the debug library).
 These functions are declared in <a name="pdf-lualib.h"><code>lualib.h</code></a>.
 
@@ -6852,11 +7143,15 @@ implementations for some of its facilities.
 
 <p>
 <hr><h3><a name="pdf-assert"><code>assert (v [, message])</code></a></h3>
-Issues an  error when
+
+
+<p>
+Calls <a href="#pdf-error"><code>error</code></a> if
 the value of its argument <code>v</code> is false (i.e., <b>nil</b> or <b>false</b>);
 otherwise, returns all its arguments.
-<code>message</code> is an error message;
-when absent, it defaults to "assertion failed!"
+In case of error,
+<code>message</code> is the error object;
+when absent, it defaults to "<code>assertion failed!</code>"
 
 
 
@@ -6887,25 +7182,21 @@ restarts automatic execution of the garbage collector.
 </li>
 
 <li><b>"<code>count</code>": </b>
-returns the total memory in use by Lua (in Kbytes) and
-a second value with the total memory in bytes modulo 1024.
-The first value has a fractional part,
-so the following equality is always true:
-
-<pre>
-     k, b = collectgarbage("count")
-     assert(k*1024 == math.floor(k)*1024 + b)
-</pre><p>
-(The second result is useful when Lua is compiled
-with a non floating-point type for numbers.)
+returns the total memory in use by Lua in Kbytes.
+The value has a fractional part,
+so that it multiplied by 1024
+gives the exact number of bytes in use by Lua
+(except for overflows).
 </li>
 
 <li><b>"<code>step</code>": </b>
 performs a garbage-collection step.
-The step "size" is controlled by <code>arg</code>
-(larger values mean more steps) in a non-specified way.
-If you want to control the step size
-you must experimentally tune the value of <code>arg</code>.
+The step "size" is controlled by <code>arg</code>.
+With a zero value,
+the collector will perform one basic (indivisible) step.
+For non-zero values,
+the collector will perform as if that amount of memory
+(in KBytes) had been allocated by Lua.
 Returns <b>true</b> if the step finished a collection cycle.
 </li>
 
@@ -6926,16 +7217,6 @@ returns a boolean that tells whether the collector is running
 (i.e., not stopped).
 </li>
 
-<li><b>"<code>generational</code>": </b>
-changes the collector to generational mode.
-This is an experimental feature (see <a href="#2.5">&sect;2.5</a>).
-</li>
-
-<li><b>"<code>incremental</code>": </b>
-changes the collector to incremental mode.
-This is the default mode.
-</li>
-
 </ul>
 
 
@@ -6955,7 +7236,7 @@ to its caller (that is, <code>dofile</code> does not run in protected mode).
 <p>
 <hr><h3><a name="pdf-error"><code>error (message [, level])</code></a></h3>
 Terminates the last protected function called
-and returns <code>message</code> as the error message.
+and returns <code>message</code> as the error object.
 Function <code>error</code> never returns.
 
 
@@ -6979,7 +7260,7 @@ A global variable (not a function) that
 holds the global environment (see <a href="#2.2">&sect;2.2</a>).
 Lua itself does not use this variable;
 changing its value does not affect any environment,
-nor vice-versa.
+nor vice versa.
 
 
 
@@ -6991,7 +7272,7 @@ nor vice-versa.
 <p>
 If <code>object</code> does not have a metatable, returns <b>nil</b>.
 Otherwise,
-if the object's metatable has a <code>"__metatable"</code> field,
+if the object's metatable has a <code>__metatable</code> field,
 returns the associated value.
 Otherwise, returns the metatable of the given object.
 
@@ -7003,27 +7284,21 @@ Otherwise, returns the metatable of the given object.
 
 
 <p>
-If <code>t</code> has a metamethod <code>__ipairs</code>,
-calls it with <code>t</code> as argument and returns the first three
-results from the call.
-
-
-<p>
-Otherwise,
-returns three values: an iterator function, the table <code>t</code>, and 0,
+Returns three values (an iterator function, the table <code>t</code>, and 0)
 so that the construction
 
 <pre>
      for i,v in ipairs(t) do <em>body</em> end
 </pre><p>
-will iterate over the pairs (<code>1,t[1]</code>), (<code>2,t[2]</code>), ...,
-up to the first integer key absent from the table.
+will iterate over the key&ndash;value pairs
+(<code>1,t[1]</code>), (<code>2,t[2]</code>), ...,
+up to the first nil value.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-load"><code>load (ld [, source [, mode [, env]]])</code></a></h3>
+<hr><h3><a name="pdf-load"><code>load (chunk [, chunkname [, mode [, env]]])</code></a></h3>
 
 
 <p>
@@ -7031,10 +7306,10 @@ Loads a chunk.
 
 
 <p>
-If <code>ld</code> is a string, the chunk is this string.
-If <code>ld</code> is a function,
+If <code>chunk</code> is a string, the chunk is this string.
+If <code>chunk</code> is a function,
 <code>load</code> calls it repeatedly to get the chunk pieces.
-Each call to <code>ld</code> must return a string that concatenates
+Each call to <code>chunk</code> must return a string that concatenates
 with previous results.
 A return of an empty string, <b>nil</b>, or no value signals the end of the chunk.
 
@@ -7050,18 +7325,22 @@ If the resulting function has upvalues,
 the first upvalue is set to the value of <code>env</code>,
 if that parameter is given,
 or to the value of the global environment.
+Other upvalues are initialized with <b>nil</b>.
 (When you load a main chunk,
 the resulting function will always have exactly one upvalue,
 the <code>_ENV</code> variable (see <a href="#2.2">&sect;2.2</a>).
-When you load a binary chunk created from a function (see <a href="#pdf-string.dump"><code>string.dump</code></a>),
-the resulting function can have arbitrary upvalues.)
+However,
+when you load a binary chunk created from a function (see <a href="#pdf-string.dump"><code>string.dump</code></a>),
+the resulting function can have an arbitrary number of upvalues.)
+All upvalues are fresh, that is,
+they are not shared with any other function.
 
 
 <p>
-<code>source</code> is used as the source of the chunk for error messages
+<code>chunkname</code> is used as the name of the chunk for error messages
 and debug information (see <a href="#4.9">&sect;4.9</a>).
 When absent,
-it defaults to <code>ld</code>, if <code>ld</code> is a string,
+it defaults to <code>chunk</code>, if <code>chunk</code> is a string,
 or to "<code>=(load)</code>" otherwise.
 
 
@@ -7074,6 +7353,12 @@ or "<code>bt</code>" (both binary and text).
 The default is "<code>bt</code>".
 
 
+<p>
+Lua does not check the consistency of binary chunks.
+Maliciously crafted binary chunks can crash
+the interpreter.
+
+
 
 
 <p>
@@ -7113,7 +7398,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>.)
 
 
@@ -7191,7 +7476,7 @@ use <a href="#pdf-string.format"><code>string.format</code></a> and <a href="#pd
 <p>
 <hr><h3><a name="pdf-rawequal"><code>rawequal (v1, v2)</code></a></h3>
 Checks whether <code>v1</code> is equal to <code>v2</code>,
-without invoking any metamethod.
+without invoking the <code>__eq</code> metamethod.
 Returns a boolean.
 
 
@@ -7200,7 +7485,7 @@ Returns a boolean.
 <p>
 <hr><h3><a name="pdf-rawget"><code>rawget (table, index)</code></a></h3>
 Gets the real value of <code>table[index]</code>,
-without invoking any metamethod.
+without invoking the <code>__index</code> metamethod.
 <code>table</code> must be a table;
 <code>index</code> may be any value.
 
@@ -7211,8 +7496,8 @@ without invoking any metamethod.
 <hr><h3><a name="pdf-rawlen"><code>rawlen (v)</code></a></h3>
 Returns the length of the object <code>v</code>,
 which must be a table or a string,
-without invoking any metamethod.
-Returns an integer number.
+without invoking the <code>__len</code> metamethod.
+Returns an integer.
 
 
 
@@ -7220,7 +7505,7 @@ Returns an integer number.
 <p>
 <hr><h3><a name="pdf-rawset"><code>rawset (table, index, value)</code></a></h3>
 Sets the real value of <code>table[index]</code> to <code>value</code>,
-without invoking any metamethod.
+without invoking the <code>__newindex</code> metamethod.
 <code>table</code> must be a table,
 <code>index</code> any value different from <b>nil</b> and NaN,
 and <code>value</code> any Lua value.
@@ -7252,10 +7537,11 @@ and <code>select</code> returns the total number of extra arguments it received.
 
 <p>
 Sets the metatable for the given table.
-(You cannot change the metatable of other types from Lua, only from&nbsp;C.)
+(To change the metatable of other types from Lua code,
+you must use the debug library (<a href="#6.10">&sect;6.10</a>).)
 If <code>metatable</code> is <b>nil</b>,
 removes the metatable of the given table.
-If the original metatable has a <code>"__metatable"</code> field,
+If the original metatable has a <code>__metatable</code> field,
 raises an error.
 
 
@@ -7273,14 +7559,20 @@ This function returns <code>table</code>.
 When called with no <code>base</code>,
 <code>tonumber</code> tries to convert its argument to a number.
 If the argument is already a number or
-a string convertible to a number (see <a href="#3.4.2">&sect;3.4.2</a>),
+a string convertible to a number,
 then <code>tonumber</code> returns this number;
 otherwise, it returns <b>nil</b>.
 
 
 <p>
+The conversion of strings can result in integers or floats,
+according to the lexical conventions of Lua (see <a href="#3.1">&sect;3.1</a>).
+(The string may have leading and trailing spaces and a sign.)
+
+
+<p>
 When called with <code>base</code>,
-then <code>e</code> should be a string to be interpreted as
+then <code>e</code> must be a string to be interpreted as
 an integer numeral in that base.
 The base may be any integer between 2 and 36, inclusive.
 In bases above&nbsp;10, the letter '<code>A</code>' (in either upper or lower case)
@@ -7295,13 +7587,13 @@ the function returns <b>nil</b>.
 <p>
 <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 reasonable format.
+converts it to a string in a human-readable format.
 (For complete control of how numbers are converted,
 use <a href="#pdf-string.format"><code>string.format</code></a>.)
 
 
 <p>
-If the metatable of <code>v</code> has a <code>"__tostring"</code> field,
+If the metatable of <code>v</code> has a <code>__tostring</code> field,
 then <code>tostring</code> calls the corresponding value
 with <code>v</code> as argument,
 and uses the result of the call as its result.
@@ -7327,9 +7619,12 @@ and "<code>userdata</code>".
 
 <p>
 <hr><h3><a name="pdf-_VERSION"><code>_VERSION</code></a></h3>
+
+
+<p>
 A global variable (not a function) that
-holds a string containing the current interpreter version.
-The current contents of this variable is "<code>Lua 5.2</code>".
+holds a string containing the running Lua version.
+The current value of this variable is "<code>Lua 5.3</code>".
 
 
 
@@ -7351,8 +7646,8 @@ except that it sets a new message handler <code>msgh</code>.
 <h2>6.2 &ndash; <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">&sect;2.6</a> for a general description of coroutines.
 
 
@@ -7362,7 +7657,7 @@ See <a href="#2.6">&sect;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>.
 
@@ -7370,6 +7665,21 @@ an object with type <code>"thread"</code>.
 
 
 <p>
+<hr><h3><a name="pdf-coroutine.isyieldable"><code>coroutine.isyieldable ()</code></a></h3>
+
+
+<p>
+Returns true when the running coroutine can yield.
+
+
+<p>
+A running coroutine is yieldable if it is not the main thread and
+it is not inside a non-yieldable C function.
+
+
+
+
+<p>
 <hr><h3><a name="pdf-coroutine.resume"><code>coroutine.resume (co [, val1, &middot;&middot;&middot;])</code></a></h3>
 
 
@@ -7388,8 +7698,8 @@ as the results from the yield.
 <p>
 If the coroutine runs without any errors,
 <code>resume</code> returns <b>true</b> plus any values passed to <code>yield</code>
-(if the coroutine yields) or any values returned by the body function
-(if the coroutine terminates).
+(when the coroutine yields) or any values returned by the body function
+(when the coroutine terminates).
 If there is any error,
 <code>resume</code> returns <b>false</b> plus the error message.
 
@@ -7431,7 +7741,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>.
@@ -7491,7 +7801,7 @@ for <a href="#pdf-package.searchers"><code>package.searchers</code></a>.
 <p>
 First <code>require</code> queries <code>package.preload[modname]</code>.
 If it has a value,
-this value (which should be a function) is the loader.
+this value (which must be a function) is the loader.
 Otherwise <code>require</code> searches for a Lua loader using the
 path stored in <a href="#pdf-package.path"><code>package.path</code></a>.
 If that also fails, it searches for a C&nbsp;loader using the
@@ -7547,7 +7857,7 @@ Default is '<code>?</code>'.</li>
 is replaced by the executable's directory.
 Default is '<code>!</code>'.</li>
 
-<li>The fifth line is a mark to ignore all text before it
+<li>The fifth line is a mark to ignore all text after it
 when building the <code>luaopen_</code> function name.
 Default is '<code>-</code>'.</li>
 
@@ -7566,7 +7876,7 @@ The path used by <a href="#pdf-require"><code>require</code></a> to search for a
 <p>
 Lua initializes the C&nbsp;path <a href="#pdf-package.cpath"><code>package.cpath</code></a> in the same way
 it initializes the Lua path <a href="#pdf-package.path"><code>package.path</code></a>,
-using the environment variable <a name="pdf-LUA_CPATH_5_2"><code>LUA_CPATH_5_2</code></a>
+using the environment variable <a name="pdf-LUA_CPATH_5_3"><code>LUA_CPATH_5_3</code></a>
 or the environment variable <a name="pdf-LUA_CPATH"><code>LUA_CPATH</code></a>
 or a default path defined in <code>luaconf.h</code>.
 
@@ -7644,7 +7954,7 @@ The path used by <a href="#pdf-require"><code>require</code></a> to search for a
 
 <p>
 At start-up, Lua initializes this variable with
-the value of the environment variable <a name="pdf-LUA_PATH_5_2"><code>LUA_PATH_5_2</code></a> or
+the value of the environment variable <a name="pdf-LUA_PATH_5_3"><code>LUA_PATH_5_3</code></a> or
 the environment variable <a name="pdf-LUA_PATH"><code>LUA_PATH</code></a> or
 with a default path defined in <code>luaconf.h</code>,
 if those environment variables are not defined.
@@ -7729,9 +8039,9 @@ The name of this C&nbsp;function is the string "<code>luaopen_</code>"
 concatenated with a copy of the module name where each dot
 is replaced by an underscore.
 Moreover, if the module name has a hyphen,
-its prefix up to (and including) the first hyphen is removed.
-For instance, if the module name is <code>a.v1-b.c</code>,
-the function name will be <code>luaopen_b_c</code>.
+its suffix after (and including) the first hyphen is removed.
+For instance, if the module name is <code>a.b.c-v2.1</code>,
+the function name will be <code>luaopen_a_b_c</code>.
 
 
 <p>
@@ -7830,7 +8140,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&nbsp;1;
 the default value for <code>j</code> is&nbsp;<code>i</code>.
@@ -7839,7 +8149,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.
 
 
 
@@ -7848,24 +8158,39 @@ Numerical codes are not necessarily portable across platforms.
 <hr><h3><a name="pdf-string.char"><code>string.char (&middot;&middot;&middot;)</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.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-string.dump"><code>string.dump (function)</code></a></h3>
+<hr><h3><a name="pdf-string.dump"><code>string.dump (function [, strip])</code></a></h3>
 
 
 <p>
-Returns a string containing a binary representation of the given function,
+Returns a string containing a binary representation
+(a <em>binary chunk</em>)
+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 may not include all debug information
+about the function,
+to save space.
+
+
+<p>
+Functions with upvalues have only their number of upvalues saved.
+When (re)loaded,
+those upvalues receive fresh instances containing <b>nil</b>.
+(You can use the debug library to serialize
+and reload the upvalues of a function
+in a way adequate to your needs.)
 
 
 
@@ -7876,11 +8201,11 @@ a copy of the function (but with new upvalues).
 
 <p>
 Looks for the first match of
-<code>pattern</code> in the string <code>s</code>.
+<code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>) in the string <code>s</code>.
 If it finds a match, then <code>find</code> returns the indices of&nbsp;<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&nbsp;1 and can be negative.
 A value of <b>true</b> as a fourth, optional argument <code>plain</code>
@@ -7911,6 +8236,9 @@ The only differences are that the options/modifiers
 <code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, <code>n</code>,
 and <code>p</code> are not supported
 and that there is an extra option, <code>q</code>.
+
+
+<p>
 The <code>q</code> option formats a string between double quotes,
 using escape sequences when necessary to ensure that
 it can safely be read back by the Lua interpreter.
@@ -7928,20 +8256,22 @@ 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>
-also expect a number,
-but the range of that number may be limited by
-the underlying C&nbsp;implementation.
-For options <code>o</code>, <code>u</code>, <code>X</code>, and <code>x</code>,
-the number cannot be negative.
-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,
+expect an integer.
+When Lua is compiled with a C89 compiler,
+options <code>A</code> and <code>a</code> (hexadecimal floats)
+do not support any modifier (flags, width, length).
+
+
+<p>
+Option <code>s</code> expects a string;
+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>.
+If the option has any modifier (flags, width, length),
+the string argument should not contain embedded zeros.
 
 
 
@@ -7950,7 +8280,8 @@ it is converted to one following the same rules of <a href="#pdf-tostring"><code
 <hr><h3><a name="pdf-string.gmatch"><code>string.gmatch (s, pattern)</code></a></h3>
 Returns an iterator function that,
 each time it is called,
-returns the next captures from <code>pattern</code> over the string <code>s</code>.
+returns the next captures from <code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>)
+over the string <code>s</code>.
 If <code>pattern</code> specifies no captures,
 then the whole match is produced in each call.
 
@@ -7988,7 +8319,7 @@ work as an anchor, as this would prevent the iteration.
 <hr><h3><a name="pdf-string.gsub"><code>string.gsub (s, pattern, repl [, n])</code></a></h3>
 Returns a copy of <code>s</code>
 in which all (or the first <code>n</code>, if given)
-occurrences of the <code>pattern</code> have been
+occurrences of the <code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>) have been
 replaced by a replacement string specified by <code>repl</code>,
 which can be a string, a table, or a function.
 <code>gsub</code> also returns, as its second value,
@@ -8053,9 +8384,9 @@ Here are some examples:
          end)
      --&gt; x="4+5 = 9"
      
-     local t = {name="lua", version="5.2"}
+     local t = {name="lua", version="5.3"}
      x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
-     --&gt; x="lua-5.2.tar.gz"
+     --&gt; x="lua-5.3.tar.gz"
 </pre>
 
 
@@ -8083,13 +8414,13 @@ The definition of what an uppercase letter is depends on the current locale.
 <p>
 <hr><h3><a name="pdf-string.match"><code>string.match (s, pattern [, init])</code></a></h3>
 Looks for the first <em>match</em> of
-<code>pattern</code> in the string <code>s</code>.
+<code>pattern</code> (see <a href="#6.4.1">&sect;6.4.1</a>) in the string <code>s</code>.
 If it finds one, then <code>match</code> returns
 the captures from the pattern;
 otherwise it returns <b>nil</b>.
 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&nbsp;1 and can be negative.
 
@@ -8097,11 +8428,42 @@ its default value is&nbsp;1 and can be negative.
 
 
 <p>
+<hr><h3><a name="pdf-string.pack"><code>string.pack (fmt, v1, v2, &middot;&middot;&middot;)</code></a></h3>
+
+
+<p>
+Returns a binary string containing the values <code>v1</code>, <code>v2</code>, etc.
+packed (that is, serialized in binary form)
+according to the format string <code>fmt</code> (see <a href="#6.4.2">&sect;6.4.2</a>). 
+
+
+
+
+<p>
+<hr><h3><a name="pdf-string.packsize"><code>string.packsize (fmt)</code></a></h3>
+
+
+<p>
+Returns the size of a string resulting from <a href="#pdf-string.pack"><code>string.pack</code></a>
+with the given format.
+The format string cannot have the variable-length options
+'<code>s</code>' or '<code>z</code>' (see <a href="#6.4.2">&sect;6.4.2</a>).
+
+
+
+
+<p>
 <hr><h3><a name="pdf-string.rep"><code>string.rep (s, n [, sep])</code></a></h3>
 Returns a string that is the concatenation of <code>n</code> copies of
 the string <code>s</code> separated by the string <code>sep</code>.
 The default value for <code>sep</code> is the empty string
 (that is, no separator).
+Returns the empty string if <code>n</code> is not positive.
+
+
+<p>
+(Note that it is very easy to exhaust the memory of your machine
+with a single call to this function.)
 
 
 
@@ -8141,6 +8503,21 @@ the function returns the empty string.
 
 
 <p>
+<hr><h3><a name="pdf-string.unpack"><code>string.unpack (fmt, s [, pos])</code></a></h3>
+
+
+<p>
+Returns the values packed in string <code>s</code> (see <a href="#pdf-string.pack"><code>string.pack</code></a>)
+according to the format string <code>fmt</code> (see <a href="#6.4.2">&sect;6.4.2</a>).
+An optional <code>pos</code> marks where
+to start reading in <code>s</code> (default is 1).
+After the read values,
+this function also returns the index of the first unread byte in <code>s</code>.
+
+
+
+
+<p>
 <hr><h3><a name="pdf-string.upper"><code>string.upper (s)</code></a></h3>
 Receives a string and returns a copy of this string with all
 lowercase letters changed to uppercase.
@@ -8149,8 +8526,21 @@ The definition of what a lowercase letter is depends on the current locale.
 
 
 
+
+
 <h3>6.4.1 &ndash; <a name="6.4.1">Patterns</a></h3>
 
+<p>
+Patterns in Lua are described by regular strings,
+which are interpreted as patterns by the pattern-matching functions
+<a href="#pdf-string.find"><code>string.find</code></a>,
+<a href="#pdf-string.gmatch"><code>string.gmatch</code></a>,
+<a href="#pdf-string.gsub"><code>string.gsub</code></a>,
+and <a href="#pdf-string.match"><code>string.match</code></a>.
+This section describes the syntax and the meaning
+(that is, what they match) of these strings.
+
+
 
 <h4>Character Class:</h4><p>
 A <em>character class</em> is used to represent a set of characters.
@@ -8189,7 +8579,8 @@ represents the character <em>x</em> itself.
 <li><b><code>%<em>x</em></code>: </b> (where <em>x</em> is any non-alphanumeric character)
 represents the character <em>x</em>.
 This is the standard way to escape the magic characters.
-Any punctuation character (even the non magic)
+Any non-alphanumeric character
+(including all punctuation characters, even the non-magical)
 can be preceded by a '<code>%</code>'
 when used to represent itself in a pattern.
 </li>
@@ -8199,7 +8590,7 @@ represents the class which is the union of all
 characters in <em>set</em>.
 A range of characters can be specified by
 separating the end characters of the range,
-in ascending order, with a '<code>-</code>',
+in ascending order, with a '<code>-</code>'.
 All classes <code>%</code><em>x</em> described above can also be used as
 components in <em>set</em>.
 All other characters in <em>set</em> represent themselves.
@@ -8211,6 +8602,14 @@ the lowercase letters plus the '<code>-</code>' character.
 
 
 <p>
+You can put a closing square bracket in a set
+by positioning it as the first character in the set.
+You can put an hyphen in a set
+by positioning it as the first or the last character in the set.
+(You can also use an escape for both cases.)
+
+
+<p>
 The interaction between ranges and classes is not defined.
 Therefore, patterns like <code>[%a-z]</code> or <code>[a-%%]</code>
 have no meaning.
@@ -8248,26 +8647,27 @@ which matches any single character in the class;
 
 <li>
 a single character class followed by '<code>*</code>',
-which matches 0 or more repetitions of characters in the class.
+which matches zero or more repetitions of characters in the class.
 These repetition items will always match the longest possible sequence;
 </li>
 
 <li>
 a single character class followed by '<code>+</code>',
-which matches 1 or more repetitions of characters in the class.
+which matches one or more repetitions of characters in the class.
 These repetition items will always match the longest possible sequence;
 </li>
 
 <li>
 a single character class followed by '<code>-</code>',
-which also matches 0 or more repetitions of characters in the class.
+which also matches zero or more repetitions of characters in the class.
 Unlike '<code>*</code>',
 these repetition items will always match the shortest possible sequence;
 </li>
 
 <li>
 a single character class followed by '<code>?</code>',
-which matches 0 or 1 occurrence of a character in the class;
+which matches zero or one occurrence of a character in the class.
+It always matches one occurrence if possible;
 </li>
 
 <li>
@@ -8340,688 +8740,669 @@ string <code>"flaaap"</code>, there will be two captures: 3&nbsp;and&nbsp;5.
 
 
 
+<h3>6.4.2 &ndash; <a name="6.4.2">Format Strings for Pack and Unpack</a></h3>
 
+<p>
+The first argument to <a href="#pdf-string.pack"><code>string.pack</code></a>,
+<a href="#pdf-string.packsize"><code>string.packsize</code></a>, and <a href="#pdf-string.unpack"><code>string.unpack</code></a>
+is a format string,
+which describes the layout of the structure being created or read.
 
 
-
-<h2>6.5 &ndash; <a name="6.5">Table Manipulation</a></h2>
-
 <p>
-This library provides generic functions for table manipulation.
-It provides all its functions inside the table <a name="pdf-table"><code>table</code></a>.
+A format string is a sequence of conversion options.
+The conversion options are as follows:
+
+<ul>
+<li><b><code>&lt;</code>: </b>sets little endian</li>
+<li><b><code>&gt;</code>: </b>sets big endian</li>
+<li><b><code>=</code>: </b>sets native endian</li>
+<li><b><code>![<em>n</em>]</code>: </b>sets maximum alignment to <code>n</code>
+(default is native alignment)</li>
+<li><b><code>b</code>: </b>a signed byte (<code>char</code>)</li>
+<li><b><code>B</code>: </b>an unsigned byte (<code>char</code>)</li>
+<li><b><code>h</code>: </b>a signed <code>short</code> (native size)</li>
+<li><b><code>H</code>: </b>an unsigned <code>short</code> (native size)</li>
+<li><b><code>l</code>: </b>a signed <code>long</code> (native size)</li>
+<li><b><code>L</code>: </b>an unsigned <code>long</code> (native size)</li>
+<li><b><code>j</code>: </b>a <code>lua_Integer</code></li>
+<li><b><code>J</code>: </b>a <code>lua_Unsigned</code></li>
+<li><b><code>T</code>: </b>a <code>size_t</code> (native size)</li>
+<li><b><code>i[<em>n</em>]</code>: </b>a signed <code>int</code> with <code>n</code> bytes
+(default is native size)</li>
+<li><b><code>I[<em>n</em>]</code>: </b>an unsigned <code>int</code> with <code>n</code> bytes
+(default is native size)</li>
+<li><b><code>f</code>: </b>a <code>float</code> (native size)</li>
+<li><b><code>d</code>: </b>a <code>double</code> (native size)</li>
+<li><b><code>n</code>: </b>a <code>lua_Number</code></li>
+<li><b><code>c<em>n</em></code>: </b>a fixed-sized string with <code>n</code> bytes</li>
+<li><b><code>z</code>: </b>a zero-terminated string</li>
+<li><b><code>s[<em>n</em>]</code>: </b>a string preceded by its length
+coded as an unsigned integer with <code>n</code> bytes
+(default is a <code>size_t</code>)</li>
+<li><b><code>x</code>: </b>one byte of padding</li>
+<li><b><code>X<em>op</em></code>: </b>an empty item that aligns
+according to option <code>op</code>
+(which is otherwise ignored)</li>
+<li><b>'<code> </code>': </b>(empty space) ignored</li>
+</ul><p>
+(A "<code>[<em>n</em>]</code>" means an optional integral numeral.)
+Except for padding, spaces, and configurations
+(options "<code>xX &lt;=&gt;!</code>"),
+each option corresponds to an argument (in <a href="#pdf-string.pack"><code>string.pack</code></a>)
+or a result (in <a href="#pdf-string.unpack"><code>string.unpack</code></a>).
 
 
 <p>
-Remember that, whenever an operation needs the length of a table,
-the table should be a proper sequence
-or have a <code>__len</code> metamethod (see <a href="#3.4.6">&sect;3.4.6</a>).
-All functions ignore non-numeric keys
-in tables given as arguments.
+For options "<code>!<em>n</em></code>", "<code>s<em>n</em></code>", "<code>i<em>n</em></code>", and "<code>I<em>n</em></code>",
+<code>n</code> can be any integer between 1 and 16.
+All integral options check overflows;
+<a href="#pdf-string.pack"><code>string.pack</code></a> checks whether the given value fits in the given size;
+<a href="#pdf-string.unpack"><code>string.unpack</code></a> checks whether the read value fits in a Lua integer.
 
 
 <p>
-For performance reasons,
-all table accesses (get/set) performed by these functions are raw.
+Any format string starts as if prefixed by "<code>!1=</code>",
+that is,
+with maximum alignment of 1 (no alignment)
+and native endianness.
 
 
 <p>
-<hr><h3><a name="pdf-table.concat"><code>table.concat (list [, sep [, i [, j]]])</code></a></h3>
+Alignment works as follows:
+For each option,
+the format gets extra padding until the data starts
+at an offset that is a multiple of the minimum between the
+option size and the maximum alignment;
+this minimum must be a power of 2.
+Options "<code>c</code>" and "<code>z</code>" are not aligned;
+option "<code>s</code>" follows the alignment of its starting integer.
 
 
 <p>
-Given a list where all elements are strings or numbers,
-returns the string <code>list[i]..sep..list[i+1] &middot;&middot;&middot; sep..list[j]</code>.
-The default value for <code>sep</code> is the empty string,
-the default for <code>i</code> is 1,
-and the default for <code>j</code> is <code>#list</code>.
-If <code>i</code> is greater than <code>j</code>, returns the empty string.
+All padding is filled with zeros by <a href="#pdf-string.pack"><code>string.pack</code></a>
+(and ignored by <a href="#pdf-string.unpack"><code>string.unpack</code></a>).
 
 
 
 
-<p>
-<hr><h3><a name="pdf-table.insert"><code>table.insert (list, [pos,] value)</code></a></h3>
 
 
-<p>
-Inserts element <code>value</code> at position <code>pos</code> in <code>list</code>,
-shifting up the elements
-<code>list[pos], list[pos+1], &middot;&middot;&middot;, list[#list]</code>.
-The default value for <code>pos</code> is <code>#list+1</code>,
-so that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end
-of list <code>t</code>.
 
+<h2>6.5 &ndash; <a name="6.5">UTF-8 Support</a></h2>
 
+<p>
+This library provides basic support for UTF-8 encoding.
+It provides all its functions inside the table <a name="pdf-utf8"><code>utf8</code></a>.
+This library does not provide any support for Unicode other
+than the handling of the encoding.
+Any operation that needs the meaning of a character,
+such as character classification, is outside its scope.
 
 
 <p>
-<hr><h3><a name="pdf-table.pack"><code>table.pack (&middot;&middot;&middot;)</code></a></h3>
+Unless stated otherwise,
+all functions that expect a byte position as a parameter
+assume that the given position is either the start of a byte sequence
+or one plus the length of the subject string.
+As in the string library,
+negative indices count from the end of the string.
 
 
 <p>
-Returns a new table with all parameters stored into keys 1, 2, etc.
-and with a field "<code>n</code>" with the total number of parameters.
-Note that the resulting table may not be a sequence.
+<hr><h3><a name="pdf-utf8.char"><code>utf8.char (&middot;&middot;&middot;)</code></a></h3>
+Receives zero or more integers,
+converts each one to its corresponding UTF-8 byte sequence
+and returns a string with the concatenation of all these sequences.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-table.remove"><code>table.remove (list [, pos])</code></a></h3>
+<hr><h3><a name="pdf-utf8.charpattern"><code>utf8.charpattern</code></a></h3>
+The pattern (a string, not a function) "<code>[\0-\x7F\xC2-\xF4][\x80-\xBF]*</code>"
+(see <a href="#6.4.1">&sect;6.4.1</a>),
+which matches exactly one UTF-8 byte sequence,
+assuming that the subject is a valid UTF-8 string.
+
+
 
 
 <p>
-Removes from <code>list</code> the element at position <code>pos</code>,
-returning the value of the removed element.
-When <code>pos</code> is an integer between 1 and <code>#list</code>,
-it shifts down the elements
-<code>list[pos+1], list[pos+2], &middot;&middot;&middot;, list[#list]</code>
-and erases element <code>list[#list]</code>;
-The index <code>pos</code> can also be 0 when <code>#list</code> is 0,
-or <code>#list + 1</code>;
-in those cases, the function erases the element <code>list[pos]</code>.
+<hr><h3><a name="pdf-utf8.codes"><code>utf8.codes (s)</code></a></h3>
 
 
 <p>
-The default value for <code>pos</code> is <code>#list</code>,
-so that a call <code>table.remove(t)</code> removes the last element
-of list <code>t</code>.
+Returns values so that the construction
+
+<pre>
+     for p, c in utf8.codes(s) do <em>body</em> end
+</pre><p>
+will iterate over all characters in string <code>s</code>,
+with <code>p</code> being the position (in bytes) and <code>c</code> the code point
+of each character.
+It raises an error if it meets any invalid byte sequence.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-table.sort"><code>table.sort (list [, comp])</code></a></h3>
+<hr><h3><a name="pdf-utf8.codepoint"><code>utf8.codepoint (s [, i [, j]])</code></a></h3>
+Returns the codepoints (as integers) from all characters in <code>s</code>
+that start between byte position <code>i</code> and <code>j</code> (both included).
+The default for <code>i</code> is 1 and for <code>j</code> is <code>i</code>.
+It raises an error if it meets any invalid byte sequence.
 
 
-<p>
-Sorts list elements in a given order, <em>in-place</em>,
-from <code>list[1]</code> to <code>list[#list]</code>.
-If <code>comp</code> is given,
-then it must be a function that receives two list elements
-and returns true when the first element must come
-before the second in the final order
-(so that <code>not comp(list[i+1],list[i])</code> will be true after the sort).
-If <code>comp</code> is not given,
-then the standard Lua operator <code>&lt;</code> is used instead.
 
 
 <p>
-The sort algorithm is not stable;
-that is, elements considered equal by the given order
-may have their relative positions changed by the sort.
+<hr><h3><a name="pdf-utf8.len"><code>utf8.len (s [, i [, j]])</code></a></h3>
+Returns the number of UTF-8 characters in string <code>s</code>
+that start between positions <code>i</code> and <code>j</code> (both inclusive).
+The default for <code>i</code> is 1 and for <code>j</code> is -1.
+If it finds any invalid byte sequence,
+returns a false value plus the position of the first invalid byte. 
 
 
 
 
 <p>
-<hr><h3><a name="pdf-table.unpack"><code>table.unpack (list [, i [, j]])</code></a></h3>
+<hr><h3><a name="pdf-utf8.offset"><code>utf8.offset (s, n [, i])</code></a></h3>
+Returns the position (in bytes) where the encoding of the
+<code>n</code>-th character of <code>s</code>
+(counting from position <code>i</code>) starts.
+A negative <code>n</code> gets characters before position <code>i</code>.
+The default for <code>i</code> is 1 when <code>n</code> is non-negative
+and <code>#s + 1</code> otherwise,
+so that <code>utf8.offset(s, -n)</code> gets the offset of the
+<code>n</code>-th character from the end of the string.
+If the specified character is neither in the subject
+nor right after its end,
+the function returns <b>nil</b>.
 
 
 <p>
-Returns the elements from the given table.
-This function is equivalent to
+As a special case,
+when <code>n</code> is 0 the function returns the start of the encoding
+of the character that contains the <code>i</code>-th byte of <code>s</code>.
 
-<pre>
-     return list[i], list[i+1], &middot;&middot;&middot;, list[j]
-</pre><p>
-By default, <code>i</code> is&nbsp;1 and <code>j</code> is <code>#list</code>.
-
-
-
-
-
-
-
-<h2>6.6 &ndash; <a name="6.6">Mathematical Functions</a></h2>
 
 <p>
-This library is an interface to the standard C&nbsp;math library.
-It provides all its functions inside the table <a name="pdf-math"><code>math</code></a>.
+This function assumes that <code>s</code> is a valid UTF-8 string.
 
 
-<p>
-<hr><h3><a name="pdf-math.abs"><code>math.abs (x)</code></a></h3>
 
 
-<p>
-Returns the absolute value of <code>x</code>.
 
 
 
+<h2>6.6 &ndash; <a name="6.6">Table Manipulation</a></h2>
 
 <p>
-<hr><h3><a name="pdf-math.acos"><code>math.acos (x)</code></a></h3>
+This library provides generic functions for table manipulation.
+It provides all its functions inside the table <a name="pdf-table"><code>table</code></a>.
 
 
 <p>
-Returns the arc cosine of <code>x</code> (in radians).
-
-
+Remember that, whenever an operation needs the length of a table,
+the table must be a proper sequence
+or have a <code>__len</code> metamethod (see <a href="#3.4.7">&sect;3.4.7</a>).
+All functions ignore non-numeric keys
+in the tables given as arguments.
 
 
 <p>
-<hr><h3><a name="pdf-math.asin"><code>math.asin (x)</code></a></h3>
+<hr><h3><a name="pdf-table.concat"><code>table.concat (list [, sep [, i [, j]]])</code></a></h3>
 
 
 <p>
-Returns the arc sine of <code>x</code> (in radians).
+Given a list where all elements are strings or numbers,
+returns the string <code>list[i]..sep..list[i+1] &middot;&middot;&middot; sep..list[j]</code>.
+The default value for <code>sep</code> is the empty string,
+the default for <code>i</code> is 1,
+and the default for <code>j</code> is <code>#list</code>.
+If <code>i</code> is greater than <code>j</code>, returns the empty string.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.atan"><code>math.atan (x)</code></a></h3>
+<hr><h3><a name="pdf-table.insert"><code>table.insert (list, [pos,] value)</code></a></h3>
 
 
 <p>
-Returns the arc tangent of <code>x</code> (in radians).
+Inserts element <code>value</code> at position <code>pos</code> in <code>list</code>,
+shifting up the elements
+<code>list[pos], list[pos+1], &middot;&middot;&middot;, list[#list]</code>.
+The default value for <code>pos</code> is <code>#list+1</code>,
+so that a call <code>table.insert(t,x)</code> inserts <code>x</code> at the end
+of list <code>t</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.atan2"><code>math.atan2 (y, x)</code></a></h3>
+<hr><h3><a name="pdf-table.move"><code>table.move (a1, f, e, t [,a2])</code></a></h3>
 
 
 <p>
-Returns the arc tangent of <code>y/x</code> (in radians),
-but uses the signs of both parameters to find the
-quadrant of the result.
-(It also handles correctly the case of <code>x</code> being zero.)
-
-
+Moves elements from table <code>a1</code> to table <code>a2</code>,
+performing the equivalent to the following
+multiple assignment:
+<code>a2[t],&middot;&middot;&middot; = a1[f],&middot;&middot;&middot;,a1[e]</code>.
+The default for <code>a2</code> is <code>a1</code>.
+The destination range can overlap with the source range.
+The number of elements to be moved must fit in a Lua integer.
 
 
 <p>
-<hr><h3><a name="pdf-math.ceil"><code>math.ceil (x)</code></a></h3>
-
-
-<p>
-Returns the smallest integer larger than or equal to <code>x</code>.
+Returns the destination table <code>a2</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.cos"><code>math.cos (x)</code></a></h3>
+<hr><h3><a name="pdf-table.pack"><code>table.pack (&middot;&middot;&middot;)</code></a></h3>
 
 
 <p>
-Returns the cosine of <code>x</code> (assumed to be in radians).
-
-
+Returns a new table with all parameters stored into keys 1, 2, etc.
+and with a field "<code>n</code>" with the total number of parameters.
+Note that the resulting table may not be a sequence.
 
 
-<p>
-<hr><h3><a name="pdf-math.cosh"><code>math.cosh (x)</code></a></h3>
 
 
 <p>
-Returns the hyperbolic cosine of <code>x</code>.
-
-
+<hr><h3><a name="pdf-table.remove"><code>table.remove (list [, pos])</code></a></h3>
 
 
 <p>
-<hr><h3><a name="pdf-math.deg"><code>math.deg (x)</code></a></h3>
+Removes from <code>list</code> the element at position <code>pos</code>,
+returning the value of the removed element.
+When <code>pos</code> is an integer between 1 and <code>#list</code>,
+it shifts down the elements
+<code>list[pos+1], list[pos+2], &middot;&middot;&middot;, list[#list]</code>
+and erases element <code>list[#list]</code>;
+The index <code>pos</code> can also be 0 when <code>#list</code> is 0,
+or <code>#list + 1</code>;
+in those cases, the function erases the element <code>list[pos]</code>.
 
 
 <p>
-Returns the angle <code>x</code> (given in radians) in degrees.
+The default value for <code>pos</code> is <code>#list</code>,
+so that a call <code>table.remove(l)</code> removes the last element
+of list <code>l</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.exp"><code>math.exp (x)</code></a></h3>
+<hr><h3><a name="pdf-table.sort"><code>table.sort (list [, comp])</code></a></h3>
 
 
 <p>
-Returns the value <em>e<sup>x</sup></em>.
-
-
+Sorts list elements in a given order, <em>in-place</em>,
+from <code>list[1]</code> to <code>list[#list]</code>.
+If <code>comp</code> is given,
+then it must be a function that receives two list elements
+and returns true when the first element must come
+before the second in the final order
+(so that, after the sort,
+<code>i &lt; j</code> implies <code>not comp(list[j],list[i])</code>).
+If <code>comp</code> is not given,
+then the standard Lua operator <code>&lt;</code> is used instead.
 
 
 <p>
-<hr><h3><a name="pdf-math.floor"><code>math.floor (x)</code></a></h3>
+Note that the <code>comp</code> function must define
+a strict partial order over the elements in the list;
+that is, it must be asymmetric and transitive.
+Otherwise, no valid sort may be possible.
 
 
 <p>
-Returns the largest integer smaller than or equal to <code>x</code>.
+The sort algorithm is not stable;
+that is, elements not comparable by the given order
+(e.g., equal elements)
+may have their relative positions changed by the sort.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.fmod"><code>math.fmod (x, y)</code></a></h3>
+<hr><h3><a name="pdf-table.unpack"><code>table.unpack (list [, i [, j]])</code></a></h3>
 
 
 <p>
-Returns the remainder of the division of <code>x</code> by <code>y</code>
-that rounds the quotient towards zero.
-
-
-
+Returns the elements from the given list.
+This function is equivalent to
 
-<p>
-<hr><h3><a name="pdf-math.frexp"><code>math.frexp (x)</code></a></h3>
+<pre>
+     return list[i], list[i+1], &middot;&middot;&middot;, list[j]
+</pre><p>
+By default, <code>i</code> is&nbsp;1 and <code>j</code> is <code>#list</code>.
 
 
-<p>
-Returns <code>m</code> and <code>e</code> such that <em>x = m2<sup>e</sup></em>,
-<code>e</code> is an integer and the absolute value of <code>m</code> is
-in the range <em>[0.5, 1)</em>
-(or zero when <code>x</code> is zero).
 
 
 
 
-<p>
-<hr><h3><a name="pdf-math.huge"><code>math.huge</code></a></h3>
 
+<h2>6.7 &ndash; <a name="6.7">Mathematical Functions</a></h2>
 
 <p>
-The value <code>HUGE_VAL</code>,
-a value larger than or equal to any other numerical value.
-
-
+This library provides basic mathematical functions.
+It provides all its functions and constants inside the table <a name="pdf-math"><code>math</code></a>.
+Functions with the annotation "<code>integer/float</code>" give
+integer results for integer arguments
+and float results for float (or mixed) arguments.
+Rounding functions
+(<a href="#pdf-math.ceil"><code>math.ceil</code></a>, <a href="#pdf-math.floor"><code>math.floor</code></a>, and <a href="#pdf-math.modf"><code>math.modf</code></a>)
+return an integer when the result fits in the range of an integer,
+or a float otherwise.
 
 
 <p>
-<hr><h3><a name="pdf-math.ldexp"><code>math.ldexp (m, e)</code></a></h3>
+<hr><h3><a name="pdf-math.abs"><code>math.abs (x)</code></a></h3>
 
 
 <p>
-Returns <em>m2<sup>e</sup></em> (<code>e</code> should be an integer).
+Returns the absolute value of <code>x</code>. (integer/float)
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.log"><code>math.log (x [, base])</code></a></h3>
+<hr><h3><a name="pdf-math.acos"><code>math.acos (x)</code></a></h3>
 
 
 <p>
-Returns the logarithm of <code>x</code> in the given base.
-The default for <code>base</code> is <em>e</em>
-(so that the function returns the natural logarithm of <code>x</code>).
+Returns the arc cosine of <code>x</code> (in radians).
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.max"><code>math.max (x, &middot;&middot;&middot;)</code></a></h3>
+<hr><h3><a name="pdf-math.asin"><code>math.asin (x)</code></a></h3>
 
 
 <p>
-Returns the maximum value among its arguments.
+Returns the arc sine of <code>x</code> (in radians).
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.min"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>
+<hr><h3><a name="pdf-math.atan"><code>math.atan (y [, x])</code></a></h3>
 
 
 <p>
-Returns the minimum value among its arguments.
-
-
 
-
-<p>
-<hr><h3><a name="pdf-math.modf"><code>math.modf (x)</code></a></h3>
+Returns the arc tangent of <code>y/x</code> (in radians),
+but uses the signs of both parameters to find the
+quadrant of the result.
+(It also handles correctly the case of <code>x</code> being zero.)
 
 
 <p>
-Returns two numbers,
-the integral part of <code>x</code> and the fractional part of <code>x</code>.
+The default value for <code>x</code> is 1,
+so that the call <code>math.atan(y)</code>
+returns the arc tangent of <code>y</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.pi"><code>math.pi</code></a></h3>
+<hr><h3><a name="pdf-math.ceil"><code>math.ceil (x)</code></a></h3>
 
 
 <p>
-The value of <em>&pi;</em>.
+Returns the smallest integral value larger than or equal to <code>x</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.pow"><code>math.pow (x, y)</code></a></h3>
+<hr><h3><a name="pdf-math.cos"><code>math.cos (x)</code></a></h3>
 
 
 <p>
-Returns <em>x<sup>y</sup></em>.
-(You can also use the expression <code>x^y</code> to compute this value.)
+Returns the cosine of <code>x</code> (assumed to be in radians).
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.rad"><code>math.rad (x)</code></a></h3>
+<hr><h3><a name="pdf-math.deg"><code>math.deg (x)</code></a></h3>
 
 
 <p>
-Returns the angle <code>x</code> (given in degrees) in radians.
-
+Converts the angle <code>x</code> from radians to degrees.
 
 
 
-<p>
-<hr><h3><a name="pdf-math.random"><code>math.random ([m [, n]])</code></a></h3>
-
 
 <p>
-This function is an interface to the simple
-pseudo-random generator function <code>rand</code> provided by Standard&nbsp;C.
-(No guarantees can be given for its statistical properties.)
+<hr><h3><a name="pdf-math.exp"><code>math.exp (x)</code></a></h3>
 
 
 <p>
-When called without arguments,
-returns a uniform pseudo-random real number
-in the range <em>[0,1)</em>.  
-When called with an integer number <code>m</code>,
-<code>math.random</code> returns
-a uniform pseudo-random integer in the range <em>[1, m]</em>.
-When called with two integer numbers <code>m</code> and <code>n</code>,
-<code>math.random</code> returns a uniform pseudo-random
-integer in the range <em>[m, n]</em>.
+Returns the value <em>e<sup>x</sup></em>
+(where <code>e</code> is the base of natural logarithms).
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x)</code></a></h3>
+<hr><h3><a name="pdf-math.floor"><code>math.floor (x)</code></a></h3>
 
 
 <p>
-Sets <code>x</code> as the "seed"
-for the pseudo-random generator:
-equal seeds produce equal sequences of numbers.
+Returns the largest integral value smaller than or equal to <code>x</code>.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.sin"><code>math.sin (x)</code></a></h3>
+<hr><h3><a name="pdf-math.fmod"><code>math.fmod (x, y)</code></a></h3>
 
 
 <p>
-Returns the sine of <code>x</code> (assumed to be in radians).
+Returns the remainder of the division of <code>x</code> by <code>y</code>
+that rounds the quotient towards zero. (integer/float)
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.sinh"><code>math.sinh (x)</code></a></h3>
+<hr><h3><a name="pdf-math.huge"><code>math.huge</code></a></h3>
 
 
 <p>
-Returns the hyperbolic sine of <code>x</code>.
+The float value <code>HUGE_VAL</code>,
+a value larger than any other numeric value.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.sqrt"><code>math.sqrt (x)</code></a></h3>
+<hr><h3><a name="pdf-math.log"><code>math.log (x [, base])</code></a></h3>
 
 
 <p>
-Returns the square root of <code>x</code>.
-(You can also use the expression <code>x^0.5</code> to compute this value.)
+Returns the logarithm of <code>x</code> in the given base.
+The default for <code>base</code> is <em>e</em>
+(so that the function returns the natural logarithm of <code>x</code>).
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.tan"><code>math.tan (x)</code></a></h3>
+<hr><h3><a name="pdf-math.max"><code>math.max (x, &middot;&middot;&middot;)</code></a></h3>
 
 
 <p>
-Returns the tangent of <code>x</code> (assumed to be in radians).
-
+Returns the argument with the maximum value,
+according to the Lua operator <code>&lt;</code>. (integer/float)
 
 
 
-<p>
-<hr><h3><a name="pdf-math.tanh"><code>math.tanh (x)</code></a></h3>
-
 
 <p>
-Returns the hyperbolic tangent of <code>x</code>.
+<hr><h3><a name="pdf-math.maxinteger"><code>math.maxinteger</code></a></h3>
+An integer with the maximum value for an integer.
 
 
 
 
-
-
-
-<h2>6.7 &ndash; <a name="6.7">Bitwise Operations</a></h2>
-
 <p>
-This library provides bitwise operations.
-It provides all its functions inside the table <a name="pdf-bit32"><code>bit32</code></a>.
+<hr><h3><a name="pdf-math.min"><code>math.min (x, &middot;&middot;&middot;)</code></a></h3>
 
 
 <p>
-Unless otherwise stated,
-all functions accept numeric arguments in the range
-<em>(-2<sup>51</sup>,+2<sup>51</sup>)</em>;
-each argument is normalized to
-the remainder of its division by <em>2<sup>32</sup></em>
-and truncated to an integer (in some unspecified way),
-so that its final value falls in the range <em>[0,2<sup>32</sup> - 1]</em>.
-Similarly, all results are in the range <em>[0,2<sup>32</sup> - 1]</em>.
-Note that <code>bit32.bnot(0)</code> is <code>0xFFFFFFFF</code>,
-which is different from <code>-1</code>.
+Returns the argument with the minimum value,
+according to the Lua operator <code>&lt;</code>. (integer/float)
 
 
-<p>
-<hr><h3><a name="pdf-bit32.arshift"><code>bit32.arshift (x, disp)</code></a></h3>
 
 
 <p>
-Returns the number <code>x</code> shifted <code>disp</code> bits to the right.
-The number <code>disp</code> may be any representable integer.
-Negative displacements shift to the left.
-
-
-<p>
-This shift operation is what is called arithmetic shift.
-Vacant bits on the left are filled
-with copies of the higher bit of <code>x</code>;
-vacant bits on the right are filled with zeros.
-In particular,
-displacements with absolute values higher than 31
-result in zero or <code>0xFFFFFFFF</code> (all original bits are shifted out).
+<hr><h3><a name="pdf-math.mininteger"><code>math.mininteger</code></a></h3>
+An integer with the minimum value for an integer.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-bit32.band"><code>bit32.band (&middot;&middot;&middot;)</code></a></h3>
+<hr><h3><a name="pdf-math.modf"><code>math.modf (x)</code></a></h3>
 
 
 <p>
-Returns the bitwise <em>and</em> of its operands.
+Returns the integral part of <code>x</code> and the fractional part of <code>x</code>.
+Its second result is always a float.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-bit32.bnot"><code>bit32.bnot (x)</code></a></h3>
+<hr><h3><a name="pdf-math.pi"><code>math.pi</code></a></h3>
 
 
 <p>
-Returns the bitwise negation of <code>x</code>.
-For any integer <code>x</code>,
-the following identity holds:
+The value of <em>&pi;</em>.
 
-<pre>
-     assert(bit32.bnot(x) == (-1 - x) % 2^32)
-</pre>
 
 
 
 <p>
-<hr><h3><a name="pdf-bit32.bor"><code>bit32.bor (&middot;&middot;&middot;)</code></a></h3>
+<hr><h3><a name="pdf-math.rad"><code>math.rad (x)</code></a></h3>
 
 
 <p>
-Returns the bitwise <em>or</em> of its operands.
-
+Converts the angle <code>x</code> from degrees to radians.
 
 
 
-<p>
-<hr><h3><a name="pdf-bit32.btest"><code>bit32.btest (&middot;&middot;&middot;)</code></a></h3>
-
 
 <p>
-Returns a boolean signaling
-whether the bitwise <em>and</em> of its operands is different from zero.
-
-
+<hr><h3><a name="pdf-math.random"><code>math.random ([m [, n]])</code></a></h3>
 
 
 <p>
-<hr><h3><a name="pdf-bit32.bxor"><code>bit32.bxor (&middot;&middot;&middot;)</code></a></h3>
+When called without arguments,
+returns a pseudo-random float with uniform distribution
+in the range  <em>[0,1)</em>.  
+When called with two integers <code>m</code> and <code>n</code>,
+<code>math.random</code> returns a pseudo-random integer
+with uniform distribution in the range <em>[m, n]</em>.
+(The value <em>n-m</em> cannot be negative and must fit in a Lua integer.)
+The call <code>math.random(n)</code> is equivalent to <code>math.random(1,n)</code>.
 
 
 <p>
-Returns the bitwise <em>exclusive or</em> of its operands.
-
+This function is an interface to the underling
+pseudo-random generator function provided by C.
 
 
 
-<p>
-<hr><h3><a name="pdf-bit32.extract"><code>bit32.extract (n, field [, width])</code></a></h3>
-
 
 <p>
-Returns the unsigned number formed by the bits
-<code>field</code> to <code>field + width - 1</code> from <code>n</code>.
-Bits are numbered from 0 (least significant) to 31 (most significant).
-All accessed bits must be in the range <em>[0, 31]</em>.
+<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x)</code></a></h3>
 
 
 <p>
-The default for <code>width</code> is 1.
+Sets <code>x</code> as the "seed"
+for the pseudo-random generator:
+equal seeds produce equal sequences of numbers.
 
 
 
 
 <p>
-<hr><h3><a name="pdf-bit32.replace"><code>bit32.replace (n, v, field [, width])</code></a></h3>
+<hr><h3><a name="pdf-math.sin"><code>math.sin (x)</code></a></h3>
 
 
 <p>
-Returns a copy of <code>n</code> with
-the bits <code>field</code> to <code>field + width - 1</code>
-replaced by the value <code>v</code>.
-See <a href="#pdf-bit32.extract"><code>bit32.extract</code></a> for details about <code>field</code> and <code>width</code>.
-
-
+Returns the sine of <code>x</code> (assumed to be in radians).
 
 
-<p>
-<hr><h3><a name="pdf-bit32.lrotate"><code>bit32.lrotate (x, disp)</code></a></h3>
 
 
 <p>
-Returns the number <code>x</code> rotated <code>disp</code> bits to the left.
-The number <code>disp</code> may be any representable integer.
+<hr><h3><a name="pdf-math.sqrt"><code>math.sqrt (x)</code></a></h3>
 
 
 <p>
-For any valid displacement,
-the following identity holds:
-
-<pre>
-     assert(bit32.lrotate(x, disp) == bit32.lrotate(x, disp % 32))
-</pre><p>
-In particular,
-negative displacements rotate to the right.
-
-
+Returns the square root of <code>x</code>.
+(You can also use the expression <code>x^0.5</code> to compute this value.)
 
 
-<p>
-<hr><h3><a name="pdf-bit32.lshift"><code>bit32.lshift (x, disp)</code></a></h3>
 
 
 <p>
-Returns the number <code>x</code> shifted <code>disp</code> bits to the left.
-The number <code>disp</code> may be any representable integer.
-Negative displacements shift to the right.
-In any direction, vacant bits are filled with zeros.
-In particular,
-displacements with absolute values higher than 31
-result in zero (all bits are shifted out).
+<hr><h3><a name="pdf-math.tan"><code>math.tan (x)</code></a></h3>
 
 
 <p>
-For positive displacements,
-the following equality holds:
+Returns the tangent of <code>x</code> (assumed to be in radians).
 
-<pre>
-     assert(bit32.lshift(b, disp) == (b * 2^disp) % 2^32)
-</pre>
 
 
 
 <p>
-<hr><h3><a name="pdf-bit32.rrotate"><code>bit32.rrotate (x, disp)</code></a></h3>
+<hr><h3><a name="pdf-math.tointeger"><code>math.tointeger (x)</code></a></h3>
 
 
 <p>
-Returns the number <code>x</code> rotated <code>disp</code> bits to the right.
-The number <code>disp</code> may be any representable integer.
-
+If the value <code>x</code> is convertible to an integer,
+returns that integer.
+Otherwise, returns <b>nil</b>.
 
-<p>
-For any valid displacement,
-the following identity holds:
 
-<pre>
-     assert(bit32.rrotate(x, disp) == bit32.rrotate(x, disp % 32))
-</pre><p>
-In particular,
-negative displacements rotate to the left.
 
 
+<p>
+<hr><h3><a name="pdf-math.type"><code>math.type (x)</code></a></h3>
 
 
 <p>
-<hr><h3><a name="pdf-bit32.rshift"><code>bit32.rshift (x, disp)</code></a></h3>
+Returns "<code>integer</code>" if <code>x</code> is an integer,
+"<code>float</code>" if it is a float,
+or <b>nil</b> if <code>x</code> is not a number.
 
 
-<p>
-Returns the number <code>x</code> shifted <code>disp</code> bits to the right.
-The number <code>disp</code> may be any representable integer.
-Negative displacements shift to the left.
-In any direction, vacant bits are filled with zeros.
-In particular,
-displacements with absolute values higher than 31
-result in zero (all bits are shifted out).
 
 
 <p>
-For positive displacements,
-the following equality holds:
+<hr><h3><a name="pdf-math.ult"><code>math.ult (m, n)</code></a></h3>
 
-<pre>
-     assert(bit32.rshift(b, disp) == math.floor(b % 2^32 / 2^disp))
-</pre>
 
 <p>
-This shift operation is what is called logical shift.
+Returns a boolean,
+true if integer <code>m</code> is below integer <code>n</code> when
+they are compared as unsigned integers.
 
 
 
@@ -9033,24 +9414,24 @@ This shift operation is what is called logical shift.
 
 <p>
 The I/O library provides two different styles for file manipulation.
-The first one uses implicit file descriptors;
+The first one uses implicit file handles;
 that is, there are operations to set a default input file and a
 default output file,
 and all input/output operations are over these default files.
-The second style uses explicit file descriptors.
+The second style uses explicit file handles.
 
 
 <p>
-When using implicit file descriptors,
+When using implicit file handles,
 all operations are supplied by table <a name="pdf-io"><code>io</code></a>.
-When using explicit file descriptors,
-the operation <a href="#pdf-io.open"><code>io.open</code></a> returns a file descriptor
-and then all operations are supplied as methods of the file descriptor.
+When using explicit file handles,
+the operation <a href="#pdf-io.open"><code>io.open</code></a> returns a file handle
+and then all operations are supplied as methods of the file handle.
 
 
 <p>
 The table <code>io</code> also provides
-three predefined file descriptors with their usual meanings from C:
+three predefined file handles with their usual meanings from C:
 <a name="pdf-io.stdin"><code>io.stdin</code></a>, <a name="pdf-io.stdout"><code>io.stdout</code></a>, and <a name="pdf-io.stderr"><code>io.stderr</code></a>.
 The I/O library never closes these files.
 
@@ -9061,7 +9442,7 @@ all I/O functions return <b>nil</b> on failure
 (plus an error message as a second result and
 a system-dependent error code as a third result)
 and some value different from <b>nil</b> on success.
-On non-Posix systems,
+On non-POSIX systems,
 the computation of the error message and error code
 in case of errors
 may be not thread safe,
@@ -9110,7 +9491,7 @@ instead of returning an error code.
 
 
 <p>
-<hr><h3><a name="pdf-io.lines"><code>io.lines ([filename &middot;&middot;&middot;])</code></a></h3>
+<hr><h3><a name="pdf-io.lines"><code>io.lines ([filename, &middot;&middot;&middot;])</code></a></h3>
 
 
 <p>
@@ -9118,12 +9499,12 @@ Opens the given file name in read mode
 and returns an iterator function that
 works like <code>file:lines(&middot;&middot;&middot;)</code> over the opened file.
 When the iterator function detects the end of file,
-it returns <b>nil</b> (to finish the loop) and automatically closes the file.
+it returns no values (to finish the loop) and automatically closes the file.
 
 
 <p>
 The call <code>io.lines()</code> (with no file name) is equivalent
-to <code>io.input():lines()</code>;
+to <code>io.input():lines("*l")</code>;
 that is, it iterates over the lines of the default input file.
 In this case it does not close the file when the loop ends.
 
@@ -9142,8 +9523,8 @@ instead of returning an error code.
 <p>
 This function opens a file,
 in the mode specified in the string <code>mode</code>.
-It returns a new file handle,
-or, in case of errors, <b>nil</b> plus an error message.
+In case of success,
+it returns a new file handle.
 
 
 <p>
@@ -9208,7 +9589,8 @@ Equivalent to <code>io.input():read(&middot;&middot;&middot;)</code>.
 
 
 <p>
-Returns a handle for a temporary file.
+In case of success,
+returns a handle for a temporary file.
 This file is opened in update mode
 and it is automatically removed when the program ends.
 
@@ -9276,7 +9658,7 @@ Returns an iterator function that,
 each time it is called,
 reads the file according to the given formats.
 When no format is given,
-uses "*l" as a default.
+uses "<code>l</code>" as a default.
 As an example, the construction
 
 <pre>
@@ -9303,8 +9685,10 @@ instead of returning an error code.
 Reads the file <code>file</code>,
 according to the given formats, which specify what to read.
 For each format,
-the function returns a string (or a number) with the characters read,
+the function returns a string or a number with the characters read,
 or <b>nil</b> if it cannot read data with the specified format.
+(In this latter case,
+the function does not read subsequent formats.)
 When called without formats,
 it uses a default format that reads the next line
 (see below).
@@ -9315,36 +9699,44 @@ The available formats are
 
 <ul>
 
-<li><b>"<code>*n</code>": </b>
-reads a number;
-this is the only format that returns a number instead of a string.
+<li><b>"<code>n</code>": </b>
+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 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>*a</code>": </b>
+<li><b>"<code>a</code>": </b>
 reads the whole file, starting at the current position.
 On end of file, it returns the empty string.
 </li>
 
-<li><b>"<code>*l</code>": </b>
+<li><b>"<code>l</code>": </b>
 reads the next line skipping the end of line,
 returning <b>nil</b> on end of file.
 This is the default format.
 </li>
 
-<li><b>"<code>*L</code>": </b>
-reads the next line keeping the end of line (if present),
+<li><b>"<code>L</code>": </b>
+reads the next line keeping the end-of-line character (if present),
 returning <b>nil</b> on end of file.
 </li>
 
 <li><b><em>number</em>: </b>
 reads a string with up to this number of bytes,
 returning <b>nil</b> on end of file.
-If number is zero,
+If <code>number</code> is zero,
 it reads nothing and returns an empty string,
 or <b>nil</b> on end of file.
 </li>
 
-</ul>
+</ul><p>
+The formats "<code>l</code>" and "<code>L</code>" should be used only for text files.
+
 
 
 
@@ -9474,10 +9866,10 @@ then the date is formatted in Coordinated Universal Time.
 After this optional character,
 if <code>format</code> is the string "<code>*t</code>",
 then <code>date</code> returns a table with the following fields:
-<code>year</code> (four digits), <code>month</code> (1&ndash;12), <code>day</code> (1&ndash;31),
+<code>year</code>, <code>month</code> (1&ndash;12), <code>day</code> (1&ndash;31),
 <code>hour</code> (0&ndash;23), <code>min</code> (0&ndash;59), <code>sec</code> (0&ndash;61),
-<code>wday</code> (weekday, Sunday is&nbsp;1),
-<code>yday</code> (day of the year),
+<code>wday</code> (weekday, 1&ndash;7, Sunday is&nbsp;1),
+<code>yday</code> (day of the year, 1&ndash;366),
 and <code>isdst</code> (daylight saving flag, a boolean).
 This last field may be absent
 if the information is not available.
@@ -9492,12 +9884,12 @@ formatted according to the same rules as the ISO&nbsp;C function <code>strftime<
 <p>
 When called without arguments,
 <code>date</code> returns a reasonable date and time representation that depends on
-the host system and on the current locale
-(that is, <code>os.date()</code> is equivalent to <code>os.date("%c")</code>).
+the host system and on the current locale.
+(More specifically, <code>os.date()</code> is equivalent to <code>os.date("%c")</code>.)
 
 
 <p>
-On non-Posix systems,
+On non-POSIX systems,
 this function may be not thread safe
 because of its reliance on C&nbsp;function <code>gmtime</code> and C&nbsp;function <code>localtime</code>.
 
@@ -9509,7 +9901,9 @@ because of its reliance on C&nbsp;function <code>gmtime</code> and C&nbsp;functi
 
 
 <p>
-Returns the number of seconds from time <code>t1</code> to time <code>t2</code>.
+Returns the difference, in seconds,
+from time <code>t1</code> to time <code>t2</code>
+(where the times are values returned by <a href="#pdf-os.time"><code>os.time</code></a>).
 In POSIX, Windows, and some other systems,
 this value is exactly <code>t2</code><em>-</em><code>t1</code>.
 
@@ -9527,7 +9921,7 @@ Its first result is <b>true</b>
 if the command terminated successfully,
 or <b>nil</b> otherwise.
 After this first result
-the function returns a string and a number,
+the function returns a string plus a number,
 as follows:
 
 <ul>
@@ -9552,7 +9946,7 @@ When called without a <code>command</code>,
 
 
 <p>
-<hr><h3><a name="pdf-os.exit"><code>os.exit ([code [, close])</code></a></h3>
+<hr><h3><a name="pdf-os.exit"><code>os.exit ([code [, close]])</code></a></h3>
 
 
 <p>
@@ -9650,17 +10044,26 @@ because of its reliance on C&nbsp;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
@@ -9797,7 +10200,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
@@ -9819,7 +10222,9 @@ but also parameters, temporaries, etc.
 
 <p>
 The first parameter or local variable has index&nbsp;1, and so on,
-until the last active variable.
+following the order that they are declared in the code,
+counting only the variables that are active
+in the current scope of the function.
 Negative indices refer to vararg parameters;
 -1 is the first vararg parameter.
 The function returns <b>nil</b> if there is no variable with the given index,
@@ -9828,9 +10233,10 @@ and raises an error when called with a level out of range.
 
 
 <p>
-Variable names starting with '<code>(</code>' (open parenthesis)
-represent internal variables
-(loop control variables, temporaries, varargs, and C&nbsp;function locals).
+Variable names starting with '<code>(</code>' (open parenthesis) 
+represent variables with no known names
+(internal variables such as loop control variables,
+and variables from chunks saved without debug information).
 
 
 <p>
@@ -9871,6 +10277,12 @@ with index <code>up</code> of the function <code>f</code>.
 The function returns <b>nil</b> if there is no upvalue with the given index.
 
 
+<p>
+Variable names starting with '<code>(</code>' (open parenthesis) 
+represent variables with no known names
+(variables from chunks saved without debug information).
+
+
 
 
 <p>
@@ -9982,7 +10394,6 @@ Otherwise, it returns the name of the upvalue.
 <p>
 Sets the given <code>value</code> as
 the Lua value associated to the given <code>udata</code>.
-<code>value</code> must be a table or <b>nil</b>;
 <code>udata</code> must be a full userdata.
 
 
@@ -10001,7 +10412,7 @@ If <code>message</code> is present but is neither a string nor <b>nil</b>,
 this function returns <code>message</code> without further processing.
 Otherwise,
 it returns a string with a traceback of the call stack.
-An optional <code>message</code> string is appended
+The optional <code>message</code> string is appended
 at the beginning of the traceback.
 An optional <code>level</code> number tells at which level
 to start the traceback
@@ -10015,7 +10426,7 @@ to start the traceback
 
 
 <p>
-Returns an unique identifier (as a light userdata)
+Returns a unique identifier (as a light userdata)
 for the upvalue numbered <code>n</code>
 from the given function.
 
@@ -10071,8 +10482,7 @@ The options are:
 <li><b><code>--</code>: </b> stops handling options;</li>
 <li><b><code>-</code>: </b> executes <code>stdin</code> as a file and stops handling options.</li>
 </ul><p>
-After handling its options, <code>lua</code> runs the given <em>script</em>,
-passing to it the given <em>args</em> as string arguments.
+After handling its options, <code>lua</code> runs the given <em>script</em>.
 When called without arguments,
 <code>lua</code> behaves as <code>lua -v -i</code>
 when the standard input (<code>stdin</code>) is a terminal,
@@ -10081,8 +10491,8 @@ and as <code>lua -</code> otherwise.
 
 <p>
 When called without option <code>-E</code>, 
-the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_2"><code>LUA_INIT_5_2</code></a>
-(or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if it is not defined)
+the interpreter checks for an environment variable <a name="pdf-LUA_INIT_5_3"><code>LUA_INIT_5_3</code></a>
+(or <a name="pdf-LUA_INIT"><code>LUA_INIT</code></a> if the versioned name is not defined)
 before running any argument.
 If the variable content has the format <code>@<em>filename</em></code>,
 then <code>lua</code> executes the file.
@@ -10112,50 +10522,71 @@ and finally run the file <code>script.lua</code> with no arguments.
 
 
 <p>
-Before starting to run the script,
-<code>lua</code> collects all arguments in the command line
+Before running any code,
+<code>lua</code> collects all command-line arguments
 in a global table called <code>arg</code>.
-The script name is stored at index 0,
+The script name goes to index 0,
 the first argument after the script name goes to index 1,
 and so on.
 Any arguments before the script name
-(that is, the interpreter name plus the options)
+(that is, the interpreter name plus its options)
 go to negative indices.
 For instance, in the call
 
 <pre>
      $ lua -la b.lua t1 t2
 </pre><p>
-the interpreter first runs the file <code>a.lua</code>,
-then creates a table
+the table is like this:
 
 <pre>
      arg = { [-2] = "lua", [-1] = "-la",
              [0] = "b.lua",
              [1] = "t1", [2] = "t2" }
 </pre><p>
-and finally runs the file <code>b.lua</code>.
-The script is called with <code>arg[1]</code>, <code>arg[2]</code>, ...
-as arguments;
-it can also access these arguments with the vararg expression '<code>...</code>'.
+If there is no script in the call,
+the interpreter name goes to index 0,
+followed by the other arguments.
+For instance, the call
+
+<pre>
+     $ lua -e "print(arg[1])"
+</pre><p>
+will print "<code>-e</code>".
+If there is a script,
+the script is called with parameters
+<code>arg[1]</code>, &middot;&middot;&middot;, <code>arg[#arg]</code>.
+(Like all chunks in Lua,
+the script is compiled as a vararg function.)
 
 
 <p>
 In interactive mode,
-if you write an incomplete statement,
+Lua repeatedly prompts and waits for a line.
+After reading a line,
+Lua first try to interpret the line as an expression.
+If it succeeds, it prints its value.
+Otherwise, it interprets the line as a statement.
+If you write an incomplete statement,
 the interpreter waits for its completion
 by issuing a different prompt.
 
 
 <p>
+If the global variable <a name="pdf-_PROMPT"><code>_PROMPT</code></a> contains a string,
+then its value is used as the prompt.
+Similarly, if the global variable <a name="pdf-_PROMPT2"><code>_PROMPT2</code></a> contains a string,
+its value is used as the secondary prompt
+(issued during incomplete statements).
+
+
+<p>
 In case of unprotected errors in the script,
 the interpreter reports the error to the standard error stream.
-If the error object is a string,
-the interpreter adds a stack traceback to it.
-Otherwise, if the error object has a metamethod <code>__tostring</code>,
+If the error object is not a string but 
+has a metamethod <code>__tostring</code>,
 the interpreter calls this metamethod to produce the final message.
-Finally, if the error object is <b>nil</b>,
-the interpreter does not report the error.
+Otherwise, the interpreter converts the error object to a string
+and adds a stack traceback to it.
 
 
 <p>
@@ -10194,67 +10625,80 @@ is a more portable solution.)
 
 <p>
 Here we list the incompatibilities that you may find when moving a program
-from Lua&nbsp;5.1 to Lua&nbsp;5.2.
+from Lua&nbsp;5.2 to Lua&nbsp;5.3.
 You can avoid some incompatibilities by compiling Lua with
 appropriate options (see file <code>luaconf.h</code>).
 However,
-all these compatibility options will be removed in the next version of Lua.
-Similarly,
-all features marked as deprecated in Lua&nbsp;5.1
-have been removed in Lua&nbsp;5.2.
+all these compatibility options will be removed in the future.
 
 
+<p>
+Lua versions can always change the C API in ways that
+do not imply source-code changes in a program,
+such as the numeric values for constants
+or the implementation of functions as macros.
+Therefore,
+you should not assume that binaries are compatible between
+different Lua versions.
+Always recompile clients of the Lua API when
+using a new version.
 
-<h2>8.1 &ndash; <a name="8.1">Changes in the Language</a></h2>
-<ul>
 
-<li>
-The concept of <em>environment</em> changed.
-Only Lua functions have environments.
-To set the environment of a Lua function,
-use the variable <code>_ENV</code> or the function <a href="#pdf-load"><code>load</code></a>.
+<p>
+Similarly, Lua versions can always change the internal representation
+of precompiled chunks;
+precompiled chunks are not compatible between different Lua versions.
 
 
 <p>
-C functions no longer have environments.
-Use an upvalue with a shared table if you need to keep
-shared state among several C functions.
-(You may use <a href="#luaL_setfuncs"><code>luaL_setfuncs</code></a> to open a C library
-with all functions sharing a common upvalue.)
+The standard paths in the official distribution may
+change between versions.
 
 
-<p>
-To manipulate the "environment" of a userdata
-(which is now called user value),
-use the new functions
-<a href="#lua_getuservalue"><code>lua_getuservalue</code></a> and <a href="#lua_setuservalue"><code>lua_setuservalue</code></a>.
-</li>
 
-<li>
-Lua identifiers cannot use locale-dependent letters.
-</li>
+<h2>8.1 &ndash; <a name="8.1">Changes in the Language</a></h2>
+<ul>
 
 <li>
-Doing a step or a full collection in the garbage collector
-does not restart the collector if it has been stopped.
-</li>
+The main difference between Lua&nbsp;5.2 and Lua&nbsp;5.3 is the
+introduction of an integer subtype for numbers.
+Although this change should not affect "normal" computations,
+some computations
+(mainly those that involve some kind of overflow)
+can give different results.
 
-<li>
-Weak tables with weak keys now perform like <em>ephemeron tables</em>.
+
+<p>
+You can fix these differences by forcing a number to be a float
+(in Lua&nbsp;5.2 all numbers were float),
+in particular writing constants with an ending <code>.0</code>
+or using <code>x = x + 0.0</code> to convert a variable.
+(This recommendation is only for a quick fix
+for an occasional incompatibility;
+it is not a general guideline for good programming.
+For good programming,
+use floats where you need floats
+and integers where you need integers.)
 </li>
 
 <li>
-The event <em>tail return</em> in debug hooks was removed.
-Instead, tail calls generate a special new event,
-<em>tail call</em>, so that the debugger can know that
-there will not be a corresponding return event.
+The conversion of a float to a string now adds a <code>.0</code> suffix
+to the result if it looks like an integer.
+(For instance, the float 2.0 will be printed as <code>2.0</code>,
+not as <code>2</code>.)
+You should always use an explicit format
+when you need a specific format for numbers.
+
+
+<p>
+(Formally this is not an incompatibility,
+because Lua does not specify how numbers are formatted as strings,
+but some programs assumed a specific format.)
 </li>
 
 <li>
-Equality between function values has changed.
-Now, a function definition may not create a new value;
-it may reuse some previous value if there is no
-observable difference to the new function.
+The generational mode for the garbage collector was removed.
+(It was an experimental feature in Lua&nbsp;5.2.)
 </li>
 
 </ul>
@@ -10266,67 +10710,57 @@ observable difference to the new function.
 <ul>
 
 <li>
-Function <code>module</code> is deprecated.
-It is easy to set up a module with regular Lua code.
-Modules are not expected to set global variables.
-</li>
-
-<li>
-Functions <code>setfenv</code> and <code>getfenv</code> were removed,
-because of the changes in environments.
-</li>
-
-<li>
-Function <code>math.log10</code> is deprecated.
-Use <a href="#pdf-math.log"><code>math.log</code></a> with 10 as its second argument, instead.
-</li>
-
-<li>
-Function <code>loadstring</code> is deprecated.
-Use <code>load</code> instead; it now accepts string arguments
-and are exactly equivalent to <code>loadstring</code>.
-</li>
-
-<li>
-Function <code>table.maxn</code> is deprecated.
-Write it in Lua if you really need it.
+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 Lua&nbsp;5.3 operate on Lua integers,
+which by default have 64&nbsp;bits.)
 </li>
 
 <li>
-Function <code>os.execute</code> now returns <b>true</b> when command
-terminates successfully and <b>nil</b> plus error information
-otherwise.
+The Table library now respects metamethods
+for setting and getting elements.
 </li>
 
 <li>
-Function <code>unpack</code> was moved into the table library
-and therefore must be called as <a href="#pdf-table.unpack"><code>table.unpack</code></a>.
+The <a href="#pdf-ipairs"><code>ipairs</code></a> iterator now respects metamethods and
+its <code>__ipairs</code> metamethod has been deprecated.
 </li>
 
 <li>
-Character class <code>%z</code> in patterns is deprecated,
-as now patterns may contain '<code>\0</code>' as a regular character.
+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 accept (and ignore) this character.
 </li>
 
 <li>
-The table <code>package.loaders</code> was renamed <code>package.searchers</code>.
+The following functions were deprecated in the mathematical library:
+<code>atan2</code>, <code>cosh</code>, <code>sinh</code>, <code>tanh</code>, <code>pow</code>,
+<code>frexp</code>, and <code>ldexp</code>.
+You can replace <code>math.pow(x,y)</code> with <code>x^y</code>;
+you can replace <code>math.atan2</code> with <code>math.atan</code>,
+which now accepts one or two parameters;
+you can replace <code>math.ldexp(x,exp)</code> with <code>x * 2.0^exp</code>.
+For the other operations,
+you can either use an external library or
+implement them in Lua.
 </li>
 
 <li>
-Lua does not have bytecode verification anymore.
-So, all functions that load code
-(<a href="#pdf-load"><code>load</code></a> and <a href="#pdf-loadfile"><code>loadfile</code></a>)
-are potentially insecure when loading untrusted binary data.
-(Actually, those functions were already insecure because
-of flaws in the verification algorithm.)
-When in doubt,
-use the <code>mode</code> argument of those functions
-to restrict them to loading textual chunks.
+The searcher for C loaders used by <a href="#pdf-require"><code>require</code></a>
+changed the way it handles versioned names.
+Now, the version should come after the module name
+(as is usual in most other tools).
+For compatibility, that searcher still tries the old format
+if it cannot find an open function according to the new style.
+(Lua&nbsp;5.2 already worked that way,
+but it did not document the change.)
 </li>
 
 <li>
-The standard paths in the official distribution may
-change between versions.
+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>
@@ -10335,75 +10769,36 @@ change between versions.
 
 
 <h2>8.3 &ndash; <a name="8.3">Changes in the API</a></h2>
-<ul>
-
-<li>
-Pseudoindex <code>LUA_GLOBALSINDEX</code> was removed.
-You must get the global environment from the registry
-(see <a href="#4.5">&sect;4.5</a>).
-</li>
-
-<li>
-Pseudoindex <code>LUA_ENVIRONINDEX</code>
-and functions <code>lua_getfenv</code>/<code>lua_setfenv</code>
-were removed,
-as C&nbsp;functions no longer have environments.
-</li>
-
-<li>
-Function <code>luaL_register</code> is deprecated.
-Use <a href="#luaL_setfuncs"><code>luaL_setfuncs</code></a> so that your module does not create globals.
-(Modules are not expected to set global variables anymore.)
-</li>
-
-<li>
-The <code>osize</code> argument to the allocation function
-may not be zero when creating a new block,
-that is, when <code>ptr</code> is <code>NULL</code>
-(see <a href="#lua_Alloc"><code>lua_Alloc</code></a>).
-Use only the test <code>ptr == NULL</code> to check whether
-the block is new.
-</li>
-
-<li>
-Finalizers (<code>__gc</code> metamethods) for userdata are called in the
-reverse order that they were marked for finalization,
-not that they were created (see <a href="#2.5.1">&sect;2.5.1</a>).
-(Most userdata are marked immediately after they are created.)
-Moreover,
-if the metatable does not have a <code>__gc</code> field when set,
-the finalizer will not be called,
-even if it is set later.
-</li>
 
-<li>
-<code>luaL_typerror</code> was removed.
-Write your own version if you need it.
-</li>
 
-<li>
-Function <code>lua_cpcall</code> is deprecated.
-You can simply push the function with <a href="#lua_pushcfunction"><code>lua_pushcfunction</code></a>
-and call it with <a href="#lua_pcall"><code>lua_pcall</code></a>.
-</li>
+<ul>
 
 <li>
-Functions <code>lua_equal</code> and <code>lua_lessthan</code> are deprecated.
-Use the new <a href="#lua_compare"><code>lua_compare</code></a> with appropriate options instead.
+Continuation functions now receive as parameters what they needed
+to get through <code>lua_getctx</code>,
+so <code>lua_getctx</code> has been removed.
+Adapt your code accordingly.
 </li>
 
 <li>
-Function <code>lua_objlen</code> was renamed <a href="#lua_rawlen"><code>lua_rawlen</code></a>.
+Function <a href="#lua_dump"><code>lua_dump</code></a> has an extra parameter, <code>strip</code>.
+Use 0 as the value of this parameter to get the old behavior.
 </li>
 
 <li>
-Function <a href="#lua_load"><code>lua_load</code></a> has an extra parameter, <code>mode</code>.
-Pass <code>NULL</code> to simulate the old behavior.
+Functions to inject/project unsigned integers
+(<code>lua_pushunsigned</code>, <code>lua_tounsigned</code>, <code>lua_tounsignedx</code>,
+<code>luaL_checkunsigned</code>, <code>luaL_optunsigned</code>)
+were deprecated.
+Use their signed equivalents with a type cast.
 </li>
 
 <li>
-Function <a href="#lua_resume"><code>lua_resume</code></a> has an extra parameter, <code>from</code>.
-Pass <code>NULL</code> or the thread doing the call.
+Macros to project non-default integer types
+(<code>luaL_checkint</code>, <code>luaL_optint</code>, <code>luaL_checklong</code>, <code>luaL_optlong</code>)
+were deprecated.
+Use their equivalent over <a href="#lua_Integer"><code>lua_Integer</code></a> with a type cast
+(or, when possible, use <a href="#lua_Integer"><code>lua_Integer</code></a> in your code).
 </li>
 
 </ul>
@@ -10415,7 +10810,13 @@ Pass <code>NULL</code> or the thread doing the call.
 
 <p>
 Here is the complete syntax of Lua in extended BNF.
-(It does not describe operator precedences.)
+As usual in extended BNF,
+{A} means 0 or more As,
+and [A] means an optional A.
+(For operator precedences, see <a href="#3.4.8">&sect;3.4.8</a>;
+for a description of the terminals
+Name, Numeral,
+and LiteralString, see <a href="#3.1">&sect;3.1</a>.)
 
 
 
@@ -10456,14 +10857,14 @@ Here is the complete syntax of Lua in extended BNF.
 
        explist ::= exp {&lsquo;<b>,</b>&rsquo; exp}
 
-       exp ::=  <b>nil</b> | <b>false</b> | <b>true</b> | Number | String | &lsquo;<b>...</b>&rsquo; | functiondef | 
+       exp ::=  <b>nil</b> | <b>false</b> | <b>true</b> | Numeral | LiteralString | &lsquo;<b>...</b>&rsquo; | functiondef | 
                 prefixexp | tableconstructor | exp binop exp | unop exp 
 
        prefixexp ::= var | functioncall | &lsquo;<b>(</b>&rsquo; exp &lsquo;<b>)</b>&rsquo;
 
        functioncall ::=  prefixexp args | prefixexp &lsquo;<b>:</b>&rsquo; Name args 
 
-       args ::=  &lsquo;<b>(</b>&rsquo; [explist] &lsquo;<b>)</b>&rsquo; | tableconstructor | String 
+       args ::=  &lsquo;<b>(</b>&rsquo; [explist] &lsquo;<b>)</b>&rsquo; | tableconstructor | LiteralString 
 
        functiondef ::= <b>function</b> funcbody
 
@@ -10479,11 +10880,12 @@ Here is the complete syntax of Lua in extended BNF.
 
        fieldsep ::= &lsquo;<b>,</b>&rsquo; | &lsquo;<b>;</b>&rsquo;
 
-       binop ::= &lsquo;<b>+</b>&rsquo; | &lsquo;<b>-</b>&rsquo; | &lsquo;<b>*</b>&rsquo; | &lsquo;<b>/</b>&rsquo; | &lsquo;<b>^</b>&rsquo; | &lsquo;<b>%</b>&rsquo; | &lsquo;<b>..</b>&rsquo; | 
+       binop ::=  &lsquo;<b>+</b>&rsquo; | &lsquo;<b>-</b>&rsquo; | &lsquo;<b>*</b>&rsquo; | &lsquo;<b>/</b>&rsquo; | &lsquo;<b>//</b>&rsquo; | &lsquo;<b>^</b>&rsquo; | &lsquo;<b>%</b>&rsquo; | 
+                &lsquo;<b>&amp;</b>&rsquo; | &lsquo;<b>~</b>&rsquo; | &lsquo;<b>|</b>&rsquo; | &lsquo;<b>&gt;&gt;</b>&rsquo; | &lsquo;<b>&lt;&lt;</b>&rsquo; | &lsquo;<b>..</b>&rsquo; | 
                 &lsquo;<b>&lt;</b>&rsquo; | &lsquo;<b>&lt;=</b>&rsquo; | &lsquo;<b>&gt;</b>&rsquo; | &lsquo;<b>&gt;=</b>&rsquo; | &lsquo;<b>==</b>&rsquo; | &lsquo;<b>~=</b>&rsquo; | 
                 <b>and</b> | <b>or</b>
 
-       unop ::= &lsquo;<b>-</b>&rsquo; | <b>not</b> | &lsquo;<b>#</b>&rsquo;
+       unop ::= &lsquo;<b>-</b>&rsquo; | <b>not</b> | &lsquo;<b>#</b>&rsquo; | &lsquo;<b>~</b>&rsquo;
 
 </pre>
 
@@ -10495,13 +10897,13 @@ Here is the complete syntax of Lua in extended BNF.
 
 
 
-<HR>
-<SMALL CLASS="footer">
+
+<P CLASS="footer">
 Last update:
-Mon Feb 23 22:24:44 BRT 2015
-</SMALL>
+Mon May 30 13:11:08 BRT 2016
+</P>
 <!--
-Last change: revised for Lua 5.2.4
+Last change: revised for Lua 5.3.3
 -->
 
 </body></html>
index a4ee991..6629304 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <HTML>
 <HEAD>
-<TITLE>Lua 5.2 readme</TITLE>
+<TITLE>Lua 5.3 readme</TITLE>
 <LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
 <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1">
 <STYLE TYPE="text/css">
@@ -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.2
+<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>
 &middot;
 <A HREF="#install">installation</A>
@@ -44,9 +43,9 @@ Welcome to Lua 5.2
 <A HREF="#license">license</A>
 &middot;
 <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
@@ -70,13 +69,12 @@ and
 updated
 <A HREF="http://www.lua.org/docs.html">documentation</A>,
 especially the
-<A HREF="http://www.lua.org/manual/5.2/">reference manual</A>,
+<A HREF="http://www.lua.org/manual/5.3/">reference manual</A>,
 which may differ slightly from the
 <A HREF="contents.html">local copy</A>
 distributed in this package.
 
 <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.2.x</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>
@@ -118,14 +115,14 @@ The <TT>Makefile</TT> there controls both the build process and the installation
   The platforms currently supported are:
 <P>
 <P CLASS="display">
-   aix ansi bsd freebsd generic linux macosx mingw posix solaris
+   aix bsd c89 freebsd generic linux macosx mingw posix solaris
 </P>
 <P>
   If your platform is listed, just do "<KBD>make xxx</KBD>", where xxx
   is your platform name.
 <P>
   If your platform is not listed, try the closest one or posix, generic,
-  ansi, in this order.
+  c89, in this order.
 <P>
 <LI>
 The compilation takes only a few moments
@@ -215,13 +212,7 @@ then try "<KBD>make linux MYLIBS=-ltermcap</KBD>".
   it will be used by any Lua clients that you build, to ensure consistency.
   Further customization is available to experts by editing the Lua sources.
 
-<P>
-  We strongly recommend that you enable dynamic loading in <TT>src/luaconf.h</TT>.
-  This is done automatically for all platforms listed above that have
-  this feature and also for Windows.
-
 <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
@@ -236,7 +227,7 @@ lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
 lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c
 ltm.c lundump.c lvm.c lzio.c
 lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c
-lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c
+lmathlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c loadlib.c linit.c
 <DT>
 interpreter:
 <DD>
@@ -263,10 +254,9 @@ compiler:
   As mentioned above, you may edit <TT>src/luaconf.h</TT> to customize
   some features before building Lua.
 
-<H2><A NAME="changes">Changes since Lua 5.1</A></H2>
-
+<H2><A NAME="changes">Changes since Lua 5.2</A></H2>
 <P>
-Here are the main changes introduced in Lua 5.2.
+Here are the main changes introduced in Lua 5.3.
 The
 <A HREF="contents.html">reference manual</A>
 lists the
@@ -274,98 +264,57 @@ lists the
 
 <H3>Main changes</H3>
 <UL>
-<LI> yieldable pcall and metamethods
-<LI> new lexical scheme for globals
-<LI> ephemeron tables
-<LI> new library for bitwise operations
-<LI> light C functions
-<LI> emergency garbage collector
-<LI> <CODE>goto</CODE> statement
-<LI> finalizers for tables
+<LI> integers (64-bit by default)
+<LI> official support for 32-bit numbers
+<LI> bitwise operators
+<LI> basic utf-8 support
+<LI> functions for packing and unpacking values
+
 </UL>
 
-Here are the other changes introduced in Lua 5.2:
+Here are the other changes introduced in Lua 5.3:
 <H3>Language</H3>
 <UL>
-<LI> no more fenv for threads or functions
-<LI> tables honor the <CODE>__len</CODE> metamethod
-<LI> hex and <CODE>\z</CODE> escapes in strings
-<LI> support for hexadecimal floats
-<LI> order metamethods work for different types
-<LI> no more verification of opcode consistency
-<LI> hook event "tail return" replaced by "tail call"
-<LI> empty statement
-<LI> <CODE>break</CODE> statement may appear in the middle of a block
+<LI> userdata can have any Lua value as uservalue
+<LI> floor division
+<LI> more flexible rules for some metamethods
 </UL>
 
 <H3>Libraries</H3>
 <UL>
-<LI> arguments for function called through <CODE>xpcall</CODE>
-<LI> optional 'mode' argument to load and loadfile (to control binary x text)
-<LI> optional 'env' argument to load and loadfile (environment for loaded chunk)
-<LI> <CODE>loadlib</CODE> may load libraries with global names (RTLD_GLOBAL)
-<LI> new function <CODE>package.searchpath</CODE>
-<LI> modules receive their paths when loaded
-<LI> optional base in <CODE>math.log</CODE>
-<LI> optional separator in <CODE>string.rep</CODE>
-<LI> <CODE>file:write</CODE> returns <CODE>file</CODE>
-<LI> closing a pipe returns exit status
-<LI> <CODE>os.exit</CODE> may close state
-<LI> new metamethods <CODE>__pairs</CODE> and <CODE>__ipairs</CODE>
-<LI> new option 'isrunning' for <CODE>collectgarbage</CODE> and <CODE>lua_gc</CODE>
-<LI> frontier patterns
-<LI> <CODE>\0</CODE> in patterns
-<LI> new option <CODE>*L</CODE> for <CODE>io.read</CODE>
-<LI> options for <CODE>io.lines</CODE>
-<LI> <CODE>debug.getlocal</CODE> can access function varargs
+<LI> <CODE>ipairs</CODE> and the table library respect metamethods
+<LI> strip option in <CODE>string.dump</CODE>
+<LI> table library respects metamethods
+<LI> new function <CODE>table.move</CODE>
+<LI> new function <CODE>string.pack</CODE>
+<LI> new function <CODE>string.unpack</CODE>
+<LI> new function <CODE>string.packsize</CODE>
 </UL>
 
 <H3>C API</H3>
 <UL>
-<LI> main thread predefined in the registry
-<LI> new functions
-<CODE>lua_absindex</CODE>,
-<CODE>lua_arith</CODE>,
-<CODE>lua_compare</CODE>,
-<CODE>lua_copy</CODE>,
-<CODE>lua_len</CODE>,
-<CODE>lua_rawgetp</CODE>,
-<CODE>lua_rawsetp</CODE>,
-<CODE>lua_upvalueid</CODE>,
-<CODE>lua_upvaluejoin</CODE>,
-<CODE>lua_version</CODE>.
-<LI> new functions
-<CODE>luaL_checkversion</CODE>,
-<CODE>luaL_setmetatable</CODE>,
-<CODE>luaL_testudata</CODE>,
-<CODE>luaL_tolstring</CODE>.
-<LI> <CODE>lua_pushstring</CODE> and <CODE>pushlstring</CODE> return string
-<LI> <CODE>nparams</CODE> and <CODE>isvararg</CODE> available in debug API
-<LI> new <CODE>lua_Unsigned</CODE>
-</UL>
-
-<H3>Implementation</H3>
-<UL>
-<LI> max constants per function raised to 2<SUP>26</SUP>
-<LI> generational mode for garbage collection (experimental)
-<LI> NaN trick (experimental)
-<LI> internal (immutable) version of ctypes
-<LI> simpler implementation for string buffers
-<LI> parser uses much less C-stack space (no more auto arrays)
+<LI> simpler API for continuation functions in C
+<LI> <CODE>lua_gettable</CODE> and similar functions return type of resulted value
+<LI> strip option in <CODE>lua_dump</CODE>
+<LI> new function: <CODE>lua_geti</CODE>
+<LI> new function: <CODE>lua_seti</CODE>
+<LI> new function: <CODE>lua_isyieldable</CODE>
+<LI> new function: <CODE>lua_numbertointeger</CODE>
+<LI> new function: <CODE>lua_rotate</CODE>
+<LI> new function: <CODE>lua_stringtonumber</CODE>
 </UL>
 
 <H3>Lua standalone interpreter</H3>
 <UL>
-<LI> new <CODE>-E</CODE> option to avoid environment variables
-<LI> handling of non-string error messages
+<LI> can be used as calculator; no need to prefix with '='
+<LI> <CODE>arg</CODE> table available to all code
 </UL>
 
 <H2><A NAME="license">License</A></H2>
+<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;
@@ -379,7 +328,7 @@ For details, see
 <A HREF="http://www.lua.org/license.html">this</A>.
 
 <BLOCKQUOTE STYLE="padding-bottom: 0em">
-Copyright &copy; 1994&ndash;2015 Lua.org, PUC-Rio.
+Copyright &copy; 1994&ndash;2016 Lua.org, PUC-Rio.
 
 <P>
 Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -404,13 +353,12 @@ THE SOFTWARE.
 </BLOCKQUOTE>
 <P>
 
-<HR>
-<SMALL CLASS="footer">
+<P CLASS="footer">
 Last update:
-Mon Feb 23 22:25:08 BRT 2015
-</SMALL>
+Tue Feb  2 22:25:27 BRST 2016
+</P>
 <!--
-Last change: revised for Lua 5.2.4
+Last change: revised for Lua 5.3.3
 -->
 
 </BODY>
index 7b4b2b7..d71c75c 100644 (file)
@@ -6,8 +6,8 @@
 # Your platform. See PLATS for possible values.
 PLAT= none
 
-CC= gcc
-CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS)
+CC= gcc -std=gnu99
+CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS)
 LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
 LIBS= -lm $(SYSLIBS) $(MYLIBS)
 
@@ -26,14 +26,14 @@ MYOBJS=
 
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
-PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
 
 LUA_A= liblua.a
 CORE_O=        lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
        lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
        ltm.o lundump.o lvm.o lzio.o
 LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \
-       lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o
+       lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
 BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
 
 LUA_T= lua
@@ -91,12 +91,16 @@ none:
 aix:
        $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
 
-ansi:
-       $(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI"
-
 bsd:
        $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
 
+c89:
+       $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
+       @echo ''
+       @echo '*** C89 does not guarantee 64-bit integers for Lua.'
+       @echo ''
+
+
 freebsd:
        $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline"
 
@@ -109,7 +113,7 @@ macosx:
        $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
 
 mingw:
-       $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \
+       $(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
        "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
        "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
        $(MAKE) "LUAC_T=luac.exe" luac.exe
@@ -118,70 +122,76 @@ posix:
        $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
 
 solaris:
-       $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl"
+       $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
 
 # list targets that do not create files (but not all makes understand .PHONY)
 .PHONY: all $(PLATS) default o a clean depend echo none
 
 # DO NOT DELETE
 
-lapi.o: lapi.c 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 \
+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
+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
+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
+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
+ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.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.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
+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 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
+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
-lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h
-lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h
-lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h
-lcode.o: lcode.c 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
-lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h
-lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h
-ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h
-ldebug.o: ldebug.c 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
-ldo.o: ldo.c 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
-ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \
- lzio.h lmem.h lundump.h
-lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \
- lstate.h ltm.h lzio.h lmem.h
-lgc.o: lgc.c 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
-linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h
-liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h
-llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \
- lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h
-lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
-lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
- ltm.h lzio.h lmem.h ldo.h lgc.h
-loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
-lobject.o: lobject.c 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
-lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h
-loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h
-lparser.o: lparser.c 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
-lstate.o: lstate.c 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
-lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \
- ltm.h lzio.h lstring.h lgc.h
-lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h
-ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
- ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
-ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h
-ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \
- lmem.h lstring.h lgc.h ltable.h
-lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h
-luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \
- ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
-lundump.o: lundump.c 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
-lvm.o: lvm.c 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
-lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \
- lzio.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
+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
+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
+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
+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
+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
+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
+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
+lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
+ lobject.h ltm.h lzio.h
+
+# (end of Makefile)
index d011431..c9455a5 100644 (file)
@@ -1,16 +1,18 @@
 /*
-** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
 
+#define lapi_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 #include <stdarg.h>
 #include <string.h>
 
-#define lapi_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lapi.h"
@@ -43,13 +45,16 @@ const char lua_ident[] =
 /* test for pseudo index */
 #define ispseudo(i)            ((i) <= LUA_REGISTRYINDEX)
 
+/* test for upvalue */
+#define isupvalue(i)           ((i) < LUA_REGISTRYINDEX)
+
 /* test for valid but not pseudo index */
 #define isstackindex(i, o)     (isvalid(o) && !ispseudo(i))
 
-#define api_checkvalidindex(L, o)  api_check(L, isvalid(o), "invalid index")
+#define api_checkvalidindex(l,o)  api_check(l, isvalid(o), "invalid index")
 
-#define api_checkstackindex(L, i, o)  \
-       api_check(L, 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) {
@@ -89,21 +94,22 @@ static void growstack (lua_State *L, void *ud) {
 }
 
 
-LUA_API int lua_checkstack (lua_State *L, int size) {
+LUA_API int lua_checkstack (lua_State *L, int n) {
   int res;
   CallInfo *ci = L->ci;
   lua_lock(L);
-  if (L->stack_last - L->top > size)  /* stack large enough? */
+  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 */
     int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;
-    if (inuse > LUAI_MAXSTACK - size)  /* can grow without overflow? */
+    if (inuse > LUAI_MAXSTACK - n)  /* can grow without overflow? */
       res = 0;  /* no */
     else  /* try to grow stack */
-      res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK);
+      res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);
   }
-  if (res && ci->top < L->top + size)
-    ci->top = L->top + size;  /* adjust frame top */
+  if (res && ci->top < L->top + n)
+    ci->top = L->top + n;  /* adjust frame top */
   lua_unlock(L);
   return res;
 }
@@ -115,10 +121,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
   lua_lock(to);
   api_checknelems(from, n);
   api_check(from, G(from) == G(to), "moving among independent states");
-  api_check(from, to->ci->top - to->top >= n, "not enough elements to move");
+  api_check(from, to->ci->top - to->top >= n, "stack overflow");
   from->top -= n;
   for (i = 0; i < n; i++) {
-    setobj2s(to, to->top++, from->top + i);
+    setobj2s(to, to->top, from->top + i);
+    to->top++;  /* stack already checked by previous 'api_check' */
   }
   lua_unlock(to);
 }
@@ -153,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;
 }
 
 
@@ -173,61 +180,56 @@ LUA_API void lua_settop (lua_State *L, int idx) {
   }
   else {
     api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
-    L->top += idx+1;  /* `subtract' index (index is negative) */
+    L->top += idx+1;  /* 'subtract' index (index is negative) */
   }
   lua_unlock(L);
 }
 
 
-LUA_API void lua_remove (lua_State *L, int idx) {
-  StkId p;
-  lua_lock(L);
-  p = index2addr(L, idx);
-  api_checkstackindex(L, idx, p);
-  while (++p < L->top) setobjs2s(L, p-1, p);
-  L->top--;
-  lua_unlock(L);
+/*
+** Reverse the stack segment from 'from' to 'to'
+** (auxiliary to 'lua_rotate')
+*/
+static void reverse (lua_State *L, StkId from, StkId to) {
+  for (; from < to; from++, to--) {
+    TValue temp;
+    setobj(L, &temp, from);
+    setobjs2s(L, from, to);
+    setobj2s(L, to, &temp);
+  }
 }
 
 
-LUA_API void lua_insert (lua_State *L, int idx) {
-  StkId p;
-  StkId q;
+/*
+** Let x = AB, where A is a prefix of length 'n'. Then,
+** rotate x n == BA. But BA == (A^r . B^r)^r.
+*/
+LUA_API void lua_rotate (lua_State *L, int idx, int n) {
+  StkId p, t, m;
   lua_lock(L);
-  p = index2addr(L, idx);
+  t = L->top - 1;  /* end of stack segment being rotated */
+  p = index2addr(L, idx);  /* start of segment */
   api_checkstackindex(L, idx, p);
-  for (q = L->top; q > p; q--)  /* use L->top as a temporary */
-    setobjs2s(L, q, q - 1);
-  setobjs2s(L, p, L->top);
+  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 */
+  reverse(L, p, t);  /* reverse the entire segment */
   lua_unlock(L);
 }
 
 
-static void moveto (lua_State *L, TValue *fr, int idx) {
-  TValue *to = index2addr(L, idx);
+LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
+  TValue *fr, *to;
+  lua_lock(L);
+  fr = index2addr(L, fromidx);
+  to = index2addr(L, toidx);
   api_checkvalidindex(L, to);
   setobj(L, to, fr);
-  if (idx < LUA_REGISTRYINDEX)  /* function upvalue? */
+  if (isupvalue(toidx))  /* function upvalue? */
     luaC_barrier(L, clCvalue(L->ci->func), fr);
   /* LUA_REGISTRYINDEX does not need gc barrier
      (collector revisits it before finishing collection) */
-}
-
-
-LUA_API void lua_replace (lua_State *L, int idx) {
-  lua_lock(L);
-  api_checknelems(L, 1);
-  moveto(L, L->top - 1, idx);
-  L->top--;
-  lua_unlock(L);
-}
-
-
-LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
-  TValue *fr;
-  lua_lock(L);
-  fr = index2addr(L, fromidx);
-  moveto(L, fr, toidx);
   lua_unlock(L);
 }
 
@@ -248,12 +250,13 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
 
 LUA_API int lua_type (lua_State *L, int idx) {
   StkId o = index2addr(L, idx);
-  return (isvalid(o) ? ttypenv(o) : LUA_TNONE);
+  return (isvalid(o) ? ttnov(o) : LUA_TNONE);
 }
 
 
 LUA_API const char *lua_typename (lua_State *L, int t) {
   UNUSED(L);
+  api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
   return ttypename(t);
 }
 
@@ -264,22 +267,28 @@ LUA_API int lua_iscfunction (lua_State *L, int idx) {
 }
 
 
+LUA_API int lua_isinteger (lua_State *L, int idx) {
+  StkId o = index2addr(L, idx);
+  return ttisinteger(o);
+}
+
+
 LUA_API int lua_isnumber (lua_State *L, int idx) {
-  TValue n;
+  lua_Number n;
   const TValue *o = index2addr(L, idx);
   return tonumber(o, &n);
 }
 
 
 LUA_API int lua_isstring (lua_State *L, int idx) {
-  int t = lua_type(L, idx);
-  return (t == LUA_TSTRING || t == LUA_TNUMBER);
+  const TValue *o = index2addr(L, idx);
+  return (ttisstring(o) || cvt2str(o));
 }
 
 
 LUA_API int lua_isuserdata (lua_State *L, int idx) {
   const TValue *o = index2addr(L, idx);
-  return (ttisuserdata(o) || ttislightuserdata(o));
+  return (ttisfulluserdata(o) || ttislightuserdata(o));
 }
 
 
@@ -291,24 +300,17 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
 
 
 LUA_API void lua_arith (lua_State *L, int op) {
-  StkId o1;  /* 1st operand */
-  StkId o2;  /* 2nd operand */
   lua_lock(L);
-  if (op != LUA_OPUNM) /* all other operations expect two operands */
-    api_checknelems(L, 2);
-  else {  /* for unary minus, add fake 2nd operand */
+  if (op != LUA_OPUNM && op != LUA_OPBNOT)
+    api_checknelems(L, 2);  /* all other operations expect two operands */
+  else {  /* for unary operations, add fake 2nd operand */
     api_checknelems(L, 1);
     setobjs2s(L, L->top, L->top - 1);
-    L->top++;
-  }
-  o1 = L->top - 2;
-  o2 = L->top - 1;
-  if (ttisnumber(o1) && ttisnumber(o2)) {
-    setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));
+    api_incr_top(L);
   }
-  else
-    luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD));
-  L->top--;
+  /* first operand at top - 2, second at top - 1; result go to top - 2 */
+  luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
+  L->top--;  /* remove second operand */
   lua_unlock(L);
 }
 
@@ -321,7 +323,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
   o2 = index2addr(L, index2);
   if (isvalid(o1) && isvalid(o2)) {
     switch (op) {
-      case LUA_OPEQ: i = equalobj(L, o1, o2); break;
+      case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
       case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
       case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
       default: api_check(L, 0, "invalid option");
@@ -332,51 +334,33 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
 }
 
 
-LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) {
-  TValue n;
-  const TValue *o = index2addr(L, idx);
-  if (tonumber(o, &n)) {
-    if (isnum) *isnum = 1;
-    return nvalue(o);
-  }
-  else {
-    if (isnum) *isnum = 0;
-    return 0;
-  }
+LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
+  size_t sz = luaO_str2num(s, L->top);
+  if (sz != 0)
+    api_incr_top(L);
+  return sz;
 }
 
 
-LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) {
-  TValue n;
+LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
+  lua_Number n;
   const TValue *o = index2addr(L, idx);
-  if (tonumber(o, &n)) {
-    lua_Integer res;
-    lua_Number num = nvalue(o);
-    lua_number2integer(res, num);
-    if (isnum) *isnum = 1;
-    return res;
-  }
-  else {
-    if (isnum) *isnum = 0;
-    return 0;
-  }
+  int isnum = tonumber(o, &n);
+  if (!isnum)
+    n = 0;  /* call to 'tonumber' may change 'n' even if it fails */
+  if (pisnum) *pisnum = isnum;
+  return n;
 }
 
 
-LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) {
-  TValue n;
+LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
+  lua_Integer res;
   const TValue *o = index2addr(L, idx);
-  if (tonumber(o, &n)) {
-    lua_Unsigned res;
-    lua_Number num = nvalue(o);
-    lua_number2unsigned(res, num);
-    if (isnum) *isnum = 1;
-    return res;
-  }
-  else {
-    if (isnum) *isnum = 0;
-    return 0;
-  }
+  int isnum = tointeger(o, &res);
+  if (!isnum)
+    res = 0;  /* call to 'tointeger' may change 'n' even if it fails */
+  if (pisnum) *pisnum = isnum;
+  return res;
 }
 
 
@@ -389,25 +373,27 @@ LUA_API int lua_toboolean (lua_State *L, int idx) {
 LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
   StkId o = index2addr(L, idx);
   if (!ttisstring(o)) {
-    lua_lock(L);  /* `luaV_tostring' may create a new string */
-    if (!luaV_tostring(L, o)) {  /* conversion failed? */
+    if (!cvt2str(o)) {  /* not convertible? */
       if (len != NULL) *len = 0;
-      lua_unlock(L);
       return NULL;
     }
+    lua_lock(L);  /* 'luaO_tostring' may create a new string */
+    luaO_tostring(L, o);
     luaC_checkGC(L);
     o = index2addr(L, idx);  /* previous call may reallocate the stack */
     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 (ttypenv(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;
@@ -426,8 +412,8 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
 
 LUA_API void *lua_touserdata (lua_State *L, int idx) {
   StkId o = index2addr(L, idx);
-  switch (ttypenv(o)) {
-    case LUA_TUSERDATA: return (rawuvalue(o) + 1);
+  switch (ttnov(o)) {
+    case LUA_TUSERDATA: return getudatamem(uvalue(o));
     case LUA_TLIGHTUSERDATA: return pvalue(o);
     default: return NULL;
   }
@@ -448,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;
   }
 }
@@ -472,9 +457,7 @@ LUA_API void lua_pushnil (lua_State *L) {
 
 LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
   lua_lock(L);
-  setnvalue(L->top, n);
-  luai_checknum(L, L->top,
-    luaG_runerror(L, "C API - attempt to push a signaling NaN"));
+  setfltvalue(L->top, n);
   api_incr_top(L);
   lua_unlock(L);
 }
@@ -482,49 +465,43 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
 
 LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
   lua_lock(L);
-  setnvalue(L->top, cast_num(n));
-  api_incr_top(L);
-  lua_unlock(L);
-}
-
-
-LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) {
-  lua_Number n;
-  lua_lock(L);
-  n = lua_unsigned2number(u);
-  setnvalue(L->top, n);
+  setivalue(L->top, n);
   api_incr_top(L);
   lua_unlock(L);
 }
 
 
+/*
+** Pushes on the stack a string with given length. Avoid using 's' when
+** 'len' == 0 (as 's' can be NULL in that case), due to later use of
+** 'memcmp' and 'memcpy'.
+*/
 LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
   TString *ts;
   lua_lock(L);
-  luaC_checkGC(L);
-  ts = luaS_newlstr(L, s, len);
+  ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
   setsvalue2s(L, L->top, ts);
   api_incr_top(L);
+  luaC_checkGC(L);
   lua_unlock(L);
   return getstr(ts);
 }
 
 
 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);
+  luaC_checkGC(L);
+  lua_unlock(L);
+  return s;
 }
 
 
@@ -532,8 +509,8 @@ LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
                                       va_list argp) {
   const char *ret;
   lua_lock(L);
-  luaC_checkGC(L);
   ret = luaO_pushvfstring(L, fmt, argp);
+  luaC_checkGC(L);
   lua_unlock(L);
   return ret;
 }
@@ -543,10 +520,10 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
   const char *ret;
   va_list argp;
   lua_lock(L);
-  luaC_checkGC(L);
   va_start(argp, fmt);
   ret = luaO_pushvfstring(L, fmt, argp);
   va_end(argp);
+  luaC_checkGC(L);
   lua_unlock(L);
   return ret;
 }
@@ -558,18 +535,20 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
     setfvalue(L->top, fn);
   }
   else {
-    Closure *cl;
+    CClosure *cl;
     api_checknelems(L, n);
     api_check(L, n <= MAXUPVAL, "upvalue index too large");
-    luaC_checkGC(L);
     cl = luaF_newCclosure(L, n);
-    cl->c.f = fn;
+    cl->f = fn;
     L->top -= n;
-    while (n--)
-      setobj2n(L, &cl->c.upvalue[n], L->top + n);
+    while (n--) {
+      setobj2n(L, &cl->upvalue[n], L->top + n);
+      /* does not need barrier because closure is white */
+    }
     setclCvalue(L, L->top, cl);
   }
   api_incr_top(L);
+  luaC_checkGC(L);
   lua_unlock(L);
 }
 
@@ -605,48 +584,77 @@ LUA_API int lua_pushthread (lua_State *L) {
 */
 
 
-LUA_API void lua_getglobal (lua_State *L, const char *var) {
+static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
+  const TValue *slot;
+  TString *str = luaS_new(L, k);
+  if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
+    setobj2s(L, L->top, slot);
+    api_incr_top(L);
+  }
+  else {
+    setsvalue2s(L, L->top, str);
+    api_incr_top(L);
+    luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
+  }
+  lua_unlock(L);
+  return ttnov(L->top - 1);
+}
+
+
+LUA_API int lua_getglobal (lua_State *L, const char *name) {
   Table *reg = hvalue(&G(L)->l_registry);
-  const TValue *gt;  /* global table */
   lua_lock(L);
-  gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
-  setsvalue2s(L, L->top++, luaS_new(L, var));
-  luaV_gettable(L, gt, L->top - 1, L->top - 1);
-  lua_unlock(L);
+  return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
 }
 
 
-LUA_API void lua_gettable (lua_State *L, int idx) {
+LUA_API int lua_gettable (lua_State *L, int idx) {
   StkId t;
   lua_lock(L);
   t = index2addr(L, idx);
   luaV_gettable(L, t, L->top - 1, L->top - 1);
   lua_unlock(L);
+  return ttnov(L->top - 1);
+}
+
+
+LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
+  lua_lock(L);
+  return auxgetstr(L, index2addr(L, idx), k);
 }
 
 
-LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
+LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
+  const TValue *slot;
   lua_lock(L);
   t = index2addr(L, idx);
-  setsvalue2s(L, L->top, luaS_new(L, k));
-  api_incr_top(L);
-  luaV_gettable(L, t, L->top - 1, L->top - 1);
+  if (luaV_fastget(L, t, n, slot, luaH_getint)) {
+    setobj2s(L, L->top, slot);
+    api_incr_top(L);
+  }
+  else {
+    setivalue(L->top, n);
+    api_incr_top(L);
+    luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
+  }
   lua_unlock(L);
+  return ttnov(L->top - 1);
 }
 
 
-LUA_API void lua_rawget (lua_State *L, int idx) {
+LUA_API int lua_rawget (lua_State *L, int idx) {
   StkId t;
   lua_lock(L);
   t = index2addr(L, idx);
   api_check(L, ttistable(t), "table expected");
   setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
   lua_unlock(L);
+  return ttnov(L->top - 1);
 }
 
 
-LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
+LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
   lua_lock(L);
   t = index2addr(L, idx);
@@ -654,10 +662,11 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
   setobj2s(L, L->top, luaH_getint(hvalue(t), n));
   api_incr_top(L);
   lua_unlock(L);
+  return ttnov(L->top - 1);
 }
 
 
-LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) {
+LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
   StkId t;
   TValue k;
   lua_lock(L);
@@ -667,29 +676,30 @@ LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) {
   setobj2s(L, L->top, luaH_get(hvalue(t), &k));
   api_incr_top(L);
   lua_unlock(L);
+  return ttnov(L->top - 1);
 }
 
 
 LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
   Table *t;
   lua_lock(L);
-  luaC_checkGC(L);
   t = luaH_new(L);
   sethvalue(L, L->top, t);
   api_incr_top(L);
   if (narray > 0 || nrec > 0)
     luaH_resize(L, t, narray, nrec);
+  luaC_checkGC(L);
   lua_unlock(L);
 }
 
 
 LUA_API int lua_getmetatable (lua_State *L, int objindex) {
   const TValue *obj;
-  Table *mt = NULL;
-  int res;
+  Table *mt;
+  int res = 0;
   lua_lock(L);
   obj = index2addr(L, objindex);
-  switch (ttypenv(obj)) {
+  switch (ttnov(obj)) {
     case LUA_TTABLE:
       mt = hvalue(obj)->metatable;
       break;
@@ -697,12 +707,10 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
       mt = uvalue(obj)->metatable;
       break;
     default:
-      mt = G(L)->mt[ttypenv(obj)];
+      mt = G(L)->mt[ttnov(obj)];
       break;
   }
-  if (mt == NULL)
-    res = 0;
-  else {
+  if (mt != NULL) {
     sethvalue(L, L->top, mt);
     api_incr_top(L);
     res = 1;
@@ -712,17 +720,15 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
 }
 
 
-LUA_API void lua_getuservalue (lua_State *L, int idx) {
+LUA_API int lua_getuservalue (lua_State *L, int idx) {
   StkId o;
   lua_lock(L);
   o = index2addr(L, idx);
-  api_check(L, ttisuserdata(o), "userdata expected");
-  if (uvalue(o)->env) {
-    sethvalue(L, L->top, uvalue(o)->env);
-  } else
-    setnilvalue(L->top);
+  api_check(L, ttisfulluserdata(o), "full userdata expected");
+  getuservalue(L, uvalue(o), L->top);
   api_incr_top(L);
   lua_unlock(L);
+  return ttnov(L->top - 1);
 }
 
 
@@ -730,17 +736,29 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) {
 ** set functions (stack -> Lua)
 */
 
+/*
+** t[k] = value at the top of the stack (where 'k' is a string)
+*/
+static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
+  const TValue *slot;
+  TString *str = luaS_new(L, k);
+  api_checknelems(L, 1);
+  if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
+    L->top--;  /* pop value */
+  else {
+    setsvalue2s(L, L->top, str);  /* push 'str' (to make it a TValue) */
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
+    L->top -= 2;  /* pop value and key */
+  }
+  lua_unlock(L);  /* lock done by caller */
+}
+
 
-LUA_API void lua_setglobal (lua_State *L, const char *var) {
+LUA_API void lua_setglobal (lua_State *L, const char *name) {
   Table *reg = hvalue(&G(L)->l_registry);
-  const TValue *gt;  /* global table */
-  lua_lock(L);
-  api_checknelems(L, 1);
-  gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
-  setsvalue2s(L, L->top++, luaS_new(L, var));
-  luaV_settable(L, gt, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
-  lua_unlock(L);
+  lua_lock(L);  /* unlock done in 'auxsetstr' */
+  auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
 }
 
 
@@ -756,54 +774,69 @@ LUA_API void lua_settable (lua_State *L, int idx) {
 
 
 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
+  lua_lock(L);  /* unlock done in 'auxsetstr' */
+  auxsetstr(L, index2addr(L, idx), k);
+}
+
+
+LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
+  const TValue *slot;
   lua_lock(L);
   api_checknelems(L, 1);
   t = index2addr(L, idx);
-  setsvalue2s(L, L->top++, luaS_new(L, k));
-  luaV_settable(L, t, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
+  if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
+    L->top--;  /* pop value */
+  else {
+    setivalue(L->top, n);
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
+    L->top -= 2;  /* pop value and key */
+  }
   lua_unlock(L);
 }
 
 
 LUA_API void lua_rawset (lua_State *L, int idx) {
-  StkId t;
+  StkId o;
+  TValue *slot;
   lua_lock(L);
   api_checknelems(L, 2);
-  t = index2addr(L, idx);
-  api_check(L, ttistable(t), "table expected");
-  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
-  invalidateTMcache(hvalue(t));
-  luaC_barrierback(L, gcvalue(t), L->top-1);
+  o = index2addr(L, idx);
+  api_check(L, ttistable(o), "table expected");
+  slot = luaH_set(L, hvalue(o), L->top - 2);
+  setobj2t(L, slot, L->top - 1);
+  invalidateTMcache(hvalue(o));
+  luaC_barrierback(L, hvalue(o), L->top-1);
   L->top -= 2;
   lua_unlock(L);
 }
 
 
-LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
-  StkId t;
+LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
+  StkId o;
   lua_lock(L);
   api_checknelems(L, 1);
-  t = index2addr(L, idx);
-  api_check(L, ttistable(t), "table expected");
-  luaH_setint(L, hvalue(t), n, L->top - 1);
-  luaC_barrierback(L, gcvalue(t), L->top-1);
+  o = index2addr(L, idx);
+  api_check(L, ttistable(o), "table expected");
+  luaH_setint(L, hvalue(o), n, L->top - 1);
+  luaC_barrierback(L, hvalue(o), L->top-1);
   L->top--;
   lua_unlock(L);
 }
 
 
 LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
-  StkId t;
-  TValue k;
+  StkId o;
+  TValue k, *slot;
   lua_lock(L);
   api_checknelems(L, 1);
-  t = index2addr(L, idx);
-  api_check(L, ttistable(t), "table expected");
+  o = index2addr(L, idx);
+  api_check(L, ttistable(o), "table expected");
   setpvalue(&k, cast(void *, p));
-  setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1);
-  luaC_barrierback(L, gcvalue(t), L->top - 1);
+  slot = luaH_set(L, hvalue(o), &k);
+  setobj2t(L, slot, L->top - 1);
+  luaC_barrierback(L, hvalue(o), L->top - 1);
   L->top--;
   lua_unlock(L);
 }
@@ -821,11 +854,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
     api_check(L, ttistable(L->top - 1), "table expected");
     mt = hvalue(L->top - 1);
   }
-  switch (ttypenv(obj)) {
+  switch (ttnov(obj)) {
     case LUA_TTABLE: {
       hvalue(obj)->metatable = mt;
       if (mt) {
-        luaC_objbarrierback(L, gcvalue(obj), mt);
+        luaC_objbarrier(L, gcvalue(obj), mt);
         luaC_checkfinalizer(L, gcvalue(obj), mt);
       }
       break;
@@ -833,13 +866,13 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
     case LUA_TUSERDATA: {
       uvalue(obj)->metatable = mt;
       if (mt) {
-        luaC_objbarrier(L, rawuvalue(obj), mt);
+        luaC_objbarrier(L, uvalue(obj), mt);
         luaC_checkfinalizer(L, gcvalue(obj), mt);
       }
       break;
     }
     default: {
-      G(L)->mt[ttypenv(obj)] = mt;
+      G(L)->mt[ttnov(obj)] = mt;
       break;
     }
   }
@@ -854,21 +887,16 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
   lua_lock(L);
   api_checknelems(L, 1);
   o = index2addr(L, idx);
-  api_check(L, ttisuserdata(o), "userdata expected");
-  if (ttisnil(L->top - 1))
-    uvalue(o)->env = NULL;
-  else {
-    api_check(L, ttistable(L->top - 1), "table expected");
-    uvalue(o)->env = hvalue(L->top - 1);
-    luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));
-  }
+  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--;
   lua_unlock(L);
 }
 
 
 /*
-** `load' and `call' functions (run Lua code)
+** 'load' and 'call' functions (run Lua code)
 */
 
 
@@ -877,17 +905,8 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
        "results from function overflow current stack size")
 
 
-LUA_API int lua_getctx (lua_State *L, int *ctx) {
-  if (L->ci->callstatus & CIST_YIELDED) {
-    if (ctx) *ctx = L->ci->u.c.ctx;
-    return L->ci->u.c.status;
-  }
-  else return LUA_OK;
-}
-
-
-LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
-                        lua_CFunction k) {
+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(L, k == NULL || !isLua(L->ci),
@@ -899,10 +918,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
   if (k != NULL && L->nny == 0) {  /* need to prepare continuation? */
     L->ci->u.c.k = k;  /* save continuation */
     L->ci->u.c.ctx = ctx;  /* save context */
-    luaD_call(L, func, nresults, 1);  /* do the call */
+    luaD_call(L, func, nresults);  /* do the call */
   }
   else  /* no continuation or no yieldable */
-    luaD_call(L, func, nresults, 0);  /* just do the call */
+    luaD_callnoyield(L, func, nresults);  /* just do the call */
   adjustresults(L, nresults);
   lua_unlock(L);
 }
@@ -912,7 +931,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
 /*
 ** Execute a protected call.
 */
-struct CallS {  /* data to `f_call' */
+struct CallS {  /* data to 'f_call' */
   StkId func;
   int nresults;
 };
@@ -920,13 +939,13 @@ struct CallS {  /* data to `f_call' */
 
 static void f_call (lua_State *L, void *ud) {
   struct CallS *c = cast(struct CallS *, ud);
-  luaD_call(L, c->func, c->nresults, 0);
+  luaD_callnoyield(L, c->func, c->nresults);
 }
 
 
 
 LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
-                        int ctx, lua_CFunction k) {
+                        lua_KContext ctx, lua_KFunction k) {
   struct CallS c;
   int status;
   ptrdiff_t func;
@@ -954,12 +973,11 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
     ci->u.c.ctx = ctx;  /* save context */
     /* save information for error recovery */
     ci->extra = savestack(L, c.func);
-    ci->u.c.old_allowhook = L->allowhook;
     ci->u.c.old_errfunc = L->errfunc;
     L->errfunc = func;
-    /* mark that function may do error recovery */
-    ci->callstatus |= CIST_YPCALL;
-    luaD_call(L, c.func, nresults, 1);  /* do the call */
+    setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */
+    ci->callstatus |= CIST_YPCALL;  /* function can do error recovery */
+    luaD_call(L, c.func, nresults);  /* do the call */
     ci->callstatus &= ~CIST_YPCALL;
     L->errfunc = ci->u.c.old_errfunc;
     status = LUA_OK;  /* if it is here, there were no errors */
@@ -980,13 +998,13 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
   status = luaD_protectedparser(L, &z, chunkname, mode);
   if (status == LUA_OK) {  /* no errors? */
     LClosure *f = clLvalue(L->top - 1);  /* get newly created function */
-    if (f->nupvalues == 1) {  /* does it have one upvalue? */
+    if (f->nupvalues >= 1) {  /* does it have an upvalue? */
       /* get global table from registry */
       Table *reg = hvalue(&G(L)->l_registry);
       const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
       /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
       setobj(L, f->upvals[0]->v, gt);
-      luaC_barrier(L, f->upvals[0], gt);
+      luaC_upvalbarrier(L, f->upvals[0]);
     }
   }
   lua_unlock(L);
@@ -994,14 +1012,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
 }
 
 
-LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
   int status;
   TValue *o;
   lua_lock(L);
   api_checknelems(L, 1);
   o = L->top - 1;
   if (isLfunction(o))
-    status = luaU_dump(L, getproto(o), writer, data, 0);
+    status = luaU_dump(L, getproto(o), writer, data, strip);
   else
     status = 1;
   lua_unlock(L);
@@ -1047,19 +1065,21 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       break;
     }
     case LUA_GCSTEP: {
-      if (g->gckind == KGC_GEN) {  /* generational mode? */
-        res = (g->GCestimate == 0);  /* true if it will do major collection */
-        luaC_forcestep(L);  /* do a single step */
+      l_mem debt = 1;  /* =1 to signal that it did an actual step */
+      lu_byte oldrunning = g->gcrunning;
+      g->gcrunning = 1;  /* allow GC to run */
+      if (data == 0) {
+        luaE_setdebt(g, -GCSTEPSIZE);  /* to do a "small" step */
+        luaC_step(L);
       }
-      else {
-       lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE;
-       if (g->gcrunning)
-         debt += g->GCdebt;  /* include current debt */
-       luaE_setdebt(g, debt);
-       luaC_forcestep(L);
-       if (g->gcstate == GCSpause)  /* end of cycle? */
-         res = 1;  /* signal it */
+      else {  /* add 'data' to total debt */
+        debt = cast(l_mem, data) * 1024 + g->GCdebt;
+        luaE_setdebt(g, debt);
+        luaC_checkGC(L);
       }
+      g->gcrunning = oldrunning;  /* restore previous state */
+      if (debt > 0 && g->gcstate == GCSpause)  /* end of cycle? */
+        res = 1;  /* signal it */
       break;
     }
     case LUA_GCSETPAUSE: {
@@ -1067,13 +1087,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       g->gcpause = data;
       break;
     }
-    case LUA_GCSETMAJORINC: {
-      res = g->gcmajorinc;
-      g->gcmajorinc = data;
-      break;
-    }
     case LUA_GCSETSTEPMUL: {
       res = g->gcstepmul;
+      if (data < 40) data = 40;  /* avoid ridiculous low values (and 0) */
       g->gcstepmul = data;
       break;
     }
@@ -1081,14 +1097,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       res = g->gcrunning;
       break;
     }
-    case LUA_GCGEN: {  /* change collector to generational mode */
-      luaC_changemode(L, KGC_GEN);
-      break;
-    }
-    case LUA_GCINC: {  /* change collector to incremental mode */
-      luaC_changemode(L, KGC_NORMAL);
-      break;
-    }
     default: res = -1;  /* invalid option */
   }
   lua_unlock(L);
@@ -1132,7 +1140,6 @@ LUA_API void lua_concat (lua_State *L, int n) {
   lua_lock(L);
   api_checknelems(L, n);
   if (n >= 2) {
-    luaC_checkGC(L);
     luaV_concat(L, n);
   }
   else if (n == 0) {  /* push empty string */
@@ -1140,6 +1147,7 @@ LUA_API void lua_concat (lua_State *L, int n) {
     api_incr_top(L);
   }
   /* else n == 1; nothing to do */
+  luaC_checkGC(L);
   lua_unlock(L);
 }
 
@@ -1175,24 +1183,24 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
 LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
   Udata *u;
   lua_lock(L);
-  luaC_checkGC(L);
-  u = luaS_newudata(L, size, NULL);
+  u = luaS_newudata(L, size);
   setuvalue(L, L->top, u);
   api_incr_top(L);
+  luaC_checkGC(L);
   lua_unlock(L);
-  return u + 1;
+  return getudatamem(u);
 }
 
 
 
 static const char *aux_upvalue (StkId fi, int n, TValue **val,
-                                GCObject **owner) {
+                                CClosure **owner, UpVal **uv) {
   switch (ttype(fi)) {
     case LUA_TCCL: {  /* C closure */
       CClosure *f = clCvalue(fi);
       if (!(1 <= n && n <= f->nupvalues)) return NULL;
       *val = &f->upvalue[n-1];
-      if (owner) *owner = obj2gco(f);
+      if (owner) *owner = f;
       return "";
     }
     case LUA_TLCL: {  /* Lua closure */
@@ -1201,9 +1209,9 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
       Proto *p = f->p;
       if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
       *val = f->upvals[n-1]->v;
-      if (owner) *owner = obj2gco(f->upvals[n - 1]);
+      if (uv) *uv = f->upvals[n - 1];
       name = p->upvalues[n-1].name;
-      return (name == NULL) ? "" : getstr(name);
+      return (name == NULL) ? "(*no name)" : getstr(name);
     }
     default: return NULL;  /* not a closure */
   }
@@ -1214,7 +1222,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
   const char *name;
   TValue *val = NULL;  /* to avoid warnings */
   lua_lock(L);
-  name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL);
+  name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL);
   if (name) {
     setobj2s(L, L->top, val);
     api_incr_top(L);
@@ -1227,16 +1235,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
 LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
   const char *name;
   TValue *val = NULL;  /* to avoid warnings */
-  GCObject *owner = NULL;  /* to avoid warnings */
+  CClosure *owner = NULL;
+  UpVal *uv = NULL;
   StkId fi;
   lua_lock(L);
   fi = index2addr(L, funcindex);
   api_checknelems(L, 1);
-  name = aux_upvalue(fi, n, &val, &owner);
+  name = aux_upvalue(fi, n, &val, &owner, &uv);
   if (name) {
     L->top--;
     setobj(L, val, L->top);
-    luaC_barrier(L, owner, L->top);
+    if (owner) { luaC_barrier(L, owner, L->top); }
+    else if (uv) { luaC_upvalbarrier(L, uv); }
   }
   lua_unlock(L);
   return name;
@@ -1278,7 +1288,11 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
   LClosure *f1;
   UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
   UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
+  luaC_upvdeccount(L, *up1);
   *up1 = *up2;
-  luaC_objbarrier(L, f1, *up2);
+  (*up1)->refcount++;
+  if (upisopen(*up1)) (*up1)->u.open.touched = 1;
+  luaC_upvalbarrier(L, *up1);
 }
 
+
index c7d34ad..6d36dee 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 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
 */
index b00f8c7..bacf43b 100644 (file)
@@ -1,9 +1,14 @@
 /*
-** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lauxlib.c,v 1.286 2016/01/08 15:33:09 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
 
+#define lauxlib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <errno.h>
 #include <stdarg.h>
 #include <string.h>
 
 
-/* This file uses only the official API of Lua.
+/*
+** This file uses only the official API of Lua.
 ** Any function declared here could be written as an application function.
 */
 
-#define lauxlib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
@@ -31,8 +34,8 @@
 */
 
 
-#define LEVELS1        12      /* size of the first part of the stack */
-#define LEVELS2        10      /* size of the second part of the stack */
+#define LEVELS1        10      /* size of the first part of the stack */
+#define LEVELS2        11      /* size of the second part of the stack */
 
 
 
@@ -64,11 +67,20 @@ static int findfield (lua_State *L, int objidx, int level) {
 }
 
 
+/*
+** Search for a name for a function in all loaded modules
+** (registry._LOADED).
+*/
 static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
   int top = lua_gettop(L);
   lua_getinfo(L, "f", ar);  /* push function */
-  lua_pushglobaltable(L);
+  lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
   if (findfield(L, top + 1, 2)) {
+    const char *name = lua_tostring(L, -1);
+    if (strncmp(name, "_G.", 3) == 0) {  /* name start with '_G.'? */
+      lua_pushstring(L, name + 3);  /* push name without prefix */
+      lua_remove(L, -2);  /* remove original name */
+    }
     lua_copy(L, -1, top + 1);  /* move name to proper place */
     lua_pop(L, 2);  /* remove pushed values */
     return 1;
@@ -81,24 +93,22 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
 
 
 static void pushfuncname (lua_State *L, lua_Debug *ar) {
-  if (*ar->namewhat != '\0')  /* is there a name? */
-    lua_pushfstring(L, "function " LUA_QS, ar->name);
+  if (pushglobalfuncname(L, ar)) {  /* try first a global name */
+    lua_pushfstring(L, "function '%s'", lua_tostring(L, -1));
+    lua_remove(L, -2);  /* remove name */
+  }
+  else if (*ar->namewhat != '\0')  /* is there a name from code? */
+    lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name);  /* use it */
   else if (*ar->what == 'm')  /* main? */
       lua_pushliteral(L, "main chunk");
-  else if (*ar->what == 'C') {
-    if (pushglobalfuncname(L, ar)) {
-      lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
-      lua_remove(L, -2);  /* remove name */
-    }
-    else
-      lua_pushliteral(L, "?");
-  }
-  else
+  else if (*ar->what != 'C')  /* for Lua functions, use <file:line> */
     lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
+  else  /* nothing left... */
+    lua_pushliteral(L, "?");
 }
 
 
-static int countlevels (lua_State *L) {
+static int lastlevel (lua_State *L) {
   lua_Debug ar;
   int li = 1, le = 1;
   /* find an upper bound */
@@ -117,14 +127,16 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
                                 const char *msg, int level) {
   lua_Debug ar;
   int top = lua_gettop(L);
-  int numlevels = countlevels(L1);
-  int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
-  if (msg) lua_pushfstring(L, "%s\n", msg);
+  int last = lastlevel(L1);
+  int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
+  if (msg)
+    lua_pushfstring(L, "%s\n", msg);
+  luaL_checkstack(L, 10, NULL);
   lua_pushliteral(L, "stack traceback:");
   while (lua_getstack(L1, level++, &ar)) {
-    if (level == mark) {  /* too many levels? */
+    if (n1-- == 0) {  /* too many levels? */
       lua_pushliteral(L, "\n\t...");  /* add a '...' */
-      level = numlevels - LEVELS2;  /* and skip to last ones */
+      level = last - LEVELS2 + 1;  /* and skip to last ones */
     }
     else {
       lua_getinfo(L1, "Slnt", &ar);
@@ -150,36 +162,47 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
 ** =======================================================
 */
 
-LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
+LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
   lua_Debug ar;
   if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
-    return luaL_error(L, "bad argument #%d (%s)", narg, extramsg);
+    return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
   lua_getinfo(L, "n", &ar);
   if (strcmp(ar.namewhat, "method") == 0) {
-    narg--;  /* do not count `self' */
-    if (narg == 0)  /* error is in the self argument itself? */
-      return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
+    arg--;  /* do not count 'self' */
+    if (arg == 0)  /* error is in the self argument itself? */
+      return luaL_error(L, "calling '%s' on bad self (%s)",
                            ar.name, extramsg);
   }
   if (ar.name == NULL)
     ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
-  return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
-                        narg, ar.name, extramsg);
+  return luaL_error(L, "bad argument #%d to '%s' (%s)",
+                        arg, ar.name, extramsg);
 }
 
 
-static int typeerror (lua_State *L, int narg, const char *tname) {
-  const char *msg = lua_pushfstring(L, "%s expected, got %s",
-                                    tname, luaL_typename(L, narg));
-  return luaL_argerror(L, narg, msg);
+static int typeerror (lua_State *L, int arg, const char *tname) {
+  const char *msg;
+  const char *typearg;  /* name for the type of the actual argument */
+  if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)
+    typearg = lua_tostring(L, -1);  /* use the given type name */
+  else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA)
+    typearg = "light userdata";  /* special name for messages */
+  else
+    typearg = luaL_typename(L, arg);  /* standard name */
+  msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg);
+  return luaL_argerror(L, arg, msg);
 }
 
 
-static void tag_error (lua_State *L, int narg, int tag) {
-  typeerror(L, narg, lua_typename(L, tag));
+static void tag_error (lua_State *L, int arg, int tag) {
+  typeerror(L, arg, lua_typename(L, tag));
 }
 
 
+/*
+** The use of 'lua_pushfstring' ensures this function does not
+** need reserved stack space when called.
+*/
 LUALIB_API void luaL_where (lua_State *L, int level) {
   lua_Debug ar;
   if (lua_getstack(L, level, &ar)) {  /* check function at level */
@@ -189,10 +212,15 @@ LUALIB_API void luaL_where (lua_State *L, int level) {
       return;
     }
   }
-  lua_pushliteral(L, "");  /* else, no information available... */
+  lua_pushfstring(L, "");  /* else, no information available... */
 }
 
 
+/*
+** Again, the use of 'lua_pushvfstring' ensures this function does
+** not need reserved stack space when called. (At worst, it generates
+** an error with "stack overflow" instead of the given message.)
+*/
 LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
   va_list argp;
   va_start(argp, fmt);
@@ -222,7 +250,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
 }
 
 
-#if !defined(inspectstat)      /* { */
+#if !defined(l_inspectstat)    /* { */
 
 #if defined(LUA_USE_POSIX)
 
@@ -231,13 +259,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
 /*
 ** use appropriate macros to interpret 'pclose' return status
 */
-#define inspectstat(stat,what)  \
+#define l_inspectstat(stat,what)  \
    if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
    else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
 
 #else
 
-#define inspectstat(stat,what)  /* no op */
+#define l_inspectstat(stat,what)  /* no op */
 
 #endif
 
@@ -249,7 +277,7 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
   if (stat == -1)  /* error? */
     return luaL_fileresult(L, 0, NULL);
   else {
-    inspectstat(stat, what);  /* interpret result */
+    l_inspectstat(stat, what);  /* interpret result */
     if (*what == 'e' && stat == 0)  /* successful termination? */
       lua_pushboolean(L, 1);
     else
@@ -270,11 +298,12 @@ LUALIB_API int luaL_execresult (lua_State *L, int stat) {
 */
 
 LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
-  luaL_getmetatable(L, tname);  /* try to get metatable */
-  if (!lua_isnil(L, -1))  /* 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 */
+  lua_createtable(L, 0, 2);  /* create metatable */
+  lua_pushstring(L, tname);
+  lua_setfield(L, -2, "__name");  /* metatable.__name = tname */
   lua_pushvalue(L, -1);
   lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
   return 1;
@@ -317,23 +346,28 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
 ** =======================================================
 */
 
-LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
+LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
                                  const char *const lst[]) {
-  const char *name = (def) ? luaL_optstring(L, narg, def) :
-                             luaL_checkstring(L, narg);
+  const char *name = (def) ? luaL_optstring(L, arg, def) :
+                             luaL_checkstring(L, arg);
   int i;
   for (i=0; lst[i]; i++)
     if (strcmp(lst[i], name) == 0)
       return i;
-  return luaL_argerror(L, narg,
-                       lua_pushfstring(L, "invalid option " LUA_QS, name));
+  return luaL_argerror(L, arg,
+                       lua_pushfstring(L, "invalid option '%s'", name));
 }
 
 
+/*
+** Ensures the stack has at least 'space' extra slots, raising an error
+** if it cannot fulfill the request. (The error handling needs a few
+** extra slots to format the error message. In case of an error without
+** this extra space, Lua will generate the same 'stack overflow' error,
+** but without 'msg'.)
+*/
 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
-  /* keep some extra space to run error routines, if needed */
-  const int extra = LUA_MINSTACK;
-  if (!lua_checkstack(L, space + extra)) {
+  if (!lua_checkstack(L, space)) {
     if (msg)
       luaL_error(L, "stack overflow (%s)", msg);
     else
@@ -342,77 +376,71 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
 }
 
 
-LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
-  if (lua_type(L, narg) != t)
-    tag_error(L, narg, t);
+LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
+  if (lua_type(L, arg) != t)
+    tag_error(L, arg, t);
 }
 
 
-LUALIB_API void luaL_checkany (lua_State *L, int narg) {
-  if (lua_type(L, narg) == LUA_TNONE)
-    luaL_argerror(L, narg, "value expected");
+LUALIB_API void luaL_checkany (lua_State *L, int arg) {
+  if (lua_type(L, arg) == LUA_TNONE)
+    luaL_argerror(L, arg, "value expected");
 }
 
 
-LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
-  const char *s = lua_tolstring(L, narg, len);
-  if (!s) tag_error(L, narg, LUA_TSTRING);
+LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
+  const char *s = lua_tolstring(L, arg, len);
+  if (!s) tag_error(L, arg, LUA_TSTRING);
   return s;
 }
 
 
-LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
+LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
                                         const char *def, size_t *len) {
-  if (lua_isnoneornil(L, narg)) {
+  if (lua_isnoneornil(L, arg)) {
     if (len)
       *len = (def ? strlen(def) : 0);
     return def;
   }
-  else return luaL_checklstring(L, narg, len);
+  else return luaL_checklstring(L, arg, len);
 }
 
 
-LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
   int isnum;
-  lua_Number d = lua_tonumberx(L, narg, &isnum);
+  lua_Number d = lua_tonumberx(L, arg, &isnum);
   if (!isnum)
-    tag_error(L, narg, LUA_TNUMBER);
+    tag_error(L, arg, LUA_TNUMBER);
   return d;
 }
 
 
-LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
-  return luaL_opt(L, luaL_checknumber, narg, def);
+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
+  return luaL_opt(L, luaL_checknumber, arg, def);
 }
 
 
-LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
-  int isnum;
-  lua_Integer d = lua_tointegerx(L, narg, &isnum);
-  if (!isnum)
-    tag_error(L, narg, LUA_TNUMBER);
-  return d;
+static void interror (lua_State *L, int arg) {
+  if (lua_isnumber(L, arg))
+    luaL_argerror(L, arg, "number has no integer representation");
+  else
+    tag_error(L, arg, LUA_TNUMBER);
 }
 
 
-LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) {
+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
   int isnum;
-  lua_Unsigned d = lua_tounsignedx(L, narg, &isnum);
-  if (!isnum)
-    tag_error(L, narg, LUA_TNUMBER);
+  lua_Integer d = lua_tointegerx(L, arg, &isnum);
+  if (!isnum) {
+    interror(L, arg);
+  }
   return d;
 }
 
 
-LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
                                                       lua_Integer def) {
-  return luaL_opt(L, luaL_checkinteger, narg, def);
-}
-
-
-LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
-                                                        lua_Unsigned def) {
-  return luaL_opt(L, luaL_checkunsigned, narg, def);
+  return luaL_opt(L, luaL_checkinteger, arg, def);
 }
 
 /* }====================================================== */
@@ -424,6 +452,47 @@ LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg,
 ** =======================================================
 */
 
+/* userdata to box arbitrary data */
+typedef struct UBox {
+  void *box;
+  size_t bsize;
+} UBox;
+
+
+static void *resizebox (lua_State *L, int idx, size_t newsize) {
+  void *ud;
+  lua_Alloc allocf = lua_getallocf(L, &ud);
+  UBox *box = (UBox *)lua_touserdata(L, idx);
+  void *temp = allocf(ud, box->box, box->bsize, newsize);
+  if (temp == NULL && newsize > 0) {  /* allocation error? */
+    resizebox(L, idx, 0);  /* free buffer */
+    luaL_error(L, "not enough memory for buffer allocation");
+  }
+  box->box = temp;
+  box->bsize = newsize;
+  return temp;
+}
+
+
+static int boxgc (lua_State *L) {
+  resizebox(L, 1, 0);
+  return 0;
+}
+
+
+static void *newbox (lua_State *L, size_t newsize) {
+  UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
+  box->box = NULL;
+  box->bsize = 0;
+  if (luaL_newmetatable(L, "LUABOX")) {  /* creating metatable? */
+    lua_pushcfunction(L, boxgc);
+    lua_setfield(L, -2, "__gc");  /* metatable.__gc = boxgc */
+  }
+  lua_setmetatable(L, -2);
+  return resizebox(L, -1, newsize);
+}
+
+
 /*
 ** check whether buffer is using a userdata on the stack as a temporary
 ** buffer
@@ -444,11 +513,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
     if (newsize < B->n || newsize - B->n < sz)
       luaL_error(L, "buffer too large");
     /* create larger buffer */
-    newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
-    /* move content to new buffer */
-    memcpy(newbuff, B->b, B->n * sizeof(char));
     if (buffonstack(B))
-      lua_remove(L, -2);  /* remove old buffer */
+      newbuff = (char *)resizebox(L, -1, newsize);
+    else {  /* no buffer yet */
+      newbuff = (char *)newbox(L, newsize);
+      memcpy(newbuff, B->b, B->n * sizeof(char));  /* copy original content */
+    }
     B->b = newbuff;
     B->size = newsize;
   }
@@ -457,9 +527,11 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
 
 
 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
-  char *b = luaL_prepbuffsize(B, l);
-  memcpy(b, s, l * sizeof(char));
-  luaL_addsize(B, l);
+  if (l > 0) {  /* avoid 'memcpy' when 's' can be NULL */
+    char *b = luaL_prepbuffsize(B, l);
+    memcpy(b, s, l * sizeof(char));
+    luaL_addsize(B, l);
+  }
 }
 
 
@@ -471,8 +543,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
 LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
   lua_State *L = B->L;
   lua_pushlstring(L, B->b, B->n);
-  if (buffonstack(B))
-    lua_remove(L, -2);  /* remove old buffer */
+  if (buffonstack(B)) {
+    resizebox(L, -2, 0);  /* delete old buffer */
+    lua_remove(L, -2);  /* remove its header from the stack */
+  }
 }
 
 
@@ -523,7 +597,7 @@ LUALIB_API int luaL_ref (lua_State *L, int t) {
   int ref;
   if (lua_isnil(L, -1)) {
     lua_pop(L, 1);  /* remove from stack */
-    return LUA_REFNIL;  /* `nil' has a unique fixed reference */
+    return LUA_REFNIL;  /* 'nil' has a unique fixed reference */
   }
   t = lua_absindex(L, t);
   lua_rawgeti(L, t, freelist);  /* get first free element */
@@ -562,7 +636,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
 typedef struct LoadF {
   int n;  /* number of pre-read characters */
   FILE *f;  /* file being read */
-  char buff[LUAL_BUFFERSIZE];  /* area for reading file */
+  char buff[BUFSIZ];  /* area for reading file */
 } LoadF;
 
 
@@ -594,7 +668,7 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
 
 
 static int skipBOM (LoadF *lf) {
-  const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
+  const char *p = "\xEF\xBB\xBF";  /* UTF-8 BOM mark */
   int c;
   lf->n = 0;
   do {
@@ -619,7 +693,7 @@ static int skipcomment (LoadF *lf, int *cp) {
   if (c == '#') {  /* first line is a comment (Unix exec. file)? */
     do {  /* skip first line */
       c = getc(lf->f);
-    } while (c != EOF && c != '\n') ;
+    } while (c != EOF && c != '\n');
     *cp = getc(lf->f);  /* skip end-of-line, if present */
     return 1;  /* there was a comment */
   }
@@ -655,7 +729,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
   readstatus = ferror(lf.f);
   if (filename) fclose(lf.f);  /* close file (even in case of errors) */
   if (readstatus) {
-    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
+    lua_settop(L, fnameindex);  /* ignore results from 'lua_load' */
     return errfile(L, "read", fnameindex);
   }
   lua_remove(L, fnameindex);
@@ -698,23 +772,23 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
 
 LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
   if (!lua_getmetatable(L, obj))  /* no metatable? */
-    return 0;
-  lua_pushstring(L, event);
-  lua_rawget(L, -2);
-  if (lua_isnil(L, -1)) {
-    lua_pop(L, 2);  /* remove metatable and metafield */
-    return 0;
-  }
+    return LUA_TNIL;
   else {
-    lua_remove(L, -2);  /* remove only metatable */
-    return 1;
+    int tt;
+    lua_pushstring(L, event);
+    tt = lua_rawget(L, -2);
+    if (tt == LUA_TNIL)  /* is metafield nil? */
+      lua_pop(L, 2);  /* remove metatable and metafield */
+    else
+      lua_remove(L, -2);  /* remove only metatable */
+    return tt;  /* return metafield type */
   }
 }
 
 
 LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
   obj = lua_absindex(L, obj);
-  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
+  if (luaL_getmetafield(L, obj, event) == LUA_TNIL)  /* no metafield? */
     return 0;
   lua_pushvalue(L, obj);
   lua_call(L, 1, 1);
@@ -722,13 +796,13 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
 }
 
 
-LUALIB_API int luaL_len (lua_State *L, int idx) {
-  int l;
+LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
+  lua_Integer l;
   int isnum;
   lua_len(L, idx);
-  l = (int)lua_tointegerx(L, -1, &isnum);
+  l = lua_tointegerx(L, -1, &isnum);
   if (!isnum)
-    luaL_error(L, "object length is not a number");
+    luaL_error(L, "object length is not an integer");
   lua_pop(L, 1);  /* remove object */
   return l;
 }
@@ -737,7 +811,13 @@ LUALIB_API int luaL_len (lua_State *L, int idx) {
 LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
   if (!luaL_callmeta(L, idx, "__tostring")) {  /* no metafield? */
     switch (lua_type(L, idx)) {
-      case LUA_TNUMBER:
+      case LUA_TNUMBER: {
+        if (lua_isinteger(L, idx))
+          lua_pushfstring(L, "%I", lua_tointeger(L, idx));
+        else
+          lua_pushfstring(L, "%f", lua_tonumber(L, idx));
+        break;
+      }
       case LUA_TSTRING:
         lua_pushvalue(L, idx);
         break;
@@ -772,8 +852,7 @@ static const char *luaL_findtable (lua_State *L, int idx,
     e = strchr(fname, '.');
     if (e == NULL) e = fname + strlen(fname);
     lua_pushlstring(L, fname, e - fname);
-    lua_rawget(L, -2);
-    if (lua_isnil(L, -1)) {  /* no such field? */
+    if (lua_rawget(L, -2) == LUA_TNIL) {  /* no such field? */
       lua_pop(L, 1);  /* remove this nil */
       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
       lua_pushlstring(L, fname, e - fname);
@@ -810,13 +889,12 @@ static int libsize (const luaL_Reg *l) {
 LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
                                  int sizehint) {
   luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);  /* get _LOADED table */
-  lua_getfield(L, -1, modname);  /* get _LOADED[modname] */
-  if (!lua_istable(L, -1)) {  /* not found? */
+  if (lua_getfield(L, -1, modname) != LUA_TTABLE) {  /* no _LOADED[modname]? */
     lua_pop(L, 1);  /* remove previous result */
     /* try global variable (and create one if it does not exist) */
     lua_pushglobaltable(L);
     if (luaL_findtable(L, 0, modname, sizehint) != NULL)
-      luaL_error(L, "name conflict for module " LUA_QS, modname);
+      luaL_error(L, "name conflict for module '%s'", modname);
     lua_pushvalue(L, -1);
     lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table */
   }
@@ -846,7 +924,6 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
 ** Returns with only the table at the stack.
 */
 LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
-  luaL_checkversion(L);
   luaL_checkstack(L, nup, "too many upvalues");
   for (; l->name != NULL; l++) {  /* fill the table with given functions */
     int i;
@@ -864,8 +941,8 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
 ** into the stack
 */
 LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
-  lua_getfield(L, idx, fname);
-  if (lua_istable(L, -1)) return 1;  /* table already there */
+  if (lua_getfield(L, idx, fname) == LUA_TTABLE)
+    return 1;  /* table already there */
   else {
     lua_pop(L, 1);  /* remove previous result */
     idx = lua_absindex(L, idx);
@@ -878,22 +955,26 @@ LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
 
 
 /*
-** stripped-down 'require'. Calls 'openf' to open a module,
-** registers the result in 'package.loaded' table and, if 'glb'
-** is true, also registers the result in the global table.
+** Stripped-down 'require': After checking "loaded" table, calls 'openf'
+** to open a module, registers the result in 'package.loaded' table and,
+** if 'glb' is true, also registers the result in the global table.
 ** Leaves resulting module on the top.
 */
 LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
                                lua_CFunction openf, int glb) {
-  lua_pushcfunction(L, openf);
-  lua_pushstring(L, modname);  /* argument to open function */
-  lua_call(L, 1, 1);  /* open module */
   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
-  lua_pushvalue(L, -2);  /* make copy of module (call result) */
-  lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
-  lua_pop(L, 1);  /* remove _LOADED table */
+  lua_getfield(L, -1, modname);  /* _LOADED[modname] */
+  if (!lua_toboolean(L, -1)) {  /* package not already loaded? */
+    lua_pop(L, 1);  /* remove field */
+    lua_pushcfunction(L, openf);
+    lua_pushstring(L, modname);  /* argument to open function */
+    lua_call(L, 1, 1);  /* call 'openf' to open module */
+    lua_pushvalue(L, -1);  /* make copy of module (call result) */
+    lua_setfield(L, -3, modname);  /* _LOADED[modname] = module */
+  }
+  lua_remove(L, -2);  /* remove _LOADED table */
   if (glb) {
-    lua_pushvalue(L, -1);  /* copy of 'mod' */
+    lua_pushvalue(L, -1);  /* copy of module */
     lua_setglobal(L, modname);  /* _G[modname] = module */
   }
 }
@@ -908,7 +989,7 @@ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
   while ((wild = strstr(s, p)) != NULL) {
     luaL_addlstring(&b, s, wild - s);  /* push prefix */
     luaL_addstring(&b, r);  /* push replacement in place of pattern */
-    s = wild + l;  /* continue after `p' */
+    s = wild + l;  /* continue after 'p' */
   }
   luaL_addstring(&b, s);  /* push last suffix */
   luaL_pushresult(&b);
@@ -928,8 +1009,8 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
 
 
 static int panic (lua_State *L) {
-  luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
-                   lua_tostring(L, -1));
+  lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
+                        lua_tostring(L, -1));
   return 0;  /* return to Lua to abort */
 }
 
@@ -941,19 +1022,14 @@ LUALIB_API lua_State *luaL_newstate (void) {
 }
 
 
-LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
+LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
   const lua_Number *v = lua_version(L);
+  if (sz != LUAL_NUMSIZES)  /* check numeric types */
+    luaL_error(L, "core and library have incompatible numeric types");
   if (v != lua_version(NULL))
     luaL_error(L, "multiple Lua VMs detected");
   else if (*v != ver)
     luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
                   ver, *v);
-  /* check conversions number -> integer types */
-  lua_pushnumber(L, -(lua_Number)0x1234);
-  if (lua_tointeger(L, -1) != -0x1234 ||
-      lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
-    luaL_error(L, "bad conversion number->int;"
-                  " must recompile Lua with proper settings");
-  lua_pop(L, 1);
 }
 
index 0fb023b..ddb7c22 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */
@@ -16,7 +16,7 @@
 
 
 
-/* extra error code for `luaL_load' */
+/* extra error code for 'luaL_load' */
 #define LUA_ERRFILE     (LUA_ERRERR+1)
 
 
@@ -26,30 +26,30 @@ typedef struct luaL_Reg {
 } luaL_Reg;
 
 
-LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver);
-#define luaL_checkversion(L)   luaL_checkversion_(L, LUA_VERSION_NUM)
+#define LUAL_NUMSIZES  (sizeof(lua_Integer)*16 + sizeof(lua_Number))
+
+LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
+#define luaL_checkversion(L)  \
+         luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
 
 LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
 LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
 LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
-LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
-LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
+LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
                                                           size_t *l);
-LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
                                           const char *def, size_t *l);
-LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
-LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
 
-LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
-LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
                                           lua_Integer def);
-LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg);
-LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg,
-                                            lua_Unsigned def);
 
 LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
-LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
-LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
+LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
+LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
 
 LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);
 LUALIB_API void  (luaL_setmetatable) (lua_State *L, const char *tname);
@@ -59,13 +59,13 @@ LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
 LUALIB_API void (luaL_where) (lua_State *L, int lvl);
 LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
 
-LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
+LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
                                    const char *const lst[]);
 
 LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
 LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
 
-/* pre-defined references */
+/* predefined references */
 #define LUA_NOREF       (-2)
 #define LUA_REFNIL      (-1)
 
@@ -83,7 +83,7 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
 
 LUALIB_API lua_State *(luaL_newstate) (void);
 
-LUALIB_API int (luaL_len) (lua_State *L, int idx);
+LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
 
 LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
                                                   const char *r);
@@ -108,16 +108,13 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
 #define luaL_newlibtable(L,l)  \
   lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
 
-#define luaL_newlib(L,l)       (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
+#define luaL_newlib(L,l)  \
+  (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
 
-#define luaL_argcheck(L, cond,numarg,extramsg) \
-               ((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
+#define luaL_argcheck(L, cond,arg,extramsg)    \
+               ((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
 #define luaL_checkstring(L,n)  (luaL_checklstring(L, (n), NULL))
 #define luaL_optstring(L,n,d)  (luaL_optlstring(L, (n), (d), NULL))
-#define luaL_checkint(L,n)     ((int)luaL_checkinteger(L, (n)))
-#define luaL_optint(L,n,d)     ((int)luaL_optinteger(L, (n), (d)))
-#define luaL_checklong(L,n)    ((long)luaL_checkinteger(L, (n)))
-#define luaL_optlong(L,n,d)    ((long)luaL_optinteger(L, (n), (d)))
 
 #define luaL_typename(L,i)     lua_typename(L, lua_type(L,(i)))
 
@@ -207,6 +204,53 @@ LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
 #endif
 
 
+/*
+** {==================================================================
+** "Abstraction Layer" for basic report of messages and errors
+** ===================================================================
+*/
+
+/* print a string */
+#if !defined(lua_writestring)
+#define lua_writestring(s,l)   fwrite((s), sizeof(char), (l), stdout)
+#endif
+
+/* print a newline and flush the output */
+#if !defined(lua_writeline)
+#define lua_writeline()        (lua_writestring("\n", 1), fflush(stdout))
+#endif
+
+/* print an error message */
+#if !defined(lua_writestringerror)
+#define lua_writestringerror(s,p) \
+        (fprintf(stderr, (s), (p)), fflush(stderr))
+#endif
+
+/* }================================================================== */
+
+
+/*
+** {============================================================
+** Compatibility with deprecated conversions
+** =============================================================
+*/
+#if defined(LUA_COMPAT_APIINTCASTS)
+
+#define luaL_checkunsigned(L,a)        ((lua_Unsigned)luaL_checkinteger(L,a))
+#define luaL_optunsigned(L,a,d)        \
+       ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
+
+#define luaL_checkint(L,n)     ((int)luaL_checkinteger(L, (n)))
+#define luaL_optint(L,n,d)     ((int)luaL_optinteger(L, (n), (d)))
+
+#define luaL_checklong(L,n)    ((long)luaL_checkinteger(L, (n)))
+#define luaL_optlong(L,n,d)    ((long)luaL_optinteger(L, (n), (d)))
+
+#endif
+/* }============================================================ */
+
+
+
 #endif
 
 
index 5255b3c..d481c4e 100644 (file)
@@ -1,9 +1,13 @@
 /*
-** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
 
+#define lbaselib_c
+#define LUA_LIB
+
+#include "lprefix.h"
 
 
 #include <ctype.h>
@@ -11,9 +15,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#define lbaselib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
@@ -32,65 +33,77 @@ static int luaB_print (lua_State *L) {
     lua_call(L, 1, 1);
     s = lua_tolstring(L, -1, &l);  /* get result */
     if (s == NULL)
-      return luaL_error(L,
-         LUA_QL("tostring") " must return a string to " LUA_QL("print"));
-    if (i>1) luai_writestring("\t", 1);
-    luai_writestring(s, l);
+      return luaL_error(L, "'tostring' must return a string to 'print'");
+    if (i>1) lua_writestring("\t", 1);
+    lua_writestring(s, l);
     lua_pop(L, 1);  /* pop result */
   }
-  luai_writeline();
+  lua_writeline();
   return 0;
 }
 
 
 #define SPACECHARS     " \f\n\r\t\v"
 
+static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
+  lua_Unsigned n = 0;
+  int neg = 0;
+  s += strspn(s, SPACECHARS);  /* skip initial spaces */
+  if (*s == '-') { s++; neg = 1; }  /* handle signal */
+  else if (*s == '+') s++;
+  if (!isalnum((unsigned char)*s))  /* no digit? */
+    return NULL;
+  do {
+    int digit = (isdigit((unsigned char)*s)) ? *s - '0'
+                   : (toupper((unsigned char)*s) - 'A') + 10;
+    if (digit >= base) return NULL;  /* invalid numeral */
+    n = n * base + digit;
+    s++;
+  } while (isalnum((unsigned char)*s));
+  s += strspn(s, SPACECHARS);  /* skip trailing spaces */
+  *pn = (lua_Integer)((neg) ? (0u - n) : n);
+  return s;
+}
+
+
 static int luaB_tonumber (lua_State *L) {
-  if (lua_isnoneornil(L, 2)) {  /* standard conversion */
-    int isnum;
-    lua_Number n = lua_tonumberx(L, 1, &isnum);
-    if (isnum) {
-      lua_pushnumber(L, n);
-      return 1;
-    }  /* else not a number; must be something */
+  if (lua_isnoneornil(L, 2)) {  /* standard conversion? */
     luaL_checkany(L, 1);
+    if (lua_type(L, 1) == LUA_TNUMBER) {  /* already a number? */
+      lua_settop(L, 1);  /* yes; return it */
+      return 1;
+    }
+    else {
+      size_t l;
+      const char *s = lua_tolstring(L, 1, &l);
+      if (s != NULL && lua_stringtonumber(L, s) == l + 1)
+        return 1;  /* successful conversion to number */
+      /* else not a number */
+    }
   }
   else {
     size_t l;
-    const char *s = luaL_checklstring(L, 1, &l);
-    const char *e = s + l;  /* end point for 's' */
-    int base = luaL_checkint(L, 2);
-    int neg = 0;
+    const char *s;
+    lua_Integer n = 0;  /* to avoid warnings */
+    lua_Integer base = luaL_checkinteger(L, 2);
+    luaL_checktype(L, 1, LUA_TSTRING);  /* no numbers as strings */
+    s = lua_tolstring(L, 1, &l);
     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
-    s += strspn(s, SPACECHARS);  /* skip initial spaces */
-    if (*s == '-') { s++; neg = 1; }  /* handle signal */
-    else if (*s == '+') s++;
-    if (isalnum((unsigned char)*s)) {
-      lua_Number n = 0;
-      do {
-        int digit = (isdigit((unsigned char)*s)) ? *s - '0'
-                       : toupper((unsigned char)*s) - 'A' + 10;
-        if (digit >= base) break;  /* invalid numeral; force a fail */
-        n = n * (lua_Number)base + (lua_Number)digit;
-        s++;
-      } while (isalnum((unsigned char)*s));
-      s += strspn(s, SPACECHARS);  /* skip trailing spaces */
-      if (s == e) {  /* no invalid trailing characters? */
-        lua_pushnumber(L, (neg) ? -n : n);
-        return 1;
-      }  /* else not a number */
+    if (b_str2int(s, (int)base, &n) == s + l) {
+      lua_pushinteger(L, n);
+      return 1;
     }  /* else not a number */
-  }
+  }  /* else not a number */
   lua_pushnil(L);  /* not a number */
   return 1;
 }
 
 
 static int luaB_error (lua_State *L) {
-  int level = luaL_optint(L, 2, 1);
+  int level = (int)luaL_optinteger(L, 2, 1);
   lua_settop(L, 1);
-  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
-    luaL_where(L, level);
+  if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
+    luaL_where(L, level);   /* add extra information */
     lua_pushvalue(L, 1);
     lua_concat(L, 2);
   }
@@ -114,7 +127,7 @@ static int luaB_setmetatable (lua_State *L) {
   luaL_checktype(L, 1, LUA_TTABLE);
   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
                     "nil or table expected");
-  if (luaL_getmetafield(L, 1, "__metatable"))
+  if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
     return luaL_error(L, "cannot change a protected metatable");
   lua_settop(L, 2);
   lua_setmetatable(L, 1);
@@ -160,19 +173,18 @@ static int luaB_rawset (lua_State *L) {
 static int luaB_collectgarbage (lua_State *L) {
   static const char *const opts[] = {"stop", "restart", "collect",
     "count", "step", "setpause", "setstepmul",
-    "setmajorinc", "isrunning", "generational", "incremental", NULL};
+    "isrunning", NULL};
   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
     LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
-    LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
+    LUA_GCISRUNNING};
   int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
-  int ex = luaL_optint(L, 2, 0);
+  int ex = (int)luaL_optinteger(L, 2, 0);
   int res = lua_gc(L, o, ex);
   switch (o) {
     case LUA_GCCOUNT: {
       int b = lua_gc(L, LUA_GCCOUNTB, 0);
-      lua_pushnumber(L, res + ((lua_Number)b/1024));
-      lua_pushinteger(L, b);
-      return 2;
+      lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024));
+      return 1;
     }
     case LUA_GCSTEP: case LUA_GCISRUNNING: {
       lua_pushboolean(L, res);
@@ -187,15 +199,16 @@ static int luaB_collectgarbage (lua_State *L) {
 
 
 static int luaB_type (lua_State *L) {
-  luaL_checkany(L, 1);
-  lua_pushstring(L, luaL_typename(L, 1));
+  int t = lua_type(L, 1);
+  luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
+  lua_pushstring(L, lua_typename(L, t));
   return 1;
 }
 
 
 static int pairsmeta (lua_State *L, const char *method, int iszero,
                       lua_CFunction iter) {
-  if (!luaL_getmetafield(L, 1, method)) {  /* no metamethod? */
+  if (luaL_getmetafield(L, 1, method) == LUA_TNIL) {  /* no metamethod? */
     luaL_checktype(L, 1, LUA_TTABLE);  /* argument must be a table */
     lua_pushcfunction(L, iter);  /* will return generator, */
     lua_pushvalue(L, 1);  /* state, */
@@ -227,18 +240,30 @@ static int luaB_pairs (lua_State *L) {
 }
 
 
+/*
+** Traversal function for 'ipairs'
+*/
 static int ipairsaux (lua_State *L) {
-  int i = luaL_checkint(L, 2);
-  luaL_checktype(L, 1, LUA_TTABLE);
-  i++;  /* next value */
+  lua_Integer i = luaL_checkinteger(L, 2) + 1;
   lua_pushinteger(L, i);
-  lua_rawgeti(L, 1, i);
-  return (lua_isnil(L, -1)) ? 1 : 2;
+  return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
 }
 
 
+/*
+** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
+** (The given "table" may not be a table.)
+*/
 static int luaB_ipairs (lua_State *L) {
+#if defined(LUA_COMPAT_IPAIRS)
   return pairsmeta(L, "__ipairs", 1, ipairsaux);
+#else
+  luaL_checkany(L, 1);
+  lua_pushcfunction(L, ipairsaux);  /* iteration function */
+  lua_pushvalue(L, 1);  /* state */
+  lua_pushinteger(L, 0);  /* initial value */
+  return 3;
+#endif
 }
 
 
@@ -284,7 +309,7 @@ static int luaB_loadfile (lua_State *L) {
 
 
 /*
-** Reader for generic `load' function: `lua_load' uses the
+** Reader for generic 'load' function: 'lua_load' uses the
 ** stack for internal stuff, so the reader cannot change the
 ** stack top. Instead, it keeps its resulting string in a
 ** reserved slot inside the stack.
@@ -328,7 +353,8 @@ static int luaB_load (lua_State *L) {
 /* }====================================================== */
 
 
-static int dofilecont (lua_State *L) {
+static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
+  (void)d1;  (void)d2;  /* only to match 'lua_Kfunction' prototype */
   return lua_gettop(L) - 1;
 }
 
@@ -339,14 +365,20 @@ static int luaB_dofile (lua_State *L) {
   if (luaL_loadfile(L, fname) != LUA_OK)
     return lua_error(L);
   lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
-  return dofilecont(L);
+  return dofilecont(L, 0, 0);
 }
 
 
 static int luaB_assert (lua_State *L) {
-  if (!lua_toboolean(L, 1))
-    return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
-  return lua_gettop(L);
+  if (lua_toboolean(L, 1))  /* condition is true? */
+    return lua_gettop(L);  /* return all arguments */
+  else {  /* error */
+    luaL_checkany(L, 1);  /* there must be a condition */
+    lua_remove(L, 1);  /* remove it */
+    lua_pushliteral(L, "assertion failed!");  /* default message */
+    lua_settop(L, 1);  /* leave only message (default if no other one) */
+    return luaB_error(L);  /* call 'error' */
+  }
 }
 
 
@@ -357,53 +389,57 @@ static int luaB_select (lua_State *L) {
     return 1;
   }
   else {
-    int i = luaL_checkint(L, 1);
+    lua_Integer i = luaL_checkinteger(L, 1);
     if (i < 0) i = n + i;
     else if (i > n) i = n;
     luaL_argcheck(L, 1 <= i, 1, "index out of range");
-    return n - i;
+    return n - (int)i;
   }
 }
 
 
-static int finishpcall (lua_State *L, int status) {
-  if (!lua_checkstack(L, 1)) {  /* no space for extra boolean? */
-    lua_settop(L, 0);  /* create space for return values */
-    lua_pushboolean(L, 0);
-    lua_pushstring(L, "stack overflow");
+/*
+** Continuation function for 'pcall' and 'xpcall'. Both functions
+** already pushed a 'true' before doing the call, so in case of success
+** 'finishpcall' only has to return everything in the stack minus
+** 'extra' values (where 'extra' is exactly the number of items to be
+** ignored).
+*/
+static int finishpcall (lua_State *L, int status, lua_KContext extra) {
+  if (status != LUA_OK && status != LUA_YIELD) {  /* error? */
+    lua_pushboolean(L, 0);  /* first result (false) */
+    lua_pushvalue(L, -2);  /* error message */
     return 2;  /* return false, msg */
   }
-  lua_pushboolean(L, status);  /* first result (status) */
-  lua_replace(L, 1);  /* put first result in first slot */
-  return lua_gettop(L);
-}
-
-
-static int pcallcont (lua_State *L) {
-  int status = lua_getctx(L, NULL);
-  return finishpcall(L, (status == LUA_YIELD));
+  else
+    return lua_gettop(L) - (int)extra;  /* return all results */
 }
 
 
 static int luaB_pcall (lua_State *L) {
   int status;
   luaL_checkany(L, 1);
-  lua_pushnil(L);
-  lua_insert(L, 1);  /* create space for status result */
-  status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
-  return finishpcall(L, (status == LUA_OK));
+  lua_pushboolean(L, 1);  /* first result if no errors */
+  lua_insert(L, 1);  /* put it in place */
+  status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
+  return finishpcall(L, status, 0);
 }
 
 
+/*
+** Do a protected call with error handling. After 'lua_rotate', the
+** stack will have <f, err, true, f, [args...]>; so, the function passes
+** 2 to 'finishpcall' to skip the 2 first values when returning results.
+*/
 static int luaB_xpcall (lua_State *L) {
   int status;
   int n = lua_gettop(L);
-  luaL_argcheck(L, n >= 2, 2, "value expected");
-  lua_pushvalue(L, 1);  /* exchange function... */
-  lua_copy(L, 2, 1);  /* ...and error handler */
-  lua_replace(L, 2);
-  status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont);
-  return finishpcall(L, (status == LUA_OK));
+  luaL_checktype(L, 2, LUA_TFUNCTION);  /* check error function */
+  lua_pushboolean(L, 1);  /* first result */
+  lua_pushvalue(L, 1);  /* function */
+  lua_rotate(L, 3, 2);  /* move them below function's arguments */
+  status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
+  return finishpcall(L, status, 2);
 }
 
 
@@ -440,19 +476,23 @@ static const luaL_Reg base_funcs[] = {
   {"tostring", luaB_tostring},
   {"type", luaB_type},
   {"xpcall", luaB_xpcall},
+  /* placeholders */
+  {"_G", NULL},
+  {"_VERSION", NULL},
   {NULL, NULL}
 };
 
 
 LUAMOD_API int luaopen_base (lua_State *L) {
-  /* set global _G */
-  lua_pushglobaltable(L);
-  lua_pushglobaltable(L);
-  lua_setfield(L, -2, "_G");
   /* open lib into global table */
+  lua_pushglobaltable(L);
   luaL_setfuncs(L, base_funcs, 0);
+  /* set global _G */
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "_G");
+  /* set global _VERSION */
   lua_pushliteral(L, LUA_VERSION);
-  lua_setfield(L, -2, "_VERSION");  /* set global _VERSION */
+  lua_setfield(L, -2, "_VERSION");
   return 1;
 }
 
index 31c7b66..1cb1d5b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $
+** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $
 ** Standard library for bitwise operations
 ** See Copyright Notice in lua.h
 */
@@ -7,20 +7,36 @@
 #define lbitlib_c
 #define LUA_LIB
 
+#include "lprefix.h"
+
+
 #include "lua.h"
 
 #include "lauxlib.h"
 #include "lualib.h"
 
 
+#if defined(LUA_COMPAT_BITLIB)         /* { */
+
+
+#define pushunsigned(L,n)      lua_pushinteger(L, (lua_Integer)(n))
+#define checkunsigned(L,i)     ((lua_Unsigned)luaL_checkinteger(L,i))
+
+
 /* number of bits to consider in a number */
 #if !defined(LUA_NBITS)
 #define LUA_NBITS      32
 #endif
 
 
+/*
+** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
+** be made in two parts to avoid problems when LUA_NBITS is equal to the
+** number of bits in a lua_Unsigned.)
+*/
 #define ALLONES                (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
 
+
 /* macro to trim extra bits */
 #define trim(x)                ((x) & ALLONES)
 
 #define mask(n)                (~((ALLONES << 1) << ((n) - 1)))
 
 
-typedef lua_Unsigned b_uint;
 
-
-
-static b_uint andaux (lua_State *L) {
+static lua_Unsigned andaux (lua_State *L) {
   int i, n = lua_gettop(L);
-  b_uint r = ~(b_uint)0;
+  lua_Unsigned r = ~(lua_Unsigned)0;
   for (i = 1; i <= n; i++)
-    r &= luaL_checkunsigned(L, i);
+    r &= checkunsigned(L, i);
   return trim(r);
 }
 
 
 static int b_and (lua_State *L) {
-  b_uint r = andaux(L);
-  lua_pushunsigned(L, r);
+  lua_Unsigned r = andaux(L);
+  pushunsigned(L, r);
   return 1;
 }
 
 
 static int b_test (lua_State *L) {
-  b_uint r = andaux(L);
+  lua_Unsigned r = andaux(L);
   lua_pushboolean(L, r != 0);
   return 1;
 }
@@ -58,32 +71,32 @@ static int b_test (lua_State *L) {
 
 static int b_or (lua_State *L) {
   int i, n = lua_gettop(L);
-  b_uint r = 0;
+  lua_Unsigned r = 0;
   for (i = 1; i <= n; i++)
-    r |= luaL_checkunsigned(L, i);
-  lua_pushunsigned(L, trim(r));
+    r |= checkunsigned(L, i);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
 
 static int b_xor (lua_State *L) {
   int i, n = lua_gettop(L);
-  b_uint r = 0;
+  lua_Unsigned r = 0;
   for (i = 1; i <= n; i++)
-    r ^= luaL_checkunsigned(L, i);
-  lua_pushunsigned(L, trim(r));
+    r ^= checkunsigned(L, i);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
 
 static int b_not (lua_State *L) {
-  b_uint r = ~luaL_checkunsigned(L, 1);
-  lua_pushunsigned(L, trim(r));
+  lua_Unsigned r = ~checkunsigned(L, 1);
+  pushunsigned(L, trim(r));
   return 1;
 }
 
 
-static int b_shift (lua_State *L, b_uint r, int i) {
+static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
   if (i < 0) {  /* shift right? */
     i = -i;
     r = trim(r);
@@ -95,54 +108,54 @@ static int b_shift (lua_State *L, b_uint r, int i) {
     else r <<= i;
     r = trim(r);
   }
-  lua_pushunsigned(L, r);
+  pushunsigned(L, r);
   return 1;
 }
 
 
 static int b_lshift (lua_State *L) {
-  return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
+  return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
 }
 
 
 static int b_rshift (lua_State *L) {
-  return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
+  return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
 }
 
 
 static int b_arshift (lua_State *L) {
-  b_uint r = luaL_checkunsigned(L, 1);
-  int i = luaL_checkint(L, 2);
-  if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
+  lua_Unsigned r = checkunsigned(L, 1);
+  lua_Integer i = luaL_checkinteger(L, 2);
+  if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
     return b_shift(L, r, -i);
   else {  /* arithmetic shift for 'negative' number */
     if (i >= LUA_NBITS) r = ALLONES;
     else
-      r = trim((r >> i) | ~(~(b_uint)0 >> i));  /* add signal bit */
-    lua_pushunsigned(L, r);
+      r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i));  /* add signal bit */
+    pushunsigned(L, r);
     return 1;
   }
 }
 
 
-static int b_rot (lua_State *L, int i) {
-  b_uint r = luaL_checkunsigned(L, 1);
-  i &= (LUA_NBITS - 1);  /* i = i % NBITS */
+static int b_rot (lua_State *L, lua_Integer d) {
+  lua_Unsigned r = checkunsigned(L, 1);
+  int i = d & (LUA_NBITS - 1);  /* i = d % NBITS */
   r = trim(r);
   if (i != 0)  /* avoid undefined shift of LUA_NBITS when i == 0 */
     r = (r << i) | (r >> (LUA_NBITS - i));
-  lua_pushunsigned(L, trim(r));
+  pushunsigned(L, trim(r));
   return 1;
 }
 
 
 static int b_lrot (lua_State *L) {
-  return b_rot(L, luaL_checkint(L, 2));
+  return b_rot(L, luaL_checkinteger(L, 2));
 }
 
 
 static int b_rrot (lua_State *L) {
-  return b_rot(L, -luaL_checkint(L, 2));
+  return b_rot(L, -luaL_checkinteger(L, 2));
 }
 
 
@@ -153,36 +166,35 @@ static int b_rrot (lua_State *L) {
 ** 'width' being used uninitialized.)
 */
 static int fieldargs (lua_State *L, int farg, int *width) {
-  int f = luaL_checkint(L, farg);
-  int w = luaL_optint(L, farg + 1, 1);
+  lua_Integer f = luaL_checkinteger(L, farg);
+  lua_Integer w = luaL_optinteger(L, farg + 1, 1);
   luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
   luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
   if (f + w > LUA_NBITS)
     luaL_error(L, "trying to access non-existent bits");
-  *width = w;
-  return f;
+  *width = (int)w;
+  return (int)f;
 }
 
 
 static int b_extract (lua_State *L) {
   int w;
-  b_uint r = luaL_checkunsigned(L, 1);
+  lua_Unsigned r = trim(checkunsigned(L, 1));
   int f = fieldargs(L, 2, &w);
   r = (r >> f) & mask(w);
-  lua_pushunsigned(L, r);
+  pushunsigned(L, r);
   return 1;
 }
 
 
 static int b_replace (lua_State *L) {
   int w;
-  b_uint r = luaL_checkunsigned(L, 1);
-  b_uint v = luaL_checkunsigned(L, 2);
+  lua_Unsigned r = trim(checkunsigned(L, 1));
+  lua_Unsigned v = trim(checkunsigned(L, 2));
   int f = fieldargs(L, 3, &w);
-  int m = mask(w);
-  v &= m;  /* erase bits outside given width */
-  r = (r & ~(m << f)) | (v << f);
-  lua_pushunsigned(L, r);
+  lua_Unsigned m = mask(w);
+  r = (r & ~(m << f)) | ((v & m) << f);
+  pushunsigned(L, r);
   return 1;
 }
 
@@ -210,3 +222,12 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) {
   return 1;
 }
 
+
+#else                                  /* }{ */
+
+
+LUAMOD_API int luaopen_bit32 (lua_State *L) {
+  return luaL_error(L, "library 'bit32' has been deprecated");
+}
+
+#endif                                 /* } */
index 820b95c..2cd0dd2 100644 (file)
@@ -1,15 +1,18 @@
 /*
-** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lcode.c,v 2.109 2016/05/13 19:09:21 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
 
-
-#include <stdlib.h>
-
 #define lcode_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <math.h>
+#include <stdlib.h>
+
 #include "lua.h"
 
 #include "lcode.h"
 #include "lvm.h"
 
 
+/* Maximum number of registers in a Lua function (must fit in 8 bits) */
+#define MAXREGS                255
+
+
 #define hasjumps(e)    ((e)->t != (e)->f)
 
 
-static int isnumeral(expdesc *e) {
-  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
+/*
+** If expression is a numeric constant, fills 'v' with its value
+** and returns 1. Otherwise, returns 0.
+*/
+static int tonumeral(expdesc *e, TValue *v) {
+  if (hasjumps(e))
+    return 0;  /* not a numeral */
+  switch (e->k) {
+    case VKINT:
+      if (v) setivalue(v, e->u.ival);
+      return 1;
+    case VKFLT:
+      if (v) setfltvalue(v, e->u.nval);
+      return 1;
+    default: return 0;
+  }
 }
 
 
+/*
+** Create a OP_LOADNIL instruction, but try to optimize: if the previous
+** instruction is also OP_LOADNIL and ranges are compatible, adjust
+** range of previous instruction instead of emitting a new one. (For
+** instance, 'local a; local b' will generate a single opcode.)
+*/
 void luaK_nil (FuncState *fs, int from, int n) {
   Instruction *previous;
   int l = from + n - 1;  /* last register to set nil */
   if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */
     previous = &fs->f->code[fs->pc-1];
-    if (GET_OPCODE(*previous) == OP_LOADNIL) {
-      int pfrom = GETARG_A(*previous);
+    if (GET_OPCODE(*previous) == OP_LOADNIL) {  /* previous is LOADNIL? */
+      int pfrom = GETARG_A(*previous);  /* get previous range */
       int pl = pfrom + GETARG_B(*previous);
       if ((pfrom <= from && from <= pl + 1) ||
           (from <= pfrom && pfrom <= l + 1)) {  /* can connect both? */
@@ -56,39 +83,86 @@ void luaK_nil (FuncState *fs, int from, int n) {
 }
 
 
+/*
+** Gets the destination address of a jump instruction. Used to traverse
+** a list of jumps.
+*/ 
+static int getjump (FuncState *fs, int pc) {
+  int offset = GETARG_sBx(fs->f->code[pc]);
+  if (offset == NO_JUMP)  /* point to itself represents end of list */
+    return NO_JUMP;  /* end of list */
+  else
+    return (pc+1)+offset;  /* turn offset into absolute position */
+}
+
+
+/*
+** Fix jump instruction at position 'pc' to jump to 'dest'.
+** (Jump addresses are relative in Lua)
+*/
+static void fixjump (FuncState *fs, int pc, int dest) {
+  Instruction *jmp = &fs->f->code[pc];
+  int offset = dest - (pc + 1);
+  lua_assert(dest != NO_JUMP);
+  if (abs(offset) > MAXARG_sBx)
+    luaX_syntaxerror(fs->ls, "control structure too long");
+  SETARG_sBx(*jmp, offset);
+}
+
+
+/*
+** Concatenate jump-list 'l2' into jump-list 'l1'
+*/
+void luaK_concat (FuncState *fs, int *l1, int l2) {
+  if (l2 == NO_JUMP) return;  /* nothing to concatenate? */
+  else if (*l1 == NO_JUMP)  /* no original list? */
+    *l1 = l2;  /* 'l1' points to 'l2' */
+  else {
+    int list = *l1;
+    int next;
+    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
+      list = next;
+    fixjump(fs, list, l2);  /* last element links to 'l2' */
+  }
+}
+
+
+/*
+** Create a jump instruction and return its position, so its destination
+** can be fixed later (with 'fixjump'). If there are jumps to
+** this position (kept in 'jpc'), link them all together so that
+** 'patchlistaux' will fix all them directly to the final destination.
+*/
 int luaK_jump (FuncState *fs) {
   int jpc = fs->jpc;  /* save list of jumps to here */
   int j;
-  fs->jpc = NO_JUMP;
+  fs->jpc = NO_JUMP;  /* no more jumps to here */
   j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
   luaK_concat(fs, &j, jpc);  /* keep them on hold */
   return j;
 }
 
 
+/*
+** Code a 'return' instruction
+*/
 void luaK_ret (FuncState *fs, int first, int nret) {
   luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
 }
 
 
+/*
+** Code a "conditional jump", that is, a test or comparison opcode
+** followed by a jump. Return jump position.
+*/
 static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
   luaK_codeABC(fs, op, A, B, C);
   return luaK_jump(fs);
 }
 
 
-static void fixjump (FuncState *fs, int pc, int dest) {
-  Instruction *jmp = &fs->f->code[pc];
-  int offset = dest-(pc+1);
-  lua_assert(dest != NO_JUMP);
-  if (abs(offset) > MAXARG_sBx)
-    luaX_syntaxerror(fs->ls, "control structure too long");
-  SETARG_sBx(*jmp, offset);
-}
-
-
 /*
-** returns current `pc' and marks it as a jump target (to avoid wrong
+** returns current 'pc' and marks it as a jump target (to avoid wrong
 ** optimizations with consecutive instructions not in the same basic block).
 */
 int luaK_getlabel (FuncState *fs) {
@@ -97,15 +171,11 @@ int luaK_getlabel (FuncState *fs) {
 }
 
 
-static int getjump (FuncState *fs, int pc) {
-  int offset = GETARG_sBx(fs->f->code[pc]);
-  if (offset == NO_JUMP)  /* point to itself represents end of list */
-    return NO_JUMP;  /* end of list */
-  else
-    return (pc+1)+offset;  /* turn offset into absolute position */
-}
-
-
+/*
+** Returns the position of the instruction "controlling" a given
+** jump (that is, its condition), or the jump itself if it is
+** unconditional.
+*/
 static Instruction *getjumpcontrol (FuncState *fs, int pc) {
   Instruction *pi = &fs->f->code[pc];
   if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))
@@ -116,37 +186,41 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
 
 
 /*
-** check whether list has any jump that do not produce a value
-** (or produce an inverted value)
+** Patch destination register for a TESTSET instruction.
+** If instruction in position 'node' is not a TESTSET, return 0 ("fails").
+** Otherwise, if 'reg' is not 'NO_REG', set it as the destination
+** register. Otherwise, change instruction to a simple 'TEST' (produces
+** no register value)
 */
-static int need_value (FuncState *fs, int list) {
-  for (; list != NO_JUMP; list = getjump(fs, list)) {
-    Instruction i = *getjumpcontrol(fs, list);
-    if (GET_OPCODE(i) != OP_TESTSET) return 1;
-  }
-  return 0;  /* not found */
-}
-
-
 static int patchtestreg (FuncState *fs, int node, int reg) {
   Instruction *i = getjumpcontrol(fs, node);
   if (GET_OPCODE(*i) != OP_TESTSET)
     return 0;  /* cannot patch other instructions */
   if (reg != NO_REG && reg != GETARG_B(*i))
     SETARG_A(*i, reg);
-  else  /* no register to put value or register already has the value */
+  else {
+     /* no register to put value or register already has the value;
+        change instruction to simple test */
     *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
-
+  }
   return 1;
 }
 
 
+/*
+** Traverse a list of tests ensuring no one produces a value
+*/
 static void removevalues (FuncState *fs, int list) {
   for (; list != NO_JUMP; list = getjump(fs, list))
       patchtestreg(fs, list, NO_REG);
 }
 
 
+/*
+** Traverse a list of tests, patching their destination address and
+** registers: tests producing values jump to 'vtarget' (and put their
+** values in 'reg'), other tests jump to 'dtarget'.
+*/
 static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
                           int dtarget) {
   while (list != NO_JUMP) {
@@ -160,15 +234,35 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
 }
 
 
+/*
+** Ensure all pending jumps to current position are fixed (jumping
+** to current position with no values) and reset list of pending
+** jumps
+*/
 static void dischargejpc (FuncState *fs) {
   patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
   fs->jpc = NO_JUMP;
 }
 
 
+/*
+** Add elements in 'list' to list of pending jumps to "here"
+** (current position)
+*/
+void luaK_patchtohere (FuncState *fs, int list) {
+  luaK_getlabel(fs);  /* mark "here" as a jump target */
+  luaK_concat(fs, &fs->jpc, list);
+}
+
+
+/*
+** Path all jumps in 'list' to jump to 'target'.
+** (The assert means that we cannot fix a jump to a forward address
+** because we only know addresses once code is generated.)
+*/
 void luaK_patchlist (FuncState *fs, int list, int target) {
-  if (target == fs->pc)
-    luaK_patchtohere(fs, list);
+  if (target == fs->pc)  /* 'target' is current position? */
+    luaK_patchtohere(fs, list);  /* add list to pending jumps */
   else {
     lua_assert(target < fs->pc);
     patchlistaux(fs, list, target, NO_REG, target);
@@ -176,42 +270,29 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
 }
 
 
-LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) {
+/*
+** Path all jumps in 'list' to close upvalues up to given 'level'
+** (The assertion checks that jumps either were closing nothing
+** or were closing higher levels, from inner blocks.)
+*/
+void luaK_patchclose (FuncState *fs, int list, int level) {
   level++;  /* argument is +1 to reserve 0 as non-op */
-  while (list != NO_JUMP) {
-    int next = getjump(fs, list);
+  for (; list != NO_JUMP; list = getjump(fs, list)) {
     lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
                 (GETARG_A(fs->f->code[list]) == 0 ||
                  GETARG_A(fs->f->code[list]) >= level));
     SETARG_A(fs->f->code[list], level);
-    list = next;
-  }
-}
-
-
-void luaK_patchtohere (FuncState *fs, int list) {
-  luaK_getlabel(fs);
-  luaK_concat(fs, &fs->jpc, list);
-}
-
-
-void luaK_concat (FuncState *fs, int *l1, int l2) {
-  if (l2 == NO_JUMP) return;
-  else if (*l1 == NO_JUMP)
-    *l1 = l2;
-  else {
-    int list = *l1;
-    int next;
-    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */
-      list = next;
-    fixjump(fs, list, l2);
   }
 }
 
 
+/*
+** Emit instruction 'i', checking for array sizes and saving also its
+** line information. Return 'i' position.
+*/
 static int luaK_code (FuncState *fs, Instruction i) {
   Proto *f = fs->f;
-  dischargejpc(fs);  /* `pc' will change */
+  dischargejpc(fs);  /* 'pc' will change */
   /* put new instruction in code array */
   luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
                   MAX_INT, "opcodes");
@@ -224,6 +305,10 @@ static int luaK_code (FuncState *fs, Instruction i) {
 }
 
 
+/*
+** Format and emit an 'iABC' instruction. (Assertions check consistency
+** of parameters versus opcode.)
+*/
 int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
   lua_assert(getOpMode(o) == iABC);
   lua_assert(getBMode(o) != OpArgN || b == 0);
@@ -233,6 +318,9 @@ int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
 }
 
 
+/*
+** Format and emit an 'iABx' instruction.
+*/
 int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
   lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
   lua_assert(getCMode(o) == OpArgN);
@@ -241,12 +329,20 @@ int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
 }
 
 
+/*
+** Emit an "extra argument" instruction (format 'iAx')
+*/
 static int codeextraarg (FuncState *fs, int a) {
   lua_assert(a <= MAXARG_Ax);
   return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
 }
 
 
+/*
+** Emit a "load constant" instruction, using either 'OP_LOADK'
+** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX'
+** instruction with "extra argument".
+*/
 int luaK_codek (FuncState *fs, int reg, int k) {
   if (k <= MAXARG_Bx)
     return luaK_codeABx(fs, OP_LOADK, reg, k);
@@ -258,22 +354,35 @@ int luaK_codek (FuncState *fs, int reg, int k) {
 }
 
 
+/*
+** Check register-stack level, keeping track of its maximum size
+** in field 'maxstacksize'
+*/
 void luaK_checkstack (FuncState *fs, int n) {
   int newstack = fs->freereg + n;
   if (newstack > fs->f->maxstacksize) {
-    if (newstack >= MAXSTACK)
-      luaX_syntaxerror(fs->ls, "function or expression too complex");
+    if (newstack >= MAXREGS)
+      luaX_syntaxerror(fs->ls,
+        "function or expression needs too many registers");
     fs->f->maxstacksize = cast_byte(newstack);
   }
 }
 
 
+/*
+** Reserve 'n' registers in register stack
+*/
 void luaK_reserveregs (FuncState *fs, int n) {
   luaK_checkstack(fs, n);
   fs->freereg += n;
 }
 
 
+/*
+** Free register 'reg', if it is neither a constant index nor
+** a local variable.
+)
+*/
 static void freereg (FuncState *fs, int reg) {
   if (!ISK(reg) && reg >= fs->nactvar) {
     fs->freereg--;
@@ -282,31 +391,58 @@ static void freereg (FuncState *fs, int reg) {
 }
 
 
+/*
+** Free register used by expression 'e' (if any)
+*/
 static void freeexp (FuncState *fs, expdesc *e) {
   if (e->k == VNONRELOC)
     freereg(fs, e->u.info);
 }
 
 
+/*
+** Free registers used by expressions 'e1' and 'e2' (if any) in proper
+** order.
+*/
+static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) {
+  int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1;
+  int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1;
+  if (r1 > r2) {
+    freereg(fs, r1);
+    freereg(fs, r2);
+  }
+  else {
+    freereg(fs, r2);
+    freereg(fs, r1);
+  }
+}
+
+
+/*
+** Add constant 'v' to prototype's list of constants (field 'k').
+** Use scanner's table to cache position of constants in constant list
+** and try to reuse constants. Because some values should not be used
+** as keys (nil cannot be a key, integer keys can collapse with float
+** keys), the caller must provide a useful 'key' for indexing the cache.
+*/
 static int addk (FuncState *fs, TValue *key, TValue *v) {
   lua_State *L = fs->ls->L;
-  TValue *idx = luaH_set(L, fs->h, key);
   Proto *f = fs->f;
+  TValue *idx = luaH_set(L, fs->ls->h, key);  /* index scanner table */
   int k, oldsize;
-  if (ttisnumber(idx)) {
-    lua_Number n = nvalue(idx);
-    lua_number2int(k, n);
-    if (luaV_rawequalobj(&f->k[k], v))
-      return k;
-    /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0");
-       go through and create a new entry for this value */
+  if (ttisinteger(idx)) {  /* is there an index there? */
+    k = cast_int(ivalue(idx));
+    /* correct value? (warning: must distinguish floats from integers!) */
+    if (k < fs->nk && ttype(&f->k[k]) == ttype(v) &&
+                      luaV_rawequalobj(&f->k[k], v))
+      return k;  /* reuse index */
   }
   /* constant not found; create a new entry */
   oldsize = f->sizek;
   k = fs->nk;
   /* numerical value does not need GC barrier;
      table has no metatable, so it does not need to invalidate cache */
-  setnvalue(idx, cast_num(k));
+  setivalue(idx, k);
   luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants");
   while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
   setobj(L, &f->k[k], v);
@@ -316,94 +452,134 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
 }
 
 
+/*
+** Add a string to list of constants and return its index.
+*/
 int luaK_stringK (FuncState *fs, TString *s) {
   TValue o;
   setsvalue(fs->ls->L, &o, s);
-  return addk(fs, &o, &o);
+  return addk(fs, &o, &o);  /* use string itself as key */
 }
 
 
-int luaK_numberK (FuncState *fs, lua_Number r) {
-  int n;
-  lua_State *L = fs->ls->L;
+/*
+** Add an integer to list of constants and return its index.
+** Integers use userdata as keys to avoid collision with floats with
+** same value; conversion to 'void*' is used only for hashing, so there
+** are no "precision" problems.
+*/
+int luaK_intK (FuncState *fs, lua_Integer n) {
+  TValue k, o;
+  setpvalue(&k, cast(void*, cast(size_t, n)));
+  setivalue(&o, n);
+  return addk(fs, &k, &o);
+}
+
+/*
+** Add a float to list of constants and return its index.
+*/
+static int luaK_numberK (FuncState *fs, lua_Number r) {
   TValue o;
-  setnvalue(&o, r);
-  if (r == 0 || luai_numisnan(NULL, r)) {  /* handle -0 and NaN */
-    /* use raw representation as key to avoid numeric problems */
-    setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r)));
-    n = addk(fs, L->top - 1, &o);
-    L->top--;
-  }
-  else
-    n = addk(fs, &o, &o);  /* regular case */
-  return n;
+  setfltvalue(&o, r);
+  return addk(fs, &o, &o);  /* use number itself as key */
 }
 
 
+/*
+** Add a boolean to list of constants and return its index.
+*/
 static int boolK (FuncState *fs, int b) {
   TValue o;
   setbvalue(&o, b);
-  return addk(fs, &o, &o);
+  return addk(fs, &o, &o);  /* use boolean itself as key */
 }
 
 
+/*
+** Add nil to list of constants and return its index.
+*/
 static int nilK (FuncState *fs) {
   TValue k, v;
   setnilvalue(&v);
   /* cannot use nil as key; instead use table itself to represent nil */
-  sethvalue(fs->ls->L, &k, fs->h);
+  sethvalue(fs->ls->L, &k, fs->ls->h);
   return addk(fs, &k, &v);
 }
 
 
+/*
+** Fix an expression to return the number of results 'nresults'.
+** Either 'e' is a multi-ret expression (function call or vararg)
+** or 'nresults' is LUA_MULTRET (as any expression can satisfy that).
+*/
 void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
   if (e->k == VCALL) {  /* expression is an open function call? */
-    SETARG_C(getcode(fs, e), nresults+1);
+    SETARG_C(getinstruction(fs, e), nresults + 1);
   }
   else if (e->k == VVARARG) {
-    SETARG_B(getcode(fs, e), nresults+1);
-    SETARG_A(getcode(fs, e), fs->freereg);
+    Instruction *pc = &getinstruction(fs, e);
+    SETARG_B(*pc, nresults + 1);
+    SETARG_A(*pc, fs->freereg);
     luaK_reserveregs(fs, 1);
   }
+  else lua_assert(nresults == LUA_MULTRET);
 }
 
 
+/*
+** Fix an expression to return one result.
+** If expression is not a multi-ret expression (function call or
+** vararg), it already returns one result, so nothing needs to be done.
+** Function calls become VNONRELOC expressions (as its result comes
+** fixed in the base register of the call), while vararg expressions
+** become VRELOCABLE (as OP_VARARG puts its results where it wants).
+** (Calls are created returning one result, so that does not need
+** to be fixed.)
+*/
 void luaK_setoneret (FuncState *fs, expdesc *e) {
   if (e->k == VCALL) {  /* expression is an open function call? */
-    e->k = VNONRELOC;
-    e->u.info = GETARG_A(getcode(fs, e));
+    /* already returns 1 value */
+    lua_assert(GETARG_C(getinstruction(fs, e)) == 2);
+    e->k = VNONRELOC;  /* result has fixed position */
+    e->u.info = GETARG_A(getinstruction(fs, e));
   }
   else if (e->k == VVARARG) {
-    SETARG_B(getcode(fs, e), 2);
+    SETARG_B(getinstruction(fs, e), 2);
     e->k = VRELOCABLE;  /* can relocate its simple result */
   }
 }
 
 
+/*
+** Ensure that expression 'e' is not a variable.
+*/
 void luaK_dischargevars (FuncState *fs, expdesc *e) {
   switch (e->k) {
-    case VLOCAL: {
-      e->k = VNONRELOC;
+    case VLOCAL: {  /* already in a register */
+      e->k = VNONRELOC;  /* becomes a non-relocatable value */
       break;
     }
-    case VUPVAL: {
+    case VUPVAL: {  /* move value to some (pending) register */
       e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
       e->k = VRELOCABLE;
       break;
     }
     case VINDEXED: {
-      OpCode op = OP_GETTABUP;  /* assume 't' is in an upvalue */
+      OpCode op;
       freereg(fs, e->u.ind.idx);
-      if (e->u.ind.vt == VLOCAL) {  /* 't' is in a register? */
+      if (e->u.ind.vt == VLOCAL) {  /* is 't' in a register? */
         freereg(fs, e->u.ind.t);
         op = OP_GETTABLE;
       }
+      else {
+        lua_assert(e->u.ind.vt == VUPVAL);
+        op = OP_GETTABUP;  /* 't' is in an upvalue */
+      }
       e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
       e->k = VRELOCABLE;
       break;
     }
-    case VVARARG:
-    case VCALL: {
+    case VVARARG: case VCALL: {
       luaK_setoneret(fs, e);
       break;
     }
@@ -412,12 +588,10 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
 }
 
 
-static int code_label (FuncState *fs, int A, int b, int jump) {
-  luaK_getlabel(fs);  /* those instructions may be jump targets */
-  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
-}
-
-
+/*
+** Ensures expression value is in register 'reg' (and therefore
+** 'e' will become a non-relocatable expression).
+*/
 static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
   luaK_dischargevars(fs, e);
   switch (e->k) {
@@ -433,13 +607,17 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
       luaK_codek(fs, reg, e->u.info);
       break;
     }
-    case VKNUM: {
+    case VKFLT: {
       luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval));
       break;
     }
+    case VKINT: {
+      luaK_codek(fs, reg, luaK_intK(fs, e->u.ival));
+      break;
+    }
     case VRELOCABLE: {
-      Instruction *pc = &getcode(fs, e);
-      SETARG_A(*pc, reg);
+      Instruction *pc = &getinstruction(fs, e);
+      SETARG_A(*pc, reg);  /* instruction will put result in 'reg' */
       break;
     }
     case VNONRELOC: {
@@ -448,7 +626,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
       break;
     }
     default: {
-      lua_assert(e->k == VVOID || e->k == VJMP);
+      lua_assert(e->k == VJMP);
       return;  /* nothing to do... */
     }
   }
@@ -457,26 +635,55 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
 }
 
 
+/*
+** Ensures expression value is in any register.
+*/
 static void discharge2anyreg (FuncState *fs, expdesc *e) {
-  if (e->k != VNONRELOC) {
-    luaK_reserveregs(fs, 1);
-    discharge2reg(fs, e, fs->freereg-1);
+  if (e->k != VNONRELOC) {  /* no fixed register yet? */
+    luaK_reserveregs(fs, 1);  /* get a register */
+    discharge2reg(fs, e, fs->freereg-1);  /* put value there */
   }
 }
 
 
+static int code_loadbool (FuncState *fs, int A, int b, int jump) {
+  luaK_getlabel(fs);  /* those instructions may be jump targets */
+  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
+}
+
+
+/*
+** check whether list has any jump that do not produce a value
+** or produce an inverted value
+*/
+static int need_value (FuncState *fs, int list) {
+  for (; list != NO_JUMP; list = getjump(fs, list)) {
+    Instruction i = *getjumpcontrol(fs, list);
+    if (GET_OPCODE(i) != OP_TESTSET) return 1;
+  }
+  return 0;  /* not found */
+}
+
+
+/*
+** Ensures final expression result (including results from its jump
+** lists) is in register 'reg'.
+** If expression has jumps, need to patch these jumps either to
+** its final position or to "load" instructions (for those tests
+** that do not produce values).
+*/
 static void exp2reg (FuncState *fs, expdesc *e, int reg) {
   discharge2reg(fs, e, reg);
-  if (e->k == VJMP)
-    luaK_concat(fs, &e->t, e->u.info);  /* put this jump in `t' list */
+  if (e->k == VJMP)  /* expression itself is a test? */
+    luaK_concat(fs, &e->t, e->u.info);  /* put this jump in 't' list */
   if (hasjumps(e)) {
     int final;  /* position after whole expression */
     int p_f = NO_JUMP;  /* position of an eventual LOAD false */
     int p_t = NO_JUMP;  /* position of an eventual LOAD true */
     if (need_value(fs, e->t) || need_value(fs, e->f)) {
       int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);
-      p_f = code_label(fs, reg, 0, 1);
-      p_t = code_label(fs, reg, 1, 0);
+      p_f = code_loadbool(fs, reg, 0, 1);
+      p_t = code_loadbool(fs, reg, 1, 0);
       luaK_patchtohere(fs, fj);
     }
     final = luaK_getlabel(fs);
@@ -489,6 +696,10 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
 }
 
 
+/*
+** Ensures final expression result (including results from its jump
+** lists) is in next available register.
+*/
 void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
   luaK_dischargevars(fs, e);
   freeexp(fs, e);
@@ -497,26 +708,39 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
 }
 
 
+/*
+** Ensures final expression result (including results from its jump
+** lists) is in some (any) register and return that register.
+*/
 int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
   luaK_dischargevars(fs, e);
-  if (e->k == VNONRELOC) {
-    if (!hasjumps(e)) return e->u.info;  /* exp is already in a register */
+  if (e->k == VNONRELOC) {  /* expression already has a register? */
+    if (!hasjumps(e))  /* no jumps? */
+      return e->u.info;  /* result is already in a register */
     if (e->u.info >= fs->nactvar) {  /* reg. is not a local? */
-      exp2reg(fs, e, e->u.info);  /* put value on it */
+      exp2reg(fs, e, e->u.info);  /* put final result in it */
       return e->u.info;
     }
   }
-  luaK_exp2nextreg(fs, e);  /* default */
+  luaK_exp2nextreg(fs, e);  /* otherwise, use next available register */
   return e->u.info;
 }
 
 
+/*
+** Ensures final expression result is either in a register or in an
+** upvalue.
+*/
 void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
   if (e->k != VUPVAL || hasjumps(e))
     luaK_exp2anyreg(fs, e);
 }
 
 
+/*
+** Ensures final expression result is either in a register or it is
+** a constant.
+*/
 void luaK_exp2val (FuncState *fs, expdesc *e) {
   if (hasjumps(e))
     luaK_exp2anyreg(fs, e);
@@ -525,29 +749,26 @@ void luaK_exp2val (FuncState *fs, expdesc *e) {
 }
 
 
+/*
+** Ensures final expression result is in a valid R/K index
+** (that is, it is either in a register or in 'k' with an index
+** in the range of R/K indices).
+** Returns R/K index.
+*/  
 int luaK_exp2RK (FuncState *fs, expdesc *e) {
   luaK_exp2val(fs, e);
-  switch (e->k) {
-    case VTRUE:
-    case VFALSE:
-    case VNIL: {
-      if (fs->nk <= MAXINDEXRK) {  /* constant fits in RK operand? */
-        e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE));
-        e->k = VK;
-        return RKASK(e->u.info);
-      }
-      else break;
-    }
-    case VKNUM: {
-      e->u.info = luaK_numberK(fs, e->u.nval);
+  switch (e->k) {  /* move constants to 'k' */
+    case VTRUE: e->u.info = boolK(fs, 1); goto vk;
+    case VFALSE: e->u.info = boolK(fs, 0); goto vk;
+    case VNIL: e->u.info = nilK(fs); goto vk;
+    case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk;
+    case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk;
+    case VK:
+     vk:
       e->k = VK;
-      /* go through */
-    }
-    case VK: {
-      if (e->u.info <= MAXINDEXRK)  /* constant fits in argC? */
+      if (e->u.info <= MAXINDEXRK)  /* constant fits in 'argC'? */
         return RKASK(e->u.info);
       else break;
-    }
     default: break;
   }
   /* not a constant in the right range: put it in a register */
@@ -555,11 +776,14 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
 }
 
 
+/*
+** Generate code to store result of expression 'ex' into variable 'var'.
+*/
 void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
   switch (var->k) {
     case VLOCAL: {
       freeexp(fs, ex);
-      exp2reg(fs, ex, var->u.info);
+      exp2reg(fs, ex, var->u.info);  /* compute 'ex' into proper place */
       return;
     }
     case VUPVAL: {
@@ -573,29 +797,32 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
       luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
       break;
     }
-    default: {
-      lua_assert(0);  /* invalid var kind to store */
-      break;
-    }
+    default: lua_assert(0);  /* invalid var kind to store */
   }
   freeexp(fs, ex);
 }
 
 
+/*
+** Emit SELF instruction (convert expression 'e' into 'e:key(e,').
+*/
 void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
   int ereg;
   luaK_exp2anyreg(fs, e);
   ereg = e->u.info;  /* register where 'e' was placed */
   freeexp(fs, e);
   e->u.info = fs->freereg;  /* base register for op_self */
-  e->k = VNONRELOC;
+  e->k = VNONRELOC;  /* self expression has a fixed register */
   luaK_reserveregs(fs, 2);  /* function and 'self' produced by op_self */
   luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key));
   freeexp(fs, key);
 }
 
 
-static void invertjump (FuncState *fs, expdesc *e) {
+/*
+** Negate condition 'e' (where 'e' is a comparison).
+*/
+static void negatecondition (FuncState *fs, expdesc *e) {
   Instruction *pc = getjumpcontrol(fs, e->u.info);
   lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
                                            GET_OPCODE(*pc) != OP_TEST);
@@ -603,9 +830,15 @@ static void invertjump (FuncState *fs, expdesc *e) {
 }
 
 
+/*
+** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond'
+** is true, code will jump if 'e' is true.) Return jump position.
+** Optimize when 'e' is 'not' something, inverting the condition
+** and removing the 'not'.
+*/
 static int jumponcond (FuncState *fs, expdesc *e, int cond) {
   if (e->k == VRELOCABLE) {
-    Instruction ie = getcode(fs, e);
+    Instruction ie = getinstruction(fs, e);
     if (GET_OPCODE(ie) == OP_NOT) {
       fs->pc--;  /* remove previous OP_NOT */
       return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
@@ -618,36 +851,42 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
 }
 
 
+/*
+** Emit code to go through if 'e' is true, jump otherwise.
+*/
 void luaK_goiftrue (FuncState *fs, expdesc *e) {
-  int pc;  /* pc of last jump */
+  int pc;  /* pc of new jump */
   luaK_dischargevars(fs, e);
   switch (e->k) {
-    case VJMP: {
-      invertjump(fs, e);
-      pc = e->u.info;
+    case VJMP: {  /* condition? */
+      negatecondition(fs, e);  /* jump when it is false */
+      pc = e->u.info;  /* save jump position */
       break;
     }
-    case VK: case VKNUM: case VTRUE: {
+    case VK: case VKFLT: case VKINT: case VTRUE: {
       pc = NO_JUMP;  /* always true; do nothing */
       break;
     }
     default: {
-      pc = jumponcond(fs, e, 0);
+      pc = jumponcond(fs, e, 0);  /* jump when false */
       break;
     }
   }
-  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */
-  luaK_patchtohere(fs, e->t);
+  luaK_concat(fs, &e->f, pc);  /* insert new jump in false list */
+  luaK_patchtohere(fs, e->t);  /* true list jumps to here (to go through) */
   e->t = NO_JUMP;
 }
 
 
+/*
+** Emit code to go through if 'e' is false, jump otherwise.
+*/
 void luaK_goiffalse (FuncState *fs, expdesc *e) {
-  int pc;  /* pc of last jump */
+  int pc;  /* pc of new jump */
   luaK_dischargevars(fs, e);
   switch (e->k) {
     case VJMP: {
-      pc = e->u.info;
+      pc = e->u.info;  /* already jump if true */
       break;
     }
     case VNIL: case VFALSE: {
@@ -655,29 +894,32 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
       break;
     }
     default: {
-      pc = jumponcond(fs, e, 1);
+      pc = jumponcond(fs, e, 1);  /* jump if true */
       break;
     }
   }
-  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */
-  luaK_patchtohere(fs, e->f);
+  luaK_concat(fs, &e->t, pc);  /* insert new jump in 't' list */
+  luaK_patchtohere(fs, e->f);  /* false list jumps to here (to go through) */
   e->f = NO_JUMP;
 }
 
 
+/*
+** Code 'not e', doing constant folding.
+*/
 static void codenot (FuncState *fs, expdesc *e) {
   luaK_dischargevars(fs, e);
   switch (e->k) {
     case VNIL: case VFALSE: {
-      e->k = VTRUE;
+      e->k = VTRUE;  /* true == not nil == not false */
       break;
     }
-    case VK: case VKNUM: case VTRUE: {
-      e->k = VFALSE;
+    case VK: case VKFLT: case VKINT: case VTRUE: {
+      e->k = VFALSE;  /* false == not "x" == not 0.5 == not 1 == not true */
       break;
     }
     case VJMP: {
-      invertjump(fs, e);
+      negatecondition(fs, e);
       break;
     }
     case VRELOCABLE:
@@ -688,118 +930,177 @@ static void codenot (FuncState *fs, expdesc *e) {
       e->k = VRELOCABLE;
       break;
     }
-    default: {
-      lua_assert(0);  /* cannot happen */
-      break;
-    }
+    default: lua_assert(0);  /* cannot happen */
   }
   /* interchange true and false lists */
   { int temp = e->f; e->f = e->t; e->t = temp; }
-  removevalues(fs, e->f);
+  removevalues(fs, e->f);  /* values are useless when negated */
   removevalues(fs, e->t);
 }
 
 
+/*
+** Create expression 't[k]'. 't' must have its final result already in a
+** register or upvalue.
+*/
 void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
-  lua_assert(!hasjumps(t));
-  t->u.ind.t = t->u.info;
-  t->u.ind.idx = luaK_exp2RK(fs, k);
-  t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
-                                 : check_exp(vkisinreg(t->k), VLOCAL);
+  lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
+  t->u.ind.t = t->u.info;  /* register or upvalue index */
+  t->u.ind.idx = luaK_exp2RK(fs, k);  /* R/K index for key */
+  t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL;
   t->k = VINDEXED;
 }
 
 
-static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
-  lua_Number r;
-  if (!isnumeral(e1) || !isnumeral(e2)) return 0;
-  if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0)
-    return 0;  /* do not attempt to divide by 0 */
-  r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval);
-  e1->u.nval = r;
-  return 1;
+/*
+** Return false if folding can raise an error.
+** Bitwise operations need operands convertible to integers; division
+** operations cannot have 0 as divisor.
+*/
+static int validop (int op, TValue *v1, TValue *v2) {
+  switch (op) {
+    case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
+    case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: {  /* conversion errors */
+      lua_Integer i;
+      return (tointeger(v1, &i) && tointeger(v2, &i));
+    }
+    case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD:  /* division by 0 */
+      return (nvalue(v2) != 0);
+    default: return 1;  /* everything else is valid */
+  }
 }
 
 
-static void codearith (FuncState *fs, OpCode op,
-                       expdesc *e1, expdesc *e2, int line) {
-  if (constfolding(op, e1, e2))
-    return;
-  else {
-    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;
-    int o1 = luaK_exp2RK(fs, e1);
-    if (o1 > o2) {
-      freeexp(fs, e1);
-      freeexp(fs, e2);
-    }
-    else {
-      freeexp(fs, e2);
-      freeexp(fs, e1);
-    }
-    e1->u.info = luaK_codeABC(fs, op, 0, o1, o2);
-    e1->k = VRELOCABLE;
-    luaK_fixline(fs, line);
+/*
+** Try to "constant-fold" an operation; return 1 iff successful.
+** (In this case, 'e1' has the final result.)
+*/
+static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) {
+  TValue v1, v2, res;
+  if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2))
+    return 0;  /* non-numeric operands or not safe to fold */
+  luaO_arith(fs->ls->L, op, &v1, &v2, &res);  /* does operation */
+  if (ttisinteger(&res)) {
+    e1->k = VKINT;
+    e1->u.ival = ivalue(&res);
   }
+  else {  /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */
+    lua_Number n = fltvalue(&res);
+    if (luai_numisnan(n) || n == 0)
+      return 0;
+    e1->k = VKFLT;
+    e1->u.nval = n;
+  }
+  return 1;
 }
 
 
-static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,
-                                                          expdesc *e2) {
-  int o1 = luaK_exp2RK(fs, e1);
-  int o2 = luaK_exp2RK(fs, e2);
-  freeexp(fs, e2);
-  freeexp(fs, e1);
-  if (cond == 0 && op != OP_EQ) {
-    int temp;  /* exchange args to replace by `<' or `<=' */
-    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */
-    cond = 1;
+/*
+** Emit code for unary expressions that "produce values"
+** (everything but 'not').
+** Expression to produce final result will be encoded in 'e'.
+*/
+static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
+  int r = luaK_exp2anyreg(fs, e);  /* opcodes operate only on registers */
+  freeexp(fs, e);
+  e->u.info = luaK_codeABC(fs, op, 0, r, 0);  /* generate opcode */
+  e->k = VRELOCABLE;  /* all those operations are relocatable */
+  luaK_fixline(fs, line);
+}
+
+
+/*
+** Emit code for binary expressions that "produce values"
+** (everything but logical operators 'and'/'or' and comparison
+** operators).
+** Expression to produce final result will be encoded in 'e1'.
+*/
+static void codebinexpval (FuncState *fs, OpCode op,
+                           expdesc *e1, expdesc *e2, int line) {
+  int rk1 = luaK_exp2RK(fs, e1);  /* both operands are "RK" */
+  int rk2 = luaK_exp2RK(fs, e2);
+  freeexps(fs, e1, e2);
+  e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2);  /* generate opcode */
+  e1->k = VRELOCABLE;  /* all those operations are relocatable */
+  luaK_fixline(fs, line);
+}
+
+
+/*
+** Emit code for comparisons.
+** 'e1' was already put in R/K form by 'luaK_infix'.
+*/
+static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
+  int rk1 = (e1->k == VK) ? RKASK(e1->u.info)
+                          : check_exp(e1->k == VNONRELOC, e1->u.info);
+  int rk2 = luaK_exp2RK(fs, e2);
+  freeexps(fs, e1, e2);
+  switch (opr) {
+    case OPR_NE: {  /* '(a ~= b)' ==> 'not (a == b)' */
+      e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2);
+      break;
+    }
+    case OPR_GT: case OPR_GE: {
+      /* '(a > b)' ==> '(b < a)';  '(a >= b)' ==> '(b <= a)' */
+      OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ);
+      e1->u.info = condjump(fs, op, 1, rk2, rk1);  /* invert operands */
+      break;
+    }
+    default: {  /* '==', '<', '<=' use their own opcodes */
+      OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ);
+      e1->u.info = condjump(fs, op, 1, rk1, rk2);
+      break;
+    }
   }
-  e1->u.info = condjump(fs, op, cond, o1, o2);
   e1->k = VJMP;
 }
 
 
+/*
+** Aplly prefix operation 'op' to expression 'e'.
+*/
 void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
-  expdesc e2;
-  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
+  static expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};  /* fake 2nd operand */
   switch (op) {
-    case OPR_MINUS: {
-      if (isnumeral(e))  /* minus constant? */
-        e->u.nval = luai_numunm(NULL, e->u.nval);  /* fold it */
-      else {
-        luaK_exp2anyreg(fs, e);
-        codearith(fs, OP_UNM, e, &e2, line);
-      }
+    case OPR_MINUS: case OPR_BNOT:
+      if (constfolding(fs, op + LUA_OPUNM, e, &ef))
+        break;
+      /* FALLTHROUGH */
+    case OPR_LEN:
+      codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
       break;
-    }
     case OPR_NOT: codenot(fs, e); break;
-    case OPR_LEN: {
-      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */
-      codearith(fs, OP_LEN, e, &e2, line);
-      break;
-    }
     default: lua_assert(0);
   }
 }
 
 
+/*
+** Process 1st operand 'v' of binary operation 'op' before reading
+** 2nd operand.
+*/
 void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
   switch (op) {
     case OPR_AND: {
-      luaK_goiftrue(fs, v);
+      luaK_goiftrue(fs, v);  /* go ahead only if 'v' is true */
       break;
     }
     case OPR_OR: {
-      luaK_goiffalse(fs, v);
+      luaK_goiffalse(fs, v);  /* go ahead only if 'v' is false */
       break;
     }
     case OPR_CONCAT: {
-      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */
+      luaK_exp2nextreg(fs, v);  /* operand must be on the 'stack' */
       break;
     }
-    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
-    case OPR_MOD: case OPR_POW: {
-      if (!isnumeral(v)) luaK_exp2RK(fs, v);
+    case OPR_ADD: case OPR_SUB:
+    case OPR_MUL: case OPR_DIV: case OPR_IDIV:
+    case OPR_MOD: case OPR_POW:
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR:
+    case OPR_SHL: case OPR_SHR: {
+      if (!tonumeral(v, NULL))
+        luaK_exp2RK(fs, v);
+      /* else keep numeral, which may be folded with 2nd operand */
       break;
     }
     default: {
@@ -810,18 +1111,24 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
 }
 
 
+/*
+** Finalize code for binary operation, after reading 2nd operand.
+** For '(a .. b .. c)' (which is '(a .. (b .. c))', because
+** concatenation is right associative), merge second CONCAT into first
+** one.
+*/
 void luaK_posfix (FuncState *fs, BinOpr op,
                   expdesc *e1, expdesc *e2, int line) {
   switch (op) {
     case OPR_AND: {
-      lua_assert(e1->t == NO_JUMP);  /* list must be closed */
+      lua_assert(e1->t == NO_JUMP);  /* list closed by 'luK_infix' */
       luaK_dischargevars(fs, e2);
       luaK_concat(fs, &e2->f, e1->f);
       *e1 = *e2;
       break;
     }
     case OPR_OR: {
-      lua_assert(e1->f == NO_JUMP);  /* list must be closed */
+      lua_assert(e1->f == NO_JUMP);  /* list closed by 'luK_infix' */
       luaK_dischargevars(fs, e2);
       luaK_concat(fs, &e2->t, e1->t);
       *e1 = *e2;
@@ -829,29 +1136,30 @@ void luaK_posfix (FuncState *fs, BinOpr op,
     }
     case OPR_CONCAT: {
       luaK_exp2val(fs, e2);
-      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
-        lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1);
+      if (e2->k == VRELOCABLE &&
+          GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) {
+        lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1);
         freeexp(fs, e1);
-        SETARG_B(getcode(fs, e2), e1->u.info);
+        SETARG_B(getinstruction(fs, e2), e1->u.info);
         e1->k = VRELOCABLE; e1->u.info = e2->u.info;
       }
       else {
         luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */
-        codearith(fs, OP_CONCAT, e1, e2, line);
+        codebinexpval(fs, OP_CONCAT, e1, e2, line);
       }
       break;
     }
     case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
-    case OPR_MOD: case OPR_POW: {
-      codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
-      break;
-    }
-    case OPR_EQ: case OPR_LT: case OPR_LE: {
-      codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
+    case OPR_IDIV: case OPR_MOD: case OPR_POW:
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR:
+    case OPR_SHL: case OPR_SHR: {
+      if (!constfolding(fs, op + LUA_OPADD, e1, e2))
+        codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line);
       break;
     }
+    case OPR_EQ: case OPR_LT: case OPR_LE:
     case OPR_NE: case OPR_GT: case OPR_GE: {
-      codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2);
+      codecomp(fs, op, e1, e2);
       break;
     }
     default: lua_assert(0);
@@ -859,15 +1167,25 @@ void luaK_posfix (FuncState *fs, BinOpr op,
 }
 
 
+/*
+** Change line information associated with current position.
+*/
 void luaK_fixline (FuncState *fs, int line) {
   fs->f->lineinfo[fs->pc - 1] = line;
 }
 
 
+/*
+** Emit a SETLIST instruction.
+** 'base' is register that keeps table;
+** 'nelems' is #table plus those to be stored now;
+** 'tostore' is number of values (in registers 'base + 1',...) to add to
+** table (or LUA_MULTRET to add up to stack top).
+*/
 void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
   int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;
   int b = (tostore == LUA_MULTRET) ? 0 : tostore;
-  lua_assert(tostore != 0);
+  lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH);
   if (c <= MAXARG_C)
     luaK_codeABC(fs, OP_SETLIST, base, b, c);
   else if (c <= MAXARG_Ax) {
index 6a1424c..cd306d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lcode.h,v 1.64 2016/01/05 16:22:37 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
 ** grep "ORDER OPR" if you change these enums  (ORDER OP)
 */
 typedef enum BinOpr {
-  OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,
+  OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
+  OPR_DIV,
+  OPR_IDIV,
+  OPR_BAND, OPR_BOR, OPR_BXOR,
+  OPR_SHL, OPR_SHR,
   OPR_CONCAT,
   OPR_EQ, OPR_LT, OPR_LE,
   OPR_NE, OPR_GT, OPR_GE,
@@ -33,10 +37,11 @@ typedef enum BinOpr {
 } BinOpr;
 
 
-typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
+typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
 
 
-#define getcode(fs,e)  ((fs)->f->code[(e)->u.info])
+/* get (pointer to) instruction of given 'expdesc' */
+#define getinstruction(fs,e)   ((fs)->f->code[(e)->u.info])
 
 #define luaK_codeAsBx(fs,o,A,sBx)      luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
 
@@ -52,7 +57,7 @@ LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
 LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
 LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
 LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
-LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
+LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n);
 LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
 LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
index ce4f6ad..2303429 100644 (file)
@@ -1,15 +1,16 @@
 /*
-** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp $
 ** Coroutine Library
 ** See Copyright Notice in lua.h
 */
 
+#define lcorolib_c
+#define LUA_LIB
 
-#include <stdlib.h>
+#include "lprefix.h"
 
 
-#define lcorolib_c
-#define LUA_LIB
+#include <stdlib.h>
 
 #include "lua.h"
 
 #include "lualib.h"
 
 
+static lua_State *getco (lua_State *L) {
+  lua_State *co = lua_tothread(L, 1);
+  luaL_argcheck(L, co, 1, "thread expected");
+  return co;
+}
+
+
 static int auxresume (lua_State *L, lua_State *co, int narg) {
   int status;
   if (!lua_checkstack(co, narg)) {
@@ -47,9 +55,8 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
 
 
 static int luaB_coresume (lua_State *L) {
-  lua_State *co = lua_tothread(L, 1);
+  lua_State *co = getco(L);
   int r;
-  luaL_argcheck(L, co, 1, "coroutine expected");
   r = auxresume(L, co, lua_gettop(L) - 1);
   if (r < 0) {
     lua_pushboolean(L, 0);
@@ -59,7 +66,7 @@ static int luaB_coresume (lua_State *L) {
   else {
     lua_pushboolean(L, 1);
     lua_insert(L, -(r + 1));
-    return r + 1;  /* return true + `resume' returns */
+    return r + 1;  /* return true + 'resume' returns */
   }
 }
 
@@ -68,7 +75,7 @@ static int luaB_auxwrap (lua_State *L) {
   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
   int r = auxresume(L, co, lua_gettop(L));
   if (r < 0) {
-    if (lua_isstring(L, -1)) {  /* error object is a string? */
+    if (lua_type(L, -1) == LUA_TSTRING) {  /* error object is a string? */
       luaL_where(L, 1);  /* add extra info */
       lua_insert(L, -2);
       lua_concat(L, 2);
@@ -102,8 +109,7 @@ static int luaB_yield (lua_State *L) {
 
 
 static int luaB_costatus (lua_State *L) {
-  lua_State *co = lua_tothread(L, 1);
-  luaL_argcheck(L, co, 1, "coroutine expected");
+  lua_State *co = getco(L);
   if (L == co) lua_pushliteral(L, "running");
   else {
     switch (lua_status(co)) {
@@ -129,6 +135,12 @@ static int luaB_costatus (lua_State *L) {
 }
 
 
+static int luaB_yieldable (lua_State *L) {
+  lua_pushboolean(L, lua_isyieldable(L));
+  return 1;
+}
+
+
 static int luaB_corunning (lua_State *L) {
   int ismain = lua_pushthread(L);
   lua_pushboolean(L, ismain);
@@ -143,6 +155,7 @@ static const luaL_Reg co_funcs[] = {
   {"status", luaB_costatus},
   {"wrap", luaB_cowrap},
   {"yield", luaB_yield},
+  {"isyieldable", luaB_yieldable},
   {NULL, NULL}
 };
 
index 93f8cad..ae9367e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lctype.c,v 1.12 2014/11/02 19:19:04 roberto Exp $
 ** 'ctype' functions for Lua
 ** See Copyright Notice in lua.h
 */
@@ -7,6 +7,9 @@
 #define lctype_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
 #include "lctype.h"
 
 #if !LUA_USE_CTYPE     /* { */
index b09b21a..99c7d12 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
 ** 'ctype' functions for Lua
 ** See Copyright Notice in lua.h
 */
index bd8df9d..786f6cd 100644 (file)
@@ -1,26 +1,37 @@
 /*
-** $Id: ldblib.c,v 1.132.1.2 2015/02/19 17:16:55 roberto Exp $
+** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
 
+#define ldblib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define ldblib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 #include "lualib.h"
 
 
-#define HOOKKEY                "_HKEY"
+/*
+** The hook table at registry[&HOOKKEY] maps threads to their current
+** hook function. (We only need the unique address of 'HOOKKEY'.)
+*/
+static const int HOOKKEY = 0;
 
 
+/*
+** If L1 != L, L1 can be in any state, and therefore there are no
+** guarantees 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");
@@ -62,35 +73,20 @@ static int db_getuservalue (lua_State *L) {
 
 
 static int db_setuservalue (lua_State *L) {
-  if (lua_type(L, 1) == LUA_TLIGHTUSERDATA)
-    luaL_argerror(L, 1, "full userdata expected, got light userdata");
   luaL_checktype(L, 1, LUA_TUSERDATA);
-  if (!lua_isnoneornil(L, 2))
-    luaL_checktype(L, 2, LUA_TTABLE);
+  luaL_checkany(L, 2);
   lua_settop(L, 2);
   lua_setuservalue(L, 1);
   return 1;
 }
 
 
-static void settabss (lua_State *L, const char *i, const char *v) {
-  lua_pushstring(L, v);
-  lua_setfield(L, -2, i);
-}
-
-
-static void settabsi (lua_State *L, const char *i, int v) {
-  lua_pushinteger(L, v);
-  lua_setfield(L, -2, i);
-}
-
-
-static void settabsb (lua_State *L, const char *i, int v) {
-  lua_pushboolean(L, v);
-  lua_setfield(L, -2, i);
-}
-
-
+/*
+** Auxiliary function used by several library functions: check for
+** an optional thread as function's first argument and set 'arg' with
+** 1 if this argument is present (so that functions can skip it to
+** access their other arguments)
+*/
 static lua_State *getthread (lua_State *L, int *arg) {
   if (lua_isthread(L, 1)) {
     *arg = 1;
@@ -98,45 +94,74 @@ static lua_State *getthread (lua_State *L, int *arg) {
   }
   else {
     *arg = 0;
-    return L;
+    return L;  /* function will operate over current thread */
   }
 }
 
 
+/*
+** Variations of 'lua_settable', used by 'db_getinfo' to put results
+** from 'lua_getinfo' into result table. Key is always a string;
+** value can be a string, an int, or a boolean.
+*/
+static void settabss (lua_State *L, const char *k, const char *v) {
+  lua_pushstring(L, v);
+  lua_setfield(L, -2, k);
+}
+
+static void settabsi (lua_State *L, const char *k, int v) {
+  lua_pushinteger(L, v);
+  lua_setfield(L, -2, k);
+}
+
+static void settabsb (lua_State *L, const char *k, int v) {
+  lua_pushboolean(L, v);
+  lua_setfield(L, -2, k);
+}
+
+
+/*
+** In function 'db_getinfo', the call to 'lua_getinfo' may push
+** results on the stack; later it creates the result table to put
+** these objects. Function 'treatstackoption' puts the result from
+** 'lua_getinfo' on top of the result table so that it can call
+** 'lua_setfield'.
+*/
 static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
-  if (L == L1) {
-    lua_pushvalue(L, -2);
-    lua_remove(L, -3);
-  }
+  if (L == L1)
+    lua_rotate(L, -2, 1);  /* exchange object and table */
   else
-    lua_xmove(L1, L, 1);
-  lua_setfield(L, -2, fname);
+    lua_xmove(L1, L, 1);  /* move object to the "main" stack */
+  lua_setfield(L, -2, fname);  /* put object into table */
 }
 
 
+/*
+** 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_isnumber(L, arg+1)) {
-    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {
+  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 */
+    lua_xmove(L, L1, 1);
+  }
+  else {  /* stack level */
+    if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) {
       lua_pushnil(L);  /* level out of range */
       return 1;
     }
   }
-  else if (lua_isfunction(L, arg+1)) {
-    lua_pushfstring(L, ">%s", options);
-    options = lua_tostring(L, -1);
-    lua_pushvalue(L, arg+1);
-    lua_xmove(L, L1, 1);
-  }
-  else
-    return luaL_argerror(L, arg+1, "function or level expected");
   if (!lua_getinfo(L1, options, &ar))
     return luaL_argerror(L, arg+2, "invalid option");
-  lua_createtable(L, 0, 2);
+  lua_newtable(L);  /* table to collect results */
   if (strchr(options, 'S')) {
     settabss(L, "source", ar.source);
     settabss(L, "short_src", ar.short_src);
@@ -170,21 +195,22 @@ static int db_getlocal (lua_State *L) {
   lua_State *L1 = getthread(L, &arg);
   lua_Debug ar;
   const char *name;
-  int nvar = luaL_checkint(L, arg+2);  /* local-variable index */
+  int nvar = (int)luaL_checkinteger(L, arg + 2);  /* local-variable index */
   if (lua_isfunction(L, arg + 1)) {  /* function argument? */
     lua_pushvalue(L, arg + 1);  /* push function */
     lua_pushstring(L, lua_getlocal(L, NULL, nvar));  /* push local name */
-    return 1;
+    return 1;  /* return only name (there is no value) */
   }
   else {  /* stack-level argument */
-    if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
+    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);  /* push local value */
+      lua_xmove(L1, L, 1);  /* move local value */
       lua_pushstring(L, name);  /* push name */
-      lua_pushvalue(L, -2);  /* re-order */
+      lua_rotate(L, -2, 1);  /* re-order */
       return 2;
     }
     else {
@@ -197,27 +223,36 @@ static int db_getlocal (lua_State *L) {
 
 static int db_setlocal (lua_State *L) {
   int arg;
+  const char *name;
   lua_State *L1 = getthread(L, &arg);
   lua_Debug ar;
-  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */
+  int level = (int)luaL_checkinteger(L, arg + 1);
+  int nvar = (int)luaL_checkinteger(L, arg + 2);
+  if (!lua_getstack(L1, level, &ar))  /* out of range? */
     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);
-  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));
+  name = lua_setlocal(L1, &ar, nvar);
+  if (name == NULL)
+    lua_pop(L1, 1);  /* pop value (if not popped by 'lua_setlocal') */
+  lua_pushstring(L, name);
   return 1;
 }
 
 
+/*
+** get (if 'get' is true) or set an upvalue from a closure
+*/
 static int auxupvalue (lua_State *L, int get) {
   const char *name;
-  int n = luaL_checkint(L, 2);
-  luaL_checktype(L, 1, LUA_TFUNCTION);
+  int n = (int)luaL_checkinteger(L, 2);  /* upvalue index */
+  luaL_checktype(L, 1, LUA_TFUNCTION);  /* closure */
   name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
   if (name == NULL) return 0;
   lua_pushstring(L, name);
-  lua_insert(L, -(get+1));
+  lua_insert(L, -(get+1));  /* no-op if get is false */
   return get + 1;
 }
 
@@ -233,13 +268,15 @@ static int db_setupvalue (lua_State *L) {
 }
 
 
+/*
+** Check whether a given upvalue from a given closure exists and
+** returns its index
+*/
 static int checkupval (lua_State *L, int argf, int argnup) {
-  lua_Debug ar;
-  int nup = luaL_checkint(L, argnup);
-  luaL_checktype(L, argf, LUA_TFUNCTION);
-  lua_pushvalue(L, argf);
-  lua_getinfo(L, ">u", &ar);
-  luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index");
+  int nup = (int)luaL_checkinteger(L, argnup);  /* upvalue index */
+  luaL_checktype(L, argf, LUA_TFUNCTION);  /* closure */
+  luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
+                   "invalid upvalue index");
   return nup;
 }
 
@@ -261,26 +298,29 @@ static int db_upvaluejoin (lua_State *L) {
 }
 
 
-#define gethooktable(L)        luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)
-
-
+/*
+** Call hook function registered at hook table for the current
+** thread (if there is one)
+*/
 static void hookf (lua_State *L, lua_Debug *ar) {
   static const char *const hooknames[] =
     {"call", "return", "line", "count", "tail call"};
-  gethooktable(L);
+  lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
   lua_pushthread(L);
-  lua_rawget(L, -2);
-  if (lua_isfunction(L, -1)) {
-    lua_pushstring(L, hooknames[(int)ar->event]);
+  if (lua_rawget(L, -2) == LUA_TFUNCTION) {  /* is there a hook function? */
+    lua_pushstring(L, hooknames[(int)ar->event]);  /* push event name */
     if (ar->currentline >= 0)
-      lua_pushinteger(L, ar->currentline);
+      lua_pushinteger(L, ar->currentline);  /* push current line */
     else lua_pushnil(L);
     lua_assert(lua_getinfo(L, "lS", ar));
-    lua_call(L, 2, 0);
+    lua_call(L, 2, 0);  /* call hook function */
   }
 }
 
 
+/*
+** Convert a string mask (for 'sethook') into a bit mask
+*/
 static int makemask (const char *smask, int count) {
   int mask = 0;
   if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
@@ -291,6 +331,9 @@ static int makemask (const char *smask, int count) {
 }
 
 
+/*
+** Convert a bit mask (for 'gethook') into a string mask
+*/
 static char *unmakemask (int mask, char *smask) {
   int i = 0;
   if (mask & LUA_MASKCALL) smask[i++] = 'c';
@@ -305,27 +348,30 @@ static int db_sethook (lua_State *L) {
   int arg, mask, count;
   lua_Hook func;
   lua_State *L1 = getthread(L, &arg);
-  if (lua_isnoneornil(L, arg+1)) {
+  if (lua_isnoneornil(L, arg+1)) {  /* no hook? */
     lua_settop(L, arg+1);
     func = NULL; mask = 0; count = 0;  /* turn off hooks */
   }
   else {
     const char *smask = luaL_checkstring(L, arg+2);
     luaL_checktype(L, arg+1, LUA_TFUNCTION);
-    count = luaL_optint(L, arg+3, 0);
+    count = (int)luaL_optinteger(L, arg + 3, 0);
     func = hookf; mask = makemask(smask, count);
   }
-  if (gethooktable(L) == 0) {  /* creating hook table? */
+  if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) {
+    lua_createtable(L, 0, 2);  /* create a hook table */
+    lua_pushvalue(L, -1);
+    lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY);  /* set it in position */
     lua_pushstring(L, "k");
     lua_setfield(L, -2, "__mode");  /** hooktable.__mode = "k" */
     lua_pushvalue(L, -1);
     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
   }
   checkstack(L, L1, 1);
-  lua_pushthread(L1); lua_xmove(L1, L, 1);
-  lua_pushvalue(L, arg+1);
-  lua_rawset(L, -3);  /* set new hook */
-  lua_sethook(L1, func, mask, count);  /* set hooks */
+  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 */
+  lua_sethook(L1, func, mask, count);
   return 0;
 }
 
@@ -336,17 +382,19 @@ static int db_gethook (lua_State *L) {
   char buff[5];
   int mask = lua_gethookmask(L1);
   lua_Hook hook = lua_gethook(L1);
-  if (hook != NULL && hook != hookf)  /* external hook? */
+  if (hook == NULL)  /* no hook? */
+    lua_pushnil(L);
+  else if (hook != hookf)  /* external hook? */
     lua_pushliteral(L, "external hook");
-  else {
-    gethooktable(L);
+  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);   /* get hook */
+    lua_rawget(L, -2);   /* 1st result = hooktable[L1] */
     lua_remove(L, -2);  /* remove hook table */
   }
-  lua_pushstring(L, unmakemask(mask, buff));
-  lua_pushinteger(L, lua_gethookcount(L1));
+  lua_pushstring(L, unmakemask(mask, buff));  /* 2nd result = mask */
+  lua_pushinteger(L, lua_gethookcount(L1));  /* 3rd result = count */
   return 3;
 }
 
@@ -354,13 +402,13 @@ static int db_gethook (lua_State *L) {
 static int db_debug (lua_State *L) {
   for (;;) {
     char buffer[250];
-    luai_writestringerror("%s", "lua_debug> ");
+    lua_writestringerror("%s", "lua_debug> ");
     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
         strcmp(buffer, "cont\n") == 0)
       return 0;
     if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
         lua_pcall(L, 0, 0, 0))
-      luai_writestringerror("%s\n", lua_tostring(L, -1));
+      lua_writestringerror("%s\n", lua_tostring(L, -1));
     lua_settop(L, 0);  /* remove eventual returns */
   }
 }
@@ -373,7 +421,7 @@ static int db_traceback (lua_State *L) {
   if (msg == NULL && !lua_isnoneornil(L, arg + 1))  /* non-string 'msg'? */
     lua_pushvalue(L, arg + 1);  /* return it untouched */
   else {
-    int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0);
+    int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
     luaL_traceback(L, L1, msg, level);
   }
   return 1;
index 9611846..e499ee3 100644 (file)
@@ -1,18 +1,19 @@
 /*
-** $Id: ldebug.c,v 2.90.1.4 2015/02/19 17:05:13 roberto Exp $
+** $Id: ldebug.c,v 2.120 2016/03/31 19:01:21 roberto Exp $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
 
+#define ldebug_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 #include <stdarg.h>
 #include <stddef.h>
 #include <string.h>
 
-
-#define ldebug_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lapi.h"
 #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);
 
 
@@ -47,6 +52,12 @@ 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 */
@@ -58,9 +69,15 @@ static void swapextra (lua_State *L) {
 
 
 /*
-** this function can be called asynchronous (e.g. during a signal)
+** This function can be called asynchronously (e.g. during a signal).
+** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
+** 'resethookcount') are for debug only, and it is no problem if they
+** get arbitrary values (causes at most one wrong hook call). 'hookmask'
+** is an atomic value. We assume that pointers are atomic too (e.g., gcc
+** ensures that for all platforms where it runs). Moreover, 'hook' is
+** always checked before being called (see 'luaD_hook').
 */
-LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
+LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
   if (func == NULL || mask == 0) {  /* turn off hooks? */
     mask = 0;
     func = NULL;
@@ -71,7 +88,6 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
   L->basehookcount = count;
   resethookcount(L);
   L->hookmask = cast_byte(mask);
-  return 1;
 }
 
 
@@ -116,7 +132,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;
@@ -162,7 +178,7 @@ 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);
@@ -176,14 +192,15 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
 
 
 LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
-  StkId pos = 0;  /* to avoid warnings */
+  StkId pos = NULL;  /* to avoid warnings */
   const char *name;
   lua_lock(L);
   swapextra(L);
   name = findlocal(L, ar->i_ci, n, &pos);
-  if (name)
+  if (name) {
     setobjs2s(L, pos, L->top - 1);
-  L->top--;  /* pop value */
+    L->top--;  /* pop value */
+  }
   swapextra(L);
   lua_unlock(L);
   return name;
@@ -303,7 +320,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);
+  swapextra(L);  /* correct before option 'L', which can raise a mem. error */
   if (strchr(what, 'L'))
     collectvalidlines(L, cl);
   lua_unlock(L);
@@ -383,18 +400,13 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
       case OP_JMP: {
         int b = GETARG_sBx(i);
         int dest = pc + 1 + b;
-        /* jump is forward and do not skip `lastpc'? */
+        /* jump is forward and do not skip 'lastpc'? */
         if (pc < dest && dest <= lastpc) {
           if (dest > jmptarget)
             jmptarget = dest;  /* update 'jmptarget' */
         }
         break;
       }
-      case OP_TEST: {
-        if (reg == a)  /* jumped code can change 'a' */
-          setreg = filterpc(pc, jmptarget);
-        break;
-      }
       default:
         if (testAMode(op) && reg == a)  /* any instruction that set A */
           setreg = filterpc(pc, jmptarget);
@@ -460,10 +472,14 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
 
 
 static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
-  TMS tm;
+  TMS tm = (TMS)0;  /* to avoid warnings */
   Proto *p = ci_func(ci)->p;  /* calling function */
   int pc = currentpc(ci);  /* calling instruction index */
   Instruction i = p->code[pc];  /* calling instruction */
+  if (ci->callstatus & CIST_HOOKED) {  /* was it called inside a hook? */
+    *name = "?";
+    return "hook";
+  }
   switch (GET_OPCODE(i)) {
     case OP_CALL:
     case OP_TAILCALL:  /* get function name */
@@ -473,25 +489,27 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
        return "for iterator";
     }
     /* all other instructions can call only through metamethods */
-    case OP_SELF:
-    case OP_GETTABUP:
-    case OP_GETTABLE: tm = TM_INDEX; break;
-    case OP_SETTABUP:
-    case OP_SETTABLE: tm = TM_NEWINDEX; break;
-    case OP_EQ: tm = TM_EQ; break;
-    case OP_ADD: tm = TM_ADD; break;
-    case OP_SUB: tm = TM_SUB; break;
-    case OP_MUL: tm = TM_MUL; break;
-    case OP_DIV: tm = TM_DIV; break;
-    case OP_MOD: tm = TM_MOD; break;
-    case OP_POW: tm = TM_POW; break;
+    case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
+      tm = TM_INDEX;
+      break;
+    case OP_SETTABUP: case OP_SETTABLE:
+      tm = TM_NEWINDEX;
+      break;
+    case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD:
+    case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND:
+    case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: {
+      int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD);  /* ORDER OP */
+      tm = cast(TMS, offset + cast_int(TM_ADD));  /* ORDER TM */
+      break;
+    }
     case OP_UNM: tm = TM_UNM; break;
+    case OP_BNOT: tm = TM_BNOT; break;
     case OP_LEN: tm = TM_LEN; break;
+    case OP_CONCAT: tm = TM_CONCAT; break;
+    case OP_EQ: tm = TM_EQ; break;
     case OP_LT: tm = TM_LT; break;
     case OP_LE: tm = TM_LE; break;
-    case OP_CONCAT: tm = TM_CONCAT; break;
-    default:
-      return NULL;  /* else no useful name can be found */
+    default: lua_assert(0);  /* other instructions cannot call a function */
   }
   *name = getstr(G(L)->tmname[tm]);
   return "metamethod";
@@ -502,17 +520,21 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
 
 
 /*
-** only ANSI way to check whether a pointer points to an array
-** (used only for error messages, so efficiency is not a big concern)
+** The subtraction of two potentially unrelated pointers is
+** not ISO C, but it should not crash a program; the subsequent
+** checks are ISO C and ensure a correct result.
 */
 static int isinstack (CallInfo *ci, const TValue *o) {
-  StkId p;
-  for (p = ci->u.l.base; p < ci->top; p++)
-    if (o == p) return 1;
-  return 0;
+  ptrdiff_t i = o - ci->u.l.base;
+  return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o);
 }
 
 
+/*
+** Checks whether value 'o' came from an upvalue. (That can only happen
+** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on
+** upvalues.)
+*/
 static const char *getupvalname (CallInfo *ci, const TValue *o,
                                  const char **name) {
   LClosure *c = ci_func(ci);
@@ -527,10 +549,9 @@ static const char *getupvalname (CallInfo *ci, const TValue *o,
 }
 
 
-l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+static const char *varinfo (lua_State *L, const TValue *o) {
+  const char *name = NULL;  /* to avoid warnings */
   CallInfo *ci = L->ci;
-  const char *name = NULL;
-  const char *t = objtypename(o);
   const char *kind = NULL;
   if (isLua(ci)) {
     kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
@@ -538,73 +559,121 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
       kind = getobjname(ci_func(ci)->p, currentpc(ci),
                         cast_int(o - ci->u.l.base), &name);
   }
-  if (kind)
-    luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
-                op, kind, name, t);
-  else
-    luaG_runerror(L, "attempt to %s a %s value", op, t);
+  return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : "";
+}
+
+
+l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
+  const char *t = luaT_objtypename(L, o);
+  luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o));
 }
 
 
-l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
-  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;
-  lua_assert(!ttisstring(p1) && !ttisnumber(p1));
+l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
+  if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
   luaG_typeerror(L, p1, "concatenate");
 }
 
 
-l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
-  TValue temp;
-  if (luaV_tonumber(p1, &temp) == NULL)
-    p2 = p1;  /* first operand is wrong */
-  luaG_typeerror(L, p2, "perform arithmetic on");
+l_noret luaG_opinterror (lua_State *L, const TValue *p1,
+                         const TValue *p2, const char *msg) {
+  lua_Number temp;
+  if (!tonumber(p1, &temp))  /* first operand is wrong? */
+    p2 = p1;  /* now second is wrong */
+  luaG_typeerror(L, p2, msg);
+}
+
+
+/*
+** Error when both values are convertible to numbers, but not to integers
+*/
+l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
+  lua_Integer temp;
+  if (!tointeger(p1, &temp))
+    p2 = p1;
+  luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
 }
 
 
 l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
-  const char *t1 = objtypename(p1);
-  const char *t2 = objtypename(p2);
-  if (t1 == t2)
+  const char *t1 = luaT_objtypename(L, p1);
+  const char *t2 = luaT_objtypename(L, p2);
+  if (strcmp(t1, t2) == 0)
     luaG_runerror(L, "attempt to compare two %s values", t1);
   else
     luaG_runerror(L, "attempt to compare %s with %s", t1, t2);
 }
 
 
-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);
 }
 
 
 l_noret luaG_errormsg (lua_State *L) {
   if (L->errfunc != 0) {  /* is there an error handling function? */
     StkId errfunc = restorestack(L, L->errfunc);
-    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
     setobjs2s(L, L->top, L->top - 1);  /* move argument */
     setobjs2s(L, L->top - 1, errfunc);  /* push function */
-    L->top++;
-    luaD_call(L, L->top - 2, 1, 0);  /* call it */
+    L->top++;  /* assume EXTRA_STACK */
+    luaD_callnoyield(L, L->top - 2, 1);  /* call it */
   }
   luaD_throw(L, LUA_ERRRUN);
 }
 
 
 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);
 }
 
+
+void luaG_traceexec (lua_State *L) {
+  CallInfo *ci = L->ci;
+  lu_byte mask = L->hookmask;
+  int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
+  if (counthook)
+    resethookcount(L);  /* reset count */
+  else if (!(mask & LUA_MASKLINE))
+    return;  /* no line hook and count != 0; nothing to be done */
+  if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
+    ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
+    return;  /* do not call hook again (VM yielded, so it did not move) */
+  }
+  if (counthook)
+    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
+  if (mask & LUA_MASKLINE) {
+    Proto *p = ci_func(ci)->p;
+    int npc = pcRel(ci->u.l.savedpc, p);
+    int newline = getfuncline(p, npc);
+    if (npc == 0 ||  /* call linehook when enter a new function, */
+        ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
+        newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
+      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
+  }
+  L->oldpc = ci->u.l.savedpc;
+  if (L->status == LUA_YIELD) {  /* did hook yield? */
+    if (counthook)
+      L->hookcount = 1;  /* undo decrement to zero */
+    ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
+    ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
+    ci->func = L->top - 1;  /* protect stack below results */
+    luaD_throw(L, LUA_YIELD);
+  }
+}
+
index 6445c76..0e31546 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 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
 */
 
 #define pcRel(pc, p)   (cast(int, (pc) - (p)->code) - 1)
 
-#define getfuncline(f,pc)      (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
+#define getfuncline(f,pc)      (((f)->lineinfo) ? (f)->lineinfo[pc] : -1)
 
 #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);
-LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2);
-LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1,
+LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
+                                                  const TValue *p2);
+LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1,
+                                                 const TValue *p2,
+                                                 const char *msg);
+LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1,
                                                  const TValue *p2);
 LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1,
                                                  const TValue *p2);
 LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...);
+LUAI_FUNC 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);
+
 
 #endif
index e9dd5fa..8804c99 100644 (file)
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,17 +1,19 @@
 /*
-** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 roberto Exp $
+** $Id: ldo.c,v 2.151 2015/12/16 16:40:07 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
 
+#define ldo_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 #include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define ldo_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lapi.h"
@@ -33,6 +35,8 @@
 
 
 
+#define errorstatus(s) ((s) > LUA_YIELD)
+
 
 /*
 ** {======================================================
 ** C++ code, with _longjmp/_setjmp when asked to use them, and with
 ** longjmp/setjmp otherwise.
 */
-#if !defined(LUAI_THROW)
+#if !defined(LUAI_THROW)                               /* { */
+
+#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)  /* { */
 
-#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP)
 /* C++ exceptions */
 #define LUAI_THROW(L,c)                throw(c)
 #define LUAI_TRY(L,c,a) \
        try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
 #define luai_jmpbuf            int  /* dummy variable */
 
-#elif defined(LUA_USE_ULONGJMP)
-/* in Unix, try _longjmp/_setjmp (more efficient) */
+#elif defined(LUA_USE_POSIX)                           /* }{ */
+
+/* in POSIX, try _longjmp/_setjmp (more efficient) */
 #define LUAI_THROW(L,c)                _longjmp((c)->b, 1)
 #define LUAI_TRY(L,c,a)                if (_setjmp((c)->b) == 0) { a }
 #define luai_jmpbuf            jmp_buf
 
-#else
-/* default handling with long jumps */
+#else                                                  /* }{ */
+
+/* ISO C handling with long jumps */
 #define LUAI_THROW(L,c)                longjmp((c)->b, 1)
 #define LUAI_TRY(L,c,a)                if (setjmp((c)->b) == 0) { a }
 #define luai_jmpbuf            jmp_buf
 
-#endif
+#endif                                                 /* } */
 
-#endif
+#endif                                                 /* } */
 
 
 
@@ -106,15 +113,19 @@ l_noret luaD_throw (lua_State *L, int errcode) {
     LUAI_THROW(L, L->errorJmp);  /* jump to it */
   }
   else {  /* thread has no error handler */
+    global_State *g = G(L);
     L->status = cast_byte(errcode);  /* mark it as dead */
-    if (G(L)->mainthread->errorJmp) {  /* main thread has a handler? */
-      setobjs2s(L, G(L)->mainthread->top++, L->top - 1);  /* copy error obj. */
-      luaD_throw(G(L)->mainthread, errcode);  /* re-throw in main thread */
+    if (g->mainthread->errorJmp) {  /* main thread has a handler? */
+      setobjs2s(L, g->mainthread->top++, L->top - 1);  /* copy error obj. */
+      luaD_throw(g->mainthread, errcode);  /* re-throw in main thread */
     }
     else {  /* no handler at all; abort */
-      if (G(L)->panic) {  /* panic function? */
+      if (g->panic) {  /* panic function? */
+        seterrorobj(L, errcode, L->top);  /* assume EXTRA_STACK */
+        if (L->ci->top < L->top)
+          L->ci->top = L->top;  /* pushing msg. can break this invariant */
         lua_unlock(L);
-        G(L)->panic(L);  /* call it (last chance to jump out) */
+        g->panic(L);  /* call panic function (last chance to jump out) */
       }
       abort();
     }
@@ -139,12 +150,17 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
 /* }====================================================== */
 
 
+/*
+** {==================================================================
+** Stack reallocation
+** ===================================================================
+*/
 static void correctstack (lua_State *L, TValue *oldstack) {
   CallInfo *ci;
-  GCObject *up;
+  UpVal *up;
   L->top = (L->top - oldstack) + L->stack;
-  for (up = L->openupval; up != NULL; up = up->gch.next)
-    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
+  for (up = L->openupval; up != NULL; up = up->u.open.next)
+    up->v = (up->v - oldstack) + L->stack;
   for (ci = L->ci; ci != NULL; ci = ci->previous) {
     ci->top = (ci->top - oldstack) + L->stack;
     ci->func = (ci->func - oldstack) + L->stack;
@@ -206,17 +222,34 @@ void luaD_shrinkstack (lua_State *L) {
   int inuse = stackinuse(L);
   int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
   if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
-  if (inuse > LUAI_MAXSTACK ||  /* handling stack overflow? */
-      goodsize >= L->stacksize)  /* would grow instead of shrink? */
-    condmovestack(L);  /* don't change stack (change only for debugging) */
+  if (L->stacksize > LUAI_MAXSTACK)  /* was handling stack overflow? */
+    luaE_freeCI(L);  /* free all CIs (list grew because of an error) */
   else
+    luaE_shrinkCI(L);  /* shrink list */
+  if (inuse <= LUAI_MAXSTACK &&  /* not handling stack overflow? */
+      goodsize < L->stacksize)  /* trying to shrink? */
     luaD_reallocstack(L, goodsize);  /* shrink it */
+  else
+    condmovestack(L,,);  /* don't change stack (change only for debugging) */
 }
 
 
+void luaD_inctop (lua_State *L) {
+  luaD_checkstack(L, 1);
+  L->top++;
+}
+
+/* }================================================================== */
+
+
+/*
+** Call a hook for the given event. Make sure there is a hook to be
+** called. (Both 'L->hook' and 'L->hookmask', which triggers this
+** function, can be changed asynchronously by signals.)
+*/
 void luaD_hook (lua_State *L, int event, int line) {
   lua_Hook hook = L->hook;
-  if (hook && L->allowhook) {
+  if (hook && L->allowhook) {  /* make sure there is a hook */
     CallInfo *ci = L->ci;
     ptrdiff_t top = savestack(L, L->top);
     ptrdiff_t ci_top = savestack(L, ci->top);
@@ -258,31 +291,34 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
   int i;
   int nfixargs = p->numparams;
   StkId base, fixed;
-  lua_assert(actual >= nfixargs);
   /* move fixed parameters to final position */
-  luaD_checkstack(L, p->maxstacksize);  /* check again for new 'base' */
   fixed = L->top - actual;  /* first fixed argument */
   base = L->top;  /* final position of first argument */
-  for (i=0; i<nfixargs; i++) {
+  for (i = 0; i < nfixargs && i < actual; i++) {
     setobjs2s(L, L->top++, fixed + i);
-    setnilvalue(fixed + i);
+    setnilvalue(fixed + i);  /* erase original copy (for GC) */
   }
+  for (; i < nfixargs; i++)
+    setnilvalue(L->top++);  /* complete missing arguments */
   return base;
 }
 
 
-static StkId tryfuncTM (lua_State *L, StkId func) {
+/*
+** Check whether __call metafield of 'func' is a function. If so, put
+** it in stack below original 'func' so that 'luaD_precall' can call
+** it. Raise an error if __call metafield is not a function.
+*/
+static void tryfuncTM (lua_State *L, StkId func) {
   const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
   StkId p;
-  ptrdiff_t funcr = savestack(L, func);
   if (!ttisfunction(tm))
     luaG_typeerror(L, func, "call");
-  /* Open a hole inside the stack at `func' */
-  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
-  incr_top(L);
-  func = restorestack(L, funcr);  /* previous call may change stack */
+  /* Open a hole inside the stack at 'func' */
+  for (p = L->top; p > func; p--)
+    setobjs2s(L, p, p-1);
+  L->top++;  /* slot ensured by caller */
   setobj2s(L, func, tm);  /* tag method is the new function to be called */
-  return func;
 }
 
 
@@ -290,79 +326,133 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
 
 
+/* macro to check stack size, preserving 'p' */
+#define checkstackp(L,n,p)  \
+  luaD_checkstackaux(L, n, \
+    ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
+    luaC_checkGC(L),  /* stack grow uses memory */ \
+    p = restorestack(L, t__))  /* 'pos' part: restore 'p' */
+
+
 /*
-** returns true if function has been executed (C function)
+** Prepares a function call: checks the stack, creates a new CallInfo
+** entry, fills in the relevant information, calls hook if needed.
+** If function is a C function, does the call, too. (Otherwise, leave
+** the execution ('luaV_execute') to the caller, to allow stackless
+** calls.) Returns true iff function has been executed (C function).
 */
 int luaD_precall (lua_State *L, StkId func, int nresults) {
   lua_CFunction f;
   CallInfo *ci;
-  int n;  /* number of arguments (Lua) or returns (C) */
-  ptrdiff_t funcr = savestack(L, func);
   switch (ttype(func)) {
+    case LUA_TCCL:  /* C closure */
+      f = clCvalue(func)->f;
+      goto Cfunc;
     case LUA_TLCF:  /* light C function */
       f = fvalue(func);
-      goto Cfunc;
-    case LUA_TCCL: {  /* C closure */
-      f = clCvalue(func)->f;
-     Cfunc:
-      luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
+     Cfunc: {
+      int n;  /* number of returns */
+      checkstackp(L, LUA_MINSTACK, func);  /* ensure minimum stack size */
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
-      ci->func = restorestack(L, funcr);
+      ci->func = func;
       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, ci, 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 */
-      luaD_checkstack(L, p->maxstacksize);
-      for (; n < p->numparams; n++)
-        setnilvalue(L->top++);  /* complete missing arguments */
-      if (!p->is_vararg) {
-        func = restorestack(L, funcr);
+      int n = cast_int(L->top - func) - 1;  /* number of real arguments */
+      int fsize = p->maxstacksize;  /* frame size */
+      checkstackp(L, fsize, func);
+      if (p->is_vararg != 1) {  /* do not use vararg? */
+        for (; n < p->numparams; n++)
+          setnilvalue(L->top++);  /* complete missing arguments */
         base = func + 1;
       }
-      else {
+      else
         base = adjust_varargs(L, p, n);
-        func = restorestack(L, funcr);  /* previous call can change stack */
-      }
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
       ci->func = func;
       ci->u.l.base = base;
-      ci->top = base + p->maxstacksize;
+      L->top = ci->top = base + fsize;
       lua_assert(ci->top <= L->stack_last);
       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;
     }
     default: {  /* not a function */
-      func = tryfuncTM(L, func);  /* retry with 'function' tag method */
+      checkstackp(L, 1, func);  /* ensure space for metamethod */
+      tryfuncTM(L, func);  /* try to get '__call' metamethod */
       return luaD_precall(L, func, nresults);  /* now it must be a function */
     }
   }
 }
 
 
-int luaD_poscall (lua_State *L, StkId firstResult) {
+/*
+** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
+** Handle most typical cases (zero results for commands, one result for
+** expressions, multiple results for tail calls/single parameters)
+** separated.
+*/
+static int moveresults (lua_State *L, const TValue *firstResult, StkId res,
+                                      int nres, int wanted) {
+  switch (wanted) {  /* handle typical cases separately */
+    case 0: break;  /* nothing to move */
+    case 1: {  /* one result needed */
+      if (nres == 0)   /* no results? */
+        firstResult = luaO_nilobject;  /* adjust with nil */
+      setobjs2s(L, res, firstResult);  /* move it to proper place */
+      break;
+    }
+    case LUA_MULTRET: {
+      int i;
+      for (i = 0; i < nres; i++)  /* move all results to correct place */
+        setobjs2s(L, res + i, firstResult + i);
+      L->top = res + nres;
+      return 0;  /* wanted == LUA_MULTRET */
+    }
+    default: {
+      int i;
+      if (wanted <= nres) {  /* enough results? */
+        for (i = 0; i < wanted; i++)  /* move wanted results to correct place */
+          setobjs2s(L, res + i, firstResult + i);
+      }
+      else {  /* not enough results; use all of them plus nils */
+        for (i = 0; i < nres; i++)  /* move all results to correct place */
+          setobjs2s(L, res + i, firstResult + i);
+        for (; i < wanted; i++)  /* complete wanted number of results */
+          setnilvalue(res + i);
+      }
+      break;
+    }
+  }
+  L->top = res + wanted;  /* top points after the last result */
+  return 1;
+}
+
+
+/*
+** Finishes a function call: calls hook if necessary, removes CallInfo,
+** moves current number of results to proper place; returns 0 iff call
+** wanted multiple (variable number of) results.
+*/
+int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
   StkId res;
-  int wanted, i;
-  CallInfo *ci = L->ci;
+  int wanted = ci->nresults;
   if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
     if (L->hookmask & LUA_MASKRET) {
       ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */
@@ -372,15 +462,24 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
     L->oldpc = ci->previous->u.l.savedpc;  /* 'oldpc' for caller function */
   }
   res = ci->func;  /* res == final position of 1st result */
-  wanted = ci->nresults;
-  L->ci = ci = ci->previous;  /* back to caller */
-  /* move results to correct place */
-  for (i = wanted; i != 0 && firstResult < L->top; i--)
-    setobjs2s(L, res++, firstResult++);
-  while (i-- > 0)
-    setnilvalue(res++);
-  L->top = res;
-  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */
+  L->ci = ci->previous;  /* back to caller */
+  /* move results to proper place */
+  return moveresults(L, firstResult, res, nres, wanted);
+}
+
+
+/*
+** Check appropriate error for stack overflow ("regular" overflow or
+** overflow while handling stack overflow). If 'nCalls' is larger than
+** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
+** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
+** allow overflow handling to work)
+*/
+static void stackerror (lua_State *L) {
+  if (L->nCcalls == LUAI_MAXCCALLS)
+    luaG_runerror(L, "C stack overflow");
+  else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
+    luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
 }
 
 
@@ -390,53 +489,67 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
 ** When returns, all the results are on the stack, starting at the original
 ** function position.
 */
-void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
-  if (++L->nCcalls >= LUAI_MAXCCALLS) {
-    if (L->nCcalls == LUAI_MAXCCALLS)
-      luaG_runerror(L, "C stack overflow");
-    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
-      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */
-  }
-  if (!allowyield) L->nny++;
+void luaD_call (lua_State *L, StkId func, int nResults) {
+  if (++L->nCcalls >= LUAI_MAXCCALLS)
+    stackerror(L);
   if (!luaD_precall(L, func, nResults))  /* is a Lua function? */
     luaV_execute(L);  /* call it */
-  if (!allowyield) L->nny--;
   L->nCcalls--;
 }
 
 
-static void finishCcall (lua_State *L) {
+/*
+** Similar to 'luaD_call', but does not allow yields during the call
+*/
+void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
+  L->nny++;
+  luaD_call(L, func, nResults);
+  L->nny--;
+}
+
+
+/*
+** Completes the execution of an interrupted C function, calling its
+** continuation function.
+*/
+static void finishCcall (lua_State *L, int status) {
   CallInfo *ci = L->ci;
   int n;
-  lua_assert(ci->u.c.k != NULL);  /* must have a continuation */
-  lua_assert(L->nny == 0);
+  /* must have a continuation and must be able to call it */
+  lua_assert(ci->u.c.k != NULL && L->nny == 0);
+  /* error status can only happen in a protected call */
+  lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD);
   if (ci->callstatus & CIST_YPCALL) {  /* was inside a pcall? */
     ci->callstatus &= ~CIST_YPCALL;  /* finish 'lua_pcall' */
     L->errfunc = ci->u.c.old_errfunc;
   }
-  /* finish 'lua_callk'/'lua_pcall' */
+  /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
+     handled */
   adjustresults(L, ci->nresults);
   /* call continuation function */
-  if (!(ci->callstatus & CIST_STAT))  /* no call status? */
-    ci->u.c.status = LUA_YIELD;  /* 'default' status */
-  lua_assert(ci->u.c.status != LUA_OK);
-  ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED;
   lua_unlock(L);
-  n = (*ci->u.c.k)(L);
+  n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
   lua_lock(L);
   api_checknelems(L, n);
   /* finish 'luaD_precall' */
-  luaD_poscall(L, L->top - n);
+  luaD_poscall(L, ci, L->top - n, n);
 }
 
 
+/*
+** Executes "full continuation" (everything in the stack) of a
+** previously interrupted coroutine until the stack is empty (or another
+** interruption long-jumps out of the loop). If the coroutine is
+** recovering from an error, 'ud' points to the error status, which must
+** be passed to the first continuation function (otherwise the default
+** status is LUA_YIELD).
+*/
 static void unroll (lua_State *L, void *ud) {
-  UNUSED(ud);
-  for (;;) {
-    if (L->ci == &L->base_ci)  /* stack is empty? */
-      return;  /* coroutine finished normally */
+  if (ud != NULL)  /* error status? */
+    finishCcall(L, *(int *)ud);  /* finish 'lua_pcallk' callee */
+  while (L->ci != &L->base_ci) {  /* something in the stack */
     if (!isLua(L->ci))  /* C function? */
-      finishCcall(L);
+      finishCcall(L, LUA_YIELD);  /* complete its execution */
     else {  /* Lua function */
       luaV_finishOp(L);  /* finish interrupted instruction */
       luaV_execute(L);  /* execute down to higher C 'boundary' */
@@ -446,7 +559,8 @@ static void unroll (lua_State *L, void *ud) {
 
 
 /*
-** check whether thread has a suspended protected call
+** Try to find a suspended protected call (a "recover point") for the
+** given thread.
 */
 static CallInfo *findpcall (lua_State *L) {
   CallInfo *ci;
@@ -458,6 +572,11 @@ static CallInfo *findpcall (lua_State *L) {
 }
 
 
+/*
+** Recovers from an error in a coroutine. Finds a recover point (if
+** there is one) and completes the execution of the interrupted
+** 'luaD_pcall'. If there is no recover point, returns zero.
+*/
 static int recover (lua_State *L, int status) {
   StkId oldtop;
   CallInfo *ci = findpcall(L);
@@ -467,12 +586,10 @@ static int recover (lua_State *L, int status) {
   luaF_close(L, oldtop);
   seterrorobj(L, status, oldtop);
   L->ci = ci;
-  L->allowhook = ci->u.c.old_allowhook;
+  L->allowhook = getoah(ci->callstatus);  /* restore original 'allowhook' */
   L->nny = 0;  /* should be zero to be yieldable */
   luaD_shrinkstack(L);
   L->errfunc = ci->u.c.old_errfunc;
-  ci->callstatus |= CIST_STAT;  /* call has error status */
-  ci->u.c.status = status;  /* (here it is) */
   return 1;  /* continue running the coroutine */
 }
 
@@ -491,11 +608,16 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
 
 
 /*
-** do the work for 'lua_resume' in protected mode
+** Do the work for 'lua_resume' in protected mode. Most of the work
+** depends on the status of the coroutine: initial state, suspended
+** inside a hook, or regularly suspended (optionally with a continuation
+** function), plus erroneous cases: non-suspended coroutine or dead
+** coroutine.
 */
 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);
@@ -509,24 +631,21 @@ static void resume (lua_State *L, void *ud) {
   else if (L->status != LUA_YIELD)
     resume_error(L, "cannot resume dead coroutine", firstArg);
   else {  /* resuming from previous yield */
-    L->status = LUA_OK;
+    L->status = LUA_OK;  /* mark that it is running (again) */
     ci->func = restorestack(L, ci->extra);
     if (isLua(ci))  /* yielded inside a hook? */
       luaV_execute(L);  /* just continue running Lua code */
     else {  /* 'common' yield */
-      if (ci->u.c.k != NULL) {  /* does it have a continuation? */
-        int n;
-        ci->u.c.status = LUA_YIELD;  /* 'default' status */
-        ci->callstatus |= CIST_YIELDED;
+      if (ci->u.c.k != NULL) {  /* does it have a continuation function? */
         lua_unlock(L);
-        n = (*ci->u.c.k)(L);  /* call continuation */
+        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, ci, firstArg, n);  /* finish 'luaD_precall' */
     }
-    unroll(L, NULL);
+    unroll(L, NULL);  /* run continuation */
   }
   lua_assert(nCcalls == L->nCcalls);
 }
@@ -534,27 +653,26 @@ static void resume (lua_State *L, void *ud) {
 
 LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
   int status;
-  int oldnny = L->nny;  /* save 'nny' */
+  unsigned short oldnny = L->nny;  /* save "number of non-yieldable" calls */
   lua_lock(L);
   luai_userstateresume(L, 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 {  /* yield or regular error */
-    while (status != LUA_OK && status != LUA_YIELD) {  /* error? */
-      if (recover(L, status))  /* recover point? */
-        status = luaD_rawrunprotected(L, unroll, NULL);  /* run continuation */
-      else {  /* unrecoverable error */
-        L->status = cast_byte(status);  /* mark thread as `dead' */
-        seterrorobj(L, status, L->top);
-        L->ci->top = L->top;
-        break;
-      }
+  else {  /* continue running after recoverable errors */
+    while (errorstatus(status) && recover(L, status)) {
+      /* unroll continuation */
+      status = luaD_rawrunprotected(L, unroll, &status);
     }
-    lua_assert(status == L->status);
+    if (errorstatus(status)) {  /* unrecoverable error? */
+      L->status = cast_byte(status);  /* mark thread as 'dead' */
+      seterrorobj(L, status, L->top);  /* push error message */
+      L->ci->top = L->top;
+    }
+    else lua_assert(status == L->status);  /* normal end or yield */
   }
   L->nny = oldnny;  /* restore 'nny' */
   L->nCcalls--;
@@ -564,7 +682,13 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
 }
 
 
-LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
+LUA_API int lua_isyieldable (lua_State *L) {
+  return (L->nny == 0);
+}
+
+
+LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
+                        lua_KFunction k) {
   CallInfo *ci = L->ci;
   luai_userstateyield(L, nresults);
   lua_lock(L);
@@ -619,7 +743,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
 /*
 ** Execute a protected parser.
 */
-struct SParser {  /* data to `f_parser' */
+struct SParser {  /* data to 'f_parser' */
   ZIO *z;
   Mbuffer buff;  /* dynamic structure used by the scanner */
   Dyndata dyd;  /* dynamic structures used by the parser */
@@ -631,31 +755,26 @@ struct SParser {  /* data to `f_parser' */
 static void checkmode (lua_State *L, const char *mode, const char *x) {
   if (mode && strchr(mode, x[0]) == NULL) {
     luaO_pushfstring(L,
-       "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode);
+       "attempt to load a %s chunk (mode is '%s')", x, mode);
     luaD_throw(L, LUA_ERRSYNTAX);
   }
 }
 
 
 static void f_parser (lua_State *L, void *ud) {
-  int i;
-  Closure *cl;
+  LClosure *cl;
   struct SParser *p = cast(struct SParser *, ud);
   int c = zgetc(p->z);  /* read first character */
   if (c == LUA_SIGNATURE[0]) {
     checkmode(L, p->mode, "binary");
-    cl = luaU_undump(L, p->z, &p->buff, p->name);
+    cl = luaU_undump(L, p->z, p->name);
   }
   else {
     checkmode(L, p->mode, "text");
     cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
   }
-  lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
-  for (i = 0; i < cl->l.nupvalues; i++) {  /* initialize upvalues */
-    UpVal *up = luaF_newupval(L);
-    cl->l.upvals[i] = up;
-    luaC_objbarrier(L, cl, up);
-  }
+  lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+  luaF_initupvals(L, cl);
 }
 
 
index d3d3082..4f5d51c 100644 (file)
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
 #include "lzio.h"
 
 
-#define luaD_checkstack(L,n)   if (L->stack_last - L->top <= (n)) \
-                                   luaD_growstack(L, n); else condmovestack(L);
+/*
+** Macro to check stack size and grow stack if needed.  Parameters
+** 'pre'/'pos' allow the macro to preserve a pointer into the
+** stack across reallocations, doing the work only when needed.
+** 'condmovestack' is used in heavy tests to force a stack reallocation
+** at every check.
+*/
+#define luaD_checkstackaux(L,n,pre,pos)  \
+       if (L->stack_last - L->top <= (n)) \
+         { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
+
+/* In general, 'pre'/'pos' are empty (nothing to save) */
+#define luaD_checkstack(L,n)   luaD_checkstackaux(L,n,(void)0,(void)0)
 
 
-#define incr_top(L) {L->top++; luaD_checkstack(L,0);}
 
 #define savestack(L,p)         ((char *)(p) - (char *)L->stack)
 #define restorestack(L,n)      ((TValue *)((char *)L->stack + (n)))
 
 
-/* type of protected functions, to be ran by `runprotected' */
+/* type of protected functions, to be ran by 'runprotected' */
 typedef void (*Pfunc) (lua_State *L, void *ud);
 
 LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
                                                   const char *mode);
 LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
 LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
-LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
-                                        int allowyield);
+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
+LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
 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, CallInfo *ci, 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);
+LUAI_FUNC void luaD_inctop (lua_State *L);
 
 LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
 LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
index 61fa2cd..016e300 100644 (file)
 /*
-** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $
 ** save precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
 
-#include <stddef.h>
-
 #define ldump_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <stddef.h>
+
 #include "lua.h"
 
 #include "lobject.h"
 #include "lstate.h"
 #include "lundump.h"
 
+
 typedef struct {
lua_State* L;
- lua_Writer writer;
void* data;
- int strip;
- int status;
 lua_State *L;
 lua_Writer writer;
 void *data;
 int strip;
 int status;
 } DumpState;
 
-#define DumpMem(b,n,size,D)    DumpBlock(b,(n)*(size),D)
-#define DumpVar(x,D)           DumpMem(&x,1,sizeof(x),D)
-
-static void DumpBlock(const void* b, size_t size, DumpState* D)
-{
- if (D->status==0)
- {
-  lua_unlock(D->L);
-  D->status=(*D->writer)(D->L,b,size,D->data);
-  lua_lock(D->L);
- }
+
+/*
+** All high-level dumps go through DumpVector; you can change it to
+** change the endianness of the result
+*/
+#define DumpVector(v,n,D)      DumpBlock(v,(n)*sizeof((v)[0]),D)
+
+#define DumpLiteral(s,D)       DumpBlock(s, sizeof(s) - sizeof(char), D)
+
+
+static void DumpBlock (const void *b, size_t size, DumpState *D) {
+  if (D->status == 0 && size > 0) {
+    lua_unlock(D->L);
+    D->status = (*D->writer)(D->L, b, size, D->data);
+    lua_lock(D->L);
+  }
 }
 
-static void DumpChar(int y, DumpState* D)
-{
- char x=(char)y;
- DumpVar(x,D);
+
+#define DumpVar(x,D)           DumpVector(&x,1,D)
+
+
+static void DumpByte (int y, DumpState *D) {
+  lu_byte x = (lu_byte)y;
+  DumpVar(x, D);
 }
 
-static void DumpInt(int x, DumpState* D)
-{
DumpVar(x,D);
+
+static void DumpInt (int x, DumpState *D) {
 DumpVar(x, D);
 }
 
-static void DumpNumber(lua_Number x, DumpState* D)
-{
DumpVar(x,D);
+
+static void DumpNumber (lua_Number x, DumpState *D) {
 DumpVar(x, D);
 }
 
-static void DumpVector(const void* b, int n, size_t size, DumpState* D)
-{
- DumpInt(n,D);
- DumpMem(b,n,size,D);
+
+static void DumpInteger (lua_Integer x, DumpState *D) {
+  DumpVar(x, D);
 }
 
-static void DumpString(const TString* s, DumpState* D)
-{
- if (s==NULL)
- {
-  size_t size=0;
-  DumpVar(size,D);
- }
- else
- {
-  size_t size=s->tsv.len+1;            /* include trailing '\0' */
-  DumpVar(size,D);
-  DumpBlock(getstr(s),size*sizeof(char),D);
- }
+
+static void DumpString (const TString *s, DumpState *D) {
+  if (s == NULL)
+    DumpByte(0, D);
+  else {
+    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(str, size - 1, D);  /* no need to save '\0' */
+  }
 }
 
-#define DumpCode(f,D)   DumpVector(f->code,f->sizecode,sizeof(Instruction),D)
-
-static void DumpFunction(const Proto* f, DumpState* D);
-
-static void DumpConstants(const Proto* f, DumpState* D)
-{
- int i,n=f->sizek;
- DumpInt(n,D);
- for (i=0; i<n; i++)
- {
-  const TValue* o=&f->k[i];
-  DumpChar(ttypenv(o),D);
-  switch (ttypenv(o))
-  {
-   case LUA_TNIL:
-       break;
-   case LUA_TBOOLEAN:
-       DumpChar(bvalue(o),D);
-       break;
-   case LUA_TNUMBER:
-       DumpNumber(nvalue(o),D);
-       break;
-   case LUA_TSTRING:
-       DumpString(rawtsvalue(o),D);
-       break;
-    default: lua_assert(0);
+
+static void DumpCode (const Proto *f, DumpState *D) {
+  DumpInt(f->sizecode, D);
+  DumpVector(f->code, f->sizecode, D);
+}
+
+
+static void DumpFunction(const Proto *f, TString *psource, DumpState *D);
+
+static void DumpConstants (const Proto *f, DumpState *D) {
+  int i;
+  int n = f->sizek;
+  DumpInt(n, D);
+  for (i = 0; i < n; i++) {
+    const TValue *o = &f->k[i];
+    DumpByte(ttype(o), D);
+    switch (ttype(o)) {
+    case LUA_TNIL:
+      break;
+    case LUA_TBOOLEAN:
+      DumpByte(bvalue(o), D);
+      break;
+    case LUA_TNUMFLT:
+      DumpNumber(fltvalue(o), D);
+      break;
+    case LUA_TNUMINT:
+      DumpInteger(ivalue(o), D);
+      break;
+    case LUA_TSHRSTR:
+    case LUA_TLNGSTR:
+      DumpString(tsvalue(o), D);
+      break;
+    default:
+      lua_assert(0);
+    }
   }
- }
- n=f->sizep;
- DumpInt(n,D);
- for (i=0; i<n; i++) DumpFunction(f->p[i],D);
 }
 
-static void DumpUpvalues(const Proto* f, DumpState* D)
-{
- int i,n=f->sizeupvalues;
- DumpInt(n,D);
- for (i=0; i<n; i++)
- {
-  DumpChar(f->upvalues[i].instack,D);
-  DumpChar(f->upvalues[i].idx,D);
- }
+
+static void DumpProtos (const Proto *f, DumpState *D) {
+  int i;
+  int n = f->sizep;
+  DumpInt(n, D);
+  for (i = 0; i < n; i++)
+    DumpFunction(f->p[i], f->source, D);
+}
+
+
+static void DumpUpvalues (const Proto *f, DumpState *D) {
+  int i, n = f->sizeupvalues;
+  DumpInt(n, D);
+  for (i = 0; i < n; i++) {
+    DumpByte(f->upvalues[i].instack, D);
+    DumpByte(f->upvalues[i].idx, D);
+  }
 }
 
-static void DumpDebug(const Proto* f, DumpState* D)
-{
int i,n;
DumpString((D->strip) ? NULL : f->source,D);
n= (D->strip) ? 0 : f->sizelineinfo;
DumpVector(f->lineinfo,n,sizeof(int),D);
n= (D->strip) ? 0 : f->sizelocvars;
DumpInt(n,D);
- for (i=0; i<n; i++)
- {
-  DumpString(f->locvars[i].varname,D);
-  DumpInt(f->locvars[i].startpc,D);
-  DumpInt(f->locvars[i].endpc,D);
- }
n= (D->strip) ? 0 : f->sizeupvalues;
- DumpInt(n,D);
for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D);
+
+static void DumpDebug (const Proto *f, DumpState *D) {
 int i, n;
 n = (D->strip) ? 0 : f->sizelineinfo;
 DumpInt(n, D);
 DumpVector(f->lineinfo, n, D);
 n = (D->strip) ? 0 : f->sizelocvars;
 DumpInt(n, D);
+  for (i = 0; i < n; i++) {
+    DumpString(f->locvars[i].varname, D);
+    DumpInt(f->locvars[i].startpc, D);
+    DumpInt(f->locvars[i].endpc, D);
+  }
+  n = (D->strip) ? 0 : f->sizeupvalues;
 DumpInt(n, D);
+  for (i = 0; i < n; i++)
   DumpString(f->upvalues[i].name, D);
 }
 
-static void DumpFunction(const Proto* f, DumpState* D)
-{
- DumpInt(f->linedefined,D);
- DumpInt(f->lastlinedefined,D);
- DumpChar(f->numparams,D);
- DumpChar(f->is_vararg,D);
- DumpChar(f->maxstacksize,D);
- DumpCode(f,D);
- DumpConstants(f,D);
- DumpUpvalues(f,D);
- DumpDebug(f,D);
+
+static void DumpFunction (const Proto *f, TString *psource, DumpState *D) {
+  if (D->strip || f->source == psource)
+    DumpString(NULL, D);  /* no debug info or same source as its parent */
+  else
+    DumpString(f->source, D);
+  DumpInt(f->linedefined, D);
+  DumpInt(f->lastlinedefined, D);
+  DumpByte(f->numparams, D);
+  DumpByte(f->is_vararg, D);
+  DumpByte(f->maxstacksize, D);
+  DumpCode(f, D);
+  DumpConstants(f, D);
+  DumpUpvalues(f, D);
+  DumpProtos(f, D);
+  DumpDebug(f, D);
 }
 
-static void DumpHeader(DumpState* D)
-{
- lu_byte h[LUAC_HEADERSIZE];
- luaU_header(h);
- DumpBlock(h,LUAC_HEADERSIZE,D);
+
+static void DumpHeader (DumpState *D) {
+  DumpLiteral(LUA_SIGNATURE, D);
+  DumpByte(LUAC_VERSION, D);
+  DumpByte(LUAC_FORMAT, D);
+  DumpLiteral(LUAC_DATA, D);
+  DumpByte(sizeof(int), D);
+  DumpByte(sizeof(size_t), D);
+  DumpByte(sizeof(Instruction), D);
+  DumpByte(sizeof(lua_Integer), D);
+  DumpByte(sizeof(lua_Number), D);
+  DumpInteger(LUAC_INT, D);
+  DumpNumber(LUAC_NUM, D);
 }
 
+
 /*
 ** dump Lua function as precompiled chunk
 */
-int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
-{
- DumpState D;
- D.L=L;
- D.writer=w;
- D.data=data;
- D.strip=strip;
- D.status=0;
- DumpHeader(&D);
- DumpFunction(f,&D);
- return D.status;
+int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data,
+              int strip) {
+  DumpState D;
+  D.L = L;
+  D.writer = w;
+  D.data = data;
+  D.strip = strip;
+  D.status = 0;
+  DumpHeader(&D);
+  DumpByte(f->sizeupvalues, &D);
+  DumpFunction(f, NULL, &D);
+  return D.status;
 }
+
index e90e152..67967da 100644 (file)
@@ -1,15 +1,17 @@
 /*
-** $Id: lfunc.c,v 2.30.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lfunc.c,v 2.45 2014/11/02 19:19:04 roberto Exp $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
 
-
-#include <stddef.h>
-
 #define lfunc_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <stddef.h>
+
 #include "lua.h"
 
 #include "lfunc.h"
 
 
 
-Closure *luaF_newCclosure (lua_State *L, int n) {
-  Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl;
-  c->c.nupvalues = cast_byte(n);
+CClosure *luaF_newCclosure (lua_State *L, int n) {
+  GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n));
+  CClosure *c = gco2ccl(o);
+  c->nupvalues = cast_byte(n);
   return c;
 }
 
 
-Closure *luaF_newLclosure (lua_State *L, int n) {
-  Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl;
-  c->l.p = NULL;
-  c->l.nupvalues = cast_byte(n);
-  while (n--) c->l.upvals[n] = NULL;
+LClosure *luaF_newLclosure (lua_State *L, int n) {
+  GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n));
+  LClosure *c = gco2lcl(o);
+  c->p = NULL;
+  c->nupvalues = cast_byte(n);
+  while (n--) c->upvals[n] = NULL;
   return c;
 }
 
-
-UpVal *luaF_newupval (lua_State *L) {
-  UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv;
-  uv->v = &uv->u.value;
-  setnilvalue(uv->v);
-  return uv;
+/*
+** fill a closure with new closed upvalues
+*/
+void luaF_initupvals (lua_State *L, LClosure *cl) {
+  int i;
+  for (i = 0; i < cl->nupvalues; i++) {
+    UpVal *uv = luaM_new(L, UpVal);
+    uv->refcount = 1;
+    uv->v = &uv->u.value;  /* make it closed */
+    setnilvalue(uv->v);
+    cl->upvals[i] = uv;
+  }
 }
 
 
 UpVal *luaF_findupval (lua_State *L, StkId level) {
-  global_State *g = G(L);
-  GCObject **pp = &L->openupval;
+  UpVal **pp = &L->openupval;
   UpVal *p;
   UpVal *uv;
-  while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
-    GCObject *o = obj2gco(p);
-    lua_assert(p->v != &p->u.value);
-    lua_assert(!isold(o) || isold(obj2gco(L)));
-    if (p->v == level) {  /* found a corresponding upvalue? */
-      if (isdead(g, o))  /* is it dead? */
-        changewhite(o);  /* resurrect it */
-      return p;
-    }
-    pp = &p->next;
+  lua_assert(isintwups(L) || L->openupval == NULL);
+  while (*pp != NULL && (p = *pp)->v >= level) {
+    lua_assert(upisopen(p));
+    if (p->v == level)  /* found a corresponding upvalue? */
+      return p;  /* return it */
+    pp = &p->u.open.next;
   }
-  /* not found: create a new one */
-  uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv;
+  /* not found: create a new upvalue */
+  uv = luaM_new(L, UpVal);
+  uv->refcount = 0;
+  uv->u.open.next = *pp;  /* link it to list of open upvalues */
+  uv->u.open.touched = 1;
+  *pp = uv;
   uv->v = level;  /* current value lives in the stack */
-  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */
-  uv->u.l.next = g->uvhead.u.l.next;
-  uv->u.l.next->u.l.prev = uv;
-  g->uvhead.u.l.next = uv;
-  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
+  if (!isintwups(L)) {  /* thread not in list of threads with upvalues? */
+    L->twups = G(L)->twups;  /* link it to the list */
+    G(L)->twups = L;
+  }
   return uv;
 }
 
 
-static void unlinkupval (UpVal *uv) {
-  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
-  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */
-  uv->u.l.prev->u.l.next = uv->u.l.next;
-}
-
-
-void luaF_freeupval (lua_State *L, UpVal *uv) {
-  if (uv->v != &uv->u.value)  /* is it open? */
-    unlinkupval(uv);  /* remove from open list */
-  luaM_free(L, uv);  /* free upvalue */
-}
-
-
 void luaF_close (lua_State *L, StkId level) {
   UpVal *uv;
-  global_State *g = G(L);
-  while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) {
-    GCObject *o = obj2gco(uv);
-    lua_assert(!isblack(o) && uv->v != &uv->u.value);
-    L->openupval = uv->next;  /* remove from `open' list */
-    if (isdead(g, o))
-      luaF_freeupval(L, uv);  /* free upvalue */
+  while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
+    lua_assert(upisopen(uv));
+    L->openupval = uv->u.open.next;  /* remove from 'open' list */
+    if (uv->refcount == 0)  /* no references? */
+      luaM_free(L, uv);  /* free upvalue */
     else {
-      unlinkupval(uv);  /* remove upvalue from 'uvhead' list */
       setobj(L, &uv->u.value, uv->v);  /* move value to upvalue slot */
       uv->v = &uv->u.value;  /* now current value lives here */
-      gch(o)->next = g->allgc;  /* link upvalue into 'allgc' list */
-      g->allgc = o;
-      luaC_checkupvalcolor(g, uv);
+      luaC_upvalbarrier(L, uv);
     }
   }
 }
 
 
 Proto *luaF_newproto (lua_State *L) {
-  Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p;
+  GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto));
+  Proto *f = gco2p(o);
   f->k = NULL;
   f->sizek = 0;
   f->p = NULL;
@@ -144,7 +134,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
 
 
 /*
-** Look for n-th local variable at line `line' in function `func'.
+** Look for n-th local variable at line 'line' in function 'func'.
 ** Returns NULL if not found.
 */
 const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
index ca0d3a3..2eeb0d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 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
 */
                          cast(int, sizeof(TValue *)*((n)-1)))
 
 
+/* test whether thread is in 'twups' list */
+#define isintwups(L)   (L->twups != L)
+
+
+/*
+** 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 {
+  TValue *v;  /* points to stack or to its own value */
+  lu_mem refcount;  /* reference counter */
+  union {
+    struct {  /* (when open) */
+      UpVal *next;  /* linked list */
+      int touched;  /* mark to avoid cycles with dead threads */
+    } open;
+    TValue value;  /* the value (when closed) */
+  } u;
+};
+
+#define upisopen(up)   ((up)->v != &(up)->u.value)
+
+
 LUAI_FUNC Proto *luaF_newproto (lua_State *L);
-LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
-LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
-LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
+LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
+LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
+LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
 LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
 LUAI_FUNC void luaF_close (lua_State *L, StkId level);
 LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
-LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
 LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
                                          int pc);
 
index 553fd17..7c29fb0 100644 (file)
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,14 +1,17 @@
 /*
-** $Id: lgc.c,v 2.140.1.3 2014/09/01 16:55:08 roberto Exp $
+** $Id: lgc.c,v 2.212 2016/03/31 19:02:03 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
 
-#include <string.h>
-
 #define lgc_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
 #include "ldebug.h"
 #include "ltm.h"
 
 
+/*
+** internal state for collector while inside the atomic phase. The
+** collector should never be in this state while running regular code.
+*/
+#define GCSinsideatomic                (GCSpause + 1)
 
 /*
 ** cost of sweeping one element (the size of a small object divided
@@ -33,8 +41,8 @@
 /* maximum number of elements to sweep in each single step */
 #define GCSWEEPMAX     (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
 
-/* maximum number of finalizers to call in each GC step */
-#define GCFINALIZENUM  4
+/* cost of calling one finalizer */
+#define GCFINALIZECOST GCSWEEPCOST
 
 
 /*
 
 
 /*
-** 'makewhite' erases all color bits plus the old bit and then
-** sets only the current white bit
+** 'makewhite' erases all color bits then sets only the current white
+** bit
 */
-#define maskcolors     (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS))
+#define maskcolors     (~(bitmask(BLACKBIT) | WHITEBITS))
 #define makewhite(g,x) \
- (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g)))
+ (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g)))
 
-#define white2gray(x)  resetbits(gch(x)->marked, WHITEBITS)
-#define black2gray(x)  resetbit(gch(x)->marked, BLACKBIT)
+#define white2gray(x)  resetbits(x->marked, WHITEBITS)
+#define black2gray(x)  resetbit(x->marked, BLACKBIT)
 
 
-#define isfinalized(x)         testbit(gch(x)->marked, FINALIZEDBIT)
+#define valiswhite(x)   (iscollectable(x) && iswhite(gcvalue(x)))
 
 #define checkdeadkey(n)        lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n)))
 
 #define markvalue(g,o) { checkconsistency(o); \
   if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
 
-#define markobject(g,t) { if ((t) && iswhite(obj2gco(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);
 
@@ -95,33 +108,38 @@ static void reallymarkobject (global_State *g, GCObject *o);
 
 
 /*
-** link table 'h' into list pointed by 'p'
+** link collectable object 'o' into list pointed by 'p'
 */
-#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h))
+#define linkgclist(o,p)        ((o)->gclist = (p), (p) = obj2gco(o))
 
 
 /*
-** if key is not marked, mark its entry as dead (therefore removing it
-** from the table)
+** If key is not marked, mark its entry as dead. This allows key to be
+** collected, but keeps its entry in the table.  A dead node is needed
+** when Lua looks up for a key (it may be part of a chain) and when
+** traversing a weak table (key might be removed from the table during
+** traversal). Other places never manipulate dead keys, because its
+** associated nil value is enough to signal that the entry is logically
+** empty.
 */
 static void removeentry (Node *n) {
   lua_assert(ttisnil(gval(n)));
   if (valiswhite(gkey(n)))
-    setdeadvalue(gkey(n));  /* unused and unmarked key; remove it */
+    setdeadvalue(wgkey(n));  /* unused and unmarked key; remove it */
 }
 
 
 /*
 ** tells whether a key or value can be cleared from a weak
 ** table. Non-collectable objects are never removed from weak
-** tables. Strings behave as `values', so are never removed too. for
+** tables. Strings behave as 'values', so are never removed too. for
 ** other objects: if really collected, cannot keep them; for objects
 ** being finalized, keep them in keys, but not in values
 */
 static int iscleared (global_State *g, const TValue *o) {
   if (!iscollectable(o)) return 0;
   else if (ttisstring(o)) {
-    markobject(g, rawtsvalue(o));  /* strings are `values', so are never weak */
+    markobject(g, tsvalue(o));  /* strings are 'values', so are never weak */
     return 0;
   }
   else return iswhite(gcvalue(o));
@@ -130,14 +148,14 @@ static int iscleared (global_State *g, const TValue *o) {
 
 /*
 ** barrier that moves collector forward, that is, mark the white object
-** being pointed by a black object.
+** being pointed by a black object. (If in sweep phase, clear the black
+** object to white [sweep it] to avoid other barrier calls for this
+** same object.)
 */
 void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
   global_State *g = G(L);
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
-  lua_assert(g->gcstate != GCSpause);
-  lua_assert(gch(o)->tt != LUA_TTABLE);
-  if (keepinvariantout(g))  /* must keep invariant? */
+  if (keepinvariant(g))  /* must keep invariant? */
     reallymarkobject(g, v);  /* restore invariant */
   else {  /* sweep phase */
     lua_assert(issweepphase(g));
@@ -148,78 +166,52 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
 
 /*
 ** barrier that moves collector backward, that is, mark the black object
-** pointing to a white object as gray again. (Current implementation
-** only works for tables; access to 'gclist' is not uniform across
-** different types.)
+** pointing to a white object as gray again.
 */
-void luaC_barrierback_ (lua_State *L, GCObject *o) {
+void luaC_barrierback_ (lua_State *L, Table *t) {
   global_State *g = G(L);
-  lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE);
-  black2gray(o);  /* make object gray (again) */
-  gco2t(o)->gclist = g->grayagain;
-  g->grayagain = o;
+  lua_assert(isblack(t) && !isdead(g, t));
+  black2gray(t);  /* make table gray (again) */
+  linkgclist(t, g->grayagain);
 }
 
 
 /*
-** barrier for prototypes. When creating first closure (cache is
-** NULL), use a forward barrier; this may be the only closure of the
-** prototype (if it is a "regular" function, with a single instance)
-** and the prototype may be big, so it is better to avoid traversing
-** it again. Otherwise, use a backward barrier, to avoid marking all
-** possible instances.
+** barrier for assignments to closed upvalues. Because upvalues are
+** shared among closures, it is impossible to know the color of all
+** closures pointing to it. So, we assume that the object being assigned
+** must be marked.
 */
-LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) {
+void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
   global_State *g = G(L);
-  lua_assert(isblack(obj2gco(p)));
-  if (p->cache == NULL) {  /* first time? */
-    luaC_objbarrier(L, p, c);
-  }
-  else {  /* use a backward barrier */
-    black2gray(obj2gco(p));  /* make prototype gray (again) */
-    p->gclist = g->grayagain;
-    g->grayagain = obj2gco(p);
-  }
+  GCObject *o = gcvalue(uv->v);
+  lua_assert(!upisopen(uv));  /* ensured by macro luaC_upvalbarrier */
+  if (keepinvariant(g))
+    markobject(g, o);
 }
 
 
-/*
-** check color (and invariants) for an upvalue that was closed,
-** i.e., moved into the 'allgc' list
-*/
-void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
-  GCObject *o = obj2gco(uv);
-  lua_assert(!isblack(o));  /* open upvalues are never black */
-  if (isgray(o)) {
-    if (keepinvariant(g)) {
-      resetoldbit(o);  /* see MOVE OLD rule */
-      gray2black(o);  /* it is being visited now */
-      markvalue(g, uv->v);
-    }
-    else {
-      lua_assert(issweepphase(g));
-      makewhite(g, o);
-    }
-  }
+void luaC_fix (lua_State *L, GCObject *o) {
+  global_State *g = G(L);
+  lua_assert(g->allgc == o);  /* object must be 1st in 'allgc' list! */
+  white2gray(o);  /* they will be gray forever */
+  g->allgc = o->next;  /* remove object from 'allgc' list */
+  o->next = g->fixedgc;  /* link it to 'fixedgc' list */
+  g->fixedgc = o;
 }
 
 
 /*
 ** create a new collectable object (with given type and size) and link
-** it to '*list'. 'offset' tells how many bytes to allocate before the
-** object itself (used only by states).
+** it to 'allgc' list.
 */
-GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
-                       int offset) {
+GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
   global_State *g = G(L);
-  char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz));
-  GCObject *o = obj2gco(raw + offset);
-  if (list == NULL)
-    list = &g->allgc;  /* standard list for collectable objects */
-  gch(o)->marked = luaC_white(g);
-  gch(o)->tt = tt;
-  gch(o)->next = *list;
-  *list = o;
+  GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz));
+  o->marked = luaC_white(g);
+  o->tt = tt;
+  o->next = g->allgc;
+  g->allgc = o;
   return o;
 }
 
@@ -241,57 +233,53 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
 ** upvalues are already linked in 'headuv' list.)
 */
 static void reallymarkobject (global_State *g, GCObject *o) {
-  lu_mem size;
+ reentry:
   white2gray(o);
-  switch (gch(o)->tt) {
-    case LUA_TSHRSTR:
-    case LUA_TLNGSTR: {
-      size = sizestring(gco2ts(o));
-      break;  /* nothing else to mark; make it black */
+  switch (o->tt) {
+    case LUA_TSHRSTR: {
+      gray2black(o);
+      g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
+      break;
     }
-    case LUA_TUSERDATA: {
-      Table *mt = gco2u(o)->metatable;
-      markobject(g, mt);
-      markobject(g, gco2u(o)->env);
-      size = sizeudata(gco2u(o));
+    case LUA_TLNGSTR: {
+      gray2black(o);
+      g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
       break;
     }
-    case LUA_TUPVAL: {
-      UpVal *uv = gco2uv(o);
-      markvalue(g, uv->v);
-      if (uv->v != &uv->u.value)  /* open? */
-        return;  /* open upvalues remain gray */
-      size = sizeof(UpVal);
+    case LUA_TUSERDATA: {
+      TValue uvalue;
+      markobjectN(g, gco2u(o)->metatable);  /* mark its metatable */
+      gray2black(o);
+      g->GCmemtrav += sizeudata(gco2u(o));
+      getuservalue(g->mainthread, gco2u(o), &uvalue);
+      if (valiswhite(&uvalue)) {  /* markvalue(g, &uvalue); */
+        o = gcvalue(&uvalue);
+        goto reentry;
+      }
       break;
     }
     case LUA_TLCL: {
-      gco2lcl(o)->gclist = g->gray;
-      g->gray = o;
-      return;
+      linkgclist(gco2lcl(o), g->gray);
+      break;
     }
     case LUA_TCCL: {
-      gco2ccl(o)->gclist = g->gray;
-      g->gray = o;
-      return;
+      linkgclist(gco2ccl(o), g->gray);
+      break;
     }
     case LUA_TTABLE: {
-      linktable(gco2t(o), &g->gray);
-      return;
+      linkgclist(gco2t(o), g->gray);
+      break;
     }
     case LUA_TTHREAD: {
-      gco2th(o)->gclist = g->gray;
-      g->gray = o;
-      return;
+      linkgclist(gco2th(o), g->gray);
+      break;
     }
     case LUA_TPROTO: {
-      gco2p(o)->gclist = g->gray;
-      g->gray = o;
-      return;
+      linkgclist(gco2p(o), g->gray);
+      break;
     }
-    default: lua_assert(0); return;
+    default: lua_assert(0); break;
   }
-  gray2black(o);
-  g->GCmemtrav += size;
 }
 
 
@@ -301,7 +289,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]);
 }
 
 
@@ -310,29 +298,41 @@ static void markmt (global_State *g) {
 */
 static void markbeingfnz (global_State *g) {
   GCObject *o;
-  for (o = g->tobefnz; o != NULL; o = gch(o)->next) {
-    makewhite(g, o);
-    reallymarkobject(g, o);
-  }
+  for (o = g->tobefnz; o != NULL; o = o->next)
+    markobject(g, o);
 }
 
 
 /*
-** mark all values stored in marked open upvalues. (See comment in
-** 'lstate.h'.)
+** Mark all values stored in marked open upvalues from non-marked threads.
+** (Values from marked threads were already marked when traversing the
+** thread.) Remove from the list threads that no longer have upvalues and
+** not-marked threads.
 */
 static void remarkupvals (global_State *g) {
-  UpVal *uv;
-  for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
-    if (isgray(obj2gco(uv)))
-      markvalue(g, uv->v);
+  lua_State *thread;
+  lua_State **p = &g->twups;
+  while ((thread = *p) != NULL) {
+    lua_assert(!isblack(thread));  /* threads are never black */
+    if (isgray(thread) && thread->openupval != NULL)
+      p = &thread->twups;  /* keep marked thread with upvalues in the list */
+    else {  /* thread is not marked or without upvalues */
+      UpVal *uv;
+      *p = thread->twups;  /* remove thread from the list */
+      thread->twups = thread;  /* mark that it is out of list */
+      for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
+        if (uv->u.open.touched) {
+          markvalue(g, uv->v);  /* remark upvalue's value */
+          uv->u.open.touched = 0;
+        }
+      }
+    }
   }
 }
 
 
 /*
-** mark root set and reset all gray lists, to start a new
-** incremental (or full) collection
+** mark root set and reset all gray lists, to start a new collection
 */
 static void restartcollection (global_State *g) {
   g->gray = g->grayagain = NULL;
@@ -352,12 +352,18 @@ static void restartcollection (global_State *g) {
 ** =======================================================
 */
 
+/*
+** Traverse a table with weak values and link it to proper list. During
+** propagate phase, keep it in 'grayagain' list, to be revisited in the
+** atomic phase. In the atomic phase, if table has any white value,
+** put it in 'weak' list, to be cleared.
+*/
 static void traverseweakvalue (global_State *g, Table *h) {
   Node *n, *limit = gnodelast(h);
-  /* if there is array part, assume it may have white values (do not
-     traverse it just to check) */
+  /* if there is array part, assume it may have white values (it is not
+     worth traversing it now just to check) */
   int hasclears = (h->sizearray > 0);
-  for (n = gnode(h, 0); n < limit; n++) {
+  for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
     checkdeadkey(n);
     if (ttisnil(gval(n)))  /* entry is empty? */
       removeentry(n);  /* remove it */
@@ -368,20 +374,30 @@ static void traverseweakvalue (global_State *g, Table *h) {
         hasclears = 1;  /* table will have to be cleared */
     }
   }
-  if (hasclears)
-    linktable(h, &g->weak);  /* has to be cleared later */
-  else  /* no white values */
-    linktable(h, &g->grayagain);  /* no need to clean */
+  if (g->gcstate == GCSpropagate)
+    linkgclist(h, g->grayagain);  /* must retraverse it in atomic phase */
+  else if (hasclears)
+    linkgclist(h, g->weak);  /* has to be cleared later */
 }
 
 
+/*
+** Traverse an ephemeron table and link it to proper list. Returns true
+** iff any object was marked during this traversal (which implies that
+** convergence has to continue). During propagation phase, keep table
+** in 'grayagain' list, to be visited again in the atomic phase. In
+** the atomic phase, if table has any white->white entry, it has to
+** be revisited during ephemeron convergence (as that key may turn
+** black). Otherwise, if it has any white key, table has to be cleared
+** (in the atomic phase).
+*/
 static int traverseephemeron (global_State *g, Table *h) {
   int marked = 0;  /* true if an object is marked in this traversal */
   int hasclears = 0;  /* true if table has white keys */
-  int prop = 0;  /* true if table has entry "white-key -> white-value" */
+  int hasww = 0;  /* true if table has entry "white-key -> white-value" */
   Node *n, *limit = gnodelast(h);
-  int i;
-  /* traverse array part (numeric keys are 'strong') */
+  unsigned int i;
+  /* traverse array part */
   for (i = 0; i < h->sizearray; i++) {
     if (valiswhite(&h->array[i])) {
       marked = 1;
@@ -396,26 +412,27 @@ static int traverseephemeron (global_State *g, Table *h) {
     else if (iscleared(g, gkey(n))) {  /* key is not marked (yet)? */
       hasclears = 1;  /* table must be cleared */
       if (valiswhite(gval(n)))  /* value not marked yet? */
-        prop = 1;  /* must propagate again */
+        hasww = 1;  /* white-white entry */
     }
     else if (valiswhite(gval(n))) {  /* value not marked yet? */
       marked = 1;
       reallymarkobject(g, gcvalue(gval(n)));  /* mark it now */
     }
   }
-  if (g->gcstate != GCSatomic || prop)
-    linktable(h, &g->ephemeron);  /* have to propagate again */
-  else if (hasclears)  /* does table have white keys? */
-    linktable(h, &g->allweak);  /* may have to clean white keys */
-  else  /* no white keys */
-    linktable(h, &g->grayagain);  /* no need to clean */
+  /* link table into proper list */
+  if (g->gcstate == GCSpropagate)
+    linkgclist(h, g->grayagain);  /* must retraverse it in atomic phase */
+  else if (hasww)  /* table has white->white entries? */
+    linkgclist(h, g->ephemeron);  /* have to propagate again */
+  else if (hasclears)  /* table has white keys? */
+    linkgclist(h, g->allweak);  /* may have to clean white keys */
   return marked;
 }
 
 
 static void traversestrongtable (global_State *g, Table *h) {
   Node *n, *limit = gnodelast(h);
-  int i;
+  unsigned int i;
   for (i = 0; i < h->sizearray; i++)  /* traverse array part */
     markvalue(g, &h->array[i]);
   for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
@@ -434,18 +451,18 @@ 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')),
        (weakkey || weakvalue))) {  /* is really weak? */
-    black2gray(obj2gco(h));  /* keep table gray */
+    black2gray(h);  /* keep table gray */
     if (!weakkey)  /* strong keys? */
       traverseweakvalue(g, h);
     else if (!weakvalue)  /* strong values? */
       traverseephemeron(g, h);
     else  /* all weak */
-      linktable(h, &g->allweak);  /* nothing to traverse now */
+      linkgclist(h, g->allweak);  /* nothing to traverse now */
   }
   else  /* not weak */
     traversestrongtable(g, h);
@@ -454,19 +471,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(obj2gco(f->cache)))
+  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 +
@@ -483,34 +505,50 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
   return sizeCclosure(cl->nupvalues);
 }
 
+/*
+** open upvalues point to values in a thread, so those values should
+** be marked when the thread is traversed except in the atomic phase
+** (because then the value cannot be changed by the thread and the
+** thread may not be traversed again)
+*/
 static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
   int i;
-  markobject(g, cl->p);  /* mark its prototype */
-  for (i = 0; i < cl->nupvalues; i++)  /* mark its upvalues */
-    markobject(g, cl->upvals[i]);
+  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) {
+      if (upisopen(uv) && g->gcstate != GCSinsideatomic)
+        uv->u.open.touched = 1;  /* can be marked in 'remarkupvals' */
+      else
+        markvalue(g, uv->v);
+    }
+  }
   return sizeLclosure(cl->nupvalues);
 }
 
 
-static lu_mem traversestack (global_State *g, lua_State *th) {
-  int n = 0;
+static lu_mem traversethread (global_State *g, lua_State *th) {
   StkId o = th->stack;
   if (o == NULL)
     return 1;  /* stack not completely built yet */
+  lua_assert(g->gcstate == GCSinsideatomic ||
+             th->openupval == NULL || isintwups(th));
   for (; o < th->top; o++)  /* mark live elements in the stack */
     markvalue(g, o);
-  if (g->gcstate == GCSatomic) {  /* final traversal? */
+  if (g->gcstate == GCSinsideatomic) {  /* final traversal? */
     StkId lim = th->stack + th->stacksize;  /* real end of stack */
     for (; o < lim; o++)  /* clear not-marked stack slice */
       setnilvalue(o);
+    /* 'remarkupvals' may have removed thread from 'twups' list */ 
+    if (!isintwups(th) && th->openupval != NULL) {
+      th->twups = g->twups;  /* link it back to the list */
+      g->twups = th;
+    }
   }
-  else {  /* count call infos to compute size */
-    CallInfo *ci;
-    for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
-      n++;
-  }
-  return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
-         sizeof(CallInfo) * n;
+  else if (g->gckind != KGC_EMERGENCY)
+    luaD_shrinkstack(th); /* do not change stack in emergency cycle */
+  return (sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+          sizeof(CallInfo) * th->nci);
 }
 
 
@@ -523,7 +561,7 @@ static void propagatemark (global_State *g) {
   GCObject *o = g->gray;
   lua_assert(isgray(o));
   gray2black(o);
-  switch (gch(o)->tt) {
+  switch (o->tt) {
     case LUA_TTABLE: {
       Table *h = gco2t(o);
       g->gray = h->gclist;  /* remove from 'gray' list */
@@ -545,10 +583,9 @@ static void propagatemark (global_State *g) {
     case LUA_TTHREAD: {
       lua_State *th = gco2th(o);
       g->gray = th->gclist;  /* remove from 'gray' list */
-      th->gclist = g->grayagain;
-      g->grayagain = o;  /* insert into 'grayagain' list */
+      linkgclist(th, g->grayagain);  /* insert into 'grayagain' list */
       black2gray(o);
-      size = traversestack(g, th);
+      size = traversethread(g, th);
       break;
     }
     case LUA_TPROTO: {
@@ -568,35 +605,12 @@ static void propagateall (global_State *g) {
 }
 
 
-static void propagatelist (global_State *g, GCObject *l) {
-  lua_assert(g->gray == NULL);  /* no grays left */
-  g->gray = l;
-  propagateall(g);  /* traverse all elements from 'l' */
-}
-
-/*
-** retraverse all gray lists. Because tables may be reinserted in other
-** lists when traversed, traverse the original lists to avoid traversing
-** twice the same table (which is not wrong, but inefficient)
-*/
-static void retraversegrays (global_State *g) {
-  GCObject *weak = g->weak;  /* save original lists */
-  GCObject *grayagain = g->grayagain;
-  GCObject *ephemeron = g->ephemeron;
-  g->weak = g->grayagain = g->ephemeron = NULL;
-  propagateall(g);  /* traverse main gray list */
-  propagatelist(g, grayagain);
-  propagatelist(g, weak);
-  propagatelist(g, ephemeron);
-}
-
-
 static void convergeephemerons (global_State *g) {
   int changed;
   do {
     GCObject *w;
     GCObject *next = g->ephemeron;  /* get ephemeron list */
-    g->ephemeron = NULL;  /* tables will return to this list when traversed */
+    g->ephemeron = NULL;  /* tables may return to this list when traversed */
     changed = 0;
     while ((w = next) != NULL) {
       next = gco2t(w)->gclist;
@@ -644,7 +658,7 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
   for (; l != f; l = gco2t(l)->gclist) {
     Table *h = gco2t(l);
     Node *n, *limit = gnodelast(h);
-    int i;
+    unsigned int i;
     for (i = 0; i < h->sizearray; i++) {
       TValue *o = &h->array[i];
       if (iscleared(g, o))  /* value was collected? */
@@ -660,26 +674,45 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
 }
 
 
+void luaC_upvdeccount (lua_State *L, UpVal *uv) {
+  lua_assert(uv->refcount > 0);
+  uv->refcount--;
+  if (uv->refcount == 0 && !upisopen(uv))
+    luaM_free(L, uv);
+}
+
+
+static void freeLclosure (lua_State *L, LClosure *cl) {
+  int i;
+  for (i = 0; i < cl->nupvalues; i++) {
+    UpVal *uv = cl->upvals[i];
+    if (uv)
+      luaC_upvdeccount(L, uv);
+  }
+  luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
+}
+
+
 static void freeobj (lua_State *L, GCObject *o) {
-  switch (gch(o)->tt) {
+  switch (o->tt) {
     case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
     case LUA_TLCL: {
-      luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
+      freeLclosure(L, gco2lcl(o));
       break;
     }
     case LUA_TCCL: {
       luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
       break;
     }
-    case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
     case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
     case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
     case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
     case LUA_TSHRSTR:
-      G(L)->strt.nuse--;
-      /* go through */
+      luaS_remove(L, gco2ts(o));  /* remove it from hash table */
+      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);
@@ -692,60 +725,26 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
 
 
 /*
-** sweep the (open) upvalues of a thread and resize its stack and
-** list of call-info structures.
-*/
-static void sweepthread (lua_State *L, lua_State *L1) {
-  if (L1->stack == NULL) return;  /* stack not completely built yet */
-  sweepwholelist(L, &L1->openupval);  /* sweep open upvalues */
-  luaE_freeCI(L1);  /* free extra CallInfo slots */
-  /* should not change the stack during an emergency gc cycle */
-  if (G(L)->gckind != KGC_EMERGENCY)
-    luaD_shrinkstack(L1);
-}
-
-
-/*
 ** sweep at most 'count' elements from a list of GCObjects erasing dead
-** objects, where a dead (not alive) object is one marked with the "old"
-** (non current) white and not fixed.
-** In non-generational mode, change all non-dead objects back to white,
-** preparing for next collection cycle.
-** In generational mode, keep black objects black, and also mark them as
-** old; stop when hitting an old object, as all objects after that
-** one will be old too.
-** When object is a thread, sweep its list of open upvalues too.
+** objects, where a dead object is one marked with the old (non current)
+** white; change all non-dead objects back to white, preparing for next
+** collection cycle. Return where to continue the traversal or NULL if
+** list is finished.
 */
 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
   global_State *g = G(L);
   int ow = otherwhite(g);
-  int toclear, toset;  /* bits to clear and to set in all live objects */
-  int tostop;  /* stop sweep when this is true */
-  if (isgenerational(g)) {  /* generational mode? */
-    toclear = ~0;  /* clear nothing */
-    toset = bitmask(OLDBIT);  /* set the old bit of all surviving objects */
-    tostop = bitmask(OLDBIT);  /* do not sweep old generation */
-  }
-  else {  /* normal mode */
-    toclear = maskcolors;  /* clear all color bits + old bit */
-    toset = luaC_white(g);  /* make object white */
-    tostop = 0;  /* do not stop */
-  }
+  int white = luaC_white(g);  /* current white */
   while (*p != NULL && count-- > 0) {
     GCObject *curr = *p;
-    int marked = gch(curr)->marked;
+    int marked = curr->marked;
     if (isdeadm(ow, marked)) {  /* is 'curr' dead? */
-      *p = gch(curr)->next;  /* remove 'curr' from list */
+      *p = curr->next;  /* remove 'curr' from list */
       freeobj(L, curr);  /* erase 'curr' */
     }
-    else {
-      if (testbits(marked, tostop))
-        return NULL;  /* stop sweeping this list */
-      if (gch(curr)->tt == LUA_TTHREAD)
-        sweepthread(L, gco2th(curr));  /* sweep thread's upvalues */
-      /* update marks */
-      gch(curr)->marked = cast_byte((marked & toclear) | toset);
-      p = &gch(curr)->next;  /* go to next element */
+    else {  /* change mark to 'white' */
+      curr->marked = cast_byte((marked & maskcolors) | white);
+      p = &curr->next;  /* go to next element */
     }
   }
   return (*p == NULL) ? NULL : p;
@@ -755,14 +754,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
 /*
 ** sweep a list until a live object (or end of list)
 */
-static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
-  GCObject ** old = p;
-  int i = 0;
+static GCObject **sweeptolive (lua_State *L, GCObject **p) {
+  GCObject **old = p;
   do {
-    i++;
     p = sweeplist(L, p, 1);
   } while (p == old);
-  if (n) *n += i;
   return p;
 }
 
@@ -775,26 +771,27 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
 ** =======================================================
 */
 
-static void checkSizes (lua_State *L) {
-  global_State *g = G(L);
-  if (g->gckind != KGC_EMERGENCY) {  /* do not change sizes in emergency */
-    int hs = g->strt.size / 2;  /* half the size of the string table */
-    if (g->strt.nuse < cast(lu_int32, hs))  /* using less than that half? */
-      luaS_resize(L, hs);  /* halve its size */
-    luaZ_freebuffer(L, &g->buff);  /* free concatenation buffer */
+/*
+** If possible, shrink string table
+*/
+static void checkSizes (lua_State *L, global_State *g) {
+  if (g->gckind != KGC_EMERGENCY) {
+    l_mem olddebt = g->GCdebt;
+    if (g->strt.nuse < g->strt.size / 4)  /* string table too big? */
+      luaS_resize(L, g->strt.size / 2);  /* shrink it a little */
+    g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
   }
 }
 
 
 static GCObject *udata2finalize (global_State *g) {
   GCObject *o = g->tobefnz;  /* get first element */
-  lua_assert(isfinalized(o));
-  g->tobefnz = gch(o)->next;  /* remove it from 'tobefnz' list */
-  gch(o)->next = g->allgc;  /* return it to 'allgc' list */
+  lua_assert(tofinalize(o));
+  g->tobefnz = o->next;  /* remove it from 'tobefnz' list */
+  o->next = g->allgc;  /* return it to 'allgc' list */
   g->allgc = o;
-  resetbit(gch(o)->marked, SEPARATED);  /* mark that it is not in 'tobefnz' */
-  lua_assert(!isold(o));  /* see MOVE OLD rule */
-  if (!keepinvariantout(g))  /* not keeping invariant? */
+  resetbit(o->marked, FINALIZEDBIT);  /* object is "normal" again */
+  if (issweepphase(g))
     makewhite(g, o);  /* "sweep" object */
   return o;
 }
@@ -802,7 +799,7 @@ static GCObject *udata2finalize (global_State *g) {
 
 static void dothecall (lua_State *L, void *ud) {
   UNUSED(ud);
-  luaD_call(L, L->top - 2, 0, 0);
+  luaD_callnoyield(L, L->top - 2, 0);
 }
 
 
@@ -839,28 +836,57 @@ static void GCTM (lua_State *L, int propagateerrors) {
 
 
 /*
+** call a few (up to 'g->gcfinnum') finalizers
+*/
+static int runafewfinalizers (lua_State *L) {
+  global_State *g = G(L);
+  unsigned int i;
+  lua_assert(!g->tobefnz || g->gcfinnum > 0);
+  for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
+    GCTM(L, 1);  /* call one finalizer */
+  g->gcfinnum = (!g->tobefnz) ? 0  /* nothing more to finalize? */
+                    : g->gcfinnum * 2;  /* else call a few more next time */
+  return i;
+}
+
+
+/*
+** call all pending finalizers
+*/
+static void callallpendingfinalizers (lua_State *L) {
+  global_State *g = G(L);
+  while (g->tobefnz)
+    GCTM(L, 0);
+}
+
+
+/*
+** find last 'next' field in list 'p' list (to add elements in its end)
+*/
+static GCObject **findlast (GCObject **p) {
+  while (*p != NULL)
+    p = &(*p)->next;
+  return p;
+}
+
+
+/*
 ** move all unreachable objects (or 'all' objects) that need
 ** finalization from list 'finobj' to list 'tobefnz' (to be finalized)
 */
-static void separatetobefnz (lua_State *L, int all) {
-  global_State *g = G(L);
-  GCObject **p = &g->finobj;
+static void separatetobefnz (global_State *g, int all) {
   GCObject *curr;
-  GCObject **lastnext = &g->tobefnz;
-  /* find last 'next' field in 'tobefnz' list (to add elements in its end) */
-  while (*lastnext != NULL)
-    lastnext = &gch(*lastnext)->next;
+  GCObject **p = &g->finobj;
+  GCObject **lastnext = findlast(&g->tobefnz);
   while ((curr = *p) != NULL) {  /* traverse all finalizable objects */
-    lua_assert(!isfinalized(curr));
-    lua_assert(testbit(gch(curr)->marked, SEPARATED));
+    lua_assert(tofinalize(curr));
     if (!(iswhite(curr) || all))  /* not being collected? */
-      p = &gch(curr)->next;  /* don't bother with it */
+      p = &curr->next;  /* don't bother with it */
     else {
-      l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
-      *p = gch(curr)->next;  /* remove 'curr' from 'finobj' list */
-      gch(curr)->next = *lastnext;  /* link at the end of 'tobefnz' list */
+      *p = curr->next;  /* remove 'curr' from 'finobj' list */
+      curr->next = *lastnext;  /* link at the end of 'tobefnz' list */
       *lastnext = curr;
-      lastnext = &gch(curr)->next;
+      lastnext = &curr->next;
     }
   }
 }
@@ -872,33 +898,29 @@ static void separatetobefnz (lua_State *L, int all) {
 */
 void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
   global_State *g = G(L);
-  if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */
-      isfinalized(o) ||                           /* ... or is finalized... */
-      gfasttm(g, mt, TM_GC) == NULL)                /* or has no finalizer? */
+  if (tofinalize(o) ||                 /* obj. is already marked... */
+      gfasttm(g, mt, TM_GC) == NULL)   /* or has no finalizer? */
     return;  /* nothing to be done */
   else {  /* move 'o' to 'finobj' list */
     GCObject **p;
-    GCheader *ho = gch(o);
-    if (g->sweepgc == &ho->next) {  /* avoid removing current sweep object */
-      lua_assert(issweepphase(g));
-      g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
+    if (issweepphase(g)) {
+      makewhite(g, o);  /* "sweep" object 'o' */
+      if (g->sweepgc == &o->next)  /* should not remove 'sweepgc' object */
+        g->sweepgc = sweeptolive(L, g->sweepgc);  /* change 'sweepgc' */
     }
     /* search for pointer pointing to 'o' */
-    for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
-    *p = ho->next;  /* remove 'o' from root list */
-    ho->next = g->finobj;  /* link it in list 'finobj' */
+    for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
+    *p = o->next;  /* remove 'o' from 'allgc' list */
+    o->next = g->finobj;  /* link it in 'finobj' list */
     g->finobj = o;
-    l_setbit(ho->marked, SEPARATED);  /* mark it as such */
-    if (!keepinvariantout(g))  /* not keeping invariant? */
-      makewhite(g, o);  /* "sweep" object */
-    else
-      resetoldbit(o);  /* see MOVE OLD rule */
+    l_setbit(o->marked, FINALIZEDBIT);  /* mark it as such */
   }
 }
 
 /* }====================================================== */
 
 
+
 /*
 ** {======================================================
 ** GC control
@@ -907,195 +929,164 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
 
 
 /*
-** set a reasonable "time" to wait before starting a new GC cycle;
-** cycle will start when memory use hits threshold
+** Set a reasonable "time" to wait before starting a new GC cycle; cycle
+** will start when memory use hits threshold. (Division by 'estimate'
+** should be OK: it cannot be zero (because Lua cannot even start with
+** less than PAUSEADJ bytes).
 */
-static void setpause (global_State *g, l_mem estimate) {
-  l_mem debt, threshold;
-  estimate = estimate / PAUSEADJ;  /* adjust 'estimate' */
+static void setpause (global_State *g) {
+  l_mem threshold, debt;
+  l_mem estimate = g->GCestimate / PAUSEADJ;  /* adjust 'estimate' */
+  lua_assert(estimate > 0);
   threshold = (g->gcpause < MAX_LMEM / estimate)  /* overflow? */
             ? estimate * g->gcpause  /* no overflow */
             : MAX_LMEM;  /* overflow; truncate to maximum */
-  debt = -cast(l_mem, threshold - gettotalbytes(g));
+  debt = gettotalbytes(g) - threshold;
   luaE_setdebt(g, debt);
 }
 
 
-#define sweepphases  \
-       (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
-
-
-/*
-** enter first sweep phase (strings) and prepare pointers for other
-** sweep phases.  The calls to 'sweeptolive' make pointers point to an
-** object inside the list (instead of to the header), so that the real
-** sweep do not need to skip objects created between "now" and the start
-** of the real sweep.
-** Returns how many objects it swept.
-*/
-static int entersweep (lua_State *L) {
-  global_State *g = G(L);
-  int n = 0;
-  g->gcstate = GCSsweepstring;
-  lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
-  /* prepare to sweep strings, finalizable objects, and regular objects */
-  g->sweepstrgc = 0;
-  g->sweepfin = sweeptolive(L, &g->finobj, &n);
-  g->sweepgc = sweeptolive(L, &g->allgc, &n);
-  return n;
-}
-
-
-/*
-** change GC mode
-*/
-void luaC_changemode (lua_State *L, int mode) {
-  global_State *g = G(L);
-  if (mode == g->gckind) return;  /* nothing to change */
-  if (mode == KGC_GEN) {  /* change to generational mode */
-    /* make sure gray lists are consistent */
-    luaC_runtilstate(L, bitmask(GCSpropagate));
-    g->GCestimate = gettotalbytes(g);
-    g->gckind = KGC_GEN;
-  }
-  else {  /* change to incremental mode */
-    /* sweep all objects to turn them back to white
-       (as white has not changed, nothing extra will be collected) */
-    g->gckind = KGC_NORMAL;
-    entersweep(L);
-    luaC_runtilstate(L, ~sweepphases);
-  }
-}
-
-
 /*
-** call all pending finalizers
+** Enter first sweep phase.
+** The call to 'sweeplist' tries to make pointer point to an object
+** inside the list (instead of to the header), so that the real sweep do
+** not need to skip objects created between "now" and the start of the
+** real sweep.
 */
-static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
+static void entersweep (lua_State *L) {
   global_State *g = G(L);
-  while (g->tobefnz) {
-    resetoldbit(g->tobefnz);
-    GCTM(L, propagateerrors);
-  }
+  g->gcstate = GCSswpallgc;
+  lua_assert(g->sweepgc == NULL);
+  g->sweepgc = sweeplist(L, &g->allgc, 1);
 }
 
 
 void luaC_freeallobjects (lua_State *L) {
   global_State *g = G(L);
-  int i;
-  separatetobefnz(L, 1);  /* separate all objects with finalizers */
+  separatetobefnz(g, 1);  /* separate all objects with finalizers */
   lua_assert(g->finobj == NULL);
-  callallpendingfinalizers(L, 0);
+  callallpendingfinalizers(L);
+  lua_assert(g->tobefnz == NULL);
   g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
   g->gckind = KGC_NORMAL;
-  sweepwholelist(L, &g->finobj);  /* finalizers can create objs. in 'finobj' */
+  sweepwholelist(L, &g->finobj);
   sweepwholelist(L, &g->allgc);
-  for (i = 0; i < g->strt.size; i++)  /* free all string lists */
-    sweepwholelist(L, &g->strt.hash[i]);
+  sweepwholelist(L, &g->fixedgc);  /* collect fixed objects */
   lua_assert(g->strt.nuse == 0);
 }
 
 
 static l_mem atomic (lua_State *L) {
   global_State *g = G(L);
-  l_mem work = -cast(l_mem, g->GCmemtrav);  /* start counting work */
+  l_mem work;
   GCObject *origweak, *origall;
-  lua_assert(!iswhite(obj2gco(g->mainthread)));
+  GCObject *grayagain = g->grayagain;  /* save original list */
+  lua_assert(g->ephemeron == NULL && g->weak == NULL);
+  lua_assert(!iswhite(g->mainthread));
+  g->gcstate = GCSinsideatomic;
+  g->GCmemtrav = 0;  /* start counting work */
   markobject(g, L);  /* mark running thread */
   /* registry and global metatables may be changed by API */
   markvalue(g, &g->l_registry);
-  markmt(g);  /* mark basic metatables */
+  markmt(g);  /* mark global metatables */
   /* remark occasional upvalues of (maybe) dead threads */
   remarkupvals(g);
   propagateall(g);  /* propagate changes */
-  work += g->GCmemtrav;  /* stop counting (do not (re)count grays) */
-  /* traverse objects caught by write barrier and by 'remarkupvals' */
-  retraversegrays(g);
-  work -= g->GCmemtrav;  /* restart counting */
+  work = g->GCmemtrav;  /* stop counting (do not recount 'grayagain') */
+  g->gray = grayagain;
+  propagateall(g);  /* traverse 'grayagain' list */
+  g->GCmemtrav = 0;  /* restart counting */
   convergeephemerons(g);
   /* at this point, all strongly accessible objects are marked. */
-  /* clear values from weak tables, before checking finalizers */
+  /* Clear values from weak tables, before checking finalizers */
   clearvalues(g, g->weak, NULL);
   clearvalues(g, g->allweak, NULL);
   origweak = g->weak; origall = g->allweak;
   work += g->GCmemtrav;  /* stop counting (objects being finalized) */
-  separatetobefnz(L, 0);  /* separate objects to be finalized */
+  separatetobefnz(g, 0);  /* separate objects to be finalized */
+  g->gcfinnum = 1;  /* there may be objects to be finalized */
   markbeingfnz(g);  /* mark objects that will be finalized */
-  propagateall(g);  /* remark, to propagate `preserveness' */
-  work -= g->GCmemtrav;  /* restart counting */
+  propagateall(g);  /* remark, to propagate 'resurrection' */
+  g->GCmemtrav = 0;  /* restart counting */
   convergeephemerons(g);
   /* at this point, all resurrected objects are marked. */
   /* remove dead objects from weak tables */
   clearkeys(g, g->ephemeron, NULL);  /* clear keys from all ephemeron tables */
-  clearkeys(g, g->allweak, NULL);  /* clear keys from all allweak tables */
+  clearkeys(g, g->allweak, NULL);  /* clear keys from all 'allweak' tables */
   /* 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' */
 }
 
 
+static lu_mem sweepstep (lua_State *L, global_State *g,
+                         int nextstate, GCObject **nextlist) {
+  if (g->sweepgc) {
+    l_mem olddebt = g->GCdebt;
+    g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+    g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
+    if (g->sweepgc)  /* is there still something to sweep? */
+      return (GCSWEEPMAX * GCSWEEPCOST);
+  }
+  /* else enter next state */
+  g->gcstate = nextstate;
+  g->sweepgc = nextlist;
+  return 0;
+}
+
+
 static lu_mem singlestep (lua_State *L) {
   global_State *g = G(L);
   switch (g->gcstate) {
     case GCSpause: {
-      /* start to count memory traversed */
       g->GCmemtrav = g->strt.size * sizeof(GCObject*);
-      lua_assert(!isgenerational(g));
       restartcollection(g);
       g->gcstate = GCSpropagate;
       return g->GCmemtrav;
     }
     case GCSpropagate: {
-      if (g->gray) {
-        lu_mem oldtrav = g->GCmemtrav;
-        propagatemark(g);
-        return g->GCmemtrav - oldtrav;  /* memory traversed in this step */
-      }
-      else {  /* no more `gray' objects */
-        lu_mem work;
-        int sw;
-        g->gcstate = GCSatomic;  /* finish mark phase */
-        g->GCestimate = g->GCmemtrav;  /* save what was counted */;
-        work = atomic(L);  /* add what was traversed by 'atomic' */
-        g->GCestimate += work;  /* estimate of total memory traversed */ 
-        sw = entersweep(L);
-        return work + sw * GCSWEEPCOST;
-      }
+      g->GCmemtrav = 0;
+      lua_assert(g->gray);
+      propagatemark(g);
+       if (g->gray == NULL)  /* no more gray objects? */
+        g->gcstate = GCSatomic;  /* finish propagate phase */
+      return g->GCmemtrav;  /* memory traversed in this step */
     }
-    case GCSsweepstring: {
-      int i;
-      for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++)
-        sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]);
-      g->sweepstrgc += i;
-      if (g->sweepstrgc >= g->strt.size)  /* no more strings to sweep? */
-        g->gcstate = GCSsweepudata;
-      return i * GCSWEEPCOST;
+    case GCSatomic: {
+      lu_mem work;
+      propagateall(g);  /* make sure gray list is empty */
+      work = atomic(L);  /* work is what was traversed by 'atomic' */
+      entersweep(L);
+      g->GCestimate = gettotalbytes(g);  /* first estimate */;
+      return work;
     }
-    case GCSsweepudata: {
-      if (g->sweepfin) {
-        g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX);
-        return GCSWEEPMAX*GCSWEEPCOST;
-      }
-      else {
-        g->gcstate = GCSsweep;
-        return 0;
-      }
+    case GCSswpallgc: {  /* sweep "regular" objects */
+      return sweepstep(L, g, GCSswpfinobj, &g->finobj);
+    }
+    case GCSswpfinobj: {  /* sweep objects with finalizers */
+      return sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
     }
-    case GCSsweep: {
-      if (g->sweepgc) {
-        g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
-        return GCSWEEPMAX*GCSWEEPCOST;
+    case GCSswptobefnz: {  /* sweep objects to be finalized */
+      return sweepstep(L, g, GCSswpend, NULL);
+    }
+    case GCSswpend: {  /* finish sweeps */
+      makewhite(g, g->mainthread);  /* sweep main thread */
+      checkSizes(L, g);
+      g->gcstate = GCScallfin;
+      return 0;
+    }
+    case GCScallfin: {  /* call remaining finalizers */
+      if (g->tobefnz && g->gckind != KGC_EMERGENCY) {
+        int n = runafewfinalizers(L);
+        return (n * GCFINALIZECOST);
       }
-      else {
-        /* sweep main thread */
-        GCObject *mt = obj2gco(g->mainthread);
-        sweeplist(L, &mt, 1);
-        checkSizes(L);
+      else {  /* emergency mode or no more finalizers */
         g->gcstate = GCSpause;  /* finish collection */
-        return GCSWEEPCOST;
+        return 0;
       }
     }
     default: lua_assert(0); return 0;
@@ -1114,105 +1105,70 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
 }
 
 
-static void generationalcollection (lua_State *L) {
-  global_State *g = G(L);
-  lua_assert(g->gcstate == GCSpropagate);
-  if (g->GCestimate == 0) {  /* signal for another major collection? */
-    luaC_fullgc(L, 0);  /* perform a full regular collection */
-    g->GCestimate = gettotalbytes(g);  /* update control */
-  }
+/*
+** get GC debt and convert it from Kb to 'work units' (avoid zero debt
+** and overflows)
+*/
+static l_mem getdebt (global_State *g) {
+  l_mem debt = g->GCdebt;
+  int stepmul = g->gcstepmul;
+  if (debt <= 0) return 0;  /* minimal debt */
   else {
-    lu_mem estimate = g->GCestimate;
-    luaC_runtilstate(L, bitmask(GCSpause));  /* run complete (minor) cycle */
-    g->gcstate = GCSpropagate;  /* skip restart */
-    if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc)
-      g->GCestimate = 0;  /* signal for a major collection */
-    else
-      g->GCestimate = estimate;  /* keep estimate from last major coll. */
-
+    debt = (debt / STEPMULADJ) + 1;
+    debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
+    return debt;
   }
-  setpause(g, gettotalbytes(g));
-  lua_assert(g->gcstate == GCSpropagate);
 }
 
-
-static void incstep (lua_State *L) {
+/*
+** performs a basic GC step when collector is running
+*/
+void luaC_step (lua_State *L) {
   global_State *g = G(L);
-  l_mem debt = g->GCdebt;
-  int stepmul = g->gcstepmul;
-  if (stepmul < 40) stepmul = 40;  /* avoid ridiculous low values (and 0) */
-  /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */
-  debt = (debt / STEPMULADJ) + 1;
-  debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
-  do {  /* always perform at least one single step */
-    lu_mem work = singlestep(L);  /* do some work */
+  l_mem debt = getdebt(g);  /* GC deficit (be paid now) */
+  if (!g->gcrunning) {  /* not running? */
+    luaE_setdebt(g, -GCSTEPSIZE * 10);  /* avoid being called too often */
+    return;
+  }
+  do {  /* repeat until pause or enough "credit" (negative debt) */
+    lu_mem work = singlestep(L);  /* perform one single step */
     debt -= work;
   } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
   if (g->gcstate == GCSpause)
-    setpause(g, g->GCestimate);  /* pause until next cycle */
+    setpause(g);  /* pause until next cycle */
   else {
-    debt = (debt / stepmul) * STEPMULADJ;  /* convert 'work units' to Kb */
+    debt = (debt / g->gcstepmul) * STEPMULADJ;  /* convert 'work units' to Kb */
     luaE_setdebt(g, debt);
+    runafewfinalizers(L);
   }
 }
 
 
 /*
-** performs a basic GC step
-*/
-void luaC_forcestep (lua_State *L) {
-  global_State *g = G(L);
-  int i;
-  if (isgenerational(g)) generationalcollection(L);
-  else incstep(L);
-  /* run a few finalizers (or all of them at the end of a collect cycle) */
-  for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
-    GCTM(L, 1);  /* call one finalizer */
-}
-
-
-/*
-** performs a basic GC step only if collector is running
-*/
-void luaC_step (lua_State *L) {
-  global_State *g = G(L);
-  if (g->gcrunning) luaC_forcestep(L);
-  else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */
-}
-
-
-
-/*
-** performs a full GC cycle; if "isemergency", does not call
-** finalizers (which could change stack positions)
+** Performs a full GC cycle; if 'isemergency', set a flag to avoid
+** some operations which could change the interpreter state in some
+** unexpected ways (running finalizers and shrinking some structures).
+** Before running the collection, check 'keepinvariant'; if it is true,
+** there may be some objects marked as black, so the collector has
+** to sweep all objects to turn them back to white (as white has not
+** changed, nothing will be collected).
 */
 void luaC_fullgc (lua_State *L, int isemergency) {
   global_State *g = G(L);
-  int origkind = g->gckind;
-  lua_assert(origkind != KGC_EMERGENCY);
-  if (isemergency)  /* do not run finalizers during emergency GC */
-    g->gckind = KGC_EMERGENCY;
-  else {
-    g->gckind = KGC_NORMAL;
-    callallpendingfinalizers(L, 1);
-  }
-  if (keepinvariant(g)) {  /* may there be some black objects? */
-    /* must sweep all objects to turn them back to white
-       (as white has not changed, nothing will be collected) */
-    entersweep(L);
+  lua_assert(g->gckind == KGC_NORMAL);
+  if (isemergency) g->gckind = KGC_EMERGENCY;  /* set flag */
+  if (keepinvariant(g)) {  /* black objects? */
+    entersweep(L); /* sweep everything to turn them back to white */
   }
   /* finish any pending sweep phase to start a new cycle */
   luaC_runtilstate(L, bitmask(GCSpause));
   luaC_runtilstate(L, ~bitmask(GCSpause));  /* start new collection */
-  luaC_runtilstate(L, bitmask(GCSpause));  /* run entire collection */
-  if (origkind == KGC_GEN) {  /* generational mode? */
-    /* generational mode must be kept in propagate phase */
-    luaC_runtilstate(L, bitmask(GCSpropagate));
-  }
-  g->gckind = origkind;
-  setpause(g, gettotalbytes(g));
-  if (!isemergency)   /* do not run finalizers during emergency GC */
-    callallpendingfinalizers(L, 1);
+  luaC_runtilstate(L, bitmask(GCScallfin));  /* run up to finalizers */
+  /* estimate must be correct after a full GC cycle */
+  lua_assert(g->GCestimate == gettotalbytes(g));
+  luaC_runtilstate(L, bitmask(GCSpause));  /* finish collection */
+  g->gckind = KGC_NORMAL;
+  setpause(g);
 }
 
 /* }====================================================== */
index 84bb1cd..aed3e18 100644 (file)
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
 */
 #define GCSpropagate   0
 #define GCSatomic      1
-#define GCSsweepstring 2
-#define GCSsweepudata  3
-#define GCSsweep       4
-#define GCSpause       5
+#define GCSswpallgc    2
+#define GCSswpfinobj   3
+#define GCSswptobefnz  4
+#define GCSswpend      5
+#define GCScallfin     6
+#define GCSpause       7
 
 
 #define issweepphase(g)  \
-       (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
+       (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
 
-#define isgenerational(g)      ((g)->gckind == KGC_GEN)
 
 /*
-** macros to tell when main invariant (white objects cannot point to black
-** ones) must be kept. During a non-generational collection, the sweep
+** macro to tell when main invariant (white objects cannot point to black
+** ones) must be kept. During a collection, the sweep
 ** phase may break the invariant, as objects turned white may point to
 ** still-black objects. The invariant is restored when sweep ends and
-** all objects are white again. During a generational collection, the
-** invariant must be kept all times.
+** all objects are white again.
 */
 
-#define keepinvariant(g)       (isgenerational(g) || g->gcstate <= GCSatomic)
-
-
-/*
-** Outside the collector, the state in generational mode is kept in
-** 'propagate', so 'keepinvariant' is always true.
-*/
-#define keepinvariantout(g)  \
-  check_exp(g->gcstate == GCSpropagate || !isgenerational(g),  \
-            g->gcstate <= GCSatomic)
+#define keepinvariant(g)       ((g)->gcstate <= GCSatomic)
 
 
 /*
 #define testbit(x,b)           testbits(x, bitmask(b))
 
 
-/* Layout for bit use in `marked' field: */
+/* Layout for bit use in 'marked' field: */
 #define WHITE0BIT      0  /* object is white (type 0) */
 #define WHITE1BIT      1  /* object is white (type 1) */
 #define BLACKBIT       2  /* object is black */
-#define FINALIZEDBIT   3  /* object has been separated for finalization */
-#define SEPARATED      4  /* object is in 'finobj' list or in 'tobefnz' */
-#define FIXEDBIT       5  /* object is fixed (should not be collected) */
-#define OLDBIT         6  /* object is old (only in generational mode) */
+#define FINALIZEDBIT   3  /* object has been marked for finalization */
 /* bit 7 is currently used by tests (luaL_checkmemory) */
 
 #define WHITEBITS      bit2mask(WHITE0BIT, WHITE1BIT)
 
 
-#define iswhite(x)      testbits((x)->gch.marked, WHITEBITS)
-#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)
+#define iswhite(x)      testbits((x)->marked, WHITEBITS)
+#define isblack(x)      testbit((x)->marked, BLACKBIT)
 #define isgray(x)  /* neither white nor black */  \
-       (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
-
-#define isold(x)       testbit((x)->gch.marked, OLDBIT)
+       (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
 
-/* MOVE OLD rule: whenever an object is moved to the beginning of
-   a GC list, its old bit must be cleared */
-#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT)
+#define tofinalize(x)  testbit((x)->marked, FINALIZEDBIT)
 
-#define otherwhite(g)  (g->currentwhite ^ WHITEBITS)
+#define otherwhite(g)  ((g)->currentwhite ^ WHITEBITS)
 #define isdeadm(ow,m)  (!(((m) ^ WHITEBITS) & (ow)))
-#define isdead(g,v)    isdeadm(otherwhite(g), (v)->gch.marked)
+#define isdead(g,v)    isdeadm(otherwhite(g), (v)->marked)
 
-#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
-#define gray2black(x)  l_setbit((x)->gch.marked, BLACKBIT)
-
-#define valiswhite(x)  (iscollectable(x) && iswhite(gcvalue(x)))
+#define changewhite(x) ((x)->marked ^= WHITEBITS)
+#define gray2black(x)  l_setbit((x)->marked, BLACKBIT)
 
 #define luaC_white(g)  cast(lu_byte, (g)->currentwhite & WHITEBITS)
 
 
-#define luaC_condGC(L,c) \
-       {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
-#define luaC_checkGC(L)                luaC_condGC(L, luaC_step(L);)
+/*
+** Does one step of collection when debt becomes positive. 'pre'/'pos'
+** allows some adjustments to be done only when needed. macro
+** 'condchangemem' is used only for heavy tests (forcing a full
+** GC cycle on every opportunity)
+*/
+#define luaC_condGC(L,pre,pos) \
+       { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
+         condchangemem(L,pre,pos); }
 
+/* more often than not, 'pre'/'pos' are empty */
+#define luaC_checkGC(L)                luaC_condGC(L,(void)0,(void)0)
 
-#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \
-       luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
 
-#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \
-       luaC_barrierback_(L,p); }
+#define luaC_barrier(L,p,v) (  \
+       (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ?  \
+       luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
 
-#define luaC_objbarrier(L,p,o)  \
-       { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
-               luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
+#define luaC_barrierback(L,p,v) (  \
+       (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
+       luaC_barrierback_(L,p) : cast_void(0))
 
-#define luaC_objbarrierback(L,p,o)  \
-   { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); }
+#define luaC_objbarrier(L,p,o) (  \
+       (isblack(p) && iswhite(o)) ? \
+       luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
 
-#define luaC_barrierproto(L,p,c) \
-   { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
+#define luaC_upvalbarrier(L,uv) ( \
+       (iscollectable((uv)->v) && !upisopen(uv)) ? \
+         luaC_upvalbarrier_(L,uv) : cast_void(0))
 
+LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
 LUAI_FUNC void luaC_freeallobjects (lua_State *L);
 LUAI_FUNC void luaC_step (lua_State *L);
-LUAI_FUNC void luaC_forcestep (lua_State *L);
 LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
 LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
-LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz,
-                                 GCObject **list, int offset);
+LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
 LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
-LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
-LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c);
+LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
+LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
 LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
-LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv);
-LUAI_FUNC void luaC_changemode (lua_State *L, int mode);
+LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
+
 
 #endif
index c1a3830..8ce94cc 100644 (file)
@@ -1,20 +1,33 @@
 /*
-** $Id: linit.c,v 1.32.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $
 ** Initialization of libraries for lua.c and other clients
 ** See Copyright Notice in lua.h
 */
 
 
+#define linit_c
+#define LUA_LIB
+
 /*
 ** If you embed Lua in your program and need to open the standard
 ** libraries, call luaL_openlibs in your program. If you need a
 ** different set of libraries, copy this file to your project and edit
 ** it to suit your needs.
+**
+** You can also *preload* libraries, so that a later 'require' can
+** open the library, which is already linked to the application.
+** For that, do the following code:
+**
+**  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
+**  lua_pushcfunction(L, luaopen_modname);
+**  lua_setfield(L, -2, modname);
+**  lua_pop(L, 1);  // remove _PRELOAD table
 */
 
+#include "lprefix.h"
 
-#define linit_c
-#define LUA_LIB
+
+#include <stddef.h>
 
 #include "lua.h"
 
@@ -34,34 +47,22 @@ static const luaL_Reg loadedlibs[] = {
   {LUA_IOLIBNAME, luaopen_io},
   {LUA_OSLIBNAME, luaopen_os},
   {LUA_STRLIBNAME, luaopen_string},
-  {LUA_BITLIBNAME, luaopen_bit32},
   {LUA_MATHLIBNAME, luaopen_math},
+  {LUA_UTF8LIBNAME, luaopen_utf8},
   {LUA_DBLIBNAME, luaopen_debug},
-  {NULL, NULL}
-};
-
-
-/*
-** these libs are preloaded and must be required before used
-*/
-static const luaL_Reg preloadedlibs[] = {
+#if defined(LUA_COMPAT_BITLIB)
+  {LUA_BITLIBNAME, luaopen_bit32},
+#endif
   {NULL, NULL}
 };
 
 
 LUALIB_API void luaL_openlibs (lua_State *L) {
   const luaL_Reg *lib;
-  /* call open functions from 'loadedlibs' and set results to global table */
+  /* "require" functions from 'loadedlibs' and set results to global table */
   for (lib = loadedlibs; lib->func; lib++) {
     luaL_requiref(L, lib->name, lib->func, 1);
     lua_pop(L, 1);  /* remove lib */
   }
-  /* add open functions from 'preloadedlibs' into 'package.preload' table */
-  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
-  for (lib = preloadedlibs; lib->func; lib++) {
-    lua_pushcfunction(L, lib->func);
-    lua_setfield(L, -2, lib->name);
-  }
-  lua_pop(L, 1);  /* remove _PRELOAD table */
 }
 
index 2a4ec4a..aa78e59 100644 (file)
 /*
-** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: liolib.c,v 2.149 2016/05/02 14:03:19 roberto Exp $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
 
+#define liolib_c
+#define LUA_LIB
 
-/*
-** This definition must come before the inclusion of 'stdio.h'; it
-** should not affect non-POSIX systems
-*/
-#if !defined(_FILE_OFFSET_BITS)
-#define        _LARGEFILE_SOURCE       1
-#define _FILE_OFFSET_BITS      64
-#endif
+#include "lprefix.h"
 
 
+#include <ctype.h>
 #include <errno.h>
+#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define liolib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 #include "lualib.h"
 
 
-#if !defined(lua_checkmode)
+
 
 /*
-** Check whether 'mode' matches '[rwa]%+?b?'.
 ** Change this macro to accept other modes for 'fopen' besides
 ** the standard ones.
 */
-#define lua_checkmode(mode) \
+#if !defined(l_checkmode)
+
+/* accepted extensions to 'mode' in 'fopen' */
+#if !defined(L_MODEEXT)
+#define L_MODEEXT      "b"
+#endif
+
+/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
+#define l_checkmode(mode) \
        (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&   \
-       (*mode != '+' || ++mode) &&  /* skip if char is '+' */  \
-       (*mode != 'b' || ++mode) &&  /* skip if char is 'b' */  \
-       (*mode == '\0'))
+       (*mode != '+' || (++mode, 1)) &&  /* skip if char is '+' */     \
+       (strspn(mode, L_MODEEXT) == strlen(mode)))
 
 #endif
 
 /*
 ** {======================================================
-** lua_popen spawns a new process connected to the current
+** l_popen spawns a new process connected to the current
 ** one through the file streams.
 ** =======================================================
 */
 
-#if !defined(lua_popen)        /* { */
-
-#if defined(LUA_USE_POPEN)     /* { */
+#if !defined(l_popen)          /* { */
 
-#define lua_popen(L,c,m)       ((void)L, fflush(NULL), popen(c,m))
-#define lua_pclose(L,file)     ((void)L, pclose(file))
+#if defined(LUA_USE_POSIX)     /* { */
 
-#elif defined(LUA_WIN)         /* }{ */
+#define l_popen(L,c,m)         (fflush(NULL), popen(c,m))
+#define l_pclose(L,file)       (pclose(file))
 
-#define lua_popen(L,c,m)               ((void)L, _popen(c,m))
-#define lua_pclose(L,file)             ((void)L, _pclose(file))
+#elif defined(LUA_USE_WINDOWS) /* }{ */
 
+#define l_popen(L,c,m)         (_popen(c,m))
+#define l_pclose(L,file)       (_pclose(file))
 
 #else                          /* }{ */
 
-#define lua_popen(L,c,m)               ((void)((void)c, m),  \
-               luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
-#define lua_pclose(L,file)             ((void)((void)L, file), -1)
-
+/* ISO C definitions */
+#define l_popen(L,c,m)  \
+         ((void)((void)c, m), \
+         luaL_error(L, "'popen' not supported"), \
+         (FILE*)0)
+#define l_pclose(L,file)               ((void)L, (void)file, -1)
 
 #endif                         /* } */
 
-#endif                 /* } */
+#endif                         /* } */
 
 /* }====================================================== */
 
 
+#if !defined(l_getc)           /* { */
+
+#if defined(LUA_USE_POSIX)
+#define l_getc(f)              getc_unlocked(f)
+#define l_lockfile(f)          flockfile(f)
+#define l_unlockfile(f)                funlockfile(f)
+#else
+#define l_getc(f)              getc(f)
+#define l_lockfile(f)          ((void)0)
+#define l_unlockfile(f)                ((void)0)
+#endif
+
+#endif                         /* } */
+
+
 /*
 ** {======================================================
-** lua_fseek: configuration for longer offsets
+** l_fseek: configuration for longer offsets
 ** =======================================================
 */
 
-#if !defined(lua_fseek)        && !defined(LUA_ANSI)   /* { */
+#if !defined(l_fseek)          /* { */
 
 #if defined(LUA_USE_POSIX)     /* { */
 
+#include <sys/types.h>
+
 #define l_fseek(f,o,w)         fseeko(f,o,w)
 #define l_ftell(f)             ftello(f)
 #define l_seeknum              off_t
 
-#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
+#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
    && defined(_MSC_VER) && (_MSC_VER >= 1400)  /* }{ */
-/* Windows (but not DDK) and Visual C++ 2005 or higher */
 
+/* Windows (but not DDK) and Visual C++ 2005 or higher */
 #define l_fseek(f,o,w)         _fseeki64(f,o,w)
 #define l_ftell(f)             _ftelli64(f)
 #define l_seeknum              __int64
 
-#endif /* } */
-
-#endif                 /* } */
-
+#else                          /* }{ */
 
-#if !defined(l_fseek)          /* default definitions */
+/* ISO C definitions */
 #define l_fseek(f,o,w)         fseek(f,o,w)
 #define l_ftell(f)             ftell(f)
 #define l_seeknum              long
-#endif
+
+#endif                         /* } */
+
+#endif                         /* } */
 
 /* }====================================================== */
 
 
 #define IO_PREFIX      "_IO_"
+#define IOPREF_LEN     (sizeof(IO_PREFIX)/sizeof(char) - 1)
 #define IO_INPUT       (IO_PREFIX "input")
 #define IO_OUTPUT      (IO_PREFIX "output")
 
@@ -161,9 +180,9 @@ static FILE *tofile (lua_State *L) {
 
 
 /*
-** When creating file handles, always creates a `closed' file handle
+** When creating file handles, always creates a 'closed' file handle
 ** before opening the actual file; so, if there is a memory error, the
-** file is not left opened.
+** handle is in a consistent state.
 */
 static LStream *newprefile (lua_State *L) {
   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
@@ -173,9 +192,14 @@ static LStream *newprefile (lua_State *L) {
 }
 
 
+/*
+** Calls the 'close' function from a file handle. The 'volatile' avoids
+** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
+** 32 bits).
+*/
 static int aux_close (lua_State *L) {
   LStream *p = tolstream(L);
-  lua_CFunction cf = p->closef;
+  volatile lua_CFunction cf = p->closef;
   p->closef = NULL;  /* mark stream as closed */
   return (*cf)(L);  /* close it */
 }
@@ -219,7 +243,7 @@ static void opencheck (lua_State *L, const char *fname, const char *mode) {
   LStream *p = newfile(L);
   p->f = fopen(fname, mode);
   if (p->f == NULL)
-    luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
+    luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
 }
 
 
@@ -228,7 +252,7 @@ static int io_open (lua_State *L) {
   const char *mode = luaL_optstring(L, 2, "r");
   LStream *p = newfile(L);
   const char *md = mode;  /* to traverse/check mode */
-  luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode");
+  luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
   p->f = fopen(filename, mode);
   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
 }
@@ -239,7 +263,7 @@ static int io_open (lua_State *L) {
 */
 static int io_pclose (lua_State *L) {
   LStream *p = tolstream(L);
-  return luaL_execresult(L, lua_pclose(L, p->f));
+  return luaL_execresult(L, l_pclose(L, p->f));
 }
 
 
@@ -247,7 +271,7 @@ static int io_popen (lua_State *L) {
   const char *filename = luaL_checkstring(L, 1);
   const char *mode = luaL_optstring(L, 2, "r");
   LStream *p = newprefile(L);
-  p->f = lua_popen(L, filename, mode);
+  p->f = l_popen(L, filename, mode);
   p->closef = &io_pclose;
   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
 }
@@ -265,7 +289,7 @@ static FILE *getiofile (lua_State *L, const char *findex) {
   lua_getfield(L, LUA_REGISTRYINDEX, findex);
   p = (LStream *)lua_touserdata(L, -1);
   if (isclosed(p))
-    luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
+    luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
   return p->f;
 }
 
@@ -300,15 +324,18 @@ static int io_output (lua_State *L) {
 static int io_readline (lua_State *L);
 
 
+/*
+** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
+** in the limit for upvalues of a closure)
+*/
+#define MAXARGLINE     250
+
 static void aux_lines (lua_State *L, int toclose) {
-  int i;
   int n = lua_gettop(L) - 1;  /* number of arguments to read */
-  /* ensure that arguments will fit here and into 'io_readline' stack */
-  luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
-  lua_pushvalue(L, 1);  /* file handle */
+  luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
   lua_pushinteger(L, n);  /* number of arguments to read */
   lua_pushboolean(L, toclose);  /* close/not close file when finished */
-  for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1);  /* copy arguments */
+  lua_rotate(L, 2, 2);  /* move 'n' and 'toclose' to their positions */
   lua_pushcclosure(L, io_readline, 3 + n);
 }
 
@@ -347,13 +374,91 @@ static int io_lines (lua_State *L) {
 */
 
 
-static int read_number (lua_State *L, FILE *f) {
-  lua_Number d;
-  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
-    lua_pushnumber(L, d);
-    return 1;
+/* maximum length of a numeral */
+#if !defined (L_MAXLENNUM)
+#define L_MAXLENNUM     200
+#endif
+
+
+/* auxiliary structure used by 'read_number' */
+typedef struct {
+  FILE *f;  /* file being read */
+  int c;  /* current character (look ahead) */
+  int n;  /* number of elements in buffer 'buff' */
+  char buff[L_MAXLENNUM + 1];  /* +1 for ending '\0' */
+} RN;
+
+
+/*
+** Add current char to buffer (if not out of space) and read next one
+*/
+static int nextc (RN *rn) {
+  if (rn->n >= L_MAXLENNUM) {  /* buffer overflow? */
+    rn->buff[0] = '\0';  /* invalidate result */
+    return 0;  /* fail */
   }
   else {
+    rn->buff[rn->n++] = rn->c;  /* save current char */
+    rn->c = l_getc(rn->f);  /* read next one */
+    return 1;
+  }
+}
+
+
+/*
+** Accept current char if it is in 'set' (of size 2)
+*/
+static int test2 (RN *rn, const char *set) {
+  if (rn->c == set[0] || rn->c == set[1])
+    return nextc(rn);
+  else return 0;
+}
+
+
+/*
+** Read a sequence of (hex)digits
+*/
+static int readdigits (RN *rn, int hex) {
+  int count = 0;
+  while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
+    count++;
+  return count;
+}
+
+
+/*
+** 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
+** correct and to convert it to a Lua number
+*/
+static int read_number (lua_State *L, FILE *f) {
+  RN rn;
+  int count = 0;
+  int hex = 0;
+  char decp[2];
+  rn.f = f; rn.n = 0;
+  decp[0] = lua_getlocaledecpoint();  /* get decimal point from locale */
+  decp[1] = '.';  /* always accept a dot */
+  l_lockfile(rn.f);
+  do { rn.c = l_getc(rn.f); } while (isspace(rn.c));  /* skip spaces */
+  test2(&rn, "-+");  /* optional signal */
+  if (test2(&rn, "00")) {
+    if (test2(&rn, "xX")) hex = 1;  /* numeral is hexadecimal */
+    else count = 1;  /* count initial '0' as a valid digit */
+  }
+  count += readdigits(&rn, hex);  /* integral part */
+  if (test2(&rn, decp))  /* decimal point? */
+    count += readdigits(&rn, hex);  /* fractional part */
+  if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) {  /* exponent mark? */
+    test2(&rn, "-+");  /* exponent signal */
+    readdigits(&rn, 0);  /* exponent digits */
+  }
+  ungetc(rn.c, rn.f);  /* unread look-ahead char */
+  l_unlockfile(rn.f);
+  rn.buff[rn.n] = '\0';  /* finish string */
+  if (lua_stringtonumber(L, rn.buff))  /* is this a valid number? */
+    return 1;  /* ok */
+  else {  /* invalid format */
    lua_pushnil(L);  /* "result" to be removed */
    return 0;  /* read fails */
   }
@@ -362,48 +467,42 @@ 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);
-  lua_pushlstring(L, NULL, 0);
+  ungetc(c, f);  /* no-op when c == EOF */
+  lua_pushliteral(L, "");
   return (c != EOF);
 }
 
 
 static int read_line (lua_State *L, FILE *f, int chop) {
   luaL_Buffer b;
+  int c = '\0';
   luaL_buffinit(L, &b);
-  for (;;) {
-    size_t l;
-    char *p = luaL_prepbuffer(&b);
-    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
-      luaL_pushresult(&b);  /* close buffer */
-      return (lua_rawlen(L, -1) > 0);  /* check whether read something */
-    }
-    l = strlen(p);
-    if (l == 0 || p[l-1] != '\n')
-      luaL_addsize(&b, l);
-    else {
-      luaL_addsize(&b, l - chop);  /* chop 'eol' if needed */
-      luaL_pushresult(&b);  /* close buffer */
-      return 1;  /* read at least an `eol' */
-    }
+  while (c != EOF && c != '\n') {  /* repeat until end of line */
+    char *buff = luaL_prepbuffer(&b);  /* preallocate buffer */
+    int i = 0;
+    l_lockfile(f);  /* no memory errors can happen inside the lock */
+    while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
+      buff[i++] = c;
+    l_unlockfile(f);
+    luaL_addsize(&b, i);
   }
+  if (!chop && c == '\n')  /* want a newline and have one? */
+    luaL_addchar(&b, c);  /* add ending newline to result */
+  luaL_pushresult(&b);  /* close buffer */
+  /* return ok if read something (either a newline or something else) */
+  return (c == '\n' || lua_rawlen(L, -1) > 0);
 }
 
 
-#define MAX_SIZE_T     (~(size_t)0)
-
 static void read_all (lua_State *L, FILE *f) {
-  size_t rlen = LUAL_BUFFERSIZE;  /* how much to read in each cycle */
+  size_t nr;
   luaL_Buffer b;
   luaL_buffinit(L, &b);
-  for (;;) {
-    char *p = luaL_prepbuffsize(&b, rlen);
-    size_t nr = fread(p, sizeof(char), rlen, f);
+  do {  /* read file in chunks of LUAL_BUFFERSIZE bytes */
+    char *p = luaL_prepbuffer(&b);
+    nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
     luaL_addsize(&b, nr);
-    if (nr < rlen) break;  /* eof? */
-    else if (rlen <= (MAX_SIZE_T / 4))  /* avoid buffers too large */
-      rlen *= 2;  /* double buffer size at each iteration */
-  }
+  } while (nr == LUAL_BUFFERSIZE);
   luaL_pushresult(&b);  /* close buffer */
 }
 
@@ -435,13 +534,13 @@ static int g_read (lua_State *L, FILE *f, int first) {
     success = 1;
     for (n = first; nargs-- && success; n++) {
       if (lua_type(L, n) == LUA_TNUMBER) {
-        size_t l = (size_t)lua_tointeger(L, n);
+        size_t l = (size_t)luaL_checkinteger(L, n);
         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
       }
       else {
-        const char *p = lua_tostring(L, n);
-        luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
-        switch (p[1]) {
+        const char *p = luaL_checkstring(L, n);
+        if (*p == '*') p++;  /* skip optional '*' (for compatibility) */
+        switch (*p) {
           case 'n':  /* number */
             success = read_number(L, f);
             break;
@@ -488,11 +587,12 @@ static int io_readline (lua_State *L) {
   if (isclosed(p))  /* file is already closed? */
     return luaL_error(L, "file is already closed");
   lua_settop(L , 1);
+  luaL_checkstack(L, n, "too many arguments");
   for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
     lua_pushvalue(L, lua_upvalueindex(3 + i));
   n = g_read(L, p->f, 2);  /* 'n' is number of results */
   lua_assert(n > 0);  /* should return at least a nil */
-  if (!lua_isnil(L, -n))  /* read at least one value? */
+  if (lua_toboolean(L, -n))  /* read at least one value? */
     return n;  /* return them */
   else {  /* first result is nil: EOF or error */
     if (n > 1) {  /* is there error information? */
@@ -517,8 +617,10 @@ static int g_write (lua_State *L, FILE *f, int arg) {
   for (; nargs--; arg++) {
     if (lua_type(L, arg) == LUA_TNUMBER) {
       /* optimization: could be done exactly as for strings */
-      status = status &&
-          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+      int len = lua_isinteger(L, arg)
+                ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
+                : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
+      status = status && (len > 0);
     }
     else {
       size_t l;
@@ -548,15 +650,15 @@ static int f_seek (lua_State *L) {
   static const char *const modenames[] = {"set", "cur", "end", NULL};
   FILE *f = tofile(L);
   int op = luaL_checkoption(L, 2, "cur", modenames);
-  lua_Number p3 = luaL_optnumber(L, 3, 0);
+  lua_Integer p3 = luaL_optinteger(L, 3, 0);
   l_seeknum offset = (l_seeknum)p3;
-  luaL_argcheck(L, (lua_Number)offset == p3, 3,
+  luaL_argcheck(L, (lua_Integer)offset == p3, 3,
                   "not an integer in proper range");
   op = l_fseek(f, offset, mode[op]);
   if (op)
     return luaL_fileresult(L, 0, NULL);  /* error */
   else {
-    lua_pushnumber(L, (lua_Number)l_ftell(f));
+    lua_pushinteger(L, (lua_Integer)l_ftell(f));
     return 1;
   }
 }
@@ -568,7 +670,7 @@ static int f_setvbuf (lua_State *L) {
   FILE *f = tofile(L);
   int op = luaL_checkoption(L, 2, NULL, modenames);
   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
-  int res = setvbuf(f, NULL, mode[op], sz);
+  int res = setvbuf(f, NULL, mode[op], (size_t)sz);
   return luaL_fileresult(L, res == 0, NULL);
 }
 
index 32cdcf1..7032827 100644 (file)
@@ -1,20 +1,24 @@
 /*
-** $Id: llex.c,v 2.63.1.3 2015/02/09 17:56:34 roberto Exp $
+** $Id: llex.c,v 2.96 2016/05/02 14:02:12 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
 
+#define llex_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 #include <locale.h>
 #include <string.h>
 
-#define llex_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lctype.h"
+#include "ldebug.h"
 #include "ldo.h"
+#include "lgc.h"
 #include "llex.h"
 #include "lobject.h"
 #include "lparser.h"
@@ -38,8 +42,9 @@ static const char *const luaX_tokens [] = {
     "end", "false", "for", "function", "goto", "if",
     "in", "local", "nil", "not", "or", "repeat",
     "return", "then", "true", "until", "while",
-    "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
-    "<number>", "<name>", "<string>"
+    "//", "..", "...", "==", ">=", "<=", "~=",
+    "<<", ">>", "::", "<eof>",
+    "<number>", "<integer>", "<name>", "<string>"
 };
 
 
@@ -53,7 +58,7 @@ static void save (LexState *ls, int c) {
   Mbuffer *b = ls->buff;
   if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) {
     size_t newsize;
-    if (luaZ_sizebuffer(b) >= MAX_SIZET/2)
+    if (luaZ_sizebuffer(b) >= MAX_SIZE/2)
       lexerror(ls, "lexical element too long", 0);
     newsize = luaZ_sizebuffer(b) * 2;
     luaZ_resizebuffer(ls->L, b, newsize);
@@ -64,24 +69,25 @@ static void save (LexState *ls, int c) {
 
 void luaX_init (lua_State *L) {
   int i;
+  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]);
-    luaS_fix(ts);  /* reserved words are never collected */
-    ts->tsv.extra = cast_byte(i+1);  /* reserved word */
+    luaC_fix(L, obj2gco(ts));  /* reserved words are never collected */
+    ts->extra = cast_byte(i+1);  /* reserved word */
   }
 }
 
 
 const char *luaX_token2str (LexState *ls, int token) {
   if (token < FIRST_RESERVED) {  /* single-byte symbols? */
-    lua_assert(token == cast(unsigned char, token));
-    return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) :
-                              luaO_pushfstring(ls->L, "char(%d)", token);
+    lua_assert(token == cast_uchar(token));
+    return luaO_pushfstring(ls->L, "'%c'", token);
   }
   else {
     const char *s = luaX_tokens[token - FIRST_RESERVED];
     if (token < TK_EOS)  /* fixed format (symbols and reserved words)? */
-      return luaO_pushfstring(ls->L, LUA_QS, s);
+      return luaO_pushfstring(ls->L, "'%s'", s);
     else  /* names, strings, and numerals */
       return s;
   }
@@ -90,11 +96,10 @@ const char *luaX_token2str (LexState *ls, int token) {
 
 static const char *txtToken (LexState *ls, int token) {
   switch (token) {
-    case TK_NAME:
-    case TK_STRING:
-    case TK_NUMBER:
+    case TK_NAME: case TK_STRING:
+    case TK_FLT: case TK_INT:
       save(ls, '\0');
-      return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff));
+      return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff));
     default:
       return luaX_token2str(ls, token);
   }
@@ -102,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);
@@ -117,24 +120,24 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
 
 
 /*
-** creates a new string and anchors it in function's table so that
-** it will not be collected until the end of the function's compilation
-** (by that time it should be anchored in function's prototype)
+** creates a new string and anchors it in scanner's table so that
+** it will not be collected until the end of the compilation
+** (by that time it should be anchored somewhere)
 */
 TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
   lua_State *L = ls->L;
-  TValue *o;  /* entry for `str' */
+  TValue *o;  /* entry for 'str' */
   TString *ts = luaS_newlstr(L, str, l);  /* create new string */
   setsvalue2s(L, L->top++, ts);  /* temporarily anchor it in stack */
-  o = luaH_set(L, ls->fs->h, L->top - 1);
-  if (ttisnil(o)) {  /* not in use yet? (see 'addK') */
+  o = luaH_set(L, ls->h, L->top - 1);
+  if (ttisnil(o)) {  /* not in use yet? */
     /* boolean value does not need GC barrier;
        table has no metatable, so it does not need to invalidate cache */
     setbvalue(o, 1);  /* t[string] = true */
     luaC_checkGC(L);
   }
   else {  /* string already present */
-    ts = rawtsvalue(keyfromval(o));  /* re-use value previously stored */
+    ts = tsvalue(keyfromval(o));  /* re-use value previously stored */
   }
   L->top--;  /* remove string from stack */
   return ts;
@@ -148,9 +151,9 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
 static void inclinenumber (LexState *ls) {
   int old = ls->current;
   lua_assert(currIsNewline(ls));
-  next(ls);  /* skip `\n' or `\r' */
+  next(ls);  /* skip '\n' or '\r' */
   if (currIsNewline(ls) && ls->current != old)
-    next(ls);  /* skip `\n\r' or `\r\n' */
+    next(ls);  /* skip '\n\r' or '\r\n' */
   if (++ls->linenumber >= MAX_INT)
     lexerror(ls, "chunk has too many lines", 0);
 }
@@ -158,7 +161,7 @@ static void inclinenumber (LexState *ls) {
 
 void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
                     int firstchar) {
-  ls->decpoint = '.';
+  ls->t.token = 0;
   ls->L = L;
   ls->current = firstchar;
   ls->lookahead.token = TK_EOS;  /* no look-ahead token */
@@ -167,8 +170,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);  /* create env name */
-  luaS_fix(ls->envn);  /* never collect this name */
+  ls->envn = luaS_newliteral(L, LUA_ENV);  /* get env name */
   luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */
 }
 
@@ -181,78 +183,70 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
 */
 
 
-
-static int check_next (LexState *ls, const char *set) {
-  if (ls->current == '\0' || !strchr(set, ls->current))
-    return 0;
-  save_and_next(ls);
-  return 1;
-}
-
-
-/*
-** change all characters 'from' in buffer to 'to'
-*/
-static void buffreplace (LexState *ls, char from, char to) {
-  size_t n = luaZ_bufflen(ls->buff);
-  char *p = luaZ_buffer(ls->buff);
-  while (n--)
-    if (p[n] == from) p[n] = to;
+static int check_next1 (LexState *ls, int c) {
+  if (ls->current == c) {
+    next(ls);
+    return 1;
+  }
+  else return 0;
 }
 
 
-#if !defined(getlocaledecpoint)
-#define getlocaledecpoint()    (localeconv()->decimal_point[0])
-#endif
-
-
-#define buff2d(b,e)    luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e)
-
 /*
-** in case of format error, try to change decimal point separator to
-** the one defined in the current locale and check again
+** Check whether current char is in set 'set' (with two chars) and
+** saves it
 */
-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
-  char old = ls->decpoint;
-  ls->decpoint = getlocaledecpoint();
-  buffreplace(ls, old, ls->decpoint);  /* try new decimal separator */
-  if (!buff2d(ls->buff, &seminfo->r)) {
-    /* format error with correct decimal point: no more options */
-    buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */
-    lexerror(ls, "malformed number", TK_NUMBER);
+static int check_next2 (LexState *ls, const char *set) {
+  lua_assert(set[2] == '\0');
+  if (ls->current == set[0] || ls->current == set[1]) {
+    save_and_next(ls);
+    return 1;
   }
+  else return 0;
 }
 
 
 /* LUA_NUMBER */
 /*
-** this function is quite liberal in what it accepts, as 'luaO_str2d'
+** this function is quite liberal in what it accepts, as 'luaO_str2num'
 ** will reject ill-formed numerals.
 */
-static void read_numeral (LexState *ls, SemInfo *seminfo) {
+static int read_numeral (LexState *ls, SemInfo *seminfo) {
+  TValue obj;
   const char *expo = "Ee";
   int first = ls->current;
   lua_assert(lisdigit(ls->current));
   save_and_next(ls);
-  if (first == '0' && check_next(ls, "Xx"))  /* hexadecimal? */
+  if (first == '0' && check_next2(ls, "xX"))  /* hexadecimal? */
     expo = "Pp";
   for (;;) {
-    if (check_next(ls, expo))  /* exponent part? */
-      check_next(ls, "+-");  /* optional exponent sign */
-    if (lisxdigit(ls->current) || ls->current == '.')
+    if (check_next2(ls, expo))  /* exponent part? */
+      check_next2(ls, "-+");  /* optional exponent sign */
+    if (lisxdigit(ls->current))
+      save_and_next(ls);
+    else if (ls->current == '.')
       save_and_next(ls);
-    else  break;
+    else break;
   }
   save(ls, '\0');
-  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */
-  if (!buff2d(ls->buff, &seminfo->r))  /* format error? */
-    trydecpoint(ls, seminfo); /* try to update decimal point separator */
+  if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0)  /* format error? */
+    lexerror(ls, "malformed number", TK_FLT);
+  if (ttisinteger(&obj)) {
+    seminfo->i = ivalue(&obj);
+    return TK_INT;
+  }
+  else {
+    lua_assert(ttisfloat(&obj));
+    seminfo->r = fltvalue(&obj);
+    return TK_FLT;
+  }
 }
 
 
 /*
-** skip a sequence '[=*[' or ']=*]' and return its number of '='s or
-** -1 if sequence is malformed
+** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, 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;
@@ -268,18 +262,22 @@ static int skip_sep (LexState *ls) {
 
 
 static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
-  save_and_next(ls);  /* skip 2nd `[' */
+  int line = ls->linenumber;  /* initial line (for error message) */
+  save_and_next(ls);  /* skip 2nd '[' */
   if (currIsNewline(ls))  /* string starts with a newline? */
     inclinenumber(ls);  /* skip it */
   for (;;) {
     switch (ls->current) {
-      case EOZ:
-        lexerror(ls, (seminfo) ? "unfinished long string" :
-                                 "unfinished long comment", TK_EOS);
+      case EOZ: {  /* error */
+        const char *what = (seminfo ? "string" : "comment");
+        const char *msg = luaO_pushfstring(ls->L,
+                     "unfinished long %s (starting at line %d)", what, line);
+        lexerror(ls, msg, TK_EOS);
         break;  /* to avoid warnings */
+      }
       case ']': {
         if (skip_sep(ls) == sep) {
-          save_and_next(ls);  /* skip 2nd `]' */
+          save_and_next(ls);  /* skip 2nd ']' */
           goto endloop;
         }
         break;
@@ -302,40 +300,65 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
 }
 
 
-static void escerror (LexState *ls, int *c, int n, const char *msg) {
-  int i;
-  luaZ_resetbuffer(ls->buff);  /* prepare error message */
-  save(ls, '\\');
-  for (i = 0; i < n && c[i] != EOZ; i++)
-    save(ls, c[i]);
-  lexerror(ls, msg, TK_STRING);
+static void esccheck (LexState *ls, int c, const char *msg) {
+  if (!c) {
+    if (ls->current != EOZ)
+      save_and_next(ls);  /* add current to buffer for error message */
+    lexerror(ls, msg, TK_STRING);
+  }
+}
+
+
+static int gethexa (LexState *ls) {
+  save_and_next(ls);
+  esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected");
+  return luaO_hexavalue(ls->current);
 }
 
 
 static int readhexaesc (LexState *ls) {
-  int c[3], i;  /* keep input for error message */
-  int r = 0;  /* result accumulator */
-  c[0] = 'x';  /* for error message */
-  for (i = 1; i < 3; i++) {  /* read two hexadecimal digits */
-    c[i] = next(ls);
-    if (!lisxdigit(c[i]))
-      escerror(ls, c, i + 1, "hexadecimal digit expected");
-    r = (r << 4) + luaO_hexavalue(c[i]);
+  int r = gethexa(ls);
+  r = (r << 4) + gethexa(ls);
+  luaZ_buffremove(ls->buff, 2);  /* remove saved chars from buffer */
+  return r;
+}
+
+
+static unsigned long readutf8esc (LexState *ls) {
+  unsigned long r;
+  int i = 4;  /* chars to be removed: '\', 'u', '{', and first digit */
+  save_and_next(ls);  /* skip 'u' */
+  esccheck(ls, ls->current == '{', "missing '{'");
+  r = gethexa(ls);  /* must have at least one digit */
+  while ((save_and_next(ls), lisxdigit(ls->current))) {
+    i++;
+    r = (r << 4) + luaO_hexavalue(ls->current);
+    esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large");
   }
+  esccheck(ls, ls->current == '}', "missing '}'");
+  next(ls);  /* skip '}' */
+  luaZ_buffremove(ls->buff, i);  /* remove saved chars from buffer */
   return r;
 }
 
 
+static void utf8esc (LexState *ls) {
+  char buff[UTF8BUFFSZ];
+  int n = luaO_utf8esc(buff, readutf8esc(ls));
+  for (; n > 0; n--)  /* add 'buff' to string */
+    save(ls, buff[UTF8BUFFSZ - n]);
+}
+
+
 static int readdecesc (LexState *ls) {
-  int c[3], i;
+  int i;
   int r = 0;  /* result accumulator */
   for (i = 0; i < 3 && lisdigit(ls->current); i++) {  /* read up to 3 digits */
-    c[i] = ls->current;
-    r = 10*r + c[i] - '0';
-    next(ls);
+    r = 10*r + ls->current - '0';
+    save_and_next(ls);
   }
-  if (r > UCHAR_MAX)
-    escerror(ls, c, i, "decimal escape too large");
+  esccheck(ls, r <= UCHAR_MAX, "decimal escape too large");
+  luaZ_buffremove(ls->buff, i);  /* remove read digits from buffer */
   return r;
 }
 
@@ -353,7 +376,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
         break;  /* to avoid warnings */
       case '\\': {  /* escape sequences */
         int c;  /* final character to be saved */
-        next(ls);  /* do not save the `\' */
+        save_and_next(ls);  /* keep '\\' for error messages */
         switch (ls->current) {
           case 'a': c = '\a'; goto read_save;
           case 'b': c = '\b'; goto read_save;
@@ -363,12 +386,14 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
           case 't': c = '\t'; goto read_save;
           case 'v': c = '\v'; goto read_save;
           case 'x': c = readhexaesc(ls); goto read_save;
+          case 'u': utf8esc(ls);  goto no_save;
           case '\n': case '\r':
             inclinenumber(ls); c = '\n'; goto only_save;
           case '\\': case '\"': case '\'':
             c = ls->current; goto read_save;
           case EOZ: goto no_save;  /* will raise an error next loop */
           case 'z': {  /* zap following span of spaces */
+            luaZ_buffremove(ls->buff, 1);  /* remove '\\' */
             next(ls);  /* skip the 'z' */
             while (lisspace(ls->current)) {
               if (currIsNewline(ls)) inclinenumber(ls);
@@ -377,15 +402,18 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) {
             goto no_save;
           }
           default: {
-            if (!lisdigit(ls->current))
-              escerror(ls, &ls->current, 1, "invalid escape sequence");
-            /* digital escape \ddd */
-            c = readdecesc(ls);
+            esccheck(ls, lisdigit(ls->current), "invalid escape sequence");
+            c = readdecesc(ls);  /* digital escape '\ddd' */
             goto only_save;
           }
         }
-       read_save: next(ls);  /* read next character */
-       only_save: save(ls, c);  /* save 'c' */
+       read_save:
+         next(ls);
+         /* go through */
+       only_save:
+         luaZ_buffremove(ls->buff, 1);  /* remove '\\' */
+         save(ls, c);
+         /* go through */
        no_save: break;
       }
       default:
@@ -417,7 +445,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
         next(ls);
         if (ls->current == '[') {  /* long comment? */
           int sep = skip_sep(ls);
-          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */
+          luaZ_resetbuffer(ls->buff);  /* 'skip_sep' may dirty the buffer */
           if (sep >= 0) {
             read_long_string(ls, NULL, sep);  /* skip long comment */
             luaZ_resetbuffer(ls->buff);  /* previous call may dirty the buff. */
@@ -435,33 +463,41 @@ 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);
-        if (ls->current != '=') return '=';
-        else { next(ls); return TK_EQ; }
+        if (check_next1(ls, '=')) return TK_EQ;
+        else return '=';
       }
       case '<': {
         next(ls);
-        if (ls->current != '=') return '<';
-        else { next(ls); return TK_LE; }
+        if (check_next1(ls, '=')) return TK_LE;
+        else if (check_next1(ls, '<')) return TK_SHL;
+        else return '<';
       }
       case '>': {
         next(ls);
-        if (ls->current != '=') return '>';
-        else { next(ls); return TK_GE; }
+        if (check_next1(ls, '=')) return TK_GE;
+        else if (check_next1(ls, '>')) return TK_SHR;
+        else return '>';
+      }
+      case '/': {
+        next(ls);
+        if (check_next1(ls, '/')) return TK_IDIV;
+        else return '/';
       }
       case '~': {
         next(ls);
-        if (ls->current != '=') return '~';
-        else { next(ls); return TK_NE; }
+        if (check_next1(ls, '=')) return TK_NE;
+        else return '~';
       }
       case ':': {
         next(ls);
-        if (ls->current != ':') return ':';
-        else { next(ls); return TK_DBCOLON; }
+        if (check_next1(ls, ':')) return TK_DBCOLON;
+        else return ':';
       }
       case '"': case '\'': {  /* short literal strings */
         read_string(ls, ls->current, seminfo);
@@ -469,18 +505,17 @@ static int llex (LexState *ls, SemInfo *seminfo) {
       }
       case '.': {  /* '.', '..', '...', or number */
         save_and_next(ls);
-        if (check_next(ls, ".")) {
-          if (check_next(ls, "."))
+        if (check_next1(ls, '.')) {
+          if (check_next1(ls, '.'))
             return TK_DOTS;   /* '...' */
           else return TK_CONCAT;   /* '..' */
         }
         else if (!lisdigit(ls->current)) return '.';
-        /* else go through */
+        else return read_numeral(ls, seminfo);
       }
       case '0': case '1': case '2': case '3': case '4':
       case '5': case '6': case '7': case '8': case '9': {
-        read_numeral(ls, seminfo);
-        return TK_NUMBER;
+        return read_numeral(ls, seminfo);
       }
       case EOZ: {
         return TK_EOS;
@@ -495,7 +530,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
                                   luaZ_bufflen(ls->buff));
           seminfo->ts = ts;
           if (isreserved(ts))  /* reserved word? */
-            return ts->tsv.extra - 1 + FIRST_RESERVED;
+            return ts->extra - 1 + FIRST_RESERVED;
           else {
             return TK_NAME;
           }
index a4acdd3..2363d87 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
 #define FIRST_RESERVED 257
 
 
+#if !defined(LUA_ENV)
+#define LUA_ENV                "_ENV"
+#endif
+
 
 /*
 * WARNING: if you change the order of this enumeration,
@@ -26,8 +30,10 @@ enum RESERVED {
   TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
   TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
   /* other terminal symbols */
-  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS,
-  TK_NUMBER, TK_NAME, TK_STRING
+  TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
+  TK_SHL, TK_SHR,
+  TK_DBCOLON, TK_EOS,
+  TK_FLT, TK_INT, TK_NAME, TK_STRING
 };
 
 /* number of reserved words */
@@ -36,6 +42,7 @@ enum RESERVED {
 
 typedef union {
   lua_Number r;
+  lua_Integer i;
   TString *ts;
 } SemInfo;  /* semantics information */
 
@@ -51,17 +58,17 @@ typedef struct Token {
 typedef struct LexState {
   int current;  /* current character (charint) */
   int linenumber;  /* input line counter */
-  int lastline;  /* line of last token `consumed' */
+  int lastline;  /* line of last token 'consumed' */
   Token t;  /* current token */
   Token lookahead;  /* look ahead token */
   struct FuncState *fs;  /* current function (parser) */
   struct lua_State *L;
   ZIO *z;  /* input stream */
   Mbuffer *buff;  /* buffer for tokens */
+  Table *h;  /* to avoid collection/reuse strings */
   struct Dyndata *dyd;  /* dynamic structures used by the parser */
   TString *source;  /* current source name */
   TString *envn;  /* environment variable name */
-  char decpoint;  /* locale decimal point */
 } LexState;
 
 
index 152dd05..f21377f 100644 (file)
@@ -1,6 +1,6 @@
 /*
-** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $
-** Limits, basic types, and some other `installation-dependent' definitions
+** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $
+** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
 
 
 #include "lua.h"
 
-
-typedef unsigned LUA_INT32 lu_int32;
-
+/*
+** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count
+** the total memory used by Lua (in bytes). Usually, 'size_t' and
+** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines.
+*/
+#if defined(LUAI_MEM)          /* { external definitions? */
 typedef LUAI_UMEM lu_mem;
-
 typedef LUAI_MEM l_mem;
+#elif LUAI_BITSINT >= 32       /* }{ */
+typedef size_t lu_mem;
+typedef ptrdiff_t l_mem;
+#else  /* 16-bit ints */       /* }{ */
+typedef unsigned long lu_mem;
+typedef long l_mem;
+#endif                         /* } */
 
 
-
-/* chars used as small naturals (so that `char' is reserved for characters) */
+/* chars used as small naturals (so that 'char' is reserved for characters) */
 typedef unsigned char lu_byte;
 
 
-#define MAX_SIZET      ((size_t)(~(size_t)0)-2)
+/* maximum value for size_t */
+#define MAX_SIZET      ((size_t)(~(size_t)0))
+
+/* maximum size visible for Lua (must be representable in a lua_Integer */
+#define MAX_SIZE       (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
+                          : (size_t)(LUA_MAXINTEGER))
+
 
-#define MAX_LUMEM      ((lu_mem)(~(lu_mem)0)-2)
+#define MAX_LUMEM      ((lu_mem)(~(lu_mem)0))
 
-#define MAX_LMEM       ((l_mem) ((MAX_LUMEM >> 1) - 2))
+#define MAX_LMEM       ((l_mem)(MAX_LUMEM >> 1))
 
 
-#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
+#define MAX_INT                INT_MAX  /* maximum value of an int */
+
 
 /*
-** conversion of pointer to integer
+** conversion of pointer to unsigned integer:
 ** this is for hashing only; there is no problem if the integer
 ** cannot hold the whole pointer value
 */
-#define IntPoint(p)  ((unsigned int)(lu_mem)(p))
+#define point2uint(p)  ((unsigned int)((size_t)(p) & UINT_MAX))
 
 
 
 /* type to ensure maximum alignment */
-#if !defined(LUAI_USER_ALIGNMENT_T)
-#define LUAI_USER_ALIGNMENT_T  union { double u; void *s; long l; }
+#if defined(LUAI_USER_ALIGNMENT_T)
+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
+#else
+typedef union {
+  lua_Number n;
+  double u;
+  void *s;
+  lua_Integer i;
+  long l;
+} L_Umaxalign;
 #endif
 
-typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
 
 
-/* result of a `usual argument conversion' over lua_Number */
+/* types of 'usual argument conversions' for lua_Number and lua_Integer */
 typedef LUAI_UACNUMBER l_uacNumber;
+typedef LUAI_UACINT l_uacInt;
 
 
 /* internal assertions for in-house debugging */
 #if defined(lua_assert)
 #define check_exp(c,e)         (lua_assert(c), (e))
 /* to avoid problems with conditions too long */
-#define lua_longassert(c)      { if (!(c)) lua_assert(0); }
+#define lua_longassert(c)      ((c) ? (void)0 : lua_assert(0))
 #else
 #define lua_assert(c)          ((void)0)
 #define check_exp(c,e)         (e)
@@ -72,38 +95,49 @@ typedef LUAI_UACNUMBER l_uacNumber;
 ** assertion for checking API calls
 */
 #if !defined(luai_apicheck)
-
-#if defined(LUA_USE_APICHECK)
-#include <assert.h>
-#define luai_apicheck(L,e)     assert(e)
-#else
-#define luai_apicheck(L,e)     lua_assert(e)
-#endif
-
+#define luai_apicheck(l,e)     lua_assert(e)
 #endif
 
 #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))
 #define cast_byte(i)   cast(lu_byte, (i))
 #define cast_num(i)    cast(lua_Number, (i))
 #define cast_int(i)    cast(int, (i))
 #define cast_uchar(i)  cast(unsigned char, (i))
 
 
+/* cast a signed lua_Integer to lua_Unsigned */
+#if !defined(l_castS2U)
+#define l_castS2U(i)   ((lua_Unsigned)(i))
+#endif
+
+/*
+** cast a lua_Unsigned to a signed lua_Integer; this cast is
+** not strict ISO C, but two-complement architectures should
+** work fine.
+*/
+#if !defined(l_castU2S)
+#define l_castU2S(i)   ((lua_Integer)(i))
+#endif
+
+
 /*
 ** non-return type
 */
 #if defined(__GNUC__)
 #define l_noret                void __attribute__((noreturn))
-#elif defined(_MSC_VER)
+#elif defined(_MSC_VER) && _MSC_VER >= 1200
 #define l_noret                void __declspec(noreturn)
 #else
 #define l_noret                void
@@ -119,29 +153,50 @@ typedef LUAI_UACNUMBER l_uacNumber;
 #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
 
 
 /*
-** type for virtual-machine instructions
+** type for virtual-machine instructions;
 ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
 */
-typedef lu_int32 Instruction;
-
+#if LUAI_BITSINT >= 32
+typedef unsigned int Instruction;
+#else
+typedef unsigned long Instruction;
+#endif
 
 
-/* maximum stack for a Lua function */
-#define MAXSTACK       250
 
+/*
+** 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  32
+#define MINSTRTABSIZE  128
+#endif
+
+
+/*
+** Size of cache for strings in the API. 'N' is the number of
+** sets (better be a prime) and "M" is the size of each set (M == 1
+** makes a direct cache.)
+*/
+#if !defined(STRCACHE_N)
+#define STRCACHE_N             53
+#define STRCACHE_M             2
 #endif
 
 
@@ -151,13 +206,21 @@ typedef lu_int32 Instruction;
 #endif
 
 
+/*
+** macros that are executed whenever 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)
+#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);}
+#define luai_threadyield(L)    {lua_unlock(L); lua_lock(L);}
 #endif
 
 
@@ -183,127 +246,78 @@ typedef lu_int32 Instruction;
 #endif
 
 #if !defined(luai_userstateresume)
-#define luai_userstateresume(L,n)       ((void)L)
+#define luai_userstateresume(L,n)      ((void)L)
 #endif
 
 #if !defined(luai_userstateyield)
-#define luai_userstateyield(L,n)        ((void)L)
+#define luai_userstateyield(L,n)       ((void)L)
 #endif
 
-/*
-** lua_number2int is a macro to convert lua_Number to int.
-** lua_number2integer is a macro to convert lua_Number to lua_Integer.
-** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned.
-** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number.
-** luai_hashnum is a macro to hash a lua_Number value into an integer.
-** The hash must be deterministic and give reasonable values for
-** both small and large values (outside the range of integers).
-*/
-
-#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK)    /* { */
-/* trick with Microsoft assembler for X86 */
-
-#define lua_number2int(i,n)  __asm {__asm fld n   __asm fistp i}
-#define lua_number2integer(i,n)                lua_number2int(i, n)
-#define lua_number2unsigned(i,n)  \
-  {__int64 l; __asm {__asm fld n   __asm fistp l} i = (unsigned int)l;}
-
-
-#elif defined(LUA_IEEE754TRICK)                /* }{ */
-/* the next trick should work on any machine using IEEE754 with
-   a 32-bit int type */
-
-union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
-
-#if !defined(LUA_IEEEENDIAN)   /* { */
-#define LUAI_EXTRAIEEE \
-  static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
-#define LUA_IEEEENDIANLOC      (ieeeendian.l_p[1] == 33)
-#else
-#define LUA_IEEEENDIANLOC      LUA_IEEEENDIAN
-#define LUAI_EXTRAIEEE         /* empty */
-#endif                         /* } */
 
-#define lua_number2int32(i,n,t) \
-  { LUAI_EXTRAIEEE \
-    volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
-    (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; }
 
-#define luai_hashnum(i,n)  \
-  { volatile union luai_Cast u; u.l_d = (n) + 1.0;  /* avoid -0 */ \
-    (i) = u.l_p[0]; (i) += u.l_p[1]; }  /* add double bits for his hash */
-
-#define lua_number2int(i,n)            lua_number2int32(i, n, int)
-#define lua_number2unsigned(i,n)       lua_number2int32(i, n, lua_Unsigned)
+/*
+** The luai_num* macros define the primitive operations over numbers.
+*/
 
-/* the trick can be expanded to lua_Integer when it is a 32-bit value */
-#if defined(LUA_IEEELL)
-#define lua_number2integer(i,n)                lua_number2int32(i, n, lua_Integer)
+/* 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
 
-#endif                         /* } */
-
-
-/* the following definitions always work, but may be slow */
-
-#if !defined(lua_number2int)
-#define lua_number2int(i,n)    ((i)=(int)(n))
+/* float division */
+#if !defined(luai_numdiv)
+#define luai_numdiv(L,a,b)      ((a)/(b))
 #endif
 
-#if !defined(lua_number2integer)
-#define lua_number2integer(i,n)        ((i)=(lua_Integer)(n))
+/*
+** 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
 
-#if !defined(lua_number2unsigned)      /* { */
-/* the following definition assures proper modulo behavior */
-#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT)
-#include <math.h>
-#define SUPUNSIGNED    ((lua_Number)(~(lua_Unsigned)0) + 1)
-#define lua_number2unsigned(i,n)  \
-       ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED))
-#else
-#define lua_number2unsigned(i,n)       ((i)=(lua_Unsigned)(n))
+/* exponentiation */
+#if !defined(luai_numpow)
+#define luai_numpow(L,a,b)      ((void)L, l_mathop(pow)(a,b))
 #endif
-#endif                         /* } */
 
-
-#if !defined(lua_unsigned2number)
-/* on several machines, coercion from unsigned to double is slow,
-   so it may be worth to avoid */
-#define lua_unsigned2number(u)  \
-    (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
+/* 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
 
 
 
-#if defined(ltable_c) && !defined(luai_hashnum)
-
-#include <float.h>
-#include <math.h>
-
-#define luai_hashnum(i,n) { int e;  \
-  n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP);  \
-  lua_number2int(i, n); i += e; }
-
-#endif
-
 
 
 /*
 ** macro to control inclusion of some hard tests on stack reallocation
 */
 #if !defined(HARDSTACKTESTS)
-#define condmovestack(L)       ((void)0)
+#define condmovestack(L,pre,pos)       ((void)0)
 #else
 /* realloc stack keeping its size */
-#define condmovestack(L)       luaD_reallocstack((L), (L)->stacksize)
+#define condmovestack(L,pre,pos)  \
+       { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
 #endif
 
 #if !defined(HARDMEMTESTS)
-#define condchangemem(L)       condmovestack(L)
+#define condchangemem(L,pre,pos)       ((void)0)
 #else
-#define condchangemem(L)  \
-       ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
+#define condchangemem(L,pre,pos)  \
+       { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
 #endif
 
 #endif
index fe9fc54..94815f1 100644 (file)
@@ -1,16 +1,18 @@
 /*
-** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */
 
+#define lmathlib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <stdlib.h>
 #include <math.h>
 
-#define lmathlib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 
 
 #undef PI
-#define PI     ((lua_Number)(3.1415926535897932384626433832795))
-#define RADIANS_PER_DEGREE     ((lua_Number)(PI/180.0))
-
+#define PI     (l_mathop(3.141592653589793238462643383279502884))
+
+
+#if !defined(l_rand)           /* { */
+#if defined(LUA_USE_POSIX)
+#define l_rand()       random()
+#define l_srand(x)     srandom(x)
+#define L_RANDMAX      2147483647      /* (2^31 - 1), following POSIX */
+#else
+#define l_rand()       rand()
+#define l_srand(x)     srand(x)
+#define L_RANDMAX      RAND_MAX
+#endif
+#endif                         /* } */
 
 
 static int math_abs (lua_State *L) {
-  lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
+  if (lua_isinteger(L, 1)) {
+    lua_Integer n = lua_tointeger(L, 1);
+    if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
+    lua_pushinteger(L, n);
+  }
+  else
+    lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
   return 1;
 }
 
@@ -33,31 +52,16 @@ static int math_sin (lua_State *L) {
   return 1;
 }
 
-static int math_sinh (lua_State *L) {
-  lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
-  return 1;
-}
-
 static int math_cos (lua_State *L) {
   lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
   return 1;
 }
 
-static int math_cosh (lua_State *L) {
-  lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
-  return 1;
-}
-
 static int math_tan (lua_State *L) {
   lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
   return 1;
 }
 
-static int math_tanh (lua_State *L) {
-  lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
-  return 1;
-}
-
 static int math_asin (lua_State *L) {
   lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
   return 1;
@@ -69,49 +73,106 @@ static int math_acos (lua_State *L) {
 }
 
 static int math_atan (lua_State *L) {
-  lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1)));
+  lua_Number y = luaL_checknumber(L, 1);
+  lua_Number x = luaL_optnumber(L, 2, 1);
+  lua_pushnumber(L, l_mathop(atan2)(y, x));
   return 1;
 }
 
-static int math_atan2 (lua_State *L) {
-  lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1),
-                                luaL_checknumber(L, 2)));
+
+static int math_toint (lua_State *L) {
+  int valid;
+  lua_Integer n = lua_tointegerx(L, 1, &valid);
+  if (valid)
+    lua_pushinteger(L, n);
+  else {
+    luaL_checkany(L, 1);
+    lua_pushnil(L);  /* value is not convertible to integer */
+  }
   return 1;
 }
 
-static int math_ceil (lua_State *L) {
-  lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1)));
-  return 1;
+
+static void pushnumint (lua_State *L, lua_Number d) {
+  lua_Integer n;
+  if (lua_numbertointeger(d, &n))  /* does 'd' fit in an integer? */
+    lua_pushinteger(L, n);  /* result is integer */
+  else
+    lua_pushnumber(L, d);  /* result is float */
 }
 
+
 static int math_floor (lua_State *L) {
-  lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1)));
+  if (lua_isinteger(L, 1))
+    lua_settop(L, 1);  /* integer is its own floor */
+  else {
+    lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1));
+    pushnumint(L, d);
+  }
+  return 1;
+}
+
+
+static int math_ceil (lua_State *L) {
+  if (lua_isinteger(L, 1))
+    lua_settop(L, 1);  /* integer is its own ceil */
+  else {
+    lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1));
+    pushnumint(L, d);
+  }
   return 1;
 }
 
+
 static int math_fmod (lua_State *L) {
-  lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
-                               luaL_checknumber(L, 2)));
+  if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) {
+    lua_Integer d = lua_tointeger(L, 2);
+    if ((lua_Unsigned)d + 1u <= 1u) {  /* special cases: -1 or 0 */
+      luaL_argcheck(L, d != 0, 2, "zero");
+      lua_pushinteger(L, 0);  /* avoid overflow with 0x80000... / -1 */
+    }
+    else
+      lua_pushinteger(L, lua_tointeger(L, 1) % d);
+  }
+  else
+    lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1),
+                                     luaL_checknumber(L, 2)));
   return 1;
 }
 
+
+/*
+** next function does not use 'modf', avoiding problems with 'double*'
+** (which is not compatible with 'float*') when lua_Number is not
+** 'double'.
+*/
 static int math_modf (lua_State *L) {
-  lua_Number ip;
-  lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip);
-  lua_pushnumber(L, ip);
-  lua_pushnumber(L, fp);
+  if (lua_isinteger(L ,1)) {
+    lua_settop(L, 1);  /* number is its own integer part */
+    lua_pushnumber(L, 0);  /* no fractional part */
+  }
+  else {
+    lua_Number n = luaL_checknumber(L, 1);
+    /* integer part (rounds toward zero) */
+    lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n);
+    pushnumint(L, ip);
+    /* fractional part (test needed for inf/-inf) */
+    lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip));
+  }
   return 2;
 }
 
+
 static int math_sqrt (lua_State *L) {
   lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
   return 1;
 }
 
-static int math_pow (lua_State *L) {
-  lua_Number x = luaL_checknumber(L, 1);
-  lua_Number y = luaL_checknumber(L, 2);
-  lua_pushnumber(L, l_mathop(pow)(x, y));
+
+static int math_ult (lua_State *L) {
+  lua_Integer a = luaL_checkinteger(L, 1);
+  lua_Integer b = luaL_checkinteger(L, 2);
+  lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b);
   return 1;
 }
 
@@ -122,145 +183,208 @@ static int math_log (lua_State *L) {
     res = l_mathop(log)(x);
   else {
     lua_Number base = luaL_checknumber(L, 2);
-    if (base == (lua_Number)10.0) res = l_mathop(log10)(x);
+#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);
   }
   lua_pushnumber(L, res);
   return 1;
 }
 
-#if defined(LUA_COMPAT_LOG10)
-static int math_log10 (lua_State *L) {
-  lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
-  return 1;
-}
-#endif
-
 static int math_exp (lua_State *L) {
   lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
   return 1;
 }
 
 static int math_deg (lua_State *L) {
-  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);
+  lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
   return 1;
 }
 
 static int math_rad (lua_State *L) {
-  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);
-  return 1;
-}
-
-static int math_frexp (lua_State *L) {
-  int e;
-  lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
-  lua_pushinteger(L, e);
-  return 2;
-}
-
-static int math_ldexp (lua_State *L) {
-  lua_Number x = luaL_checknumber(L, 1);
-  int ep = luaL_checkint(L, 2);
-  lua_pushnumber(L, l_mathop(ldexp)(x, ep));
+  lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
   return 1;
 }
 
 
-
 static int math_min (lua_State *L) {
   int n = lua_gettop(L);  /* number of arguments */
-  lua_Number dmin = luaL_checknumber(L, 1);
+  int imin = 1;  /* index of current minimum value */
   int i;
-  for (i=2; i<=n; i++) {
-    lua_Number d = luaL_checknumber(L, i);
-    if (d < dmin)
-      dmin = d;
+  luaL_argcheck(L, n >= 1, 1, "value expected");
+  for (i = 2; i <= n; i++) {
+    if (lua_compare(L, i, imin, LUA_OPLT))
+      imin = i;
   }
-  lua_pushnumber(L, dmin);
+  lua_pushvalue(L, imin);
   return 1;
 }
 
 
 static int math_max (lua_State *L) {
   int n = lua_gettop(L);  /* number of arguments */
-  lua_Number dmax = luaL_checknumber(L, 1);
+  int imax = 1;  /* index of current maximum value */
   int i;
-  for (i=2; i<=n; i++) {
-    lua_Number d = luaL_checknumber(L, i);
-    if (d > dmax)
-      dmax = d;
+  luaL_argcheck(L, n >= 1, 1, "value expected");
+  for (i = 2; i <= n; i++) {
+    if (lua_compare(L, imax, i, LUA_OPLT))
+      imax = i;
   }
-  lua_pushnumber(L, dmax);
+  lua_pushvalue(L, imax);
   return 1;
 }
 
-
+/*
+** This function uses 'double' (instead of 'lua_Number') to ensure that
+** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0'
+** will keep full precision (ensuring that 'r' is always less than 1.0.)
+*/
 static int math_random (lua_State *L) {
-  /* the `%' avoids the (rare) case of r==1, and is needed also because on
-     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
-  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+  lua_Integer low, up;
+  double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0));
   switch (lua_gettop(L)) {  /* check number of arguments */
     case 0: {  /* no arguments */
-      lua_pushnumber(L, r);  /* Number between 0 and 1 */
-      break;
+      lua_pushnumber(L, (lua_Number)r);  /* Number between 0 and 1 */
+      return 1;
     }
     case 1: {  /* only upper limit */
-      lua_Number u = luaL_checknumber(L, 1);
-      luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty");
-      lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0));  /* [1, u] */
+      low = 1;
+      up = luaL_checkinteger(L, 1);
       break;
     }
     case 2: {  /* lower and upper limits */
-      lua_Number l = luaL_checknumber(L, 1);
-      lua_Number u = luaL_checknumber(L, 2);
-      luaL_argcheck(L, l <= u, 2, "interval is empty");
-      lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l);  /* [l, u] */
+      low = luaL_checkinteger(L, 1);
+      up = luaL_checkinteger(L, 2);
       break;
     }
     default: return luaL_error(L, "wrong number of arguments");
   }
+  /* random integer in the interval [low, up] */
+  luaL_argcheck(L, low <= up, 1, "interval is empty"); 
+  luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1,
+                   "interval too large");
+  r *= (double)(up - low) + 1.0;
+  lua_pushinteger(L, (lua_Integer)r + low);
   return 1;
 }
 
 
 static int math_randomseed (lua_State *L) {
-  srand(luaL_checkunsigned(L, 1));
-  (void)rand(); /* discard first value to avoid undesirable correlations */
+  l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
+  (void)l_rand(); /* discard first value to avoid undesirable correlations */
   return 0;
 }
 
 
+static int math_type (lua_State *L) {
+  if (lua_type(L, 1) == LUA_TNUMBER) {
+      if (lua_isinteger(L, 1))
+        lua_pushliteral(L, "integer"); 
+      else
+        lua_pushliteral(L, "float"); 
+  }
+  else {
+    luaL_checkany(L, 1);
+    lua_pushnil(L);
+  }
+  return 1;
+}
+
+
+/*
+** {==================================================================
+** Deprecated functions (for compatibility only)
+** ===================================================================
+*/
+#if defined(LUA_COMPAT_MATHLIB)
+
+static int math_cosh (lua_State *L) {
+  lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_sinh (lua_State *L) {
+  lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_tanh (lua_State *L) {
+  lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+static int math_pow (lua_State *L) {
+  lua_Number x = luaL_checknumber(L, 1);
+  lua_Number y = luaL_checknumber(L, 2);
+  lua_pushnumber(L, l_mathop(pow)(x, y));
+  return 1;
+}
+
+static int math_frexp (lua_State *L) {
+  int e;
+  lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e));
+  lua_pushinteger(L, e);
+  return 2;
+}
+
+static int math_ldexp (lua_State *L) {
+  lua_Number x = luaL_checknumber(L, 1);
+  int ep = (int)luaL_checkinteger(L, 2);
+  lua_pushnumber(L, l_mathop(ldexp)(x, ep));
+  return 1;
+}
+
+static int math_log10 (lua_State *L) {
+  lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1)));
+  return 1;
+}
+
+#endif
+/* }================================================================== */
+
+
+
 static const luaL_Reg mathlib[] = {
   {"abs",   math_abs},
   {"acos",  math_acos},
   {"asin",  math_asin},
-  {"atan2", math_atan2},
   {"atan",  math_atan},
   {"ceil",  math_ceil},
-  {"cosh",   math_cosh},
   {"cos",   math_cos},
   {"deg",   math_deg},
   {"exp",   math_exp},
+  {"tointeger", math_toint},
   {"floor", math_floor},
   {"fmod",   math_fmod},
-  {"frexp", math_frexp},
-  {"ldexp", math_ldexp},
-#if defined(LUA_COMPAT_LOG10)
-  {"log10", math_log10},
-#endif
+  {"ult",   math_ult},
   {"log",   math_log},
   {"max",   math_max},
   {"min",   math_min},
   {"modf",   math_modf},
-  {"pow",   math_pow},
   {"rad",   math_rad},
   {"random",     math_random},
   {"randomseed", math_randomseed},
-  {"sinh",   math_sinh},
   {"sin",   math_sin},
   {"sqrt",  math_sqrt},
-  {"tanh",   math_tanh},
   {"tan",   math_tan},
+  {"type", math_type},
+#if defined(LUA_COMPAT_MATHLIB)
+  {"atan2", math_atan},
+  {"cosh",   math_cosh},
+  {"sinh",   math_sinh},
+  {"tanh",   math_tanh},
+  {"pow",   math_pow},
+  {"frexp", math_frexp},
+  {"ldexp", math_ldexp},
+  {"log10", math_log10},
+#endif
+  /* placeholders */
+  {"pi", NULL},
+  {"huge", NULL},
+  {"maxinteger", NULL},
+  {"mininteger", NULL},
   {NULL, NULL}
 };
 
@@ -272,8 +396,12 @@ LUAMOD_API int luaopen_math (lua_State *L) {
   luaL_newlib(L, mathlib);
   lua_pushnumber(L, PI);
   lua_setfield(L, -2, "pi");
-  lua_pushnumber(L, HUGE_VAL);
+  lua_pushnumber(L, (lua_Number)HUGE_VAL);
   lua_setfield(L, -2, "huge");
+  lua_pushinteger(L, LUA_MAXINTEGER);
+  lua_setfield(L, -2, "maxinteger");
+  lua_pushinteger(L, LUA_MININTEGER);
+  lua_setfield(L, -2, "mininteger");
   return 1;
 }
 
index ee343e3..0a0476c 100644 (file)
@@ -1,15 +1,17 @@
 /*
-** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 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
 */
 
-
-#include <stddef.h>
-
 #define lmem_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <stddef.h>
+
 #include "lua.h"
 
 #include "ldebug.h"
 /*
 ** About the realloc function:
 ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
-** (`osize' is the old size, `nsize' is the new size)
+** ('osize' is the old size, 'nsize' is the new size)
 **
-** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no
+** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no
 ** matter 'x').
 **
-** * frealloc(ud, p, x, 0) frees the block `p'
+** * frealloc(ud, p, x, 0) frees the block 'p'
 ** (in this specific case, frealloc must return NULL);
 ** particularly, frealloc(ud, NULL, 0, 0) does nothing
-** (which is equivalent to free(NULL) in ANSI C)
+** (which is equivalent to free(NULL) in ISO C)
 **
 ** frealloc returns NULL if it cannot create or reallocate the area
 ** (any reallocation to an equal or smaller size cannot fail!)
@@ -83,9 +85,8 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
 #endif
   newblock = (*g->frealloc)(g->ud, block, osize, nsize);
   if (newblock == NULL && nsize > 0) {
-    api_check(L, nsize > realosize,
-                 "realloc cannot fail when shrinking a block");
-    if (g->gcrunning) {
+    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 */
     }
index bd4f4e0..30f4848 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lmem.h,v 1.43 2014/12/19 17:26:14 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */
 
 
 /*
-** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is
-** always constant.
-** The macro is somewhat complex to avoid warnings:
-** +1 avoids warnings of "comparison has constant result";
-** cast to 'void' avoids warnings of "value unused".
+** This macro reallocs a vector 'b' from 'on' to 'n' elements, where
+** each element has size 'e'. In case of arithmetic overflow of the
+** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because
+** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e).
+**
+** (The macro is somewhat complex to avoid warnings:  The 'sizeof'
+** comparison avoids a runtime comparison when overflow cannot occur.
+** The compiler should be able to optimize the real test by itself, but
+** when it does it, it may give a warning about "comparison is always
+** false due to limited range of data type"; the +1 tricks the compiler,
+** avoiding this warning but also this optimization.)
 */
 #define luaM_reallocv(L,b,on,n,e) \
-  (cast(void, \
-     (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \
+  (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \
+      ? luaM_toobig(L) : cast_void(0)) , \
    luaM_realloc_(L, (b), (on)*(e), (n)*(e)))
 
+/*
+** Arrays of chars do not need any test
+*/
+#define luaM_reallocvchar(L,b,on,n)  \
+    cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
+
 #define luaM_freemem(L, b, s)  luaM_realloc_(L, (b), (s), 0)
 #define luaM_free(L, b)                luaM_realloc_(L, (b), sizeof(*(b)), 0)
-#define luaM_freearray(L, b, n)   luaM_reallocv(L, (b), n, 0, sizeof((b)[0]))
+#define luaM_freearray(L, b, n)   luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0)
 
 #define luaM_malloc(L,s)       luaM_realloc_(L, NULL, 0, (s))
 #define luaM_new(L,t)          cast(t *, luaM_malloc(L, sizeof(t)))
index bedbea3..7911928 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $
 ** Dynamic library loader for Lua
 ** See Copyright Notice in lua.h
 **
@@ -8,22 +8,16 @@
 ** systems.
 */
 
+#define loadlib_c
+#define LUA_LIB
 
-/*
-** if needed, includes windows header before everything else
-*/
-#if defined(_WIN32)
-#include <windows.h>
-#endif
+#include "lprefix.h"
 
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-
-#define loadlib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 
 
 /*
-** LUA_PATH and LUA_CPATH are the names of the environment
+** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment
 ** variables that Lua check to set its paths.
 */
-#if !defined(LUA_PATH)
-#define LUA_PATH       "LUA_PATH"
+#if !defined(LUA_PATH_VAR)
+#define LUA_PATH_VAR   "LUA_PATH"
 #endif
 
-#if !defined(LUA_CPATH)
-#define LUA_CPATH      "LUA_CPATH"
+#if !defined(LUA_CPATH_VAR)
+#define LUA_CPATH_VAR  "LUA_CPATH"
 #endif
 
 #define LUA_PATHSUFFIX         "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
 
-#define LUA_PATHVERSION                LUA_PATH LUA_PATHSUFFIX
-#define LUA_CPATHVERSION       LUA_CPATH LUA_PATHSUFFIX
+#define LUA_PATHVARVERSION             LUA_PATH_VAR LUA_PATHSUFFIX
+#define LUA_CPATHVARVERSION            LUA_CPATH_VAR LUA_PATHSUFFIX
 
 /*
 ** LUA_PATH_SEP is the character that separates templates in a path.
 #define LUA_OFSEP      "_"
 
 
-/* table (in the registry) that keeps handles for all loaded C libraries */
-#define CLIBS          "_CLIBS"
+/*
+** unique key for table in the registry that keeps handles
+** for all loaded C libraries
+*/
+static const int CLIBS = 0;
 
 #define LIB_FAIL       "open"
 
-
-/* error codes for ll_loadfunc */
-#define ERRLIB         1
-#define ERRFUNC                2
-
 #define setprogdir(L)          ((void)0)
 
 
 /*
 ** system-dependent functions
 */
-static void ll_unloadlib (void *lib);
-static void *ll_load (lua_State *L, const char *path, int seeglb);
-static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
 
+/*
+** unload library 'lib'
+*/
+static void lsys_unloadlib (void *lib);
+
+/*
+** load C library in file 'path'. If 'seeglb', load with all names in
+** the library global.
+** Returns the library; in case of error, returns NULL plus an
+** error string in the stack.
+*/
+static void *lsys_load (lua_State *L, const char *path, int seeglb);
+
+/*
+** Try to find a function named 'sym' in library 'lib'.
+** Returns the function; in case of error, returns NULL plus an
+** error string in the stack.
+*/
+static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym);
 
 
-#if defined(LUA_USE_DLOPEN)
+
+
+#if defined(LUA_USE_DLOPEN)    /* { */
 /*
 ** {========================================================================
 ** This is an implementation of loadlib based on the dlfcn interface.
@@ -126,20 +136,32 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);
 
 #include <dlfcn.h>
 
-static void ll_unloadlib (void *lib) {
+/*
+** 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__)
+#define cast_func(p) (__extension__ (lua_CFunction)(p))
+#else
+#define cast_func(p) ((lua_CFunction)(p))
+#endif
+
+
+static void lsys_unloadlib (void *lib) {
   dlclose(lib);
 }
 
 
-static void *ll_load (lua_State *L, const char *path, int seeglb) {
+static void *lsys_load (lua_State *L, const char *path, int seeglb) {
   void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
   if (lib == NULL) lua_pushstring(L, dlerror());
   return lib;
 }
 
 
-static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
-  lua_CFunction f = (lua_CFunction)dlsym(lib, sym);
+static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
+  lua_CFunction f = cast_func(dlsym(lib, sym));
   if (f == NULL) lua_pushstring(L, dlerror());
   return f;
 }
@@ -148,13 +170,15 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
 
 
 
-#elif defined(LUA_DL_DLL)
+#elif defined(LUA_DL_DLL)      /* }{ */
 /*
 ** {======================================================================
 ** This is an implementation of loadlib for Windows using native functions.
 ** =======================================================================
 */
 
+#include <windows.h>
+
 #undef setprogdir
 
 /*
@@ -190,12 +214,12 @@ static void pusherror (lua_State *L) {
     lua_pushfstring(L, "system error %d\n", error);
 }
 
-static void ll_unloadlib (void *lib) {
+static void lsys_unloadlib (void *lib) {
   FreeLibrary((HMODULE)lib);
 }
 
 
-static void *ll_load (lua_State *L, const char *path, int seeglb) {
+static void *lsys_load (lua_State *L, const char *path, int seeglb) {
   HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS);
   (void)(seeglb);  /* not used: symbols are 'global' by default */
   if (lib == NULL) pusherror(L);
@@ -203,7 +227,7 @@ static void *ll_load (lua_State *L, const char *path, int seeglb) {
 }
 
 
-static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
   lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym);
   if (f == NULL) pusherror(L);
   return f;
@@ -212,7 +236,7 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
 /* }====================================================== */
 
 
-#else
+#else                          /* }{ */
 /*
 ** {======================================================
 ** Fallback for other systems
@@ -226,31 +250,34 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
 #define DLMSG  "dynamic libraries not enabled; check your Lua installation"
 
 
-static void ll_unloadlib (void *lib) {
+static void lsys_unloadlib (void *lib) {
   (void)(lib);  /* not used */
 }
 
 
-static void *ll_load (lua_State *L, const char *path, int seeglb) {
+static void *lsys_load (lua_State *L, const char *path, int seeglb) {
   (void)(path); (void)(seeglb);  /* not used */
   lua_pushliteral(L, DLMSG);
   return NULL;
 }
 
 
-static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
+static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
   (void)(lib); (void)(sym);  /* not used */
   lua_pushliteral(L, DLMSG);
   return NULL;
 }
 
 /* }====================================================== */
-#endif
+#endif                         /* } */
 
 
-static void *ll_checkclib (lua_State *L, const char *path) {
+/*
+** return registry.CLIBS[path]
+*/
+static void *checkclib (lua_State *L, const char *path) {
   void *plib;
-  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+  lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
   lua_getfield(L, -1, path);
   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
@@ -258,8 +285,12 @@ static void *ll_checkclib (lua_State *L, const char *path) {
 }
 
 
-static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
-  lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+/*
+** registry.CLIBS[path] = plib        -- for queries
+** registry.CLIBS[#CLIBS + 1] = plib  -- also keep a list of all libraries
+*/
+static void addtoclib (lua_State *L, const char *path, void *plib) {
+  lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
   lua_pushlightuserdata(L, plib);
   lua_pushvalue(L, -1);
   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
@@ -269,33 +300,49 @@ static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
 
 
 /*
-** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
+** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
 ** handles in list CLIBS
 */
 static int gctm (lua_State *L) {
-  int n = luaL_len(L, 1);
+  lua_Integer n = luaL_len(L, 1);
   for (; n >= 1; n--) {  /* for each handle, in reverse order */
     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
-    ll_unloadlib(lua_touserdata(L, -1));
+    lsys_unloadlib(lua_touserdata(L, -1));
     lua_pop(L, 1);  /* pop handle */
   }
   return 0;
 }
 
 
-static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
-  void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
+
+/* error codes for 'lookforfunc' */
+#define ERRLIB         1
+#define ERRFUNC                2
+
+/*
+** Look for a C function named 'sym' in a dynamically loaded library
+** 'path'.
+** First, check whether the library is already loaded; if not, try
+** to load it.
+** Then, if 'sym' is '*', return true (as library has been loaded).
+** Otherwise, look for symbol 'sym' in the library and push a
+** C function with that symbol.
+** Return 0 and 'true' or a function in the stack; in case of
+** errors, return an error code and an error message in the stack.
+*/
+static int lookforfunc (lua_State *L, const char *path, const char *sym) {
+  void *reg = checkclib(L, path);  /* check loaded C libraries */
   if (reg == NULL) {  /* must load library? */
-    reg = ll_load(L, path, *sym == '*');
+    reg = lsys_load(L, path, *sym == '*');  /* global symbols if 'sym'=='*' */
     if (reg == NULL) return ERRLIB;  /* unable to load library */
-    ll_addtoclib(L, path, reg);
+    addtoclib(L, path, reg);
   }
   if (*sym == '*') {  /* loading only library (no function)? */
     lua_pushboolean(L, 1);  /* return 'true' */
     return 0;  /* no errors */
   }
   else {
-    lua_CFunction f = ll_sym(L, reg, sym);
+    lua_CFunction f = lsys_sym(L, reg, sym);
     if (f == NULL)
       return ERRFUNC;  /* unable to find function */
     lua_pushcfunction(L, f);  /* else create new function */
@@ -307,7 +354,7 @@ static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
 static int ll_loadlib (lua_State *L) {
   const char *path = luaL_checkstring(L, 1);
   const char *init = luaL_checkstring(L, 2);
-  int stat = ll_loadfunc(L, path, init);
+  int stat = lookforfunc(L, path, init);
   if (stat == 0)  /* no errors? */
     return 1;  /* return the loaded function */
   else {  /* error; error message is on stack top */
@@ -360,7 +407,7 @@ static const char *searchpath (lua_State *L, const char *name,
     lua_remove(L, -2);  /* remove path template */
     if (readable(filename))  /* does file exist and is readable? */
       return filename;  /* return that file name */
-    lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
+    lua_pushfstring(L, "\n\tno file '%s'", filename);
     lua_remove(L, -2);  /* remove file name */
     luaL_addvalue(&msg);  /* concatenate error msg. entry */
   }
@@ -390,7 +437,7 @@ static const char *findfile (lua_State *L, const char *name,
   lua_getfield(L, lua_upvalueindex(1), pname);
   path = lua_tostring(L, -1);
   if (path == NULL)
-    luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
+    luaL_error(L, "'package.%s' must be a string", pname);
   return searchpath(L, name, path, ".", dirsep);
 }
 
@@ -401,8 +448,7 @@ static int checkload (lua_State *L, int stat, const char *filename) {
     return 2;  /* return open function and file name */
   }
   else
-    return luaL_error(L, "error loading module " LUA_QS
-                         " from file " LUA_QS ":\n\t%s",
+    return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s",
                           lua_tostring(L, 1), filename, lua_tostring(L, -1));
 }
 
@@ -416,21 +462,29 @@ static int searcher_Lua (lua_State *L) {
 }
 
 
+/*
+** Try to find a load function for module 'modname' at file 'filename'.
+** First, change '.' to '_' in 'modname'; then, if 'modname' has
+** the form X-Y (that is, it has an "ignore mark"), build a function
+** name "luaopen_X" and look for it. (For compatibility, if that
+** fails, it also tries "luaopen_Y".) If there is no ignore mark,
+** look for a function named "luaopen_modname".
+*/
 static int loadfunc (lua_State *L, const char *filename, const char *modname) {
-  const char *funcname;
+  const char *openfunc;
   const char *mark;
   modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
   mark = strchr(modname, *LUA_IGMARK);
   if (mark) {
     int stat;
-    funcname = lua_pushlstring(L, modname, mark - modname);
-    funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
-    stat = ll_loadfunc(L, filename, funcname);
+    openfunc = lua_pushlstring(L, modname, mark - modname);
+    openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc);
+    stat = lookforfunc(L, filename, openfunc);
     if (stat != ERRFUNC) return stat;
     modname = mark + 1;  /* else go ahead and try old-style name */
   }
-  funcname = lua_pushfstring(L, LUA_POF"%s", modname);
-  return ll_loadfunc(L, filename, funcname);
+  openfunc = lua_pushfstring(L, LUA_POF"%s", modname);
+  return lookforfunc(L, filename, openfunc);
 }
 
 
@@ -455,8 +509,7 @@ static int searcher_Croot (lua_State *L) {
     if (stat != ERRFUNC)
       return checkload(L, 0, filename);  /* real error */
     else {  /* open function not found */
-      lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS,
-                         name, filename);
+      lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename);
       return 1;
     }
   }
@@ -468,8 +521,7 @@ static int searcher_Croot (lua_State *L) {
 static int searcher_preload (lua_State *L) {
   const char *name = luaL_checkstring(L, 1);
   lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
-  lua_getfield(L, -1, name);
-  if (lua_isnil(L, -1))  /* not found? */
+  if (lua_getfield(L, -1, name) == LUA_TNIL)  /* not found? */
     lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
   return 1;
 }
@@ -479,17 +531,15 @@ static void findloader (lua_State *L, const char *name) {
   int i;
   luaL_Buffer msg;  /* to build error message */
   luaL_buffinit(L, &msg);
-  lua_getfield(L, lua_upvalueindex(1), "searchers");  /* will be at index 3 */
-  if (!lua_istable(L, 3))
-    luaL_error(L, LUA_QL("package.searchers") " must be a table");
+  /* push 'package.searchers' to index 3 in the stack */
+  if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE)
+    luaL_error(L, "'package.searchers' must be a table");
   /*  iterate over available searchers to find a loader */
   for (i = 1; ; i++) {
-    lua_rawgeti(L, 3, i);  /* get a searcher */
-    if (lua_isnil(L, -1)) {  /* no more searchers? */
+    if (lua_rawgeti(L, 3, i) == LUA_TNIL) {  /* no more searchers? */
       lua_pop(L, 1);  /* remove nil */
       luaL_pushresult(&msg);  /* create error message */
-      luaL_error(L, "module " LUA_QS " not found:%s",
-                    name, lua_tostring(L, -1));
+      luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1));
     }
     lua_pushstring(L, name);
     lua_call(L, 1, 2);  /* call it */
@@ -520,8 +570,7 @@ static int ll_require (lua_State *L) {
   lua_call(L, 2, 1);  /* run loader to load module */
   if (!lua_isnil(L, -1))  /* non-nil return? */
     lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */
-  lua_getfield(L, 2, name);
-  if (lua_isnil(L, -1)) {   /* module did not set a value? */
+  if (lua_getfield(L, 2, name) == LUA_TNIL) {   /* module set no value? */
     lua_pushboolean(L, 1);  /* use true as result */
     lua_pushvalue(L, -1);  /* extra copy to be returned */
     lua_setfield(L, 2, name);  /* _LOADED[name] = true */
@@ -548,7 +597,7 @@ static void set_env (lua_State *L) {
   if (lua_getstack(L, 1, &ar) == 0 ||
       lua_getinfo(L, "f", &ar) == 0 ||  /* get calling function */
       lua_iscfunction(L, -1))
-    luaL_error(L, LUA_QL("module") " not called from a Lua function");
+    luaL_error(L, "'module' not called from a Lua function");
   lua_pushvalue(L, -2);  /* copy new environment table to top */
   lua_setupvalue(L, -2, 1);
   lua_pop(L, 1);  /* remove function */
@@ -587,9 +636,8 @@ static int ll_module (lua_State *L) {
   int lastarg = lua_gettop(L);  /* last parameter */
   luaL_pushmodule(L, modname, 1);  /* get/create module table */
   /* check whether table already has a _NAME field */
-  lua_getfield(L, -1, "_NAME");
-  if (!lua_isnil(L, -1))  /* is table an initialized module? */
-    lua_pop(L, 1);
+  if (lua_getfield(L, -1, "_NAME") != LUA_TNIL)
+    lua_pop(L, 1);  /* table is an initialized module */
   else {  /* no; initialize it */
     lua_pop(L, 1);
     modinit(L, modname);
@@ -659,6 +707,12 @@ static const luaL_Reg pk_funcs[] = {
 #if defined(LUA_COMPAT_MODULE)
   {"seeall", ll_seeall},
 #endif
+  /* placeholders */
+  {"preload", NULL},
+  {"cpath", NULL},
+  {"path", NULL},
+  {"searchers", NULL},
+  {"loaded", NULL},
   {NULL, NULL}
 };
 
@@ -678,42 +732,50 @@ static void createsearcherstable (lua_State *L) {
   int i;
   /* create 'searchers' table */
   lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
-  /* fill it with pre-defined searchers */
+  /* fill it with predefined searchers */
   for (i=0; searchers[i] != NULL; i++) {
     lua_pushvalue(L, -2);  /* set 'package' as upvalue for all searchers */
     lua_pushcclosure(L, searchers[i], 1);
     lua_rawseti(L, -2, i+1);
   }
+#if defined(LUA_COMPAT_LOADERS)
+  lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
+  lua_setfield(L, -3, "loaders");  /* put it in field 'loaders' */
+#endif
+  lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
 }
 
 
-LUAMOD_API int luaopen_package (lua_State *L) {
-  /* create table CLIBS to keep track of loaded C libraries */
-  luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
-  lua_createtable(L, 0, 1);  /* metatable for CLIBS */
+/*
+** create table CLIBS to keep track of loaded C libraries,
+** setting a finalizer to close all libraries when closing state.
+*/
+static void createclibstable (lua_State *L) {
+  lua_newtable(L);  /* create CLIBS table */
+  lua_createtable(L, 0, 1);  /* create metatable for CLIBS */
   lua_pushcfunction(L, gctm);
   lua_setfield(L, -2, "__gc");  /* set finalizer for CLIBS table */
   lua_setmetatable(L, -2);
-  /* create `package' table */
-  luaL_newlib(L, pk_funcs);
+  lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS);  /* set CLIBS table in registry */
+}
+
+
+LUAMOD_API int luaopen_package (lua_State *L) {
+  createclibstable(L);
+  luaL_newlib(L, pk_funcs);  /* create 'package' table */
   createsearcherstable(L);
-#if defined(LUA_COMPAT_LOADERS)
-  lua_pushvalue(L, -1);  /* make a copy of 'searchers' table */
-  lua_setfield(L, -3, "loaders");  /* put it in field `loaders' */
-#endif
-  lua_setfield(L, -2, "searchers");  /* put it in field 'searchers' */
   /* set field 'path' */
-  setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT);
+  setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT);
   /* set field 'cpath' */
-  setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT);
+  setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
   /* store config information */
   lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n"
                      LUA_EXEC_DIR "\n" LUA_IGMARK "\n");
   lua_setfield(L, -2, "config");
-  /* set field `loaded' */
+  /* set field 'loaded' */
   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
   lua_setfield(L, -2, "loaded");
-  /* set field `preload' */
+  /* set field 'preload' */
   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
   lua_setfield(L, -2, "preload");
   lua_pushglobaltable(L);
index 882d994..a44b385 100644 (file)
@@ -1,17 +1,22 @@
 /*
-** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lobject.c,v 2.111 2016/05/20 14:07:48 roberto Exp $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
 
+#define lobject_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
+
+#include <locale.h>
+#include <math.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define lobject_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lctype.h"
@@ -36,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);
@@ -46,14 +55,15 @@ int luaO_int2fb (unsigned int x) {
 
 /* converts back */
 int luaO_fb2int (int x) {
-  int e = (x >> 3) & 0x1f;
-  if (e == 0) return x;
-  else return ((x & 7) + 8) << (e - 1);
+  return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1);
 }
 
 
+/*
+** 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,
@@ -70,29 +80,90 @@ int luaO_ceillog2 (unsigned int x) {
 }
 
 
-lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
+static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
+                                                   lua_Integer v2) {
   switch (op) {
-    case LUA_OPADD: return luai_numadd(NULL, v1, v2);
-    case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
-    case LUA_OPMUL: return luai_nummul(NULL, v1, v2);
-    case LUA_OPDIV: return luai_numdiv(NULL, v1, v2);
-    case LUA_OPMOD: return luai_nummod(NULL, v1, v2);
-    case LUA_OPPOW: return luai_numpow(NULL, v1, v2);
-    case LUA_OPUNM: return luai_numunm(NULL, v1);
+    case LUA_OPADD: return intop(+, v1, v2);
+    case LUA_OPSUB:return intop(-, v1, v2);
+    case LUA_OPMUL:return intop(*, v1, v2);
+    case LUA_OPMOD: return luaV_mod(L, v1, v2);
+    case LUA_OPIDIV: return luaV_div(L, v1, v2);
+    case LUA_OPBAND: return intop(&, v1, v2);
+    case LUA_OPBOR: return intop(|, v1, v2);
+    case LUA_OPBXOR: return intop(^, v1, v2);
+    case LUA_OPSHL: return luaV_shiftl(v1, v2);
+    case LUA_OPSHR: return luaV_shiftl(v1, -v2);
+    case LUA_OPUNM: return intop(-, 0, v1);
+    case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
     default: lua_assert(0); return 0;
   }
 }
 
 
-int luaO_hexavalue (int c) {
-  if (lisdigit(c)) return c - '0';
-  else return ltolower(c) - 'a' + 10;
+static lua_Number numarith (lua_State *L, int op, lua_Number v1,
+                                                  lua_Number v2) {
+  switch (op) {
+    case LUA_OPADD: return luai_numadd(L, v1, v2);
+    case LUA_OPSUB: return luai_numsub(L, v1, v2);
+    case LUA_OPMUL: return luai_nummul(L, v1, v2);
+    case LUA_OPDIV: return luai_numdiv(L, v1, v2);
+    case LUA_OPPOW: return luai_numpow(L, v1, v2);
+    case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
+    case LUA_OPUNM: return luai_numunm(L, v1);
+    case LUA_OPMOD: {
+      lua_Number m;
+      luai_nummod(L, v1, v2, m);
+      return m;
+    }
+    default: lua_assert(0); return 0;
+  }
 }
 
 
-#if !defined(lua_strx2number)
+void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
+                 TValue *res) {
+  switch (op) {
+    case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
+    case LUA_OPSHL: case LUA_OPSHR:
+    case LUA_OPBNOT: {  /* operate only on integers */
+      lua_Integer i1; lua_Integer i2;
+      if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
+        setivalue(res, intarith(L, op, i1, i2));
+        return;
+      }
+      else break;  /* go to the end */
+    }
+    case LUA_OPDIV: case LUA_OPPOW: {  /* operate only on floats */
+      lua_Number n1; lua_Number n2;
+      if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+        setfltvalue(res, numarith(L, op, n1, n2));
+        return;
+      }
+      else break;  /* go to the end */
+    }
+    default: {  /* other operations */
+      lua_Number n1; lua_Number n2;
+      if (ttisinteger(p1) && ttisinteger(p2)) {
+        setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
+        return;
+      }
+      else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+        setfltvalue(res, numarith(L, op, n1, n2));
+        return;
+      }
+      else break;  /* go to the end */
+    }
+  }
+  /* 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));
+}
 
-#include <math.h>
+
+int luaO_hexavalue (int c) {
+  if (lisdigit(c)) return c - '0';
+  else return (ltolower(c) - 'a') + 10;
+}
 
 
 static int isneg (const char **s) {
@@ -102,122 +173,285 @@ static int isneg (const char **s) {
 }
 
 
-static lua_Number readhexa (const char **s, lua_Number r, int *count) {
-  for (; lisxdigit(cast_uchar(**s)); (*s)++) {  /* read integer part */
-    r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
-    (*count)++;
-  }
-  return r;
-}
 
+/*
+** {==================================================================
+** Lua's implementation for 'lua_strx2number'
+** ===================================================================
+*/
+
+#if !defined(lua_strx2number)
+
+/* maximum number of significant digits to read (to avoid overflows
+   even with single floats) */
+#define MAXSIGDIG      30
 
 /*
 ** convert an hexadecimal numeric string to a number, following
 ** C99 specification for 'strtod'
 */
 static lua_Number lua_strx2number (const char *s, char **endptr) {
-  lua_Number r = 0.0;
-  int e = 0, i = 0;
-  int neg = 0;  /* 1 if number is negative */
+  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 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') */
-  s += 2;  /* skip '0x' */
-  r = readhexa(&s, r, &i);  /* read integer part */
-  if (*s == '.') {
-    s++;  /* skip dot */
-    r = readhexa(&s, r, &e);  /* read fractional part */
+  for (s += 2; ; s++) {  /* skip '0x' and read numeral */
+    if (*s == 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)? */
+        nosigdig++;
+      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 (hasdot) e--;  /* decimal digit? correct exponent */
+    }
+    else break;  /* neither a dot nor a digit */
   }
-  if (i == 0 && e == 0)
-    return 0.0;  /* invalid format (no digit) */
-  e *= -4;  /* each fractional digit divides value by 2^-4 */
+  if (nosigdig + sigdig == 0)  /* no digits? */
+    return 0.0;  /* invalid format */
   *endptr = cast(char *, s);  /* valid up to here */
+  e *= 4;  /* each digit multiplies/divides value by 2^4 */
   if (*s == 'p' || *s == 'P') {  /* exponent part? */
-    int exp1 = 0;
-    int neg1;
+    int exp1 = 0;  /* exponent value */
+    int neg1;  /* exponent signal */
     s++;  /* skip 'p' */
     neg1 = isneg(&s);  /* signal */
     if (!lisdigit(cast_uchar(*s)))
-      goto ret;  /* must have at least one digit */
+      return 0.0;  /* invalid; must have at least one digit */
     while (lisdigit(cast_uchar(*s)))  /* read exponent */
       exp1 = exp1 * 10 + *(s++) - '0';
     if (neg1) exp1 = -exp1;
     e += exp1;
+    *endptr = cast(char *, s);  /* valid up to here */
   }
-  *endptr = cast(char *, s);  /* valid up to here */
- ret:
   if (neg) r = -r;
   return l_mathop(ldexp)(r, e);
 }
 
 #endif
+/* }====================================================== */
+
 
+/* maximum length of a numeral */
+#if !defined (L_MAXLENNUM)
+#define L_MAXLENNUM    200
+#endif
 
-int luaO_str2d (const char *s, size_t len, lua_Number *result) {
+static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
   char *endptr;
-  if (strpbrk(s, "nN"))  /* reject 'inf' and 'nan' */
-    return 0;
-  else if (strpbrk(s, "xX"))  /* hexa? */
-    *result = lua_strx2number(s, &endptr);
+  *result = (mode == 'x') ? lua_strx2number(s, &endptr)  /* try to convert */
+                          : lua_str2number(s, &endptr);
+  if (endptr == s) return NULL;  /* nothing recognized? */
+  while (lisspace(cast_uchar(*endptr))) endptr++;  /* skip trailing spaces */
+  return (*endptr == '\0') ? endptr : NULL;  /* OK if no trailing characters */
+}
+
+
+/*
+** Convert string 's' to a Lua number (put in 'result'). Return NULL
+** on fail or the address of the ending '\0' on success.
+** 'pmode' points to (and 'mode' contains) special things in the string:
+** - 'x'/'X' means an hexadecimal numeral
+** - 'n'/'N' means 'inf' or 'nan' (which should be rejected)
+** - '.' just optimizes the search for the common case (nothing special)
+** This function accepts both the current locale or a dot as the radix
+** mark. If the convertion fails, it may mean number has a dot but
+** locale accepts something else. In that case, the code copies 's'
+** to a buffer (because 's' is read-only), changes the dot to the
+** current locale radix mark, and tries to convert again.
+*/
+static const char *l_str2d (const char *s, lua_Number *result) {
+  const char *endptr;
+  const char *pmode = strpbrk(s, ".xXnN");
+  int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
+  if (mode == 'n')  /* reject 'inf' and 'nan' */
+    return NULL;
+  endptr = l_str2dloc(s, result, mode);  /* try to convert */
+  if (endptr == NULL) {  /* failed? may be a different locale */
+    char buff[L_MAXLENNUM + 1];
+    char *pdot = strchr(s, '.');
+    if (strlen(s) > L_MAXLENNUM || pdot == NULL)
+      return NULL;  /* string too long or no dot; fail */
+    strcpy(buff, s);  /* copy string to buffer */
+    buff[pdot - s] = lua_getlocaledecpoint();  /* correct decimal point */
+    endptr = l_str2dloc(buff, result, mode);  /* try again */
+    if (endptr != NULL)
+      endptr = s + (endptr - buff);  /* make relative to 's' */
+  }
+  return endptr;
+}
+
+
+#define MAXBY10                cast(lua_Unsigned, LUA_MAXINTEGER / 10)
+#define MAXLASTD       cast_int(LUA_MAXINTEGER % 10)
+
+static const char *l_str2int (const char *s, lua_Integer *result) {
+  lua_Unsigned a = 0;
+  int empty = 1;
+  int neg;
+  while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
+  neg = isneg(&s);
+  if (s[0] == '0' &&
+      (s[1] == 'x' || s[1] == 'X')) {  /* hex? */
+    s += 2;  /* skip '0x' */
+    for (; lisxdigit(cast_uchar(*s)); s++) {
+      a = a * 16 + luaO_hexavalue(*s);
+      empty = 0;
+    }
+  }
+  else {  /* decimal */
+    for (; lisdigit(cast_uchar(*s)); s++) {
+      int d = *s - '0';
+      if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg))  /* overflow? */
+        return NULL;  /* do not accept it (as integer) */
+      a = a * 10 + d;
+      empty = 0;
+    }
+  }
+  while (lisspace(cast_uchar(*s))) s++;  /* skip trailing spaces */
+  if (empty || *s != '\0') return NULL;  /* something wrong in the numeral */
+  else {
+    *result = l_castU2S((neg) ? 0u - a : a);
+    return s;
+  }
+}
+
+
+size_t luaO_str2num (const char *s, TValue *o) {
+  lua_Integer i; lua_Number n;
+  const char *e;
+  if ((e = l_str2int(s, &i)) != NULL) {  /* try as an integer */
+    setivalue(o, i);
+  }
+  else if ((e = l_str2d(s, &n)) != NULL) {  /* else try as a float */
+    setfltvalue(o, n);
+  }
   else
-    *result = lua_str2number(s, &endptr);
-  if (endptr == s) return 0;  /* nothing recognized */
-  while (lisspace(cast_uchar(*endptr))) endptr++;
-  return (endptr == s + len);  /* OK if no trailing characters */
+    return 0;  /* conversion failed */
+  return (e - s) + 1;  /* success; return string size */
+}
+
+
+int luaO_utf8esc (char *buff, unsigned long x) {
+  int n = 1;  /* number of bytes put in buffer (backwards) */
+  lua_assert(x <= 0x10FFFF);
+  if (x < 0x80)  /* ascii? */
+    buff[UTF8BUFFSZ - 1] = cast(char, x);
+  else {  /* need continuation bytes */
+    unsigned int mfb = 0x3f;  /* maximum that fits in first byte */
+    do {  /* add continuation bytes */
+      buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f));
+      x >>= 6;  /* remove added bits */
+      mfb >>= 1;  /* now there is one less bit available in first byte */
+    } while (x > mfb);  /* still needs continuation byte? */
+    buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x);  /* add first byte */
+  }
+  return n;
 }
 
 
+/* maximum length of the conversion of a number to a string */
+#define MAXNUMBER2STR  50
+
+
+/*
+** Convert a number object to a string
+*/
+void luaO_tostring (lua_State *L, StkId obj) {
+  char buff[MAXNUMBER2STR];
+  size_t len;
+  lua_assert(ttisnumber(obj));
+  if (ttisinteger(obj))
+    len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
+  else {
+    len = lua_number2str(buff, sizeof(buff), fltvalue(obj));
+#if !defined(LUA_COMPAT_FLOATSTRING)
+    if (buff[strspn(buff, "-0123456789")] == '\0') {  /* looks like an int? */
+      buff[len++] = lua_getlocaledecpoint();
+      buff[len++] = '0';  /* adds '.0' to result */
+    }
+#endif
+  }
+  setsvalue2s(L, obj, luaS_newlstr(L, buff, len));
+}
+
 
 static void pushstr (lua_State *L, const char *str, size_t l) {
-  setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
+  setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
+  luaD_inctop(L);
 }
 
 
-/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
+/*
+** this function handles only '%d', '%c', '%f', '%p', and '%s' 
+   conventional formats, plus Lua-specific '%I' and '%U'
+*/
 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
   int n = 0;
   for (;;) {
     const char *e = strchr(fmt, '%');
     if (e == NULL) break;
-    luaD_checkstack(L, 2);  /* fmt + item */
     pushstr(L, fmt, e - fmt);
     switch (*(e+1)) {
-      case 's': {
+      case 's': {  /* zero-terminated string */
         const char *s = va_arg(argp, char *);
         if (s == NULL) s = "(null)";
         pushstr(L, s, strlen(s));
         break;
       }
-      case 'c': {
-        char buff;
-        buff = cast(char, va_arg(argp, int));
-        pushstr(L, &buff, 1);
+      case 'c': {  /* an 'int' as a character */
+        char buff = cast(char, va_arg(argp, int));
+        if (lisprint(cast_uchar(buff)))
+          pushstr(L, &buff, 1);
+        else  /* non-printable character; print its code */
+          luaO_pushfstring(L, "<\\%d>", cast_uchar(buff));
         break;
       }
-      case 'd': {
-        setnvalue(L->top++, cast_num(va_arg(argp, int)));
-        break;
+      case 'd': {  /* an 'int' */
+        setivalue(L->top, va_arg(argp, int));
+        goto top2str;
+      }
+      case 'I': {  /* a 'lua_Integer' */
+        setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
+        goto top2str;
       }
-      case 'f': {
-        setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
+      case 'f': {  /* a 'lua_Number' */
+        setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
+      top2str:  /* convert the top element to a string */
+        luaD_inctop(L);
+        luaO_tostring(L, L->top - 1);
         break;
       }
-      case 'p': {
-        char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
-        int l = sprintf(buff, "%p", va_arg(argp, void *));
+      case 'p': {  /* a pointer */
+        char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
+        int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
         pushstr(L, buff, l);
         break;
       }
+      case 'U': {  /* an 'int' as a UTF-8 sequence */
+        char buff[UTF8BUFFSZ];
+        int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long)));
+        pushstr(L, buff + UTF8BUFFSZ - l, l);
+        break;
+      }
       case '%': {
         pushstr(L, "%", 1);
         break;
       }
       default: {
-        luaG_runerror(L,
-            "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
-            *(e + 1));
+        luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
+                         *(e + 1));
       }
     }
     n += 2;
index bc0bb69..2d52b41 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.71.1.2 2014/05/07 14:14:58 roberto Exp $
+** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
 /*
 ** Extra tags for non-values
 */
-#define LUA_TPROTO     LUA_NUMTAGS
-#define LUA_TUPVAL     (LUA_NUMTAGS+1)
-#define LUA_TDEADKEY   (LUA_NUMTAGS+2)
+#define LUA_TPROTO     LUA_NUMTAGS             /* function prototypes */
+#define LUA_TDEADKEY   (LUA_NUMTAGS+1)         /* removed keys in tables */
 
 /*
 ** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
 */
-#define LUA_TOTALTAGS  (LUA_TUPVAL+2)
+#define LUA_TOTALTAGS  (LUA_TPROTO + 2)
 
 
 /*
@@ -36,8 +35,6 @@
 ** bit 6: whether value is collectable
 */
 
-#define VARBITS                (3 << 4)
-
 
 /*
 ** LUA_TFUNCTION variants:
 #define LUA_TLNGSTR    (LUA_TSTRING | (1 << 4))  /* long strings */
 
 
+/* Variant tags for numbers */
+#define LUA_TNUMFLT    (LUA_TNUMBER | (0 << 4))  /* float numbers */
+#define LUA_TNUMINT    (LUA_TNUMBER | (1 << 4))  /* integer numbers */
+
+
 /* Bit mark for collectable types */
 #define BIT_ISCOLLECTABLE      (1 << 6)
 
@@ -65,9 +67,9 @@
 
 
 /*
-** Union of all collectable objects
+** Common type for all collectable objects
 */
-typedef union GCObject GCObject;
+typedef struct GCObject GCObject;
 
 
 /*
@@ -78,21 +80,12 @@ typedef union GCObject GCObject;
 
 
 /*
-** Common header in struct form
+** Common type has only the common header
 */
-typedef struct GCheader {
+struct GCObject {
   CommonHeader;
-} GCheader;
-
-
-
-/*
-** Union of all Lua values
-*/
-typedef union Value Value;
-
+};
 
-#define numfield       lua_Number n;    /* numbers */
 
 
 
@@ -101,9 +94,26 @@ typedef union Value Value;
 ** an actual value plus a tag with its type.
 */
 
+/*
+** Union of all Lua values
+*/
+typedef union Value {
+  GCObject *gc;    /* collectable objects */
+  void *p;         /* light userdata */
+  int b;           /* booleans */
+  lua_CFunction f; /* light C functions */
+  lua_Integer i;   /* integer numbers */
+  lua_Number n;    /* float numbers */
+} Value;
+
+
 #define TValuefields   Value value_; int tt_
 
-typedef struct lua_TValue TValue;
+
+typedef struct lua_TValue {
+  TValuefields;
+} TValue;
+
 
 
 /* macro defining a nil value */
@@ -111,7 +121,6 @@ typedef struct lua_TValue TValue;
 
 
 #define val_(o)                ((o)->value_)
-#define num_(o)                (val_(o).n)
 
 
 /* raw type tag of a TValue */
@@ -124,13 +133,15 @@ typedef struct lua_TValue TValue;
 #define ttype(o)       (rttype(o) & 0x3F)
 
 /* type tag of a TValue with no variants (bits 0-3) */
-#define ttypenv(o)     (novariant(rttype(o)))
+#define ttnov(o)       (novariant(rttype(o)))
 
 
 /* Macros to test type */
 #define checktag(o,t)          (rttype(o) == (t))
-#define checktype(o,t)         (ttypenv(o) == (t))
-#define ttisnumber(o)          checktag((o), LUA_TNUMBER)
+#define checktype(o,t)         (ttnov(o) == (t))
+#define ttisnumber(o)          checktype((o), LUA_TNUMBER)
+#define ttisfloat(o)           checktag((o), LUA_TNUMFLT)
+#define ttisinteger(o)         checktag((o), LUA_TNUMINT)
 #define ttisnil(o)             checktag((o), LUA_TNIL)
 #define ttisboolean(o)         checktag((o), LUA_TBOOLEAN)
 #define ttislightuserdata(o)   checktag((o), LUA_TLIGHTUSERDATA)
@@ -143,27 +154,27 @@ typedef struct lua_TValue TValue;
 #define ttisCclosure(o)                checktag((o), ctb(LUA_TCCL))
 #define ttisLclosure(o)                checktag((o), ctb(LUA_TLCL))
 #define ttislcf(o)             checktag((o), LUA_TLCF)
-#define ttisuserdata(o)                checktag((o), ctb(LUA_TUSERDATA))
+#define ttisfulluserdata(o)    checktag((o), ctb(LUA_TUSERDATA))
 #define ttisthread(o)          checktag((o), ctb(LUA_TTHREAD))
 #define ttisdeadkey(o)         checktag((o), LUA_TDEADKEY)
 
-#define ttisequal(o1,o2)       (rttype(o1) == rttype(o2))
 
 /* Macros to access values */
-#define nvalue(o)      check_exp(ttisnumber(o), num_(o))
+#define ivalue(o)      check_exp(ttisinteger(o), val_(o).i)
+#define fltvalue(o)    check_exp(ttisfloat(o), val_(o).n)
+#define nvalue(o)      check_exp(ttisnumber(o), \
+       (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
 #define gcvalue(o)     check_exp(iscollectable(o), val_(o).gc)
 #define pvalue(o)      check_exp(ttislightuserdata(o), val_(o).p)
-#define rawtsvalue(o)  check_exp(ttisstring(o), &val_(o).gc->ts)
-#define tsvalue(o)     (&rawtsvalue(o)->tsv)
-#define rawuvalue(o)   check_exp(ttisuserdata(o), &val_(o).gc->u)
-#define uvalue(o)      (&rawuvalue(o)->uv)
-#define clvalue(o)     check_exp(ttisclosure(o), &val_(o).gc->cl)
-#define clLvalue(o)    check_exp(ttisLclosure(o), &val_(o).gc->cl.l)
-#define clCvalue(o)    check_exp(ttisCclosure(o), &val_(o).gc->cl.c)
+#define tsvalue(o)     check_exp(ttisstring(o), gco2ts(val_(o).gc))
+#define uvalue(o)      check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
+#define clvalue(o)     check_exp(ttisclosure(o), gco2cl(val_(o).gc))
+#define clLvalue(o)    check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
+#define clCvalue(o)    check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
 #define fvalue(o)      check_exp(ttislcf(o), val_(o).f)
-#define hvalue(o)      check_exp(ttistable(o), &val_(o).gc->h)
+#define hvalue(o)      check_exp(ttistable(o), gco2t(val_(o).gc))
 #define bvalue(o)      check_exp(ttisboolean(o), val_(o).b)
-#define thvalue(o)     check_exp(ttisthread(o), &val_(o).gc->th)
+#define thvalue(o)     check_exp(ttisthread(o), gco2th(val_(o).gc))
 /* a dead value may get the 'gc' field, but cannot access its contents */
 #define deadvalue(o)   check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
 
@@ -174,18 +185,27 @@ typedef struct lua_TValue TValue;
 
 
 /* Macros for internal tests */
-#define righttt(obj)           (ttype(obj) == gcvalue(obj)->gch.tt)
+#define righttt(obj)           (ttype(obj) == gcvalue(obj)->tt)
 
-#define checkliveness(g,obj) \
+#define checkliveness(L,obj) \
        lua_longassert(!iscollectable(obj) || \
-                       (righttt(obj) && !isdead(g,gcvalue(obj))))
+               (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))
 
 
 /* Macros to set values */
 #define settt_(o,t)    ((o)->tt_=(t))
 
-#define setnvalue(obj,x) \
-  { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); }
+#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)
 
@@ -199,48 +219,46 @@ typedef struct lua_TValue TValue;
   { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); }
 
 #define setgcovalue(L,obj,x) \
-  { TValue *io=(obj); GCObject *i_g=(x); \
-    val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); }
+  { TValue *io = (obj); GCObject *i_g=(x); \
+    val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
 
 #define setsvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    TString *x_ = (x); \
-    val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); TString *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
+    checkliveness(L,io); }
 
 #define setuvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); Udata *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
+    checkliveness(L,io); }
 
 #define setthvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); lua_State *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
+    checkliveness(L,io); }
 
 #define setclLvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); LClosure *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
+    checkliveness(L,io); }
 
 #define setclCvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); CClosure *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
+    checkliveness(L,io); }
 
 #define sethvalue(L,obj,x) \
-  { TValue *io=(obj); \
-    val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
-    checkliveness(G(L),io); }
+  { TValue *io = (obj); Table *x_ = (x); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
+    checkliveness(L,io); }
 
 #define setdeadvalue(obj)      settt_(obj, LUA_TDEADKEY)
 
 
 
 #define setobj(L,obj1,obj2) \
-       { const TValue *io2=(obj2); TValue *io1=(obj1); \
-         io1->value_ = io2->value_; io1->tt_ = io2->tt_; \
-         checkliveness(G(L),io1); }
+       { TValue *io1=(obj1); *io1 = *(obj2); \
+         (void)L; checkliveness(L,io1); }
 
 
 /*
@@ -256,188 +274,110 @@ typedef struct lua_TValue TValue;
 #define setptvalue2s   setptvalue
 /* from table to same table */
 #define setobjt2t      setobj
-/* to table */
-#define setobj2t       setobj
 /* to new object */
 #define setobj2n       setobj
 #define setsvalue2n    setsvalue
 
+/* to table (define it as an expression to be used in macros) */
+#define setobj2t(L,o1,o2)  ((void)L, *(o1)=*(o2), checkliveness(L,(o1)))
+
 
-/* check whether a number is valid (useful only for NaN trick) */
-#define luai_checknum(L,o,c)   { /* empty */ }
 
 
 /*
 ** {======================================================
-** NaN Trick
+** types and prototypes
 ** =======================================================
 */
-#if defined(LUA_NANTRICK)
 
-/*
-** numbers are represented in the 'd_' field. All other values have the
-** value (NNMARK | tag) in 'tt__'. A number with such pattern would be
-** a "signaled NaN", which is never generated by regular operations by
-** the CPU (nor by 'strtod')
-*/
-
-/* allows for external implementation for part of the trick */
-#if !defined(NNMARK)   /* { */
-
-
-#if !defined(LUA_IEEEENDIAN)
-#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
-#endif
-
-
-#define NNMARK         0x7FF7A500
-#define NNMASK         0x7FFFFF00
-
-#undef TValuefields
-#undef NILCONSTANT
-
-#if (LUA_IEEEENDIAN == 0)      /* { */
-
-/* little endian */
-#define TValuefields  \
-       union { struct { Value v__; int tt__; } i; double d__; } u
-#define NILCONSTANT    {{{NULL}, tag2tt(LUA_TNIL)}}
-/* field-access macros */
-#define v_(o)          ((o)->u.i.v__)
-#define d_(o)          ((o)->u.d__)
-#define tt_(o)         ((o)->u.i.tt__)
-
-#else                          /* }{ */
-
-/* big endian */
-#define TValuefields  \
-       union { struct { int tt__; Value v__; } i; double d__; } u
-#define NILCONSTANT    {{tag2tt(LUA_TNIL), {NULL}}}
-/* field-access macros */
-#define v_(o)          ((o)->u.i.v__)
-#define d_(o)          ((o)->u.d__)
-#define tt_(o)         ((o)->u.i.tt__)
-
-#endif                         /* } */
-
-#endif                 /* } */
 
+typedef TValue *StkId;  /* index to stack elements */
 
-/* correspondence with standard representation */
-#undef val_
-#define val_(o)                v_(o)
-#undef num_
-#define num_(o)                d_(o)
-
-
-#undef numfield
-#define numfield       /* no such field; numbers are the entire struct */
-
-/* basic check to distinguish numbers from non-numbers */
-#undef ttisnumber
-#define ttisnumber(o)  ((tt_(o) & NNMASK) != NNMARK)
-
-#define tag2tt(t)      (NNMARK | (t))
-
-#undef rttype
-#define rttype(o)      (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff)
-
-#undef settt_
-#define settt_(o,t)    (tt_(o) = tag2tt(t))
-
-#undef setnvalue
-#define setnvalue(obj,x) \
-       { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); }
 
-#undef setobj
-#define setobj(L,obj1,obj2) \
-       { const TValue *o2_=(obj2); TValue *o1_=(obj1); \
-         o1_->u = o2_->u; \
-         checkliveness(G(L),o1_); }
 
 
 /*
-** these redefinitions are not mandatory, but these forms are more efficient
+** Header for string value; string bytes follow the end of this structure
+** (aligned according to 'UTString'; see next).
 */
-
-#undef checktag
-#undef checktype
-#define checktag(o,t)  (tt_(o) == tag2tt(t))
-#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS))
-
-#undef ttisequal
-#define ttisequal(o1,o2)  \
-       (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
-
-
-#undef luai_checknum
-#define luai_checknum(L,o,c)   { if (!ttisnumber(o)) c; }
-
-#endif
-/* }====================================================== */
-
+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;
+  union {
+    size_t lnglen;  /* length for long strings */
+    struct TString *hnext;  /* linked list for hash table */
+  } u;
+} TString;
 
 
 /*
-** {======================================================
-** types and prototypes
-** =======================================================
+** Ensures that address after this type is always fully aligned.
 */
+typedef union UTString {
+  L_Umaxalign dummy;  /* ensures maximum alignment for strings */
+  TString tsv;
+} UTString;
 
 
-union Value {
-  GCObject *gc;    /* collectable objects */
-  void *p;         /* light userdata */
-  int b;           /* booleans */
-  lua_CFunction f; /* light C functions */
-  numfield         /* numbers */
-};
-
-
-struct lua_TValue {
-  TValuefields;
-};
+/*
+** Get the actual string (array of bytes) from a 'TString'.
+** (Access to 'extra' ensures that value is really a 'TString'.)
+*/
+#define getstr(ts)  \
+  check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))
 
 
-typedef TValue *StkId;  /* index to stack elements */
+/* 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 string value; string bytes follow the end of this structure
+** Header for userdata; memory area follows the end of this structure
+** (aligned according to 'UUdata'; see next).
 */
-typedef union TString {
-  L_Umaxalign dummy;  /* ensures maximum alignment for strings */
-  struct {
-    CommonHeader;
-    lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
-    unsigned int hash;
-    size_t len;  /* number of characters in string */
-  } tsv;
-} TString;
-
+typedef struct Udata {
+  CommonHeader;
+  lu_byte ttuv_;  /* user value's tag */
+  struct Table *metatable;
+  size_t len;  /* number of bytes */
+  union Value user_;  /* user value */
+} Udata;
 
-/* get the actual string (array of bytes) from a TString */
-#define getstr(ts)     cast(const char *, (ts) + 1)
 
-/* get the actual string (array of bytes) from a Lua value */
-#define svalue(o)       getstr(rawtsvalue(o))
+/*
+** Ensures that address after this type is always fully aligned.
+*/
+typedef union UUdata {
+  L_Umaxalign dummy;  /* ensures maximum alignment for 'local' udata */
+  Udata uv;
+} UUdata;
 
 
 /*
-** Header for userdata; memory area follows the end of this structure
+**  Get the address of memory block inside 'Udata'.
+** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
 */
-typedef union Udata {
-  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
-  struct {
-    CommonHeader;
-    struct Table *metatable;
-    struct Table *env;
-    size_t len;  /* number of bytes */
-  } uv;
-} Udata;
+#define getudatamem(u)  \
+  check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))
 
+#define setuservalue(L,u,o) \
+       { const TValue *io=(o); Udata *iu = (u); \
+         iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
+         checkliveness(L,io); }
+
+
+#define getuservalue(L,u,o) \
+       { TValue *io=(o); const Udata *iu = (u); \
+         io->value_ = iu->user_; settt_(io, iu->ttuv_); \
+         checkliveness(L,io); }
 
 
 /*
@@ -445,7 +385,7 @@ typedef union Udata {
 */
 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;
 
@@ -466,26 +406,26 @@ typedef struct LocVar {
 */
 typedef struct Proto {
   CommonHeader;
+  lu_byte numparams;  /* number of fixed parameters */
+  lu_byte is_vararg;  /* 2: declared vararg; 1: uses vararg */
+  lu_byte maxstacksize;  /* number of registers needed by this function */
+  int sizeupvalues;  /* size of 'upvalues' */
+  int sizek;  /* size of 'k' */
+  int sizecode;
+  int sizelineinfo;
+  int sizep;  /* size of 'p' */
+  int sizelocvars;
+  int linedefined;  /* debug information  */
+  int lastlinedefined;  /* debug information  */
   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 */
-  union Closure *cache;  /* last created closure with this prototype */
+  struct LClosure *cache;  /* last-created closure with this prototype */
   TString  *source;  /* used for debug information */
-  int sizeupvalues;  /* size of 'upvalues' */
-  int sizek;  /* size of `k' */
-  int sizecode;
-  int sizelineinfo;
-  int sizep;  /* size of `p' */
-  int sizelocvars;
-  int linedefined;
-  int lastlinedefined;
   GCObject *gclist;
-  lu_byte numparams;  /* number of fixed parameters */
-  lu_byte is_vararg;
-  lu_byte maxstacksize;  /* maximum stack used by this function */
 } Proto;
 
 
@@ -493,17 +433,7 @@ typedef struct Proto {
 /*
 ** Lua Upvalues
 */
-typedef struct UpVal {
-  CommonHeader;
-  TValue *v;  /* points to stack or to its own value */
-  union {
-    TValue value;  /* the value (when closed) */
-    struct {  /* double linked list (when open) */
-      struct UpVal *prev;
-      struct UpVal *next;
-    } l;
-  } u;
-} UpVal;
+typedef struct UpVal UpVal;
 
 
 /*
@@ -545,12 +475,19 @@ typedef union Closure {
 typedef union TKey {
   struct {
     TValuefields;
-    struct Node *next;  /* for chaining */
+    int next;  /* for chaining (offset for next node) */
   } nk;
   TValue tvk;
 } TKey;
 
 
+/* copy a value into a key without messing up field 'next' */
+#define setnodekey(L,key,obj) \
+       { TKey *k_=(key); const TValue *io_=(obj); \
+         k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
+         (void)L; checkliveness(L,io_); }
+
+
 typedef struct Node {
   TValue i_val;
   TKey i_key;
@@ -560,8 +497,8 @@ typedef struct Node {
 typedef struct Table {
   CommonHeader;
   lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
-  lu_byte lsizenode;  /* log2 of size of `node' array */
-  int sizearray;  /* size of `array' array */
+  lu_byte lsizenode;  /* log2 of size of 'node' array */
+  unsigned int sizearray;  /* size of 'array' array */
   TValue *array;  /* array part */
   Node *node;
   Node *lastfree;  /* any free position is before this position */
@@ -572,7 +509,7 @@ typedef struct Table {
 
 
 /*
-** `module' operation for hashing (size is always a power of 2)
+** 'module' operation for hashing (size is always a power of 2)
 */
 #define lmod(s,size) \
        (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))
@@ -590,13 +527,18 @@ typedef struct Table {
 
 LUAI_DDEC const TValue luaO_nilobject_;
 
+/* size of buffer for 'luaO_utf8esc' function */
+#define UTF8BUFFSZ     8
 
 LUAI_FUNC int luaO_int2fb (unsigned int x);
 LUAI_FUNC int luaO_fb2int (int x);
+LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
 LUAI_FUNC int luaO_ceillog2 (unsigned int x);
-LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2);
-LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result);
+LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
+                           const TValue *p2, TValue *res);
+LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
 LUAI_FUNC int luaO_hexavalue (int c);
+LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj);
 LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
                                                        va_list argp);
 LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
index 4190dc7..a1cbef8 100644 (file)
@@ -1,13 +1,16 @@
 /*
-** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lopcodes.c,v 1.55 2015/01/05 13:48:33 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
 
-
 #define lopcodes_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <stddef.h>
 
 #include "lopcodes.h"
 
@@ -31,10 +34,17 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "ADD",
   "SUB",
   "MUL",
-  "DIV",
   "MOD",
   "POW",
+  "DIV",
+  "IDIV",
+  "BAND",
+  "BOR",
+  "BXOR",
+  "SHL",
+  "SHR",
   "UNM",
+  "BNOT",
   "NOT",
   "LEN",
   "CONCAT",
@@ -79,10 +89,17 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_ADD */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_SUB */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_MUL */
- ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_DIV */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_MOD */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_POW */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_DIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_IDIV */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_BAND */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_BOR */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_BXOR */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_SHL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)           /* OP_SHR */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)           /* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC)           /* OP_BNOT */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)           /* OP_NOT */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)           /* OP_LEN */
  ,opmode(0, 1, OpArgR, OpArgR, iABC)           /* OP_CONCAT */
index 8e2f80a..864b8e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.142.1.2 2014/10/20 18:32:09 roberto Exp $
+** $Id: lopcodes.h,v 1.148 2014/10/25 11:50:46 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
   We assume that instructions are unsigned numbers.
   All instructions have an opcode in the first 6 bits.
   Instructions can have the following fields:
-       `A' : 8 bits
-       `B' : 9 bits
-       `C' : 9 bits
+       'A' : 8 bits
+       'B' : 9 bits
+       'C' : 9 bits
        'Ax' : 26 bits ('A', 'B', and 'C' together)
-       `Bx' : 18 bits (`B' and `C' together)
-       `sBx' : signed Bx
+       'Bx' : 18 bits ('B' and 'C' together)
+       'sBx' : signed Bx
 
   A signed argument is represented in excess K; that is, the number
   value is the unsigned value minus K. K is exactly the maximum value
@@ -58,7 +58,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx};  /* basic instruction format */
 */
 #if SIZE_Bx < LUAI_BITSINT-1
 #define MAXARG_Bx        ((1<<SIZE_Bx)-1)
-#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */
+#define MAXARG_sBx        (MAXARG_Bx>>1)         /* 'sBx' is signed */
 #else
 #define MAXARG_Bx        MAX_INT
 #define MAXARG_sBx        MAX_INT
@@ -76,10 +76,10 @@ enum OpMode {iABC, iABx, iAsBx, iAx};  /* basic instruction format */
 #define MAXARG_C        ((1<<SIZE_C)-1)
 
 
-/* creates a mask with `n' 1 bits at position `p' */
+/* creates a mask with 'n' 1 bits at position 'p' */
 #define MASK1(n,p)     ((~((~(Instruction)0)<<(n)))<<(p))
 
-/* creates a mask with `n' 0 bits at position `p' */
+/* creates a mask with 'n' 0 bits at position 'p' */
 #define MASK0(n,p)     (~MASK1(n,p))
 
 /*
@@ -187,10 +187,17 @@ OP_SELF,/*        A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]             */
 OP_ADD,/*      A B C   R(A) := RK(B) + RK(C)                           */
 OP_SUB,/*      A B C   R(A) := RK(B) - RK(C)                           */
 OP_MUL,/*      A B C   R(A) := RK(B) * RK(C)                           */
-OP_DIV,/*      A B C   R(A) := RK(B) / RK(C)                           */
 OP_MOD,/*      A B C   R(A) := RK(B) % RK(C)                           */
 OP_POW,/*      A B C   R(A) := RK(B) ^ RK(C)                           */
+OP_DIV,/*      A B C   R(A) := RK(B) / RK(C)                           */
+OP_IDIV,/*     A B C   R(A) := RK(B) // RK(C)                          */
+OP_BAND,/*     A B C   R(A) := RK(B) & RK(C)                           */
+OP_BOR,/*      A B C   R(A) := RK(B) | RK(C)                           */
+OP_BXOR,/*     A B C   R(A) := RK(B) ~ RK(C)                           */
+OP_SHL,/*      A B C   R(A) := RK(B) << RK(C)                          */
+OP_SHR,/*      A B C   R(A) := RK(B) >> RK(C)                          */
 OP_UNM,/*      A B     R(A) := -R(B)                                   */
+OP_BNOT,/*     A B     R(A) := ~R(B)                                   */
 OP_NOT,/*      A B     R(A) := not R(B)                                */
 OP_LEN,/*      A B     R(A) := length of R(B)                          */
 
@@ -231,16 +238,16 @@ OP_EXTRAARG/*     Ax      extra (larger) argument for previous opcode     */
 
 /*===========================================================================
   Notes:
-  (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then `top' is
+  (*) In OP_CALL, if (B == 0) then B = top. If (C == 0), then 'top' is
   set to last_result+1, so next open instruction (OP_CALL, OP_RETURN,
-  OP_SETLIST) may use `top'.
+  OP_SETLIST) may use 'top'.
 
   (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
   set top (like in OP_CALL with C == 0).
 
-  (*) In OP_RETURN, if (B == 0) then return up to `top'.
+  (*) In OP_RETURN, if (B == 0) then return up to 'top'.
 
-  (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next
+  (*) In OP_SETLIST, if (B == 0) then B = 'top'; if (C == 0) then next
   'instruction' is EXTRAARG(real C).
 
   (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
@@ -248,7 +255,7 @@ OP_EXTRAARG/*       Ax      extra (larger) argument for previous opcode     */
   (*) For comparisons, A specifies what condition the test should accept
   (true or false).
 
-  (*) All `skips' (pc++) assume that next instruction is a jump.
+  (*) All 'skips' (pc++) assume that next instruction is a jump.
 
 ===========================================================================*/
 
index 052ba17..4810655 100644 (file)
@@ -1,9 +1,14 @@
 /*
-** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: loslib.c,v 1.64 2016/04/18 13:06:55 roberto Exp $
 ** Standard Operating System library
 ** See Copyright Notice in lua.h
 */
 
+#define loslib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <errno.h>
 #include <locale.h>
@@ -11,9 +16,6 @@
 #include <string.h>
 #include <time.h>
 
-#define loslib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 
 
 /*
-** list of valid conversion specifiers for the 'strftime' function
+** {==================================================================
+** List of valid conversion specifiers for the 'strftime' function;
+** options are grouped by length; group of length 2 start with '||'.
+** ===================================================================
 */
-#if !defined(LUA_STRFTIMEOPTIONS)
-
-#if !defined(LUA_USE_POSIX)
-#define LUA_STRFTIMEOPTIONS    { "aAbBcdHIjmMpSUwWxXyYz%", "" }
-#else
-#define LUA_STRFTIMEOPTIONS \
-       { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
-         "", "E", "cCxXyY",  \
-         "O", "deHImMSuUVwWy" }
-#endif
+#if !defined(LUA_STRFTIMEOPTIONS)      /* { */
 
+/* options for ANSI C 89 */
+#define L_STRFTIMEC89          "aAbBcdHIjmMpSUwWxXyYZ%"
+
+/* options for ISO C 99 and POSIX */
+#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
+       "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy"
+
+/* options for Windows */
+#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
+       "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y"
+
+#if defined(LUA_USE_WINDOWS)
+#define LUA_STRFTIMEOPTIONS    L_STRFTIMEWIN
+#elif defined(LUA_USE_C89)
+#define LUA_STRFTIMEOPTIONS    L_STRFTIMEC89
+#else  /* C99 specification */
+#define LUA_STRFTIMEOPTIONS    L_STRFTIMEC99
 #endif
 
+#endif                                 /* } */
+/* }================================================================== */
 
 
 /*
-** By default, Lua uses tmpnam except when POSIX is available, where it
-** uses mkstemp.
+** {==================================================================
+** Configuration for time-related stuff
+** ===================================================================
 */
-#if defined(LUA_USE_MKSTEMP)
-#include <unistd.h>
-#define LUA_TMPNAMBUFSIZE      32
-#define lua_tmpnam(b,e) { \
-        strcpy(b, "/tmp/lua_XXXXXX"); \
-        e = mkstemp(b); \
-        if (e != -1) close(e); \
-        e = (e == -1); }
 
-#elif !defined(lua_tmpnam)
+#if !defined(l_time_t)         /* { */
+/*
+** type to represent time_t in Lua
+*/
+#define l_timet                        lua_Integer
+#define l_pushtime(L,t)                lua_pushinteger(L,(lua_Integer)(t))
 
-#define LUA_TMPNAMBUFSIZE      L_tmpnam
-#define lua_tmpnam(b,e)                { e = (tmpnam(b) == NULL); }
+static time_t l_checktime (lua_State *L, int arg) {
+  lua_Integer t = luaL_checkinteger(L, arg);
+  luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
+  return (time_t)t;
+}
 
-#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_GMTIME_R)
+
+#if defined(LUA_USE_POSIX)     /* { */
 
 #define l_gmtime(t,r)          gmtime_r(t,r)
 #define l_localtime(t,r)       localtime_r(t,r)
 
-#elif !defined(l_gmtime)
+#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                         /* } */
+
+/* }================================================================== */
+
+
+/*
+** {==================================================================
+** 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)     /* { */
+
+#include <unistd.h>
 
-#define l_gmtime(t,r)          ((void)r, gmtime(t))
-#define l_localtime(t,r)       ((void)r, localtime(t))
+#define LUA_TMPNAMBUFSIZE      32
 
+#if !defined(LUA_TMPNAMTEMPLATE)
+#define LUA_TMPNAMTEMPLATE     "/tmp/lua_XXXXXX"
 #endif
 
+#define lua_tmpnam(b,e) { \
+        strcpy(b, LUA_TMPNAMTEMPLATE); \
+        e = mkstemp(b); \
+        if (e != -1) close(e); \
+        e = (e == -1); }
+
+#else                          /* }{ */
+
+/* ISO C definitions */
+#define LUA_TMPNAMBUFSIZE      L_tmpnam
+#define lua_tmpnam(b,e)                { e = (tmpnam(b) == NULL); }
+
+#endif                         /* } */
+
+#endif                         /* } */
+/* }================================================================== */
+
+
 
 
 static int os_execute (lua_State *L) {
@@ -145,45 +206,67 @@ static void setboolfield (lua_State *L, const char *key, int value) {
   lua_setfield(L, -2, key);
 }
 
+
+/*
+** Set all fields from structure 'tm' in the table on top of the stack
+*/
+static void setallfields (lua_State *L, struct tm *stm) {
+  setfield(L, "sec", stm->tm_sec);
+  setfield(L, "min", stm->tm_min);
+  setfield(L, "hour", stm->tm_hour);
+  setfield(L, "day", stm->tm_mday);
+  setfield(L, "month", stm->tm_mon + 1);
+  setfield(L, "year", stm->tm_year + 1900);
+  setfield(L, "wday", stm->tm_wday + 1);
+  setfield(L, "yday", stm->tm_yday + 1);
+  setboolfield(L, "isdst", stm->tm_isdst);
+}
+
+
 static int getboolfield (lua_State *L, const char *key) {
   int res;
-  lua_getfield(L, -1, key);
-  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
+  res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
   lua_pop(L, 1);
   return res;
 }
 
 
-static int getfield (lua_State *L, const char *key, int d) {
-  int res, isnum;
-  lua_getfield(L, -1, key);
-  res = (int)lua_tointegerx(L, -1, &isnum);
-  if (!isnum) {
-    if (d < 0)
-      return luaL_error(L, "field " LUA_QS " missing in date table", key);
+/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
+#if !defined(L_MAXDATEFIELD)
+#define L_MAXDATEFIELD (INT_MAX / 2)
+#endif
+
+static int getfield (lua_State *L, const char *key, int d, int delta) {
+  int isnum;
+  int t = lua_getfield(L, -1, key);  /* get field and its type */
+  lua_Integer res = lua_tointegerx(L, -1, &isnum);
+  if (!isnum) {  /* field is not an integer? */
+    if (t != LUA_TNIL)  /* some other value? */
+      return luaL_error(L, "field '%s' is not an integer", key);
+    else if (d < 0)  /* absent field; no default? */
+      return luaL_error(L, "field '%s' missing in date table", key);
     res = d;
   }
+  else {
+    if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
+      return luaL_error(L, "field '%s' is out-of-bound", key);
+    res -= delta;
+  }
   lua_pop(L, 1);
-  return res;
+  return (int)res;
 }
 
 
 static const char *checkoption (lua_State *L, const char *conv, char *buff) {
-  static const char *const options[] = LUA_STRFTIMEOPTIONS;
-  unsigned int i;
-  for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {
-    if (*conv != '\0' && strchr(options[i], *conv) != NULL) {
-      buff[1] = *conv;
-      if (*options[i + 1] == '\0') {  /* one-char conversion specifier? */
-        buff[2] = '\0';  /* end buffer */
-        return conv + 1;
-      }
-      else if (*(conv + 1) != '\0' &&
-               strchr(options[i + 1], *(conv + 1)) != NULL) {
-        buff[2] = *(conv + 1);  /* valid two-char conversion specifier */
-        buff[3] = '\0';  /* end buffer */
-        return conv + 2;
-      }
+  const char *option;
+  int oplen = 1;
+  for (option = LUA_STRFTIMEOPTIONS; *option != '\0'; option += oplen) {
+    if (*option == '|')  /* next block? */
+      oplen++;  /* next length */
+    else if (memcmp(conv, option, oplen) == 0) {  /* match? */
+      memcpy(buff, conv, oplen);  /* copy valid option to buffer */
+      buff[oplen] = '\0';
+      return conv + oplen;  /* return next item */
     }
   }
   luaL_argerror(L, 1,
@@ -192,44 +275,40 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) {
 }
 
 
+/* maximum size for an individual 'strftime' item */
+#define SIZETIMEFMT    250
+
+
 static int os_date (lua_State *L) {
   const char *s = luaL_optstring(L, 1, "%c");
-  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
+  time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
   struct tm tmr, *stm;
   if (*s == '!') {  /* UTC? */
     stm = l_gmtime(&t, &tmr);
-    s++;  /* skip `!' */
+    s++;  /* skip '!' */
   }
   else
     stm = l_localtime(&t, &tmr);
   if (stm == NULL)  /* invalid date? */
-    lua_pushnil(L);
-  else if (strcmp(s, "*t") == 0) {
+    luaL_error(L, "time result cannot be represented in this installation");
+  if (strcmp(s, "*t") == 0) {
     lua_createtable(L, 0, 9);  /* 9 = number of fields */
-    setfield(L, "sec", stm->tm_sec);
-    setfield(L, "min", stm->tm_min);
-    setfield(L, "hour", stm->tm_hour);
-    setfield(L, "day", stm->tm_mday);
-    setfield(L, "month", stm->tm_mon+1);
-    setfield(L, "year", stm->tm_year+1900);
-    setfield(L, "wday", stm->tm_wday+1);
-    setfield(L, "yday", stm->tm_yday+1);
-    setboolfield(L, "isdst", stm->tm_isdst);
+    setallfields(L, stm);
   }
   else {
-    char cc[4];
+    char cc[4];  /* buffer for individual conversion specifiers */
     luaL_Buffer b;
     cc[0] = '%';
     luaL_buffinit(L, &b);
     while (*s) {
-      if (*s != '%')  /* no conversion specifier? */
+      if (*s != '%')  /* not a conversion specifier? */
         luaL_addchar(&b, *s++);
       else {
         size_t reslen;
-        char buff[200];  /* should be big enough for any conversion result */
-        s = checkoption(L, s + 1, cc);
-        reslen = strftime(buff, sizeof(buff), cc, stm);
-        luaL_addlstring(&b, buff, reslen);
+        char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
+        s = checkoption(L, s + 1, cc + 1);  /* copy specifier to 'cc' */
+        reslen = strftime(buff, SIZETIMEFMT, cc, stm);
+        luaL_addsize(&b, reslen);
       }
     }
     luaL_pushresult(&b);
@@ -246,26 +325,27 @@ static int os_time (lua_State *L) {
     struct tm ts;
     luaL_checktype(L, 1, LUA_TTABLE);
     lua_settop(L, 1);  /* make sure table is at the top */
-    ts.tm_sec = getfield(L, "sec", 0);
-    ts.tm_min = getfield(L, "min", 0);
-    ts.tm_hour = getfield(L, "hour", 12);
-    ts.tm_mday = getfield(L, "day", -1);
-    ts.tm_mon = getfield(L, "month", -1) - 1;
-    ts.tm_year = getfield(L, "year", -1) - 1900;
+    ts.tm_sec = getfield(L, "sec", 0, 0);
+    ts.tm_min = getfield(L, "min", 0, 0);
+    ts.tm_hour = getfield(L, "hour", 12, 0);
+    ts.tm_mday = getfield(L, "day", -1, 0);
+    ts.tm_mon = getfield(L, "month", -1, 1);
+    ts.tm_year = getfield(L, "year", -1, 1900);
     ts.tm_isdst = getboolfield(L, "isdst");
     t = mktime(&ts);
+    setallfields(L, &ts);  /* update fields with normalized values */
   }
-  if (t == (time_t)(-1))
-    lua_pushnil(L);
-  else
-    lua_pushnumber(L, (lua_Number)t);
+  if (t != (time_t)(l_timet)t || t == (time_t)(-1))
+    luaL_error(L, "time result cannot be represented in this installation");
+  l_pushtime(L, t);
   return 1;
 }
 
 
 static int os_difftime (lua_State *L) {
-  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
-                             (time_t)(luaL_optnumber(L, 2, 0))));
+  time_t t1 = l_checktime(L, 1);
+  time_t t2 = l_checktime(L, 2);
+  lua_pushnumber(L, (lua_Number)difftime(t1, t2));
   return 1;
 }
 
@@ -289,7 +369,7 @@ static int os_exit (lua_State *L) {
   if (lua_isboolean(L, 1))
     status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
   else
-    status = luaL_optint(L, 1, EXIT_SUCCESS);
+    status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
   if (lua_toboolean(L, 2))
     lua_close(L);
   if (L) exit(status);  /* 'if' to avoid warnings for unreachable 'return' */
index 9e1a9ca..22530a5 100644 (file)
@@ -1,15 +1,17 @@
 /*
-** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lparser.c,v 2.153 2016/05/13 19:10:16 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
 
-
-#include <string.h>
-
 #define lparser_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
 #include "lcode.h"
 #define hasmultret(k)          ((k) == VCALL || (k) == VVARARG)
 
 
+/* because all strings are unified by the scanner, the parser
+   can use pointer equality for string equality */
+#define eqstr(a,b)     ((a) == (b))
+
 
 /*
 ** nodes for block list (list of active blocks)
 */
 typedef struct BlockCnt {
   struct BlockCnt *previous;  /* chain */
-  short firstlabel;  /* index of first label in this block */
-  short firstgoto;  /* index of first pending goto in this block */
+  int firstlabel;  /* index of first label in this block */
+  int firstgoto;  /* index of first pending goto in this block */
   lu_byte nactvar;  /* # active locals outside the block */
   lu_byte upval;  /* true if some variable in the block is an upvalue */
-  lu_byte isloop;  /* true if `block' is a loop */
+  lu_byte isloop;  /* true if 'block' is a loop */
 } BlockCnt;
 
 
@@ -57,19 +63,9 @@ static void statement (LexState *ls);
 static void expr (LexState *ls, expdesc *v);
 
 
-static void anchor_token (LexState *ls) {
-  /* last token from outer function must be EOS */
-  lua_assert(ls->fs != NULL || ls->t.token == TK_EOS);
-  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
-    TString *ts = ls->t.seminfo.ts;
-    luaX_newstring(ls, getstr(ts), ts->tsv.len);
-  }
-}
-
-
 /* semantic error */
 static l_noret semerror (LexState *ls, const char *msg) {
-  ls->t.token = 0;  /* remove 'near to' from final message */
+  ls->t.token = 0;  /* remove "near <token>" from final message */
   luaX_syntaxerror(ls, msg);
 }
 
@@ -168,7 +164,8 @@ static int registerlocalvar (LexState *ls, TString *varname) {
   int oldsize = f->sizelocvars;
   luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
                   LocVar, SHRT_MAX, "local variables");
-  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
+  while (oldsize < f->sizelocvars)
+    f->locvars[oldsize++].varname = NULL;
   f->locvars[fs->nlocvars].varname = varname;
   luaC_objbarrier(ls->L, f, varname);
   return fs->nlocvars++;
@@ -222,7 +219,7 @@ static int searchupvalue (FuncState *fs, TString *name) {
   int i;
   Upvaldesc *up = fs->f->upvalues;
   for (i = 0; i < fs->nups; i++) {
-    if (luaS_eqstr(up[i].name, name)) return i;
+    if (eqstr(up[i].name, name)) return i;
   }
   return -1;  /* not found */
 }
@@ -234,7 +231,8 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
   checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues");
   luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues,
                   Upvaldesc, MAXUPVAL, "upvalues");
-  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL;
+  while (oldsize < f->sizeupvalues)
+    f->upvalues[oldsize++].name = NULL;
   f->upvalues[fs->nups].instack = (v->k == VLOCAL);
   f->upvalues[fs->nups].idx = cast_byte(v->u.info);
   f->upvalues[fs->nups].name = name;
@@ -246,7 +244,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
 static int searchvar (FuncState *fs, TString *n) {
   int i;
   for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
-    if (luaS_eqstr(n, getlocvar(fs, i)->varname))
+    if (eqstr(n, getlocvar(fs, i)->varname))
       return i;
   }
   return -1;  /* not found */
@@ -259,7 +257,8 @@ static int searchvar (FuncState *fs, TString *n) {
 */
 static void markupval (FuncState *fs, int level) {
   BlockCnt *bl = fs->bl;
-  while (bl->nactvar > level) bl = bl->previous;
+  while (bl->nactvar > level)
+    bl = bl->previous;
   bl->upval = 1;
 }
 
@@ -268,27 +267,26 @@ static void markupval (FuncState *fs, int level) {
   Find variable with given name 'n'. If it is an upvalue, add this
   upvalue into all intermediate functions.
 */
-static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
+static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
   if (fs == NULL)  /* no more levels? */
-    return VVOID;  /* default is global */
+    init_exp(var, VVOID, 0);  /* default is global */
   else {
     int v = searchvar(fs, n);  /* look up locals at current level */
     if (v >= 0) {  /* found? */
       init_exp(var, VLOCAL, v);  /* variable is local */
       if (!base)
         markupval(fs, v);  /* local will be used as an upval */
-      return VLOCAL;
     }
     else {  /* not found as local at current level; try upvalues */
       int idx = searchupvalue(fs, n);  /* try existing upvalues */
       if (idx < 0) {  /* not found? */
-        if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */
-          return VVOID;  /* not found; is a global */
+        singlevaraux(fs->prev, n, var, 0);  /* try upper levels */
+        if (var->k == VVOID)  /* not found? */
+          return;  /* it is a global */
         /* else was LOCAL or UPVAL */
         idx  = newupvalue(fs, n, var);  /* will be a new upvalue */
       }
-      init_exp(var, VUPVAL, idx);
-      return VUPVAL;
+      init_exp(var, VUPVAL, idx);  /* new or old upvalue */
     }
   }
 }
@@ -297,10 +295,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
 static void singlevar (LexState *ls, expdesc *var) {
   TString *varname = str_checkname(ls);
   FuncState *fs = ls->fs;
-  if (singlevaraux(fs, varname, var, 1) == VVOID) {  /* global name? */
+  singlevaraux(fs, varname, var, 1);
+  if (var->k == VVOID) {  /* global name? */
     expdesc key;
     singlevaraux(fs, ls->envn, var, 1);  /* get environment variable */
-    lua_assert(var->k == VLOCAL || var->k == VUPVAL);
+    lua_assert(var->k != VVOID);  /* this one must exist */
     codestring(ls, &key, varname);  /* key is variable name */
     luaK_indexed(fs, var, &key);  /* env[varname] */
   }
@@ -342,11 +341,11 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
   FuncState *fs = ls->fs;
   Labellist *gl = &ls->dyd->gt;
   Labeldesc *gt = &gl->arr[g];
-  lua_assert(luaS_eqstr(gt->name, label->name));
+  lua_assert(eqstr(gt->name, label->name));
   if (gt->nactvar < label->nactvar) {
     TString *vname = getlocvar(fs, gt->nactvar)->varname;
     const char *msg = luaO_pushfstring(ls->L,
-      "<goto %s> at line %d jumps into the scope of local " LUA_QS,
+      "<goto %s> at line %d jumps into the scope of local '%s'",
       getstr(gt->name), gt->line, getstr(vname));
     semerror(ls, msg);
   }
@@ -369,7 +368,7 @@ static int findlabel (LexState *ls, int g) {
   /* check labels in current block for a match */
   for (i = bl->firstlabel; i < dyd->label.n; i++) {
     Labeldesc *lb = &dyd->label.arr[i];
-    if (luaS_eqstr(lb->name, gt->name)) {  /* correct label? */
+    if (eqstr(lb->name, gt->name)) {  /* correct label? */
       if (gt->nactvar > lb->nactvar &&
           (bl->upval || dyd->label.n > bl->firstlabel))
         luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -390,7 +389,7 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name,
   l->arr[n].line = line;
   l->arr[n].nactvar = ls->fs->nactvar;
   l->arr[n].pc = pc;
-  l->n++;
+  l->n = n + 1;
   return n;
 }
 
@@ -403,7 +402,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
   Labellist *gl = &ls->dyd->gt;
   int i = ls->fs->bl->firstgoto;
   while (i < gl->n) {
-    if (luaS_eqstr(gl->arr[i].name, lb->name))
+    if (eqstr(gl->arr[i].name, lb->name))
       closegoto(ls, i, lb);
     else
       i++;
@@ -412,7 +411,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
 
 
 /*
-** "export" pending gotos to outer level, to check them against
+** export pending gotos to outer level, to check them against
 ** outer labels; if the block being exited has upvalues, and
 ** the goto exits the scope of any variable (which can be the
 ** upvalue), close those variables being exited.
@@ -448,7 +447,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
 
 
 /*
-** create a label named "break" to resolve break statements
+** create a label named 'break' to resolve break statements
 */
 static void breaklabel (LexState *ls) {
   TString *n = luaS_new(ls->L, "break");
@@ -463,7 +462,7 @@ static void breaklabel (LexState *ls) {
 static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
   const char *msg = isreserved(gt->name)
                     ? "<%s> at line %d not inside a loop"
-                    : "no visible label " LUA_QS " for <goto> at line %d";
+                    : "no visible label '%s' for <goto> at line %d";
   msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
   semerror(ls, msg);
 }
@@ -503,7 +502,8 @@ static Proto *addprototype (LexState *ls) {
   if (fs->np >= f->sizep) {
     int oldsize = f->sizep;
     luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
-    while (oldsize < f->sizep) f->p[oldsize++] = NULL;
+    while (oldsize < f->sizep)
+      f->p[oldsize++] = NULL;
   }
   f->p[fs->np++] = clp = luaF_newproto(L);
   luaC_objbarrier(L, f, clp);
@@ -525,7 +525,6 @@ static void codeclosure (LexState *ls, expdesc *v) {
 
 
 static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
-  lua_State *L = ls->L;
   Proto *f;
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->ls = ls;
@@ -544,10 +543,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
   f = fs->f;
   f->source = ls->source;
   f->maxstacksize = 2;  /* registers 0/1 are always valid */
-  fs->h = luaH_new(L);
-  /* anchor table of constants (to avoid being collected) */
-  sethvalue2s(L, L->top, fs->h);
-  incr_top(L);
   enterblock(fs, bl, 0);
 }
 
@@ -572,9 +567,6 @@ static void close_func (LexState *ls) {
   f->sizeupvalues = fs->nups;
   lua_assert(fs->bl == NULL);
   ls->fs = fs->prev;
-  /* last token read was anchored in defunct function; must re-anchor it */
-  anchor_token(ls);
-  L->top--;  /* pop table of constants */
   luaC_checkGC(L);
 }
 
@@ -588,7 +580,7 @@ static void close_func (LexState *ls) {
 /*
 ** check whether current token is in the follow set of a block.
 ** 'until' closes syntactical blocks, but do not close scope,
-** so it handled in separate.
+** so it is handled in separate.
 */
 static int block_follow (LexState *ls, int withuntil) {
   switch (ls->t.token) {
@@ -602,7 +594,7 @@ static int block_follow (LexState *ls, int withuntil) {
 
 
 static void statlist (LexState *ls) {
-  /* statlist -> { stat [`;'] } */
+  /* statlist -> { stat [';'] } */
   while (!block_follow(ls, 1)) {
     if (ls->t.token == TK_RETURN) {
       statement(ls);
@@ -643,14 +635,14 @@ static void yindex (LexState *ls, expdesc *v) {
 struct ConsControl {
   expdesc v;  /* last list item read */
   expdesc *t;  /* table descriptor */
-  int nh;  /* total number of `record' elements */
+  int nh;  /* total number of 'record' elements */
   int na;  /* total number of array elements */
   int tostore;  /* number of array elements pending to be stored */
 };
 
 
 static void recfield (LexState *ls, struct ConsControl *cc) {
-  /* recfield -> (NAME | `['exp1`]') = exp1 */
+  /* recfield -> (NAME | '['exp1']') = exp1 */
   FuncState *fs = ls->fs;
   int reg = ls->fs->freereg;
   expdesc key, val;
@@ -757,12 +749,12 @@ static void constructor (LexState *ls, expdesc *t) {
 
 
 static void parlist (LexState *ls) {
-  /* parlist -> [ param { `,' param } ] */
+  /* parlist -> [ param { ',' param } ] */
   FuncState *fs = ls->fs;
   Proto *f = fs->f;
   int nparams = 0;
   f->is_vararg = 0;
-  if (ls->t.token != ')') {  /* is `parlist' not empty? */
+  if (ls->t.token != ')') {  /* is 'parlist' not empty? */
     do {
       switch (ls->t.token) {
         case TK_NAME: {  /* param -> NAME */
@@ -770,12 +762,12 @@ static void parlist (LexState *ls) {
           nparams++;
           break;
         }
-        case TK_DOTS: {  /* param -> `...' */
+        case TK_DOTS: {  /* param -> '...' */
           luaX_next(ls);
-          f->is_vararg = 1;
+          f->is_vararg = 2;  /* declared vararg */
           break;
         }
-        default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
+        default: luaX_syntaxerror(ls, "<name> or '...' expected");
       }
     } while (!f->is_vararg && testnext(ls, ','));
   }
@@ -786,7 +778,7 @@ static void parlist (LexState *ls) {
 
 
 static void body (LexState *ls, expdesc *e, int ismethod, int line) {
-  /* body ->  `(' parlist `)' block END */
+  /* body ->  '(' parlist ')' block END */
   FuncState new_fs;
   BlockCnt bl;
   new_fs.f = addprototype(ls);
@@ -808,7 +800,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
 
 
 static int explist (LexState *ls, expdesc *v) {
-  /* explist -> expr { `,' expr } */
+  /* explist -> expr { ',' expr } */
   int n = 1;  /* at least one expression */
   expr(ls, v);
   while (testnext(ls, ',')) {
@@ -825,7 +817,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
   expdesc args;
   int base, nparams;
   switch (ls->t.token) {
-    case '(': {  /* funcargs -> `(' [ explist ] `)' */
+    case '(': {  /* funcargs -> '(' [ explist ] ')' */
       luaX_next(ls);
       if (ls->t.token == ')')  /* arg list is empty? */
         args.k = VVOID;
@@ -842,7 +834,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
     }
     case TK_STRING: {  /* funcargs -> STRING */
       codestring(ls, &args, ls->t.seminfo.ts);
-      luaX_next(ls);  /* must use `seminfo' before `next' */
+      luaX_next(ls);  /* must use 'seminfo' before 'next' */
       break;
     }
     default: {
@@ -908,14 +900,14 @@ static void suffixedexp (LexState *ls, expdesc *v) {
         fieldsel(ls, v);
         break;
       }
-      case '[': {  /* `[' exp1 `]' */
+      case '[': {  /* '[' exp1 ']' */
         expdesc key;
         luaK_exp2anyregup(fs, v);
         yindex(ls, &key);
         luaK_indexed(fs, v, &key);
         break;
       }
-      case ':': {  /* `:' NAME funcargs */
+      case ':': {  /* ':' NAME funcargs */
         expdesc key;
         luaX_next(ls);
         checkname(ls, &key);
@@ -935,14 +927,19 @@ static void suffixedexp (LexState *ls, expdesc *v) {
 
 
 static void simpleexp (LexState *ls, expdesc *v) {
-  /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
+  /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... |
                   constructor | FUNCTION body | suffixedexp */
   switch (ls->t.token) {
-    case TK_NUMBER: {
-      init_exp(v, VKNUM, 0);
+    case TK_FLT: {
+      init_exp(v, VKFLT, 0);
       v->u.nval = ls->t.seminfo.r;
       break;
     }
+    case TK_INT: {
+      init_exp(v, VKINT, 0);
+      v->u.ival = ls->t.seminfo.i;
+      break;
+    }
     case TK_STRING: {
       codestring(ls, v, ls->t.seminfo.ts);
       break;
@@ -962,7 +959,8 @@ static void simpleexp (LexState *ls, expdesc *v) {
     case TK_DOTS: {  /* vararg */
       FuncState *fs = ls->fs;
       check_condition(ls, fs->f->is_vararg,
-                      "cannot use " LUA_QL("...") " outside a vararg function");
+                      "cannot use '...' outside a vararg function");
+      fs->f->is_vararg = 1;  /* function actually uses vararg */
       init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
       break;
     }
@@ -988,6 +986,7 @@ static UnOpr getunopr (int op) {
   switch (op) {
     case TK_NOT: return OPR_NOT;
     case '-': return OPR_MINUS;
+    case '~': return OPR_BNOT;
     case '#': return OPR_LEN;
     default: return OPR_NOUNOPR;
   }
@@ -999,9 +998,15 @@ static BinOpr getbinopr (int op) {
     case '+': return OPR_ADD;
     case '-': return OPR_SUB;
     case '*': return OPR_MUL;
-    case '/': return OPR_DIV;
     case '%': return OPR_MOD;
     case '^': return OPR_POW;
+    case '/': return OPR_DIV;
+    case TK_IDIV: return OPR_IDIV;
+    case '&': return OPR_BAND;
+    case '|': return OPR_BOR;
+    case '~': return OPR_BXOR;
+    case TK_SHL: return OPR_SHL;
+    case TK_SHR: return OPR_SHR;
     case TK_CONCAT: return OPR_CONCAT;
     case TK_NE: return OPR_NE;
     case TK_EQ: return OPR_EQ;
@@ -1020,19 +1025,24 @@ static const struct {
   lu_byte left;  /* left priority for each binary operator */
   lu_byte right; /* right priority */
 } priority[] = {  /* ORDER OPR */
-   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `*' `/' `%' */
-   {10, 9}, {5, 4},                 /* ^, .. (right associative) */
-   {3, 3}, {3, 3}, {3, 3},          /* ==, <, <= */
-   {3, 3}, {3, 3}, {3, 3},          /* ~=, >, >= */
-   {2, 2}, {1, 1}                   /* and, or */
+   {10, 10}, {10, 10},           /* '+' '-' */
+   {11, 11}, {11, 11},           /* '*' '%' */
+   {14, 13},                  /* '^' (right associative) */
+   {11, 11}, {11, 11},           /* '/' '//' */
+   {6, 6}, {4, 4}, {5, 5},   /* '&' '|' '~' */
+   {7, 7}, {7, 7},           /* '<<' '>>' */
+   {9, 8},                   /* '..' (right associative) */
+   {3, 3}, {3, 3}, {3, 3},   /* ==, <, <= */
+   {3, 3}, {3, 3}, {3, 3},   /* ~=, >, >= */
+   {2, 2}, {1, 1}            /* and, or */
 };
 
-#define UNARY_PRIORITY 8  /* priority for unary operators */
+#define UNARY_PRIORITY 12  /* priority for unary operators */
 
 
 /*
 ** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
-** where `binop' is any binary operator with a priority higher than `limit'
+** where 'binop' is any binary operator with a priority higher than 'limit'
 */
 static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
   BinOpr op;
@@ -1046,7 +1056,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
     luaK_prefix(ls->fs, uop, v, line);
   }
   else simpleexp(ls, v);
-  /* expand while operators have priorities higher than `limit' */
+  /* expand while operators have priorities higher than 'limit' */
   op = getbinopr(ls->t.token);
   while (op != OPR_NOBINOPR && priority[op].left > limit) {
     expdesc v2;
@@ -1146,7 +1156,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
                     "C levels");
     assignment(ls, &nv, nvars+1);
   }
-  else {  /* assignment -> `=' explist */
+  else {  /* assignment -> '=' explist */
     int nexps;
     checknext(ls, '=');
     nexps = explist(ls, &e);
@@ -1170,7 +1180,7 @@ static int cond (LexState *ls) {
   /* cond -> exp */
   expdesc v;
   expr(ls, &v);  /* read condition */
-  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */
+  if (v.k == VNIL) v.k = VFALSE;  /* 'falses' are all equal here */
   luaK_goiftrue(ls->fs, &v);
   return v.f;
 }
@@ -1195,9 +1205,9 @@ static void gotostat (LexState *ls, int pc) {
 static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
   int i;
   for (i = fs->bl->firstlabel; i < ll->n; i++) {
-    if (luaS_eqstr(label, ll->arr[i].name)) {
+    if (eqstr(label, ll->arr[i].name)) {
       const char *msg = luaO_pushfstring(fs->ls->L,
-                          "label " LUA_QS " already defined on line %d",
+                          "label '%s' already defined on line %d",
                           getstr(label), ll->arr[i].line);
       semerror(fs->ls, msg);
     }
@@ -1220,7 +1230,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
   checkrepeated(fs, ll, label);  /* check for repeated labels */
   checknext(ls, TK_DBCOLON);  /* skip double colon */
   /* create new entry for this label */
-  l = newlabelentry(ls, ll, label, line, fs->pc);
+  l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs));
   skipnoopstat(ls);  /* skip other no-op statements */
   if (block_follow(ls, 0)) {  /* label is last no-op statement in the block? */
     /* assume that locals are already out of scope */
@@ -1321,7 +1331,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
   if (testnext(ls, ','))
     exp1(ls);  /* optional step */
   else {  /* default step = 1 */
-    luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1));
+    luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
     luaK_reserveregs(fs, 1);
   }
   forbody(ls, base, line, 1, 1);
@@ -1359,15 +1369,15 @@ static void forstat (LexState *ls, int line) {
   TString *varname;
   BlockCnt bl;
   enterblock(fs, &bl, 1);  /* scope for loop and control variables */
-  luaX_next(ls);  /* skip `for' */
+  luaX_next(ls);  /* skip 'for' */
   varname = str_checkname(ls);  /* first variable name */
   switch (ls->t.token) {
     case '=': fornum(ls, varname, line); break;
     case ',': case TK_IN: forlist(ls, varname); break;
-    default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
+    default: luaX_syntaxerror(ls, "'=' or 'in' expected");
   }
   check_match(ls, TK_END, TK_FOR, line);
-  leaveblock(fs);  /* loop scope (`break' jumps to this point) */
+  leaveblock(fs);  /* loop scope ('break' jumps to this point) */
 }
 
 
@@ -1397,7 +1407,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
     enterblock(fs, &bl, 0);
     jf = v.f;
   }
-  statlist(ls);  /* `then' part */
+  statlist(ls);  /* 'then' part */
   leaveblock(fs);
   if (ls->t.token == TK_ELSE ||
       ls->t.token == TK_ELSEIF)  /* followed by 'else'/'elseif'? */
@@ -1414,7 +1424,7 @@ static void ifstat (LexState *ls, int line) {
   while (ls->t.token == TK_ELSEIF)
     test_then_block(ls, &escapelist);  /* ELSEIF cond THEN block */
   if (testnext(ls, TK_ELSE))
-    block(ls);  /* `else' part */
+    block(ls);  /* 'else' part */
   check_match(ls, TK_END, TK_IF, line);
   luaK_patchtohere(fs, escapelist);  /* patch escape list to 'if' end */
 }
@@ -1432,7 +1442,7 @@ static void localfunc (LexState *ls) {
 
 
 static void localstat (LexState *ls) {
-  /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */
+  /* stat -> LOCAL NAME {',' NAME} ['=' explist] */
   int nvars = 0;
   int nexps;
   expdesc e;
@@ -1452,7 +1462,7 @@ static void localstat (LexState *ls) {
 
 
 static int funcname (LexState *ls, expdesc *v) {
-  /* funcname -> NAME {fieldsel} [`:' NAME] */
+  /* funcname -> NAME {fieldsel} [':' NAME] */
   int ismethod = 0;
   singlevar(ls, v);
   while (ls->t.token == '.')
@@ -1473,7 +1483,7 @@ static void funcstat (LexState *ls, int line) {
   ismethod = funcname(ls, &v);
   body(ls, &b, ismethod, line);
   luaK_storevar(ls->fs, &v, &b);
-  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */
+  luaK_fixline(ls->fs, line);  /* definition "happens" in the first line */
 }
 
 
@@ -1488,7 +1498,7 @@ static void exprstat (LexState *ls) {
   }
   else {  /* stat -> func */
     check_condition(ls, v.v.k == VCALL, "syntax error");
-    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */
+    SETARG_C(getinstruction(fs, &v.v), 1);  /* call statement uses no results */
   }
 }
 
@@ -1505,8 +1515,8 @@ static void retstat (LexState *ls) {
     if (hasmultret(e.k)) {
       luaK_setmultret(fs, &e);
       if (e.k == VCALL && nret == 1) {  /* tail call? */
-        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
-        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
+        SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
+        lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
       }
       first = fs->nactvar;
       nret = LUA_MULTRET;  /* return all values */
@@ -1515,8 +1525,8 @@ static void retstat (LexState *ls) {
       if (nret == 1)  /* only one single value? */
         first = luaK_exp2anyreg(fs, &e);
       else {
-        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */
-        first = fs->nactvar;  /* return all `active' values */
+        luaK_exp2nextreg(fs, &e);  /* values must go to the stack */
+        first = fs->nactvar;  /* return all active values */
         lua_assert(nret == fs->freereg - first);
       }
     }
@@ -1605,7 +1615,7 @@ static void mainfunc (LexState *ls, FuncState *fs) {
   BlockCnt bl;
   expdesc v;
   open_func(ls, fs, &bl);
-  fs->f->is_vararg = 1;  /* main function is always vararg */
+  fs->f->is_vararg = 2;  /* main function is always declared vararg */
   init_exp(&v, VLOCAL, 0);  /* create and... */
   newupvalue(fs, ls->envn, &v);  /* ...set environment upvalue */
   luaX_next(ls);  /* read first token */
@@ -1615,16 +1625,19 @@ static void mainfunc (LexState *ls, FuncState *fs) {
 }
 
 
-Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
-                      Dyndata *dyd, const char *name, int firstchar) {
+LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+                       Dyndata *dyd, const char *name, int firstchar) {
   LexState lexstate;
   FuncState funcstate;
-  Closure *cl = luaF_newLclosure(L, 1);  /* create main closure */
-  /* anchor closure (to avoid being collected) */
-  setclLvalue(L, L->top, cl);
-  incr_top(L);
-  funcstate.f = cl->l.p = luaF_newproto(L);
+  LClosure *cl = luaF_newLclosure(L, 1);  /* create main closure */
+  setclLvalue(L, L->top, cl);  /* anchor it (to avoid being collected) */
+  luaD_inctop(L);
+  lexstate.h = luaH_new(L);  /* create table for scanner */
+  sethvalue(L, L->top, lexstate.h);  /* anchor it */
+  luaD_inctop(L);
+  funcstate.f = cl->p = luaF_newproto(L);
   funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
+  lua_assert(iswhite(funcstate.f));  /* do not need barrier here */
   lexstate.buff = buff;
   lexstate.dyd = dyd;
   dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
@@ -1633,6 +1646,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
   lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
   /* all scopes should be correctly finished */
   lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
-  return cl;  /* it's on the stack too */
+  L->top--;  /* remove scanner's table */
+  return cl;  /* closure is on the stack, too */
 }
 
index 0346e3c..02e9b03 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
 
 
 /*
-** Expression descriptor
+** Expression and variable descriptor.
+** Code generation for variables and expressions can be delayed to allow
+** optimizations; An 'expdesc' structure describes a potentially-delayed
+** variable/expression. It has a description of its "main" value plus a
+** list of conditional jumps that can also produce its value (generated
+** by short-circuit operators 'and'/'or').
 */
 
+/* kinds of variables/expressions */
 typedef enum {
-  VVOID,       /* no value */
-  VNIL,
-  VTRUE,
-  VFALSE,
-  VK,          /* info = index of constant in `k' */
-  VKNUM,       /* nval = numerical value */
-  VNONRELOC,   /* info = result register */
-  VLOCAL,      /* info = local register */
-  VUPVAL,       /* info = index of upvalue in 'upvalues' */
-  VINDEXED,    /* t = table register/upvalue; idx = index R/K */
-  VJMP,                /* info = instruction pc */
-  VRELOCABLE,  /* info = instruction pc */
-  VCALL,       /* info = instruction pc */
-  VVARARG      /* info = instruction pc */
+  VVOID,  /* when 'expdesc' describes the last expression a list,
+             this kind means an empty list (so, no expression) */
+  VNIL,  /* constant nil */
+  VTRUE,  /* constant true */
+  VFALSE,  /* constant false */
+  VK,  /* constant in 'k'; info = index of constant in 'k' */
+  VKFLT,  /* floating constant; nval = numerical float value */
+  VKINT,  /* integer constant; nval = numerical integer value */
+  VNONRELOC,  /* expression has its value in a fixed register;
+                 info = result register */
+  VLOCAL,  /* local variable; info = local register */
+  VUPVAL,  /* upvalue variable; info = index of upvalue in 'upvalues' */
+  VINDEXED,  /* indexed variable;
+                ind.vt = whether 't' is register or upvalue;
+                ind.t = table register or upvalue;
+                ind.idx = key's R/K index */
+  VJMP,  /* expression is a test/comparison;
+            info = pc of corresponding jump instruction */
+  VRELOCABLE,  /* expression can put result in any register;
+                  info = instruction pc */
+  VCALL,  /* expression is a function call; info = instruction pc */
+  VVARARG  /* vararg expression; info = instruction pc */
 } expkind;
 
 
@@ -40,16 +54,17 @@ typedef enum {
 typedef struct expdesc {
   expkind k;
   union {
+    lua_Integer ival;    /* for VKINT */
+    lua_Number nval;  /* for VKFLT */
+    int info;  /* for generic use */
     struct {  /* for indexed variables (VINDEXED) */
       short idx;  /* index (R/K) */
       lu_byte t;  /* table (register or upvalue) */
       lu_byte vt;  /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
     } ind;
-    int info;  /* for generic use */
-    lua_Number nval;  /* for VKNUM */
   } u;
-  int t;  /* patch list of `exit when true' */
-  int f;  /* patch list of `exit when false' */
+  int t;  /* patch list of 'exit when true' */
+  int f;  /* patch list of 'exit when false' */
 } expdesc;
 
 
@@ -95,15 +110,14 @@ struct BlockCnt;  /* defined in lparser.c */
 /* state needed to generate code for a given function */
 typedef struct FuncState {
   Proto *f;  /* current function header */
-  Table *h;  /* table to find (and reuse) elements in `k' */
   struct FuncState *prev;  /* enclosing function */
   struct LexState *ls;  /* lexical state */
   struct BlockCnt *bl;  /* chain of current blocks */
-  int pc;  /* next position to code (equivalent to `ncode') */
+  int pc;  /* next position to code (equivalent to 'ncode') */
   int lasttarget;   /* 'label' of last 'jump label' */
-  int jpc;  /* list of pending jumps to `pc' */
-  int nk;  /* number of elements in `k' */
-  int np;  /* number of elements in `p' */
+  int jpc;  /* list of pending jumps to 'pc' */
+  int nk;  /* number of elements in 'k' */
+  int np;  /* number of elements in 'p' */
   int firstlocal;  /* index of first local var (in Dyndata array) */
   short nlocvars;  /* number of elements in 'f->locvars' */
   lu_byte nactvar;  /* number of active local variables */
@@ -112,8 +126,8 @@ typedef struct FuncState {
 } FuncState;
 
 
-LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
-                                Dyndata *dyd, const char *name, int firstchar);
+LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+                                 Dyndata *dyd, const char *name, int firstchar);
 
 
 #endif
diff --git a/src/lprefix.h b/src/lprefix.h
new file mode 100644 (file)
index 0000000..02daa83
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
+** Definitions for Lua code that must come before any other header file
+** See Copyright Notice in lua.h
+*/
+
+#ifndef lprefix_h
+#define lprefix_h
+
+
+/*
+** Allows POSIX/XSI stuff
+*/
+#if !defined(LUA_USE_C89)      /* { */
+
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE           600
+#elif _XOPEN_SOURCE == 0
+#undef _XOPEN_SOURCE  /* use -D_XOPEN_SOURCE=0 to undefine it */
+#endif
+
+/*
+** Allows manipulation of large files in gcc and some other compilers
+*/
+#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
+#define _LARGEFILE_SOURCE       1
+#define _FILE_OFFSET_BITS       64
+#endif
+
+#endif                         /* } */
+
+
+/*
+** Windows stuff
+*/
+#if defined(_WIN32)    /* { */
+
+#if !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS  /* avoid warnings about ISO C functions */
+#endif
+
+#endif                 /* } */
+
+#endif
+
index c7f2672..9194ac3 100644 (file)
@@ -1,16 +1,18 @@
 /*
-** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $
+** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
 
+#define lstate_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 #include <stddef.h>
 #include <string.h>
 
-#define lstate_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "lapi.h"
 #define LUAI_GCPAUSE   200  /* 200% */
 #endif
 
-#if !defined(LUAI_GCMAJOR)
-#define LUAI_GCMAJOR   200  /* 200% */
-#endif
-
 #if !defined(LUAI_GCMUL)
 #define LUAI_GCMUL     200 /* GC runs 'twice the speed' of memory allocation */
 #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.
@@ -57,9 +52,7 @@
 ** thread state + extra space
 */
 typedef struct LX {
-#if defined(LUAI_EXTRASPACE)
-  char buff[LUAI_EXTRASPACE];
-#endif
+  lu_byte extra_[LUA_EXTRASPACE];
   lua_State l;
 } LX;
 
@@ -78,13 +71,12 @@ typedef struct LG {
 
 
 /*
-** Compute an initial seed as random as possible. In ANSI, rely on
-** Address Space Layout Randomization (if present) to increase
-** randomness..
+** Compute an initial seed as random as possible. Rely on Address Space
+** Layout Randomization (if present) to increase randomness..
 */
 #define addbuff(b,p,e) \
   { size_t t = cast(size_t, e); \
-    memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
+    memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
 
 static unsigned int makeseed (lua_State *L) {
   char buff[4 * sizeof(size_t)];
@@ -101,10 +93,14 @@ static unsigned int makeseed (lua_State *L) {
 
 /*
 ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
-** invariant
+** invariant (and avoiding underflows in 'totalbytes')
 */
 void luaE_setdebt (global_State *g, l_mem debt) {
-  g->totalbytes -= (debt - g->GCdebt);
+  l_mem tb = gettotalbytes(g);
+  lua_assert(tb > 0);
+  if (debt < tb - MAX_LMEM)
+    debt = tb - MAX_LMEM;  /* will make 'totalbytes == MAX_LMEM' */
+  g->totalbytes = tb - debt;
   g->GCdebt = debt;
 }
 
@@ -115,10 +111,14 @@ CallInfo *luaE_extendCI (lua_State *L) {
   L->ci->next = ci;
   ci->previous = L->ci;
   ci->next = NULL;
+  L->nci++;
   return ci;
 }
 
 
+/*
+** free all CallInfo structures not in use by a thread
+*/
 void luaE_freeCI (lua_State *L) {
   CallInfo *ci = L->ci;
   CallInfo *next = ci->next;
@@ -126,6 +126,24 @@ void luaE_freeCI (lua_State *L) {
   while ((ci = next) != NULL) {
     next = ci->next;
     luaM_free(L, ci);
+    L->nci--;
+  }
+}
+
+
+/*
+** free half of the CallInfo structures not in use by a thread
+*/
+void luaE_shrinkCI (lua_State *L) {
+  CallInfo *ci = L->ci;
+  CallInfo *next2;  /* next's next */
+  /* while there are two nexts */
+  while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
+    luaM_free(L, ci->next);  /* free next */
+    L->nci--;
+    ci->next = next2;  /* remove 'next' from the list */
+    next2->previous = ci;
+    ci = next2;  /* keep next's next */
   }
 }
 
@@ -155,6 +173,7 @@ static void freestack (lua_State *L) {
     return;  /* stack not completely built yet */
   L->ci = &L->base_ci;  /* free the entire 'ci' list */
   luaE_freeCI(L);
+  lua_assert(L->nci == 0);
   luaM_freearray(L, L->stack, L->stacksize);  /* free stack array */
 }
 
@@ -163,34 +182,32 @@ static void freestack (lua_State *L) {
 ** Create registry table and its predefined values
 */
 static void init_registry (lua_State *L, global_State *g) {
-  TValue mt;
+  TValue temp;
   /* create registry */
   Table *registry = luaH_new(L);
   sethvalue(L, &g->l_registry, registry);
   luaH_resize(L, registry, LUA_RIDX_LAST, 0);
   /* registry[LUA_RIDX_MAINTHREAD] = L */
-  setthvalue(L, &mt, L);
-  luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
+  setthvalue(L, &temp, L);  /* temp = L */
+  luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
   /* registry[LUA_RIDX_GLOBALS] = table of globals */
-  sethvalue(L, &mt, luaH_new(L));
-  luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
+  sethvalue(L, &temp, luaH_new(L));  /* temp = new table (global table) */
+  luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
 }
 
 
 /*
-** open parts of the state that may cause memory-allocation errors
+** open parts of the state that may cause memory-allocation errors.
+** ('g->version' != NULL flags that the state was completely build)
 */
 static void f_luaopen (lua_State *L, void *ud) {
   global_State *g = G(L);
   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);
-  luaS_fix(g->memerrmsg);  /* it should never be collected */
   g->gcrunning = 1;  /* allow gc */
   g->version = lua_version(NULL);
   luai_userstateopen(L);
@@ -198,14 +215,16 @@ static void f_luaopen (lua_State *L, void *ud) {
 
 
 /*
-** preinitialize a state with consistent values without allocating
+** preinitialize a thread with consistent values without allocating
 ** any memory (to avoid errors)
 */
-static void preinit_state (lua_State *L, global_State *g) {
+static void preinit_thread (lua_State *L, global_State *g) {
   G(L) = g;
   L->stack = NULL;
   L->ci = NULL;
+  L->nci = 0;
   L->stacksize = 0;
+  L->twups = L;  /* thread has no upvalues */
   L->errorJmp = NULL;
   L->nCcalls = 0;
   L->hook = NULL;
@@ -227,7 +246,6 @@ static void close_state (lua_State *L) {
   if (g->version)  /* closing a fully built state? */
     luai_userstateclose(L);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
-  luaZ_freebuffer(L, &g->buff);
   freestack(L);
   lua_assert(gettotalbytes(g) == sizeof(LG));
   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);  /* free main block */
@@ -235,17 +253,28 @@ static void close_state (lua_State *L) {
 
 
 LUA_API lua_State *lua_newthread (lua_State *L) {
+  global_State *g = G(L);
   lua_State *L1;
   lua_lock(L);
   luaC_checkGC(L);
-  L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th;
+  /* create new thread */
+  L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
+  L1->marked = luaC_white(g);
+  L1->tt = LUA_TTHREAD;
+  /* link it on list 'allgc' */
+  L1->next = g->allgc;
+  g->allgc = obj2gco(L1);
+  /* anchor it on L stack */
   setthvalue(L, L->top, L1);
   api_incr_top(L);
-  preinit_state(L1, G(L));
+  preinit_thread(L1, g);
   L1->hookmask = L->hookmask;
   L1->basehookcount = L->basehookcount;
   L1->hook = L->hook;
   resethookcount(L1);
+  /* initialize L1 extra space */
+  memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
+         LUA_EXTRASPACE);
   luai_userstatethread(L, L1);
   stack_init(L1, L);  /* init stack */
   lua_unlock(L);
@@ -273,36 +302,31 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g = &l->g;
   L->next = NULL;
   L->tt = LUA_TTHREAD;
-  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+  g->currentwhite = bitmask(WHITE0BIT);
   L->marked = luaC_white(g);
-  g->gckind = KGC_NORMAL;
-  preinit_state(L, g);
+  preinit_thread(L, g);
   g->frealloc = f;
   g->ud = ud;
   g->mainthread = L;
   g->seed = makeseed(L);
-  g->uvhead.u.l.prev = &g->uvhead;
-  g->uvhead.u.l.next = &g->uvhead;
   g->gcrunning = 0;  /* no GC while building state */
   g->GCestimate = 0;
-  g->strt.size = 0;
-  g->strt.nuse = 0;
+  g->strt.size = g->strt.nuse = 0;
   g->strt.hash = NULL;
   setnilvalue(&g->l_registry);
-  luaZ_initbuffer(L, &g->buff);
   g->panic = NULL;
   g->version = NULL;
   g->gcstate = GCSpause;
-  g->allgc = NULL;
-  g->finobj = NULL;
-  g->tobefnz = NULL;
-  g->sweepgc = g->sweepfin = NULL;
+  g->gckind = KGC_NORMAL;
+  g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
+  g->sweepgc = NULL;
   g->gray = g->grayagain = NULL;
   g->weak = g->ephemeron = g->allweak = NULL;
+  g->twups = NULL;
   g->totalbytes = sizeof(LG);
   g->GCdebt = 0;
+  g->gcfinnum = 0;
   g->gcpause = LUAI_GCPAUSE;
-  g->gcmajorinc = LUAI_GCMAJOR;
   g->gcstepmul = LUAI_GCMUL;
   for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
index daffd9a..b3033be 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstate.h,v 2.130 2015/12/16 16:39:38 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */
 
 /*
 
-** Some notes about garbage-collected objects:  All objects in Lua must
-** be kept somehow accessible until being freed.
+** Some notes about garbage-collected objects: All objects in Lua must
+** be kept somehow accessible until being freed, so all objects always
+** belong to one (and only one) of these lists, using field 'next' of
+** the 'CommonHeader' for the link:
 **
-** Lua keeps most objects linked in list g->allgc. The link uses field
-** 'next' of the CommonHeader.
-**
-** Strings are kept in several lists headed by the array g->strt.hash.
-**
-** Open upvalues are not subject to independent garbage collection. They
-** are collected together with their respective threads. Lua keeps a
-** double-linked list with all open upvalues (g->uvhead) so that it can
-** mark objects referred by them. (They are always gray, so they must
-** be remarked in the atomic step. Usually their contents would be marked
-** when traversing the respective threads, but the thread may already be
-** dead, while the upvalue is still accessible through closures.)
-**
-** Objects with finalizers are kept in the list g->finobj.
-**
-** The list g->tobefnz links all objects being finalized.
+** 'allgc': all objects not marked for finalization;
+** 'finobj': all objects marked for finalization;
+** 'tobefnz': all objects ready to be finalized; 
+** 'fixedgc': all objects that are not to be collected (currently
+** only small strings, such as reserved words).
 
 */
 
 struct lua_longjmp;  /* defined in ldo.c */
 
 
+/*
+** Atomic type (relative to signals) to better ensure that 'lua_sethook' 
+** is thread safe
+*/
+#if !defined(l_signalT)
+#include <signal.h>
+#define l_signalT      sig_atomic_t
+#endif
+
 
 /* extra stack space to handle TM calls and some other extras */
 #define EXTRA_STACK   5
@@ -53,66 +53,72 @@ struct lua_longjmp;  /* defined in ldo.c */
 /* kinds of Garbage Collection */
 #define KGC_NORMAL     0
 #define KGC_EMERGENCY  1       /* gc was forced by an allocation failure */
-#define KGC_GEN                2       /* generational collection */
 
 
 typedef struct stringtable {
-  GCObject **hash;
-  lu_int32 nuse;  /* number of elements */
+  TString **hash;
+  int nuse;  /* number of elements */
   int size;
 } stringtable;
 
 
 /*
-** information about a call
+** Information about a call.
+** When a thread yields, 'func' is adjusted to pretend that the
+** top function has only the yielded values in its stack; in that
+** case, the actual 'func' value is saved in field 'extra'. 
+** When a function calls another with a continuation, 'extra' keeps
+** the function index so that, in case of errors, the continuation
+** function can be called with the correct top.
 */
 typedef struct CallInfo {
   StkId func;  /* function index in the stack */
   StkId        top;  /* top for this function */
   struct CallInfo *previous, *next;  /* dynamic call link */
-  short nresults;  /* expected number of results from this function */
-  lu_byte callstatus;
-  ptrdiff_t extra;
   union {
     struct {  /* only for Lua functions */
       StkId base;  /* base for this function */
       const Instruction *savedpc;
     } l;
     struct {  /* only for C functions */
-      int ctx;  /* context info. in case of yields */
-      lua_CFunction k;  /* continuation in case of yields */
+      lua_KFunction k;  /* continuation in case of yields */
       ptrdiff_t old_errfunc;
-      lu_byte old_allowhook;
-      lu_byte status;
+      lua_KContext ctx;  /* context info. in case of yields */
     } c;
   } u;
+  ptrdiff_t extra;
+  short nresults;  /* expected number of results from this function */
+  lu_byte callstatus;
 } CallInfo;
 
 
 /*
 ** Bits in CallInfo status
 */
-#define CIST_LUA       (1<<0)  /* call is running a Lua function */
-#define CIST_HOOKED    (1<<1)  /* call is running a debug hook */
-#define CIST_REENTRY   (1<<2)  /* call is running on same invocation of
-                                   luaV_execute of previous call */
-#define CIST_YIELDED   (1<<3)  /* call reentered after suspension */
+#define CIST_OAH       (1<<0)  /* original value of 'allowhook' */
+#define CIST_LUA       (1<<1)  /* call is running a Lua function */
+#define CIST_HOOKED    (1<<2)  /* call is running a debug hook */
+#define CIST_FRESH     (1<<3)  /* call is running on a fresh invocation
+                                   of luaV_execute */
 #define CIST_YPCALL    (1<<4)  /* call is a yieldable protected call */
-#define CIST_STAT      (1<<5)  /* call has an error status (pcall) */
-#define CIST_TAIL      (1<<6)  /* call was tail called */
-#define CIST_HOOKYIELD (1<<7)  /* last hook called yielded */
-
+#define 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)
 
+/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
+#define setoah(st,v)   ((st) = ((st) & ~CIST_OAH) | (v))
+#define getoah(st)     ((st) & CIST_OAH)
+
 
 /*
-** `global state', shared by all threads of this state
+** 'global state', shared by all threads of this state
 */
 typedef struct global_State {
   lua_Alloc frealloc;  /* function to reallocate memory */
-  void *ud;         /* auxiliary data to `frealloc' */
-  lu_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
+  void *ud;         /* auxiliary data to 'frealloc' */
+  l_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
   l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
   lu_mem GCmemtrav;  /* memory traversed by the GC */
   lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
@@ -123,36 +129,36 @@ typedef struct global_State {
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gckind;  /* kind of GC running */
   lu_byte gcrunning;  /* true if GC is running */
-  int sweepstrgc;  /* position of sweep in `strt' */
   GCObject *allgc;  /* list of all collectable objects */
+  GCObject **sweepgc;  /* current position of sweep in list */
   GCObject *finobj;  /* list of collectable objects with finalizers */
-  GCObject **sweepgc;  /* current position of sweep in list 'allgc' */
-  GCObject **sweepfin;  /* current position of sweep in list 'finobj' */
   GCObject *gray;  /* list of gray objects */
   GCObject *grayagain;  /* list of objects to be traversed atomically */
   GCObject *weak;  /* list of tables with weak values */
   GCObject *ephemeron;  /* list of ephemeron tables (weak keys) */
   GCObject *allweak;  /* list of all-weak tables */
   GCObject *tobefnz;  /* list of userdata to be GC */
-  UpVal uvhead;  /* head of double-linked list of all open upvalues */
-  Mbuffer buff;  /* temporary buffer for string concatenation */
+  GCObject *fixedgc;  /* list of objects not to be collected */
+  struct lua_State *twups;  /* list of threads with open upvalues */
+  unsigned int gcfinnum;  /* number of finalizers to call in each GC step */
   int gcpause;  /* size of pause between successive GCs */
-  int gcmajorinc;  /* pause between major collections (only in gen. mode) */
-  int gcstepmul;  /* GC `granularity' */
+  int gcstepmul;  /* GC 'granularity' */
   lua_CFunction panic;  /* to be called in unprotected errors */
   struct lua_State *mainthread;
   const lua_Number *version;  /* pointer to version number */
   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_N][STRCACHE_M];  /* cache for strings in API */
 } global_State;
 
 
 /*
-** `per thread' state
+** 'per thread' state
 */
 struct lua_State {
   CommonHeader;
+  unsigned short nci;  /* number of items in 'ci' list */
   lu_byte status;
   StkId top;  /* first free slot in the stack */
   global_State *l_G;
@@ -160,19 +166,20 @@ struct lua_State {
   const Instruction *oldpc;  /* last pc traced */
   StkId stack_last;  /* last free slot in the stack */
   StkId stack;  /* stack base */
+  UpVal *openupval;  /* list of open upvalues in this stack */
+  GCObject *gclist;
+  struct lua_State *twups;  /* list of threads with open upvalues */
+  struct lua_longjmp *errorJmp;  /* current error recover point */
+  CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
+  volatile lua_Hook hook;
+  ptrdiff_t errfunc;  /* current error handling function (stack index) */
   int stacksize;
+  int basehookcount;
+  int hookcount;
   unsigned short nny;  /* number of non-yieldable calls in stack */
   unsigned short nCcalls;  /* number of nested C calls */
-  lu_byte hookmask;
+  l_signalT hookmask;
   lu_byte allowhook;
-  int basehookcount;
-  int hookcount;
-  lua_Hook hook;
-  GCObject *openupval;  /* list of open upvalues in this stack */
-  GCObject *gclist;
-  struct lua_longjmp *errorJmp;  /* current error recover point */
-  ptrdiff_t errfunc;  /* current error handling function (stack index) */
-  CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
 };
 
 
@@ -180,48 +187,47 @@ struct lua_State {
 
 
 /*
-** Union of all collectable objects
+** Union of all collectable objects (only for conversions)
 */
-union GCObject {
-  GCheader gch;  /* common header */
-  union TString ts;
-  union Udata u;
+union GCUnion {
+  GCObject gc;  /* common header */
+  struct TString ts;
+  struct Udata u;
   union Closure cl;
   struct Table h;
   struct Proto p;
-  struct UpVal uv;
   struct lua_State th;  /* thread */
 };
 
 
-#define gch(o)         (&(o)->gch)
+#define cast_u(o)      cast(union GCUnion *, (o))
 
 /* macros to convert a GCObject into a specific value */
-#define rawgco2ts(o)  \
-       check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts))
-#define gco2ts(o)      (&rawgco2ts(o)->tsv)
-#define rawgco2u(o)    check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
-#define gco2u(o)       (&rawgco2u(o)->uv)
-#define gco2lcl(o)     check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l))
-#define gco2ccl(o)     check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c))
+#define gco2ts(o)  \
+       check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
+#define gco2u(o)  check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u))
+#define gco2lcl(o)  check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l))
+#define gco2ccl(o)  check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c))
 #define gco2cl(o)  \
-       check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl))
-#define gco2t(o)       check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
-#define gco2p(o)       check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
-#define gco2uv(o)      check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
-#define gco2th(o)      check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
+       check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
+#define gco2t(o)  check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h))
+#define gco2p(o)  check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p))
+#define gco2th(o)  check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th))
+
 
-/* macro to convert any Lua object into a GCObject */
-#define obj2gco(v)     (cast(GCObject *, (v)))
+/* macro to convert a Lua object into a GCObject */
+#define obj2gco(v) \
+       check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc)))
 
 
 /* actual number of total bytes allocated */
-#define gettotalbytes(g)       ((g)->totalbytes + (g)->GCdebt)
+#define gettotalbytes(g)       cast(lu_mem, (g)->totalbytes + (g)->GCdebt)
 
 LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);
+LUAI_FUNC void luaE_shrinkCI (lua_State *L);
 
 
 #endif
index af96c89..9351766 100644 (file)
@@ -1,23 +1,30 @@
 /*
-** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
 
-
-#include <string.h>
-
 #define lstring_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
+#include "ldebug.h"
+#include "ldo.h"
 #include "lmem.h"
 #include "lobject.h"
 #include "lstate.h"
 #include "lstring.h"
 
 
+#define MEMERRMSG       "not enough memory"
+
+
 /*
 ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
 ** compute its hash
 ** equality for long strings
 */
 int luaS_eqlngstr (TString *a, TString *b) {
-  size_t len = a->tsv.len;
-  lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR);
+  size_t len = a->u.lnglen;
+  lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
   return (a == b) ||  /* same instance or... */
-    ((len == b->tsv.len) &&  /* equal length and ... */
+    ((len == b->u.lnglen) &&  /* equal length and ... */
      (memcmp(getstr(a), getstr(b), len) == 0));  /* equal contents */
 }
 
 
-/*
-** equality for strings
-*/
-int luaS_eqstr (TString *a, TString *b) {
-  return (a->tsv.tt == b->tsv.tt) &&
-         (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b));
-}
-
-
 unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
   unsigned int h = seed ^ cast(unsigned int, l);
-  size_t l1;
   size_t step = (l >> LUAI_HASHLIMIT) + 1;
-  for (l1 = l; l1 >= step; l1 -= step)
-    h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
+  for (; l >= step; l -= step)
+    h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
   return h;
 }
 
 
+unsigned int luaS_hashlongstr (TString *ts) {
+  lua_assert(ts->tt == LUA_TLNGSTR);
+  if (ts->extra == 0) {  /* no hash? */
+    ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash);
+    ts->extra = 1;  /* now it has its hash */
+  }
+  return ts->hash;
+}
+
+
 /*
 ** resizes the string table
 */
 void luaS_resize (lua_State *L, int newsize) {
   int i;
   stringtable *tb = &G(L)->strt;
-  /* cannot resize while GC is traversing strings */
-  luaC_runtilstate(L, ~bitmask(GCSsweepstring));
-  if (newsize > tb->size) {
-    luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
-    for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL;
+  if (newsize > tb->size) {  /* grow table if needed */
+    luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
+    for (i = tb->size; i < newsize; i++)
+      tb->hash[i] = NULL;
   }
-  /* rehash */
-  for (i=0; i<tb->size; i++) {
-    GCObject *p = tb->hash[i];
+  for (i = 0; i < tb->size; i++) {  /* rehash */
+    TString *p = tb->hash[i];
     tb->hash[i] = NULL;
     while (p) {  /* for each node in the list */
-      GCObject *next = gch(p)->next;  /* save next */
-      unsigned int h = lmod(gco2ts(p)->hash, newsize);  /* new position */
-      gch(p)->next = tb->hash[h];  /* chain it */
+      TString *hnext = p->u.hnext;  /* save next */
+      unsigned int h = lmod(p->hash, newsize);  /* new position */
+      p->u.hnext = tb->hash[h];  /* chain it */
       tb->hash[h] = p;
-      resetoldbit(p);  /* see MOVE OLD rule */
-      p = next;
+      p = hnext;
     }
   }
-  if (newsize < tb->size) {
-    /* shrinking slice must be empty */
+  if (newsize < tb->size) {  /* shrink table if needed */
+    /* vanishing slice should be empty */
     lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL);
-    luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *);
+    luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
   }
   tb->size = 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, j;
+  for (i = 0; i < STRCACHE_N; i++)
+    for (j = 0; j < STRCACHE_M; j++) {
+    if (iswhite(g->strcache[i][j]))  /* will entry be collected? */
+      g->strcache[i][j] = 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, j;
+  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_N; i++)  /* fill cache with valid strings */
+    for (j = 0; j < STRCACHE_M; j++)
+      g->strcache[i][j] = g->memerrmsg;
+}
+
+
+
+/*
 ** creates a new string object
 */
-static TString *createstrobj (lua_State *L, const char *str, size_t l,
-                              int tag, unsigned int h, GCObject **list) {
+static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
   TString *ts;
+  GCObject *o;
   size_t totalsize;  /* total size of TString object */
-  totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
-  ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts;
-  ts->tsv.len = l;
-  ts->tsv.hash = h;
-  ts->tsv.extra = 0;
-  memcpy(ts+1, str, l*sizeof(char));
-  ((char *)(ts+1))[l] = '\0';  /* ending 0 */
+  totalsize = sizelstring(l);
+  o = luaC_newobj(L, tag, totalsize);
+  ts = gco2ts(o);
+  ts->hash = h;
+  ts->extra = 0;
+  getstr(ts)[l] = '\0';  /* ending 0 */
   return ts;
 }
 
 
-/*
-** creates a new short string, inserting it into string table
-*/
-static TString *newshrstr (lua_State *L, const char *str, size_t l,
-                                       unsigned int h) {
-  GCObject **list;  /* (pointer to) list where it will be inserted */
+TString *luaS_createlngstrobj (lua_State *L, size_t l) {
+  TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed);
+  ts->u.lnglen = l;
+  return ts;
+}
+
+
+void luaS_remove (lua_State *L, TString *ts) {
   stringtable *tb = &G(L)->strt;
-  TString *s;
-  if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
-    luaS_resize(L, tb->size*2);  /* too crowded */
-  list = &tb->hash[lmod(h, tb->size)];
-  s = createstrobj(L, str, l, LUA_TSHRSTR, h, list);
-  tb->nuse++;
-  return s;
+  TString **p = &tb->hash[lmod(ts->hash, tb->size)];
+  while (*p != ts)  /* find previous element */
+    p = &(*p)->u.hnext;
+  *p = (*p)->u.hnext;  /* remove element from its list */
+  tb->nuse--;
 }
 
 
@@ -131,22 +165,31 @@ static TString *newshrstr (lua_State *L, const char *str, size_t l,
 ** checks whether short string exists and reuses it or creates a new one
 */
 static TString *internshrstr (lua_State *L, const char *str, size_t l) {
-  GCObject *o;
+  TString *ts;
   global_State *g = G(L);
   unsigned int h = luaS_hash(str, l, g->seed);
-  for (o = g->strt.hash[lmod(h, g->strt.size)];
-       o != NULL;
-       o = gch(o)->next) {
-    TString *ts = rawgco2ts(o);
-    if (h == ts->tsv.hash &&
-        l == ts->tsv.len &&
+  TString **list = &g->strt.hash[lmod(h, g->strt.size)];
+  lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */
+  for (ts = *list; ts != NULL; ts = ts->u.hnext) {
+    if (l == ts->shrlen &&
         (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
-      if (isdead(G(L), o))  /* string is dead (but was not collected yet)? */
-        changewhite(o);  /* resurrect it */
+      /* found! */
+      if (isdead(g, ts))  /* dead (but not collected yet)? */
+        changewhite(ts);  /* resurrect it */
       return ts;
     }
   }
-  return newshrstr(L, str, l, h);  /* not found; create a new string */
+  if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
+    luaS_resize(L, g->strt.size * 2);
+    list = &g->strt.hash[lmod(h, g->strt.size)];  /* recompute with new size */
+  }
+  ts = createstrobj(L, l, LUA_TSHRSTR, h);
+  memcpy(getstr(ts), str, l * sizeof(char));
+  ts->shrlen = cast_byte(l);
+  ts->u.hnext = *list;
+  *list = ts;
+  g->strt.nuse++;
+  return ts;
 }
 
 
@@ -157,29 +200,49 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
   if (l <= LUAI_MAXSHORTLEN)  /* short string? */
     return internshrstr(L, str, l);
   else {
-    if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
+    TString *ts;
+    if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
       luaM_toobig(L);
-    return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL);
+    ts = luaS_createlngstrobj(L, l);
+    memcpy(getstr(ts), str, l * sizeof(char));
+    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_N;  /* hash */
+  int j;
+  TString **p = G(L)->strcache[i];
+  for (j = 0; j < STRCACHE_M; j++) {
+    if (strcmp(str, getstr(p[j])) == 0)  /* hit? */
+      return p[j];  /* that is it */
+  }
+  /* normal route */
+  for (j = STRCACHE_M - 1; j > 0; j--)
+    p[j] = p[j - 1];  /* move out last element */
+  /* new element is first in the list */
+  p[0] = luaS_newlstr(L, str, strlen(str));
+  return p[0];
 }
 
 
-Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
+Udata *luaS_newudata (lua_State *L, size_t s) {
   Udata *u;
-  if (s > MAX_SIZET - sizeof(Udata))
+  GCObject *o;
+  if (s > MAX_SIZE - sizeof(Udata))
     luaM_toobig(L);
-  u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u;
-  u->uv.len = s;
-  u->uv.metatable = NULL;
-  u->uv.env = e;
+  o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s));
+  u = gco2u(o);
+  u->len = s;
+  u->metatable = NULL;
+  setuservalue(L, u, luaO_nilobject);
   return u;
 }
 
index 260e7f1..27efd20 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
 #include "lstate.h"
 
 
-#define sizestring(s)  (sizeof(union TString)+((s)->len+1)*sizeof(char))
+#define sizelstring(l)  (sizeof(union UTString) + ((l) + 1) * sizeof(char))
 
-#define sizeudata(u)   (sizeof(union Udata)+(u)->len)
+#define sizeludata(l)  (sizeof(union UUdata) + (l))
+#define sizeudata(u)   sizeludata((u)->len)
 
 #define luaS_newliteral(L, s)  (luaS_newlstr(L, "" s, \
                                  (sizeof(s)/sizeof(char))-1))
 
-#define luaS_fix(s)    l_setbit((s)->tsv.marked, FIXEDBIT)
-
 
 /*
 ** test whether a string is a reserved word
 */
-#define isreserved(s)  ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0)
+#define isreserved(s)  ((s)->tt == LUA_TSHRSTR && (s)->extra > 0)
 
 
 /*
 ** equality for short strings, which are always internalized
 */
-#define eqshrstr(a,b)  check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b))
+#define eqshrstr(a,b)  check_exp((a)->tt == LUA_TSHRSTR, (a) == (b))
 
 
 LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
+LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
 LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
-LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
-LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
+LUAI_FUNC 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);
 LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
+LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
 
 
 #endif
index 9261fd2..12264f8 100644 (file)
@@ -1,19 +1,24 @@
 /*
-** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lstrlib.c,v 1.251 2016/05/20 14:13:21 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */
 
+#define lstrlib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <ctype.h>
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define lstrlib_c
-#define LUA_LIB
-
 #include "lua.h"
 
 #include "lauxlib.h"
 
 /*
 ** maximum number of captures that a pattern can do during
-** pattern-matching. This limit is arbitrary.
+** pattern-matching. This limit is arbitrary, but must fit in
+** an unsigned char.
 */
 #if !defined(LUA_MAXCAPTURES)
 #define LUA_MAXCAPTURES                32
 #endif
 
 
-/* macro to `unsign' a character */
+/* macro to 'unsign' a character */
 #define uchar(c)       ((unsigned char)(c))
 
 
+/*
+** Some sizes are better limited to fit in 'int', but must also fit in
+** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
+*/
+#define MAX_SIZET      ((size_t)(~(size_t)0))
+
+#define MAXSIZE  \
+       (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
+
+
+
 
 static int str_len (lua_State *L) {
   size_t l;
@@ -43,22 +60,22 @@ static int str_len (lua_State *L) {
 
 
 /* translate a relative string position: negative means back from end */
-static size_t posrelat (ptrdiff_t pos, size_t len) {
-  if (pos >= 0) return (size_t)pos;
+static lua_Integer posrelat (lua_Integer pos, size_t len) {
+  if (pos >= 0) return pos;
   else if (0u - (size_t)pos > len) return 0;
-  else return len - ((size_t)-pos) + 1;
+  else return (lua_Integer)len + pos + 1;
 }
 
 
 static int str_sub (lua_State *L) {
   size_t l;
   const char *s = luaL_checklstring(L, 1, &l);
-  size_t start = posrelat(luaL_checkinteger(L, 2), l);
-  size_t end = posrelat(luaL_optinteger(L, 3, -1), l);
+  lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
+  lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
   if (start < 1) start = 1;
-  if (end > l) end = l;
+  if (end > (lua_Integer)l) end = l;
   if (start <= end)
-    lua_pushlstring(L, s + start - 1, end - start + 1);
+    lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
   else lua_pushliteral(L, "");
   return 1;
 }
@@ -102,25 +119,23 @@ static int str_upper (lua_State *L) {
 }
 
 
-/* reasonable limit to avoid arithmetic overflow */
-#define MAXSIZE                ((~(size_t)0) >> 1)
-
 static int str_rep (lua_State *L) {
   size_t l, lsep;
   const char *s = luaL_checklstring(L, 1, &l);
-  int n = luaL_checkint(L, 2);
+  lua_Integer n = luaL_checkinteger(L, 2);
   const char *sep = luaL_optlstring(L, 3, "", &lsep);
   if (n <= 0) lua_pushliteral(L, "");
-  else if (l + lsep < l || l + lsep >= MAXSIZE / n)  /* may overflow? */
+  else if (l + lsep < l || l + lsep > MAXSIZE / n)  /* may overflow? */
     return luaL_error(L, "resulting string too large");
   else {
-    size_t totallen = n * l + (n - 1) * lsep;
+    size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
     luaL_Buffer b;
     char *p = luaL_buffinitsize(L, &b, totallen);
     while (n-- > 1) {  /* first n-1 copies (followed by separator) */
       memcpy(p, s, l * sizeof(char)); p += l;
-      if (lsep > 0) {  /* avoid empty 'memcpy' (may be expensive) */
-        memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+      if (lsep > 0) {  /* empty 'memcpy' is not that cheap */
+        memcpy(p, sep, lsep * sizeof(char));
+        p += lsep;
       }
     }
     memcpy(p, s, l * sizeof(char));  /* last copy (not followed by separator) */
@@ -133,15 +148,15 @@ static int str_rep (lua_State *L) {
 static int str_byte (lua_State *L) {
   size_t l;
   const char *s = luaL_checklstring(L, 1, &l);
-  size_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
-  size_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
+  lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
+  lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
   int n, i;
   if (posi < 1) posi = 1;
-  if (pose > l) pose = l;
+  if (pose > (lua_Integer)l) pose = l;
   if (posi > pose) return 0;  /* empty interval; return no values */
-  n = (int)(pose -  posi + 1);
-  if (posi + n <= pose)  /* (size_t -> int) overflow? */
+  if (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]));
@@ -155,7 +170,7 @@ static int str_char (lua_State *L) {
   luaL_Buffer b;
   char *p = luaL_buffinitsize(L, &b, n);
   for (i=1; i<=n; i++) {
-    int c = luaL_checkint(L, i);
+    lua_Integer c = luaL_checkinteger(L, i);
     luaL_argcheck(L, uchar(c) == c, i, "value out of range");
     p[i - 1] = uchar(c);
   }
@@ -164,19 +179,20 @@ static int str_char (lua_State *L) {
 }
 
 
-static int writer (lua_State *L, const void* b, size_t size, void* B) {
+static int writer (lua_State *L, const void *b, size_t size, void *B) {
   (void)L;
-  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
+  luaL_addlstring((luaL_Buffer *) B, (const char *)b, size);
   return 0;
 }
 
 
 static int str_dump (lua_State *L) {
   luaL_Buffer b;
+  int strip = lua_toboolean(L, 2);
   luaL_checktype(L, 1, LUA_TFUNCTION);
   lua_settop(L, 1);
   luaL_buffinit(L,&b);
-  if (lua_dump(L, writer, &b) != 0)
+  if (lua_dump(L, writer, &b, strip) != 0)
     return luaL_error(L, "unable to dump given function");
   luaL_pushresult(&b);
   return 1;
@@ -196,12 +212,12 @@ static int str_dump (lua_State *L) {
 
 
 typedef struct MatchState {
-  int matchdepth;  /* control for recursive depth (to avoid C stack overflow) */
   const char *src_init;  /* init of source string */
   const char *src_end;  /* end ('\0') of source string */
   const char *p_end;  /* end ('\0') of pattern */
   lua_State *L;
-  int level;  /* total number of captures (finished or unfinished) */
+  int matchdepth;  /* control for recursive depth (to avoid C stack overflow) */
+  unsigned char level;  /* total number of captures (finished or unfinished) */
   struct {
     const char *init;
     ptrdiff_t len;
@@ -243,16 +259,16 @@ static const char *classend (MatchState *ms, const char *p) {
   switch (*p++) {
     case L_ESC: {
       if (p == ms->p_end)
-        luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
+        luaL_error(ms->L, "malformed pattern (ends with '%%')");
       return p+1;
     }
     case '[': {
       if (*p == '^') p++;
-      do {  /* look for a `]' */
+      do {  /* look for a ']' */
         if (p == ms->p_end)
-          luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+          luaL_error(ms->L, "malformed pattern (missing ']')");
         if (*(p++) == L_ESC && p < ms->p_end)
-          p++;  /* skip escapes (e.g. `%]') */
+          p++;  /* skip escapes (e.g. '%]') */
       } while (*p != ']');
       return p+1;
     }
@@ -287,7 +303,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
   int sig = 1;
   if (*(p+1) == '^') {
     sig = 0;
-    p++;  /* skip the `^' */
+    p++;  /* skip the '^' */
   }
   while (++p < ec) {
     if (*p == L_ESC) {
@@ -325,8 +341,7 @@ static int singlematch (MatchState *ms, const char *s, const char *p,
 static const char *matchbalance (MatchState *ms, const char *s,
                                    const char *p) {
   if (p >= ms->p_end - 1)
-    luaL_error(ms->L, "malformed pattern "
-                      "(missing arguments to " LUA_QL("%%b") ")");
+    luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
   if (*s != *p) return NULL;
   else {
     int b = *p;
@@ -425,7 +440,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
         break;
       }
       case '$': {
-        if ((p + 1) != ms->p_end)  /* is the `$' the last char in pattern? */
+        if ((p + 1) != ms->p_end)  /* is the '$' the last char in pattern? */
           goto dflt;  /* no; go to default */
         s = (s == ms->src_end) ? s : NULL;  /* check end of string */
         break;
@@ -443,8 +458,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
             const char *ep; char previous;
             p += 2;
             if (*p != '[')
-              luaL_error(ms->L, "missing " LUA_QL("[") " after "
-                                 LUA_QL("%%f") " in pattern");
+              luaL_error(ms->L, "missing '[' after '%%f' in pattern");
             ep = classend(ms, p);  /* points to what is next */
             previous = (s == ms->src_init) ? '\0' : *(s - 1);
             if (!matchbracketclass(uchar(previous), p, ep - 1) &&
@@ -490,7 +504,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;
@@ -514,16 +528,16 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
 static const char *lmemfind (const char *s1, size_t l1,
                                const char *s2, size_t l2) {
   if (l2 == 0) return s1;  /* empty strings are everywhere */
-  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */
+  else if (l2 > l1) return NULL;  /* avoids a negative 'l1' */
   else {
-    const char *init;  /* to search for a `*s2' inside `s1' */
-    l2--;  /* 1st char will be checked by `memchr' */
-    l1 = l1-l2;  /* `s2' cannot be found after that */
+    const char *init;  /* to search for a '*s2' inside 's1' */
+    l2--;  /* 1st char will be checked by 'memchr' */
+    l1 = l1-l2;  /* 's2' cannot be found after that */
     while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
       init++;   /* 1st char is already checked */
       if (memcmp(init, s2+1, l2) == 0)
         return init-1;
-      else {  /* correct `l1' and `s1' to try again */
+      else {  /* correct 'l1' and 's1' to try again */
         l1 -= init-s1;
         s1 = init;
       }
@@ -539,13 +553,13 @@ static void push_onecapture (MatchState *ms, int i, const char *s,
     if (i == 0)  /* ms->level == 0, too */
       lua_pushlstring(ms->L, s, e - s);  /* add whole match */
     else
-      luaL_error(ms->L, "invalid capture index");
+      luaL_error(ms->L, "invalid capture index %%%d", i + 1);
   }
   else {
     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);
   }
@@ -574,23 +588,39 @@ static int nospecials (const char *p, size_t l) {
 }
 
 
+static void prepstate (MatchState *ms, lua_State *L,
+                       const char *s, size_t ls, const char *p, size_t lp) {
+  ms->L = L;
+  ms->matchdepth = MAXCCALLS;
+  ms->src_init = s;
+  ms->src_end = s + ls;
+  ms->p_end = p + lp;
+}
+
+
+static void reprepstate (MatchState *ms) {
+  ms->level = 0;
+  lua_assert(ms->matchdepth == MAXCCALLS);
+}
+
+
 static int str_find_aux (lua_State *L, int find) {
   size_t ls, lp;
   const char *s = luaL_checklstring(L, 1, &ls);
   const char *p = luaL_checklstring(L, 2, &lp);
-  size_t init = posrelat(luaL_optinteger(L, 3, 1), ls);
+  lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
   if (init < 1) init = 1;
-  else if (init > ls + 1) {  /* start after string's end? */
+  else if (init > (lua_Integer)ls + 1) {  /* start after string's end? */
     lua_pushnil(L);  /* cannot find anything */
     return 1;
   }
   /* explicit request or no special characters? */
   if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
     /* do a plain search */
-    const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp);
+    const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
     if (s2) {
-      lua_pushinteger(L, s2 - s + 1);
-      lua_pushinteger(L, s2 - s + lp);
+      lua_pushinteger(L, (s2 - s) + 1);
+      lua_pushinteger(L, (s2 - s) + lp);
       return 2;
     }
   }
@@ -601,18 +631,13 @@ static int str_find_aux (lua_State *L, int find) {
     if (anchor) {
       p++; lp--;  /* skip anchor character */
     }
-    ms.L = L;
-    ms.matchdepth = MAXCCALLS;
-    ms.src_init = s;
-    ms.src_end = s + ls;
-    ms.p_end = p + lp;
+    prepstate(&ms, L, s, ls, p, lp);
     do {
       const char *res;
-      ms.level = 0;
-      lua_assert(ms.matchdepth == MAXCCALLS);
+      reprepstate(&ms);
       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;
         }
@@ -636,29 +661,25 @@ static int str_match (lua_State *L) {
 }
 
 
+/* state for 'gmatch' */
+typedef struct GMatchState {
+  const char *src;  /* current position */
+  const char *p;  /* pattern */
+  const char *lastmatch;  /* end of last match */
+  MatchState ms;  /* match state */
+} GMatchState;
+
+
 static int gmatch_aux (lua_State *L) {
-  MatchState ms;
-  size_t ls, lp;
-  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
-  const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
+  GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
   const char *src;
-  ms.L = L;
-  ms.matchdepth = MAXCCALLS;
-  ms.src_init = s;
-  ms.src_end = s+ls;
-  ms.p_end = p + lp;
-  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
-       src <= ms.src_end;
-       src++) {
+  gm->ms.L = L;
+  for (src = gm->src; src <= gm->ms.src_end; src++) {
     const char *e;
-    ms.level = 0;
-    lua_assert(ms.matchdepth == MAXCCALLS);
-    if ((e = match(&ms, src, p)) != NULL) {
-      lua_Integer newstart = e-s;
-      if (e == src) newstart++;  /* empty match? go at least one position */
-      lua_pushinteger(L, newstart);
-      lua_replace(L, lua_upvalueindex(3));
-      return push_captures(&ms, src, e);
+    reprepstate(&gm->ms);
+    if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
+      gm->src = gm->lastmatch = e;
+      return push_captures(&gm->ms, src, e);
     }
   }
   return 0;  /* not found */
@@ -666,10 +687,14 @@ static int gmatch_aux (lua_State *L) {
 
 
 static int gmatch (lua_State *L) {
-  luaL_checkstring(L, 1);
-  luaL_checkstring(L, 2);
-  lua_settop(L, 2);
-  lua_pushinteger(L, 0);
+  size_t ls, lp;
+  const char *s = luaL_checklstring(L, 1, &ls);
+  const char *p = luaL_checklstring(L, 2, &lp);
+  GMatchState *gm;
+  lua_settop(L, 2);  /* keep them on closure to avoid being collected */
+  gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
+  prepstate(&gm->ms, L, s, ls, p, lp);
+  gm->src = s; gm->p = p; gm->lastmatch = NULL;
   lua_pushcclosure(L, gmatch_aux, 3);
   return 1;
 }
@@ -678,7 +703,8 @@ static int gmatch (lua_State *L) {
 static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
                                                    const char *e) {
   size_t l, i;
-  const char *news = lua_tolstring(ms->L, 3, &l);
+  lua_State *L = ms->L;
+  const char *news = lua_tolstring(L, 3, &l);
   for (i = 0; i < l; i++) {
     if (news[i] != L_ESC)
       luaL_addchar(b, news[i]);
@@ -686,14 +712,15 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
       i++;  /* skip ESC */
       if (!isdigit(uchar(news[i]))) {
         if (news[i] != L_ESC)
-          luaL_error(ms->L, "invalid use of " LUA_QL("%c")
-                           " in replacement string", L_ESC);
+          luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
         luaL_addchar(b, news[i]);
       }
       else if (news[i] == '0')
           luaL_addlstring(b, s, e - s);
       else {
         push_onecapture(ms, news[i] - '1', s, e);
+        luaL_tolstring(L, -1, NULL);  /* if number, convert it to string */
+        lua_remove(L, -2);  /* remove original value */
         luaL_addvalue(b);  /* add capture to accumulated result */
       }
     }
@@ -734,12 +761,13 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
 
 static int str_gsub (lua_State *L) {
   size_t srcl, lp;
-  const char *src = luaL_checklstring(L, 1, &srcl);
-  const char *p = luaL_checklstring(L, 2, &lp);
-  int tr = lua_type(L, 3);
-  size_t max_s = luaL_optinteger(L, 4, srcl+1);
+  const char *src = luaL_checklstring(L, 1, &srcl);  /* subject */
+  const char *p = luaL_checklstring(L, 2, &lp);  /* pattern */
+  const char *lastmatch = NULL;  /* end of last match */
+  int tr = lua_type(L, 3);  /* replacement type */
+  lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1);  /* max replacements */
   int anchor = (*p == '^');
-  size_t n = 0;
+  lua_Integer n = 0;  /* replacement count */
   MatchState ms;
   luaL_Buffer b;
   luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
@@ -749,25 +777,18 @@ static int str_gsub (lua_State *L) {
   if (anchor) {
     p++; lp--;  /* skip anchor character */
   }
-  ms.L = L;
-  ms.matchdepth = MAXCCALLS;
-  ms.src_init = src;
-  ms.src_end = src+srcl;
-  ms.p_end = p + lp;
+  prepstate(&ms, L, src, srcl, p, lp);
   while (n < max_s) {
     const char *e;
-    ms.level = 0;
-    lua_assert(ms.matchdepth == MAXCCALLS);
-    e = match(&ms, src, p);
-    if (e) {
+    reprepstate(&ms);  /* (re)prepare state for new match */
+    if ((e = match(&ms, src, p)) != NULL && e != lastmatch) {  /* match? */
       n++;
-      add_value(&ms, &b, src, e, tr);
+      add_value(&ms, &b, src, e, tr);  /* add replacement to buffer */
+      src = lastmatch = e;
     }
-    if (e && e>src) /* non empty match? */
-      src = e;  /* skip it */
-    else if (src < ms.src_end)
+    else if (src < ms.src_end)  /* otherwise, skip one character */
       luaL_addchar(&b, *src++);
-    else break;
+    else break;  /* end of subject */
     if (anchor) break;
   }
   luaL_addlstring(&b, src, ms.src_end-src);
@@ -786,65 +807,116 @@ static int str_gsub (lua_State *L) {
 ** =======================================================
 */
 
+#if !defined(lua_number2strx)  /* { */
+
 /*
-** LUA_INTFRMLEN is the length modifier for integer conversions in
-** 'string.format'; LUA_INTFRM_T is the integer type corresponding to
-** the previous length
+** Hexadecimal floating-point formatter
 */
-#if !defined(LUA_INTFRMLEN)    /* { */
-#if defined(LUA_USE_LONGLONG)
 
-#define LUA_INTFRMLEN          "ll"
-#define LUA_INTFRM_T           long long
+#include <math.h>
 
-#else
+#define SIZELENMOD     (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
 
-#define LUA_INTFRMLEN          "l"
-#define LUA_INTFRM_T           long
 
-#endif
-#endif                         /* } */
+/*
+** 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)
 
 
 /*
-** LUA_FLTFRMLEN is the length modifier for float conversions in
-** 'string.format'; LUA_FLTFRM_T is the float type corresponding to
-** the previous length
+** Add integer part of 'x' to buffer and return new 'x'
 */
-#if !defined(LUA_FLTFRMLEN)
+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 */
+}
 
-#define LUA_FLTFRMLEN          ""
-#define LUA_FLTFRM_T           double
 
-#endif
+static int num2straux (char *buff, int sz, lua_Number x) {
+  if (x != x || x == HUGE_VAL || x == -HUGE_VAL)  /* inf or NaN? */
+    return l_sprintf(buff, sz, LUA_NUMBER_FMT, x);  /* equal to '%g' */
+  else if (x == 0) {  /* can be -0... */
+    /* create "0" or "-0" followed by exponent */
+    return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x);
+  }
+  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 += l_sprintf(buff + n, sz - n, "p%+d", e);  /* add exponent */
+    lua_assert(n < sz);
+    return n;
+  }
+}
+
+
+static int lua_number2strx (lua_State *L, char *buff, int sz,
+                            const char *fmt, lua_Number x) {
+  int n = num2straux(buff, sz, 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', -maxfloat), and is equal to 99 + 3 ('-', '.',
+** and '\0') + number of decimal digits to represent maxfloat (which
+** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
+** expenses", such as locale-dependent stuff)
+*/
+#define MAX_ITEM        (120 + l_mathlim(MAX_10_EXP))
 
 
-/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
-#define MAX_ITEM       512
 /* valid flags in a format specification */
 #define FLAGS  "-+ #0"
+
 /*
-** maximum size of each format specification (such as '%-099.99d')
-** (+10 accounts for %99.99x plus margin of error)
+** maximum size of each format specification (such as "%-099.99d")
 */
-#define MAX_FORMAT     (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
+#define MAX_FORMAT     32
 
 
-static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
-  size_t l;
-  const char *s = luaL_checklstring(L, arg, &l);
+static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
   luaL_addchar(b, '"');
-  while (l--) {
+  while (len--) {
     if (*s == '"' || *s == '\\' || *s == '\n') {
       luaL_addchar(b, '\\');
       luaL_addchar(b, *s);
     }
-    else if (*s == '\0' || iscntrl(uchar(*s))) {
+    else if (iscntrl(uchar(*s))) {
       char buff[10];
       if (!isdigit(uchar(*(s+1))))
-        sprintf(buff, "\\%d", (int)uchar(*s));
+        l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
       else
-        sprintf(buff, "\\%03d", (int)uchar(*s));
+        l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
       luaL_addstring(b, buff);
     }
     else
@@ -854,6 +926,57 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
   luaL_addchar(b, '"');
 }
 
+
+/*
+** Ensures the 'buff' string uses a dot as the radix character.
+*/
+static void checkdp (char *buff, int nb) {
+  if (memchr(buff, '.', nb) == NULL) {  /* no dot? */
+    char point = lua_getlocaledecpoint();  /* try locale point */
+    char *ppoint = memchr(buff, point, nb);
+    if (ppoint) *ppoint = '.';  /* change it to a dot */
+  }
+}
+
+
+static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
+  switch (lua_type(L, arg)) {
+    case LUA_TSTRING: {
+      size_t len;
+      const char *s = lua_tolstring(L, arg, &len);
+      addquoted(b, s, len);
+      break;
+    }
+    case LUA_TNUMBER: {
+      char *buff = luaL_prepbuffsize(b, MAX_ITEM);
+      int nb;
+      if (!lua_isinteger(L, arg)) {  /* float? */
+        lua_Number n = lua_tonumber(L, arg);  /* write as hexa ('%a') */
+        nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
+        checkdp(buff, nb);  /* ensure it uses a dot */
+      }
+      else {  /* integers */
+        lua_Integer n = lua_tointeger(L, arg);
+        const char *format = (n == LUA_MININTEGER)  /* corner case? */
+                           ? "0x%" LUA_INTEGER_FRMLEN "x"  /* use hexa */
+                           : LUA_INTEGER_FMT;  /* else use default format */
+        nb = l_sprintf(buff, MAX_ITEM, format, n);
+      }
+      luaL_addsize(b, nb);
+      break;
+    }
+    case LUA_TNIL: case LUA_TBOOLEAN: {
+      luaL_tolstring(L, arg, NULL);
+      luaL_addvalue(b);
+      break;
+    }
+    default: {
+      luaL_argerror(L, arg, "value has no literal form");
+    }
+  }
+}
+
+
 static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
   const char *p = strfrmt;
   while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++;  /* skip flags */
@@ -869,8 +992,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;
 }
@@ -903,7 +1026,7 @@ static int str_format (lua_State *L) {
     else if (*++strfrmt == L_ESC)
       luaL_addchar(&b, *strfrmt++);  /* %% */
     else { /* format item */
-      char form[MAX_FORMAT];  /* to store the format (`%...') */
+      char form[MAX_FORMAT];  /* to store the format ('%...') */
       char *buff = luaL_prepbuffsize(&b, MAX_ITEM);  /* to put formatted item */
       int nb = 0;  /* number of bytes in added item */
       if (++arg > top)
@@ -911,62 +1034,55 @@ static int str_format (lua_State *L) {
       strfrmt = scanformat(L, strfrmt, form);
       switch (*strfrmt++) {
         case 'c': {
-          nb = sprintf(buff, form, luaL_checkint(L, arg));
-          break;
-        }
-        case 'd': case 'i': {
-          lua_Number n = luaL_checknumber(L, arg);
-          LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
-          lua_Number diff = n - (lua_Number)ni;
-          luaL_argcheck(L, -1 < diff && diff < 1, arg,
-                        "not a number in proper range");
-          addlenmod(form, LUA_INTFRMLEN);
-          nb = sprintf(buff, form, ni);
+          nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
           break;
         }
+        case 'd': case 'i':
         case 'o': case 'u': case 'x': case 'X': {
-          lua_Number n = luaL_checknumber(L, arg);
-          unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
-          lua_Number diff = n - (lua_Number)ni;
-          luaL_argcheck(L, -1 < diff && diff < 1, arg,
-                        "not a non-negative number in proper range");
-          addlenmod(form, LUA_INTFRMLEN);
-          nb = sprintf(buff, form, ni);
+          lua_Integer n = luaL_checkinteger(L, arg);
+          addlenmod(form, LUA_INTEGER_FRMLEN);
+          nb = l_sprintf(buff, MAX_ITEM, form, n);
           break;
         }
-        case 'e': case 'E': case 'f':
-#if defined(LUA_USE_AFORMAT)
         case 'a': case 'A':
-#endif
+          addlenmod(form, LUA_NUMBER_FRMLEN);
+          nb = lua_number2strx(L, buff, MAX_ITEM, form,
+                                  luaL_checknumber(L, arg));
+          break;
+        case 'e': case 'E': case 'f':
         case 'g': case 'G': {
-          addlenmod(form, LUA_FLTFRMLEN);
-          nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg));
+          addlenmod(form, LUA_NUMBER_FRMLEN);
+          nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg));
           break;
         }
         case 'q': {
-          addquoted(L, &b, arg);
+          addliteral(L, &b, arg);
           break;
         }
         case 's': {
           size_t l;
           const char *s = luaL_tolstring(L, arg, &l);
-          if (!strchr(form, '.') && l >= 100) {
-            /* no precision and string is too long to be formatted;
-               keep original string */
-            luaL_addvalue(&b);
-            break;
-          }
+          if (form[2] == '\0')  /* no modifiers? */
+            luaL_addvalue(&b);  /* keep entire string */
           else {
-            nb = sprintf(buff, form, s);
-            lua_pop(L, 1);  /* remove result from 'luaL_tolstring' */
-            break;
+            luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
+            if (!strchr(form, '.') && l >= 100) {
+              /* no precision and string is too long to be formatted */
+              luaL_addvalue(&b);  /* keep entire string */
+            }
+            else {  /* format the string into 'buff' */
+              nb = l_sprintf(buff, MAX_ITEM, form, s);
+              lua_pop(L, 1);  /* remove result from 'luaL_tolstring' */
+            }
           }
+          break;
         }
-        default: {  /* also treat cases `pnLlh' */
-          return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
-                               LUA_QL("format"), *(strfrmt - 1));
+        default: {  /* also treat cases 'pnLlh' */
+          return luaL_error(L, "invalid option '%%%c' to 'format'",
+                               *(strfrmt - 1));
         }
       }
+      lua_assert(nb < MAX_ITEM);
       luaL_addsize(&b, nb);
     }
   }
@@ -977,6 +1093,450 @@ static int str_format (lua_State *L) {
 /* }====================================================== */
 
 
+/*
+** {======================================================
+** PACK/UNPACK
+** =======================================================
+*/
+
+
+/* value used for padding */
+#if !defined(LUAL_PACKPADBYTE)
+#define LUAL_PACKPADBYTE               0x00
+#endif
+
+/* maximum size for the binary representation of an integer */
+#define MAXINTSIZE     16
+
+/* number of bits in a character */
+#define NB     CHAR_BIT
+
+/* mask for one character (NB 1's) */
+#define MC     ((1 << NB) - 1)
+
+/* size of a lua_Integer */
+#define SZINT  ((int)sizeof(lua_Integer))
+
+
+/* dummy union to get native endianness */
+static const union {
+  int dummy;
+  char little;  /* true iff machine is little endian */
+} nativeendian = {1};
+
+
+/* dummy structure to get native alignment requirements */
+struct cD {
+  char c;
+  union { double d; void *p; lua_Integer i; lua_Number n; } u;
+};
+
+#define MAXALIGN       (offsetof(struct cD, u))
+
+
+/*
+** Union for serializing floats
+*/
+typedef union Ftypes {
+  float f;
+  double d;
+  lua_Number n;
+  char buff[5 * sizeof(lua_Number)];  /* enough for any float type */
+} Ftypes;
+
+
+/*
+** information to pack/unpack stuff
+*/
+typedef struct Header {
+  lua_State *L;
+  int islittle;
+  int maxalign;
+} Header;
+
+
+/*
+** options for pack/unpack
+*/
+typedef enum KOption {
+  Kint,                /* signed integers */
+  Kuint,       /* unsigned integers */
+  Kfloat,      /* floating-point numbers */
+  Kchar,       /* fixed-length strings */
+  Kstring,     /* strings with prefixed length */
+  Kzstr,       /* zero-terminated strings */
+  Kpadding,    /* padding */
+  Kpaddalign,  /* padding for alignment */
+  Knop         /* no-op (configuration or spaces) */
+} KOption;
+
+
+/*
+** Read an integer numeral from string 'fmt' or return 'df' if
+** there is no numeral
+*/
+static int digit (int c) { return '0' <= c && c <= '9'; }
+
+static int getnum (const char **fmt, int df) {
+  if (!digit(**fmt))  /* no number? */
+    return df;  /* return default value */
+  else {
+    int a = 0;
+    do {
+      a = a*10 + (*((*fmt)++) - '0');
+    } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
+    return a;
+  }
+}
+
+
+/*
+** Read an integer numeral and raises an error if it is larger
+** than the maximum size for integers.
+*/
+static int getnumlimit (Header *h, const char **fmt, int df) {
+  int sz = getnum(fmt, df);
+  if (sz > MAXINTSIZE || sz <= 0)
+    luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
+                     sz, MAXINTSIZE);
+  return sz;
+}
+
+
+/*
+** Initialize Header
+*/
+static void initheader (lua_State *L, Header *h) {
+  h->L = L;
+  h->islittle = nativeendian.little;
+  h->maxalign = 1;
+}
+
+
+/*
+** Read and classify next option. 'size' is filled with option's size.
+*/
+static KOption getoption (Header *h, const char **fmt, int *size) {
+  int opt = *((*fmt)++);
+  *size = 0;  /* default */
+  switch (opt) {
+    case 'b': *size = sizeof(char); return Kint;
+    case 'B': *size = sizeof(char); return Kuint;
+    case 'h': *size = sizeof(short); return Kint;
+    case 'H': *size = sizeof(short); return Kuint;
+    case 'l': *size = sizeof(long); return Kint;
+    case 'L': *size = sizeof(long); return Kuint;
+    case 'j': *size = sizeof(lua_Integer); return Kint;
+    case 'J': *size = sizeof(lua_Integer); return Kuint;
+    case 'T': *size = sizeof(size_t); return Kuint;
+    case 'f': *size = sizeof(float); return Kfloat;
+    case 'd': *size = sizeof(double); return Kfloat;
+    case 'n': *size = sizeof(lua_Number); return Kfloat;
+    case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
+    case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
+    case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
+    case 'c':
+      *size = getnum(fmt, -1);
+      if (*size == -1)
+        luaL_error(h->L, "missing size for format option 'c'");
+      return Kchar;
+    case 'z': return Kzstr;
+    case 'x': *size = 1; return Kpadding;
+    case 'X': return Kpaddalign;
+    case ' ': break;
+    case '<': h->islittle = 1; break;
+    case '>': h->islittle = 0; break;
+    case '=': h->islittle = nativeendian.little; break;
+    case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
+    default: luaL_error(h->L, "invalid format option '%c'", opt);
+  }
+  return Knop;
+}
+
+
+/*
+** Read, classify, and fill other details about the next option.
+** 'psize' is filled with option's size, 'notoalign' with its
+** alignment requirements.
+** Local variable 'size' gets the size to be aligned. (Kpadal option
+** always gets its full alignment, other options are limited by 
+** the maximum alignment ('maxalign'). Kchar option needs no alignment
+** despite its size.
+*/
+static KOption getdetails (Header *h, size_t totalsize,
+                           const char **fmt, int *psize, int *ntoalign) {
+  KOption opt = getoption(h, fmt, psize);
+  int align = *psize;  /* usually, alignment follows size */
+  if (opt == Kpaddalign) {  /* 'X' gets alignment from following option */
+    if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
+      luaL_argerror(h->L, 1, "invalid next option for option 'X'");
+  }
+  if (align <= 1 || opt == Kchar)  /* need no alignment? */
+    *ntoalign = 0;
+  else {
+    if (align > h->maxalign)  /* enforce maximum alignment */
+      align = h->maxalign;
+    if ((align & (align - 1)) != 0)  /* is 'align' not a power of 2? */
+      luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
+    *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
+  }
+  return opt;
+}
+
+
+/*
+** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
+** The final 'if' handles the case when 'size' is larger than
+** the size of a Lua integer, correcting the extra sign-extension
+** bytes if necessary (by default they would be zeros).
+*/
+static void packint (luaL_Buffer *b, lua_Unsigned n,
+                     int islittle, int size, int neg) {
+  char *buff = luaL_prepbuffsize(b, size);
+  int i;
+  buff[islittle ? 0 : size - 1] = (char)(n & MC);  /* first byte */
+  for (i = 1; i < size; i++) {
+    n >>= NB;
+    buff[islittle ? i : size - 1 - i] = (char)(n & MC);
+  }
+  if (neg && size > SZINT) {  /* negative number need sign extension? */
+    for (i = SZINT; i < size; i++)  /* correct extra bytes */
+      buff[islittle ? i : size - 1 - i] = (char)MC;
+  }
+  luaL_addsize(b, size);  /* add result to buffer */
+}
+
+
+/*
+** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
+** given 'islittle' is different from native endianness.
+*/
+static void copywithendian (volatile char *dest, volatile const char *src,
+                            int size, int islittle) {
+  if (islittle == nativeendian.little) {
+    while (size-- != 0)
+      *(dest++) = *(src++);
+  }
+  else {
+    dest += size - 1;
+    while (size-- != 0)
+      *(dest--) = *(src++);
+  }
+}
+
+
+static int str_pack (lua_State *L) {
+  luaL_Buffer b;
+  Header h;
+  const char *fmt = luaL_checkstring(L, 1);  /* format string */
+  int arg = 1;  /* current argument to pack */
+  size_t totalsize = 0;  /* accumulate total size of result */
+  initheader(L, &h);
+  lua_pushnil(L);  /* mark to separate arguments from string buffer */
+  luaL_buffinit(L, &b);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+    totalsize += ntoalign + size;
+    while (ntoalign-- > 0)
+     luaL_addchar(&b, LUAL_PACKPADBYTE);  /* fill alignment */
+    arg++;
+    switch (opt) {
+      case Kint: {  /* signed integers */
+        lua_Integer n = luaL_checkinteger(L, arg);
+        if (size < SZINT) {  /* need overflow check? */
+          lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
+          luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
+        }
+        packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
+        break;
+      }
+      case Kuint: {  /* unsigned integers */
+        lua_Integer n = luaL_checkinteger(L, arg);
+        if (size < SZINT)  /* need overflow check? */
+          luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
+                           arg, "unsigned overflow");
+        packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
+        break;
+      }
+      case Kfloat: {  /* floating-point options */
+        volatile Ftypes u;
+        char *buff = luaL_prepbuffsize(&b, size);
+        lua_Number n = luaL_checknumber(L, arg);  /* get argument */
+        if (size == sizeof(u.f)) u.f = (float)n;  /* copy it into 'u' */
+        else if (size == sizeof(u.d)) u.d = (double)n;
+        else u.n = n;
+        /* move 'u' to final result, correcting endianness if needed */
+        copywithendian(buff, u.buff, size, h.islittle);
+        luaL_addsize(&b, size);
+        break;
+      }
+      case Kchar: {  /* fixed-size string */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, len <= (size_t)size, arg,
+                         "string longer than given size");
+        luaL_addlstring(&b, s, len);  /* add string */
+        while (len++ < (size_t)size)  /* pad extra space */
+          luaL_addchar(&b, LUAL_PACKPADBYTE);
+        break;
+      }
+      case Kstring: {  /* strings with length count */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, size >= (int)sizeof(size_t) ||
+                         len < ((size_t)1 << (size * NB)),
+                         arg, "string length does not fit in given size");
+        packint(&b, (lua_Unsigned)len, h.islittle, size, 0);  /* pack length */
+        luaL_addlstring(&b, s, len);
+        totalsize += len;
+        break;
+      }
+      case Kzstr: {  /* zero-terminated string */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
+        luaL_addlstring(&b, s, len);
+        luaL_addchar(&b, '\0');  /* add zero at the end */
+        totalsize += len + 1;
+        break;
+      }
+      case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE);  /* FALLTHROUGH */
+      case Kpaddalign: case Knop:
+        arg--;  /* undo increment */
+        break;
+    }
+  }
+  luaL_pushresult(&b);
+  return 1;
+}
+
+
+static int str_packsize (lua_State *L) {
+  Header h;
+  const char *fmt = luaL_checkstring(L, 1);  /* format string */
+  size_t totalsize = 0;  /* accumulate total size of result */
+  initheader(L, &h);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+    size += ntoalign;  /* total space used by option */
+    luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
+                     "format result too large");
+    totalsize += size;
+    switch (opt) {
+      case Kstring:  /* strings with length count */
+      case Kzstr:    /* zero-terminated string */
+        luaL_argerror(L, 1, "variable-length format");
+        /* call never return, but to avoid warnings: *//* FALLTHROUGH */
+      default:  break;
+    }
+  }
+  lua_pushinteger(L, (lua_Integer)totalsize);
+  return 1;
+}
+
+
+/*
+** Unpack an integer with 'size' bytes and 'islittle' endianness.
+** If size is smaller than the size of a Lua integer and integer
+** is signed, must do sign extension (propagating the sign to the
+** higher bits); if size is larger than the size of a Lua integer,
+** it must check the unread bytes to see whether they do not cause an
+** overflow.
+*/
+static lua_Integer unpackint (lua_State *L, const char *str,
+                              int islittle, int size, int issigned) {
+  lua_Unsigned res = 0;
+  int i;
+  int limit = (size  <= SZINT) ? size : SZINT;
+  for (i = limit - 1; i >= 0; i--) {
+    res <<= NB;
+    res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
+  }
+  if (size < SZINT) {  /* real size smaller than lua_Integer? */
+    if (issigned) {  /* needs sign extension? */
+      lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
+      res = ((res ^ mask) - mask);  /* do sign extension */
+    }
+  }
+  else if (size > SZINT) {  /* must check unread bytes */
+    int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
+    for (i = limit; i < size; i++) {
+      if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
+        luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
+    }
+  }
+  return (lua_Integer)res;
+}
+
+
+static int str_unpack (lua_State *L) {
+  Header h;
+  const char *fmt = luaL_checkstring(L, 1);
+  size_t ld;
+  const char *data = luaL_checklstring(L, 2, &ld);
+  size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
+  int n = 0;  /* number of results */
+  luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
+  initheader(L, &h);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
+    if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
+      luaL_argerror(L, 2, "data string too short");
+    pos += ntoalign;  /* skip alignment */
+    /* stack space for item + next position */
+    luaL_checkstack(L, 2, "too many results");
+    n++;
+    switch (opt) {
+      case Kint:
+      case Kuint: {
+        lua_Integer res = unpackint(L, data + pos, h.islittle, size,
+                                       (opt == Kint));
+        lua_pushinteger(L, res);
+        break;
+      }
+      case Kfloat: {
+        volatile Ftypes u;
+        lua_Number num;
+        copywithendian(u.buff, data + pos, size, h.islittle);
+        if (size == sizeof(u.f)) num = (lua_Number)u.f;
+        else if (size == sizeof(u.d)) num = (lua_Number)u.d;
+        else num = u.n;
+        lua_pushnumber(L, num);
+        break;
+      }
+      case Kchar: {
+        lua_pushlstring(L, data + pos, size);
+        break;
+      }
+      case Kstring: {
+        size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
+        luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
+        lua_pushlstring(L, data + pos + size, len);
+        pos += len;  /* skip string */
+        break;
+      }
+      case Kzstr: {
+        size_t len = (int)strlen(data + pos);
+        lua_pushlstring(L, data + pos, len);
+        pos += len + 1;  /* skip string plus final '\0' */
+        break;
+      }
+      case Kpaddalign: case Kpadding: case Knop:
+        n--;  /* undo increment */
+        break;
+    }
+    pos += size;
+  }
+  lua_pushinteger(L, pos + 1);  /* next position */
+  return n + 1;
+}
+
+/* }====================================================== */
+
+
 static const luaL_Reg strlib[] = {
   {"byte", str_byte},
   {"char", str_char},
@@ -992,6 +1552,9 @@ static const luaL_Reg strlib[] = {
   {"reverse", str_reverse},
   {"sub", str_sub},
   {"upper", str_upper},
+  {"pack", str_pack},
+  {"packsize", str_packsize},
+  {"unpack", str_unpack},
   {NULL, NULL}
 };
 
index 5d76f97..7e15b71 100644 (file)
@@ -1,27 +1,30 @@
 /*
-** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
 
+#define ltable_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
 
 /*
 ** 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
+** in its main position (i.e. the 'original' position that its hash gives
 ** to it), then the colliding element is in its own main position.
 ** Hence even when the load factor reaches 100%, performance remains good.
 */
 
-#include <string.h>
-
-#define ltable_c
-#define LUA_CORE
+#include <math.h>
+#include <limits.h>
 
 #include "lua.h"
 
 
 
 /*
-** max size of array part is 2^MAXBITS
+** Maximum size of array part (MAXASIZE) is 2^MAXABITS. MAXABITS is
+** the largest integer such that MAXASIZE fits in an unsigned int.
 */
-#if LUAI_BITSINT >= 32
-#define MAXBITS                30
-#else
-#define MAXBITS                (LUAI_BITSINT-2)
-#endif
+#define MAXABITS       cast_int(sizeof(int) * CHAR_BIT - 1)
+#define MAXASIZE       (1u << MAXABITS)
 
-#define MAXASIZE       (1 << MAXBITS)
+/*
+** Maximum size of hash part is 2^MAXHBITS. MAXHBITS is the largest
+** integer such that 2^MAXHBITS fits in a signed int. (Note that the
+** maximum number of elements in a table, 2^MAXABITS + 2^MAXHBITS, still
+** fits comfortably in an unsigned int.)
+*/
+#define MAXHBITS       (MAXABITS - 1)
 
 
 #define hashpow2(t,n)          (gnode(t, lmod((n), sizenode(t))))
 
-#define hashstr(t,str)         hashpow2(t, (str)->tsv.hash)
+#define hashstr(t,str)         hashpow2(t, (str)->hash)
 #define hashboolean(t,p)       hashpow2(t, p)
+#define hashint(t,i)           hashpow2(t, i)
 
 
 /*
@@ -61,7 +69,7 @@
 #define hashmod(t,n)   (gnode(t, ((n) % ((sizenode(t)-1)|1))))
 
 
-#define hashpointer(t,p)       hashmod(t, IntPoint(p))
+#define hashpointer(t,p)       hashmod(t, point2uint(p))
 
 
 #define dummynode              (&dummynode_)
 
 static const Node dummynode_ = {
   {NILCONSTANT},  /* value */
-  {{NILCONSTANT, NULL}}  /* key */
+  {{NILCONSTANT, 0}}  /* key */
 };
 
 
 /*
-** hash for lua_Numbers
+** Hash for floating-point numbers.
+** The main computation should be just
+**     n = frexp(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 Node *hashnum (const Table *t, lua_Number n) {
+#if !defined(l_hashfloat)
+static int l_hashfloat (lua_Number n) {
   int i;
-  luai_hashnum(i, 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) == cast_num(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
 
 
 /*
-** returns the `main' position of an element in a table (that is, the index
+** returns the 'main' position of an element in a table (that is, the index
 ** of its hash value)
 */
 static Node *mainposition (const Table *t, const TValue *key) {
   switch (ttype(key)) {
-    case LUA_TNUMBER:
-      return hashnum(t, nvalue(key));
-    case LUA_TLNGSTR: {
-      TString *s = rawtsvalue(key);
-      if (s->tsv.extra == 0) {  /* no hash? */
-        s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash);
-        s->tsv.extra = 1;  /* now it has its hash */
-      }
-      return hashstr(t, rawtsvalue(key));
-    }
+    case LUA_TNUMINT:
+      return hashint(t, ivalue(key));
+    case LUA_TNUMFLT:
+      return hashmod(t, l_hashfloat(fltvalue(key)));
     case LUA_TSHRSTR:
-      return hashstr(t, rawtsvalue(key));
+      return hashstr(t, tsvalue(key));
+    case LUA_TLNGSTR:
+      return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
     case LUA_TBOOLEAN:
       return hashboolean(t, bvalue(key));
     case LUA_TLIGHTUSERDATA:
@@ -115,67 +133,68 @@ static Node *mainposition (const Table *t, const TValue *key) {
     case LUA_TLCF:
       return hashpointer(t, fvalue(key));
     default:
+      lua_assert(!ttisdeadkey(key));
       return hashpointer(t, gcvalue(key));
   }
 }
 
 
 /*
-** returns the index for `key' if `key' is an appropriate key to live in
-** the array part of the table, -1 otherwise.
+** returns the index for 'key' if 'key' is an appropriate key to live in
+** the array part of the table, 0 otherwise.
 */
-static int arrayindex (const TValue *key) {
-  if (ttisnumber(key)) {
-    lua_Number n = nvalue(key);
-    int k;
-    lua_number2int(k, n);
-    if (luai_numeq(cast_num(k), n))
-      return k;
+static unsigned int arrayindex (const TValue *key) {
+  if (ttisinteger(key)) {
+    lua_Integer k = ivalue(key);
+    if (0 < k && (lua_Unsigned)k <= MAXASIZE)
+      return cast(unsigned int, k);  /* 'key' is an appropriate array index */
   }
-  return -1;  /* `key' did not match some condition */
+  return 0;  /* 'key' did not match some condition */
 }
 
 
 /*
-** returns the index of a `key' for table traversals. First goes all
+** returns the index of a 'key' for table traversals. First goes all
 ** elements in the array part, then elements in the hash part. The
-** beginning of a traversal is signaled by -1.
+** beginning of a traversal is signaled by 0.
 */
-static int findindex (lua_State *L, Table *t, StkId key) {
-  int i;
-  if (ttisnil(key)) return -1;  /* first iteration */
+static unsigned int findindex (lua_State *L, Table *t, StkId key) {
+  unsigned int i;
+  if (ttisnil(key)) return 0;  /* first iteration */
   i = arrayindex(key);
-  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
-    return i-1;  /* yes; that's the index (corrected to C) */
+  if (i != 0 && i <= t->sizearray)  /* is 'key' inside array part? */
+    return i;  /* yes; that's the index */
   else {
+    int nx;
     Node *n = mainposition(t, key);
-    for (;;) {  /* check whether `key' is somewhere in the chain */
-      /* key may be dead already, but it is ok to use it in `next' */
+    for (;;) {  /* check whether 'key' is somewhere in the chain */
+      /* key may be dead already, but it is ok to use it in 'next' */
       if (luaV_rawequalobj(gkey(n), key) ||
             (ttisdeadkey(gkey(n)) && iscollectable(key) &&
              deadvalue(gkey(n)) == gcvalue(key))) {
         i = cast_int(n - gnode(t, 0));  /* key index in hash table */
         /* hash elements are numbered after array ones */
-        return i + t->sizearray;
+        return (i + 1) + t->sizearray;
       }
-      else n = gnext(n);
-      if (n == NULL)
-        luaG_runerror(L, "invalid key to " LUA_QL("next"));  /* key not found */
+      nx = gnext(n);
+      if (nx == 0)
+        luaG_runerror(L, "invalid key to 'next'");  /* key not found */
+      else n += nx;
     }
   }
 }
 
 
 int luaH_next (lua_State *L, Table *t, StkId key) {
-  int i = findindex(L, t, key);  /* find original element */
-  for (i++; i < t->sizearray; i++) {  /* try first array part */
+  unsigned int i = findindex(L, t, key);  /* find original element */
+  for (; i < t->sizearray; i++) {  /* try first array part */
     if (!ttisnil(&t->array[i])) {  /* a non-nil value? */
-      setnvalue(key, cast_num(i+1));
+      setivalue(key, i + 1);
       setobj2s(L, key+1, &t->array[i]);
       return 1;
     }
   }
-  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */
+  for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) {  /* hash part */
     if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */
       setobj2s(L, key, gkey(gnode(t, i)));
       setobj2s(L, key+1, gval(gnode(t, i)));
@@ -192,32 +211,38 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
 ** ==============================================================
 */
 
-
-static int computesizes (int nums[], int *narray) {
+/*
+** 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. '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 *pna) {
   int i;
-  int twotoi;  /* 2^i */
-  int a = 0;  /* number of elements smaller than 2^i */
-  int na = 0;  /* number of elements to go to array part */
-  int n = 0;  /* optimal size for array part */
-  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
+  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 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 smaller than 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;
 }
 
 
-static int countint (const TValue *key, int *nums) {
-  int k = arrayindex(key);
-  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */
+static int countint (const TValue *key, unsigned int *nums) {
+  unsigned int k = arrayindex(key);
+  if (k != 0) {  /* is 'key' an appropriate array index? */
     nums[luaO_ceillog2(k)]++;  /* count as such */
     return 1;
   }
@@ -226,20 +251,26 @@ static int countint (const TValue *key, int *nums) {
 }
 
 
-static int numusearray (const Table *t, 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;
-  int ttlg;  /* 2^lg */
-  int ause = 0;  /* summation of `nums' */
-  int i = 1;  /* count to traverse all array keys */
-  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */
-    int lc = 0;  /* counter */
-    int lim = ttlg;
+  unsigned int ttlg;  /* 2^lg */
+  unsigned int ause = 0;  /* summation of 'nums' */
+  unsigned int i = 1;  /* count to traverse all array keys */
+  /* traverse each slice */
+  for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) {
+    unsigned int lc = 0;  /* counter */
+    unsigned int lim = ttlg;
     if (lim > t->sizearray) {
       lim = t->sizearray;  /* adjust upper limit */
       if (i > lim)
         break;  /* no more elements to count */
     }
-    /* count elements in range (2^(lg-1), 2^lg] */
+    /* count elements in range (2^(lg - 1), 2^lg] */
     for (; i <= lim; i++) {
       if (!ttisnil(&t->array[i-1]))
         lc++;
@@ -251,9 +282,9 @@ static int numusearray (const Table *t, int *nums) {
 }
 
 
-static int numusehash (const Table *t, int *nums, int *pnasize) {
+static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
   int totaluse = 0;  /* total number of elements */
-  int ause = 0;  /* summation of `nums' */
+  int ause = 0;  /* elements added to 'nums' (can go to array part) */
   int i = sizenode(t);
   while (i--) {
     Node *n = &t->node[i];
@@ -262,13 +293,13 @@ static int numusehash (const Table *t, int *nums, int *pnasize) {
       totaluse++;
     }
   }
-  *pnasize += ause;
+  *pna += ause;
   return totaluse;
 }
 
 
-static void setarrayvector (lua_State *L, Table *t, int size) {
-  int i;
+static void setarrayvector (lua_State *L, Table *t, unsigned int size) {
+  unsigned int i;
   luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
   for (i=t->sizearray; i<size; i++)
      setnilvalue(&t->array[i]);
@@ -276,23 +307,23 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
 }
 
 
-static void setnodevector (lua_State *L, Table *t, int size) {
+static void setnodevector (lua_State *L, Table *t, unsigned int size) {
   int lsize;
   if (size == 0) {  /* no elements to hash part? */
-    t->node = cast(Node *, dummynode);  /* use common `dummynode' */
+    t->node = cast(Node *, dummynode);  /* use common 'dummynode' */
     lsize = 0;
   }
   else {
     int i;
     lsize = luaO_ceillog2(size);
-    if (lsize > MAXBITS)
+    if (lsize > MAXHBITS)
       luaG_runerror(L, "table overflow");
     size = twoto(lsize);
     t->node = luaM_newvector(L, size, Node);
-    for (i=0; i<size; i++) {
+    for (i = 0; i < (int)size; i++) {
       Node *n = gnode(t, i);
-      gnext(n) = NULL;
-      setnilvalue(gkey(n));
+      gnext(n) = 0;
+      setnilvalue(wgkey(n));
       setnilvalue(gval(n));
     }
   }
@@ -301,9 +332,11 @@ static void setnodevector (lua_State *L, Table *t, int size) {
 }
 
 
-void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
-  int i;
-  int oldasize = t->sizearray;
+void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
+                                          unsigned int nhsize) {
+  unsigned int i;
+  int j;
+  unsigned int oldasize = t->sizearray;
   int oldhsize = t->lsizenode;
   Node *nold = t->node;  /* save old hash ... */
   if (nasize > oldasize)  /* array part must grow? */
@@ -321,8 +354,8 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
     luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
   }
   /* re-insert elements from hash part */
-  for (i = twoto(oldhsize) - 1; i >= 0; i--) {
-    Node *old = nold+i;
+  for (j = twoto(oldhsize) - 1; j >= 0; j--) {
+    Node *old = nold + j;
     if (!ttisnil(gval(old))) {
       /* doesn't need barrier/invalidate cache, as entry was
          already present in the table */
@@ -330,32 +363,35 @@ void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
     }
   }
   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 */
 }
 
 
-void luaH_resizearray (lua_State *L, Table *t, int nasize) {
+void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
   int nsize = isdummy(t->node) ? 0 : sizenode(t);
   luaH_resize(L, t, nasize, nsize);
 }
 
-
+/*
+** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i
+*/
 static void rehash (lua_State *L, Table *t, const TValue *ek) {
-  int nasize, na;
-  int nums[MAXBITS+1];  /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */
+  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<=MAXBITS; 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 */
+  for (i = 0; i <= MAXABITS; i++) nums[i] = 0;  /* reset counts */
+  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);
 }
 
 
@@ -366,7 +402,8 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) {
 
 
 Table *luaH_new (lua_State *L) {
-  Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h;
+  GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table));
+  Table *t = gco2t(o);
   t->metatable = NULL;
   t->flags = cast_byte(~0);
   t->array = NULL;
@@ -404,37 +441,51 @@ static Node *getfreepos (Table *t) {
 */
 TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
   Node *mp;
+  TValue aux;
   if (ttisnil(key)) luaG_runerror(L, "table index is nil");
-  else if (ttisnumber(key) && luai_numisnan(L, nvalue(key)))
-    luaG_runerror(L, "table index is NaN");
+  else if (ttisfloat(key)) {
+    lua_Integer k;
+    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? */
     Node *othern;
-    Node *n = getfreepos(t);  /* get a free place */
-    if (n == NULL) {  /* cannot find a free place? */
+    Node *f = getfreepos(t);  /* get a free place */
+    if (f == NULL) {  /* cannot find a free place? */
       rehash(L, t, key);  /* grow table */
-      /* whatever called 'newkey' take care of TM cache and GC barrier */
+      /* whatever called 'newkey' takes care of TM cache */
       return luaH_set(L, t, key);  /* insert key into grown table */
     }
-    lua_assert(!isdummy(n));
+    lua_assert(!isdummy(f));
     othern = mainposition(t, gkey(mp));
     if (othern != mp) {  /* is colliding node out of its main position? */
       /* yes; move colliding node into free position */
-      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */
-      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */
-      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
-      gnext(mp) = NULL;  /* now `mp' is free */
+      while (othern + gnext(othern) != mp)  /* find previous */
+        othern += gnext(othern);
+      gnext(othern) = cast_int(f - othern);  /* rechain to point to 'f' */
+      *f = *mp;  /* copy colliding node into free pos. (mp->next also goes) */
+      if (gnext(mp) != 0) {
+        gnext(f) += cast_int(mp - f);  /* correct 'next' */
+        gnext(mp) = 0;  /* now 'mp' is free */
+      }
       setnilvalue(gval(mp));
     }
     else {  /* colliding node is in its own main position */
       /* new node will go into free position */
-      gnext(n) = gnext(mp);  /* chain new position */
-      gnext(mp) = n;
-      mp = n;
+      if (gnext(mp) != 0)
+        gnext(f) = cast_int((mp + gnext(mp)) - f);  /* chain new position */
+      else lua_assert(gnext(f) == 0);
+      gnext(mp) = cast_int(f - mp);
+      mp = f;
     }
   }
-  setobj2t(L, gkey(mp), key);
-  luaC_barrierback(L, obj2gco(t), key);
+  setnodekey(L, &mp->i_key, key);
+  luaC_barrierback(L, t, key);
   lua_assert(ttisnil(gval(mp)));
   return gval(mp);
 }
@@ -443,18 +494,21 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
 /*
 ** search function for integers
 */
-const TValue *luaH_getint (Table *t, int key) {
+const TValue *luaH_getint (Table *t, lua_Integer key) {
   /* (1 <= key && key <= t->sizearray) */
-  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
-    return &t->array[key-1];
+  if (l_castS2U(key) - 1 < t->sizearray)
+    return &t->array[key - 1];
   else {
-    lua_Number nk = cast_num(key);
-    Node *n = hashnum(t, nk);
-    do {  /* check whether `key' is somewhere in the chain */
-      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
+    Node *n = hashint(t, key);
+    for (;;) {  /* check whether 'key' is somewhere in the chain */
+      if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key)
         return gval(n);  /* that's it */
-      else n = gnext(n);
-    } while (n);
+      else {
+        int nx = gnext(n);
+        if (nx == 0) break;
+        n += nx;
+      }
+    }
     return luaO_nilobject;
   }
 }
@@ -463,15 +517,50 @@ const TValue *luaH_getint (Table *t, int key) {
 /*
 ** search function for short strings
 */
-const TValue *luaH_getstr (Table *t, TString *key) {
+const TValue *luaH_getshortstr (Table *t, TString *key) {
   Node *n = hashstr(t, key);
-  lua_assert(key->tsv.tt == LUA_TSHRSTR);
-  do {  /* check whether `key' is somewhere in the chain */
-    if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key))
+  lua_assert(key->tt == LUA_TSHRSTR);
+  for (;;) {  /* check whether 'key' is somewhere in the chain */
+    const TValue *k = gkey(n);
+    if (ttisshrstring(k) && eqshrstr(tsvalue(k), key))
+      return gval(n);  /* that's it */
+    else {
+      int nx = gnext(n);
+      if (nx == 0)
+        return luaO_nilobject;  /* not found */
+      n += nx;
+    }
+  }
+}
+
+
+/*
+** "Generic" get version. (Not that generic: not valid for integers,
+** which may be in array part, nor for floats with integral values.)
+*/
+static const TValue *getgeneric (Table *t, const TValue *key) {
+  Node *n = mainposition(t, key);
+  for (;;) {  /* check whether 'key' is somewhere in the chain */
+    if (luaV_rawequalobj(gkey(n), key))
       return gval(n);  /* that's it */
-    else n = gnext(n);
-  } while (n);
-  return luaO_nilobject;
+    else {
+      int nx = gnext(n);
+      if (nx == 0)
+        return luaO_nilobject;  /* not found */
+      n += nx;
+    }
+  }
+}
+
+
+const TValue *luaH_getstr (Table *t, TString *key) {
+  if (key->tt == LUA_TSHRSTR)
+    return luaH_getshortstr(t, key);
+  else {  /* for long strings, use generic case */
+    TValue ko;
+    setsvalue(cast(lua_State *, NULL), &ko, key);
+    return getgeneric(t, &ko);
+  }
 }
 
 
@@ -480,25 +569,17 @@ const TValue *luaH_getstr (Table *t, TString *key) {
 */
 const TValue *luaH_get (Table *t, const TValue *key) {
   switch (ttype(key)) {
-    case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key));
+    case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
+    case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
     case LUA_TNIL: return luaO_nilobject;
-    case LUA_TNUMBER: {
-      int k;
-      lua_Number n = nvalue(key);
-      lua_number2int(k, n);
-      if (luai_numeq(cast_num(k), n)) /* index is int? */
+    case LUA_TNUMFLT: {
+      lua_Integer k;
+      if (luaV_tointeger(key, &k, 0)) /* index is int? */
         return luaH_getint(t, k);  /* use specialized version */
-      /* else go through */
-    }
-    default: {
-      Node *n = mainposition(t, key);
-      do {  /* check whether `key' is somewhere in the chain */
-        if (luaV_rawequalobj(gkey(n), key))
-          return gval(n);  /* that's it */
-        else n = gnext(n);
-      } while (n);
-      return luaO_nilobject;
-    }
+      /* else... */
+    }  /* FALLTHROUGH */
+    default:
+      return getgeneric(t, key);
   }
 }
 
@@ -515,14 +596,14 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
 }
 
 
-void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
+void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
   const TValue *p = luaH_getint(t, key);
   TValue *cell;
   if (p != luaO_nilobject)
     cell = cast(TValue *, p);
   else {
     TValue k;
-    setnvalue(&k, cast_num(key));
+    setivalue(&k, key);
     cell = luaH_newkey(L, t, &k);
   }
   setobj2t(L, cell, value);
@@ -532,16 +613,16 @@ void luaH_setint (lua_State *L, Table *t, int key, TValue *value) {
 static int unbound_search (Table *t, unsigned int j) {
   unsigned int i = j;  /* i is zero or a present index */
   j++;
-  /* find `i' and `j' such that i is present and j is not */
+  /* find 'i' and 'j' such that i is present and j is not */
   while (!ttisnil(luaH_getint(t, j))) {
     i = j;
-    j *= 2;
-    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */
+    if (j > cast(unsigned int, MAX_INT)/2) {  /* overflow? */
       /* table was built with bad purposes: resort to linear search */
       i = 1;
       while (!ttisnil(luaH_getint(t, i))) i++;
       return i - 1;
     }
+    j *= 2;
   }
   /* now do a binary search between them */
   while (j - i > 1) {
@@ -554,7 +635,7 @@ static int unbound_search (Table *t, unsigned int j) {
 
 
 /*
-** Try to find a boundary in table `t'. A `boundary' is an integer index
+** Try to find a boundary in table 't'. A 'boundary' is an integer index
 ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
 */
 int luaH_getn (Table *t) {
index d69449b..213cc13 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 roberto Exp $
+** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
 
 
 #define gnode(t,i)     (&(t)->node[i])
-#define gkey(n)                (&(n)->i_key.tvk)
 #define gval(n)                (&(n)->i_val)
 #define gnext(n)       ((n)->i_key.nk.next)
 
+
+/* 'const' to avoid wrong writings that can mess up field 'next' */ 
+#define gkey(n)                cast(const TValue*, (&(n)->i_key.tvk))
+
+/*
+** writable version of 'gkey'; allows updates to individual fields,
+** but not to the whole (which has incompatible type)
+*/
+#define wgkey(n)               (&(n)->i_key.nk)
+
 #define invalidateTMcache(t)   ((t)->flags = 0)
 
+
 /* returns the key, given the value of a table entry */
 #define keyfromval(v) \
   (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val))))
 
 
-LUAI_FUNC const TValue *luaH_getint (Table *t, int key);
-LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value);
+LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
+LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
+                                                    TValue *value);
+LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
 LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
 LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
 LUAI_FUNC Table *luaH_new (lua_State *L);
-LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize);
-LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
+LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
+                                                    unsigned int nhsize);
+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
 LUAI_FUNC void luaH_free (lua_State *L, Table *t);
 LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
 LUAI_FUNC int luaH_getn (Table *t);
index 99764d2..98b2f87 100644 (file)
@@ -1,15 +1,18 @@
 /*
-** $Id: ltablib.c,v 1.65.1.2 2014/05/07 16:32:55 roberto Exp $
+** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */
 
+#define ltablib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
 
 #include <limits.h>
 #include <stddef.h>
-
-#define ltablib_c
-#define LUA_LIB
+#include <string.h>
 
 #include "lua.h"
 
 #include "lualib.h"
 
 
-#define aux_getn(L,n)  (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n))
+/*
+** Operations that an object must define to mimic a table
+** (some functions only need some of them)
+*/
+#define TAB_R  1                       /* read */
+#define TAB_W  2                       /* write */
+#define TAB_L  4                       /* length */
+#define TAB_RW (TAB_R | TAB_W)         /* read/write */
+
+
+#define aux_getn(L,n,w)        (checktab(L, n, (w) | TAB_L), luaL_len(L, n))
+
 
+static int checkfield (lua_State *L, const char *key, int n) {
+  lua_pushstring(L, key);
+  return (lua_rawget(L, -n) != LUA_TNIL);
+}
+
+
+/*
+** Check that 'arg' either is a table or can behave like one (that is,
+** has a metatable with the required metamethods)
+*/
+static void checktab (lua_State *L, int arg, int what) {
+  if (lua_type(L, arg) != LUA_TTABLE) {  /* is it not a table? */
+    int n = 1;  /* number of elements to pop */
+    if (lua_getmetatable(L, arg) &&  /* must have metatable */
+        (!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
+        (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
+        (!(what & TAB_L) || checkfield(L, "__len", ++n))) {
+      lua_pop(L, n);  /* pop metatable and tested metamethods */
+    }
+    else
+      luaL_checktype(L, arg, LUA_TTABLE);  /* force an error */
+  }
+}
 
 
 #if defined(LUA_COMPAT_MAXN)
@@ -40,65 +77,102 @@ static int maxn (lua_State *L) {
 
 
 static int tinsert (lua_State *L) {
-  int e = aux_getn(L, 1) + 1;  /* first empty element */
-  int pos;  /* where to insert new element */
+  lua_Integer e = aux_getn(L, 1, TAB_RW) + 1;  /* first empty element */
+  lua_Integer pos;  /* where to insert new element */
   switch (lua_gettop(L)) {
     case 2: {  /* called with only 2 arguments */
       pos = e;  /* insert new element at the end */
       break;
     }
     case 3: {
-      int i;
-      pos = luaL_checkint(L, 2);  /* 2nd argument is the position */
+      lua_Integer i;
+      pos = luaL_checkinteger(L, 2);  /* 2nd argument is the position */
       luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
       for (i = e; i > pos; i--) {  /* move up elements */
-        lua_rawgeti(L, 1, i-1);
-        lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */
+        lua_geti(L, 1, i - 1);
+        lua_seti(L, 1, i);  /* t[i] = t[i - 1] */
       }
       break;
     }
     default: {
-      return luaL_error(L, "wrong number of arguments to " LUA_QL("insert"));
+      return luaL_error(L, "wrong number of arguments to 'insert'");
     }
   }
-  lua_rawseti(L, 1, pos);  /* t[pos] = v */
+  lua_seti(L, 1, pos);  /* t[pos] = v */
   return 0;
 }
 
 
 static int tremove (lua_State *L) {
-  int size = aux_getn(L, 1);
-  int pos = luaL_optint(L, 2, size);
+  lua_Integer size = aux_getn(L, 1, TAB_RW);
+  lua_Integer pos = luaL_optinteger(L, 2, size);
   if (pos != size)  /* validate 'pos' if given */
     luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
-  lua_rawgeti(L, 1, pos);  /* result = t[pos] */
+  lua_geti(L, 1, pos);  /* result = t[pos] */
   for ( ; pos < size; pos++) {
-    lua_rawgeti(L, 1, pos+1);
-    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */
+    lua_geti(L, 1, pos + 1);
+    lua_seti(L, 1, pos);  /* t[pos] = t[pos + 1] */
   }
   lua_pushnil(L);
-  lua_rawseti(L, 1, pos);  /* t[pos] = nil */
+  lua_seti(L, 1, pos);  /* t[pos] = nil */
   return 1;
 }
 
 
-static void addfield (lua_State *L, luaL_Buffer *b, int i) {
-  lua_rawgeti(L, 1, i);
+/*
+** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
+** possible, copy in increasing order, which is better for rehashing.
+** "possible" means destination after original range, or smaller
+** than origin, or copying to another table.
+*/
+static int tmove (lua_State *L) {
+  lua_Integer f = luaL_checkinteger(L, 2);
+  lua_Integer e = luaL_checkinteger(L, 3);
+  lua_Integer t = luaL_checkinteger(L, 4);
+  int tt = !lua_isnoneornil(L, 5) ? 5 : 1;  /* destination table */
+  checktab(L, 1, TAB_R);
+  checktab(L, tt, TAB_W);
+  if (e >= f) {  /* otherwise, nothing to move */
+    lua_Integer n, i;
+    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 > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
+      for (i = 0; i < n; i++) {
+        lua_geti(L, 1, f + i);
+        lua_seti(L, tt, t + i);
+      }
+    }
+    else {
+      for (i = n - 1; i >= 0; i--) {
+        lua_geti(L, 1, f + i);
+        lua_seti(L, tt, t + i);
+      }
+    }
+  }
+  lua_pushvalue(L, tt);  /* return destination table */
+  return 1;
+}
+
+
+static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
+  lua_geti(L, 1, i);
   if (!lua_isstring(L, -1))
-    luaL_error(L, "invalid value (%s) at index %d in table for "
-                  LUA_QL("concat"), luaL_typename(L, -1), i);
+    luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
+                  luaL_typename(L, -1), i);
   luaL_addvalue(b);
 }
 
 
 static int tconcat (lua_State *L) {
   luaL_Buffer b;
+  lua_Integer last = aux_getn(L, 1, TAB_R);
   size_t lsep;
-  int i, last;
   const char *sep = luaL_optlstring(L, 2, "", &lsep);
-  luaL_checktype(L, 1, LUA_TTABLE);
-  i = luaL_optint(L, 3, 1);
-  last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1));
+  lua_Integer i = luaL_optinteger(L, 3, 1);
+  last = luaL_optinteger(L, 4, last);
   luaL_buffinit(L, &b);
   for (; i < last; i++) {
     addfield(L, &b, i);
@@ -118,36 +192,31 @@ static int tconcat (lua_State *L) {
 */
 
 static int pack (lua_State *L) {
+  int i;
   int n = lua_gettop(L);  /* number of elements to pack */
   lua_createtable(L, n, 1);  /* create result table */
+  lua_insert(L, 1);  /* put it at index 1 */
+  for (i = n; i >= 1; i--)  /* assign elements */
+    lua_seti(L, 1, i);
   lua_pushinteger(L, n);
-  lua_setfield(L, -2, "n");  /* t.n = number of elements */
-  if (n > 0) {  /* at least one element? */
-    int i;
-    lua_pushvalue(L, 1);
-    lua_rawseti(L, -2, 1);  /* insert first element */
-    lua_replace(L, 1);  /* move table into index 1 */
-    for (i = n; i >= 2; i--)  /* assign other elements */
-      lua_rawseti(L, 1, i);
-  }
+  lua_setfield(L, 1, "n");  /* t.n = number of elements */
   return 1;  /* return table */
 }
 
 
 static int unpack (lua_State *L) {
-  int i, e;
-  unsigned int n;
-  luaL_checktype(L, 1, LUA_TTABLE);
-  i = luaL_optint(L, 2, 1);
-  e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1));
+  lua_Unsigned n;
+  lua_Integer i = luaL_optinteger(L, 2, 1);
+  lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
   if (i > e) return 0;  /* empty range */
-  n = (unsigned int)e - (unsigned int)i;  /* number of elements minus 1 */
-  if (n > (INT_MAX - 10) || !lua_checkstack(L, ++n))
+  n = (lua_Unsigned)e - i;  /* number of elements minus 1 (avoid overflows) */
+  if (n >= (unsigned int)INT_MAX  || !lua_checkstack(L, (int)(++n)))
     return luaL_error(L, "too many results to unpack");
-  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */
-  while (i++ < e)  /* push arg[i + 1...e] */
-    lua_rawgeti(L, 1, i);
-  return n;
+  for (; i < e; i++) {  /* push arg[i..e - 1] (to avoid overflows) */
+    lua_geti(L, 1, i);
+  }
+  lua_geti(L, 1, e);  /* push last element */
+  return (int)n;
 }
 
 /* }====================================================== */
@@ -157,102 +226,197 @@ static int unpack (lua_State *L) {
 /*
 ** {======================================================
 ** Quicksort
-** (based on `Algorithms in MODULA-3', Robert Sedgewick;
+** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
 **  Addison-Wesley, 1993.)
 ** =======================================================
 */
 
 
-static void set2 (lua_State *L, int i, int j) {
-  lua_rawseti(L, 1, i);
-  lua_rawseti(L, 1, j);
+/* type for array indices */
+typedef unsigned int IdxT;
+
+
+/*
+** Produce a "random" 'unsigned int' to randomize pivot choice. This
+** macro is used only when 'sort' detects a big imbalance in the result
+** of a partition. (If you don't want/need this "randomness", ~0 is a
+** good choice.)
+*/
+#if !defined(l_randomizePivot)         /* { */
+
+#include <time.h>
+
+/* size of 'e' measured in number of 'unsigned int's */
+#define sof(e)         (sizeof(e) / sizeof(unsigned int))
+
+/*
+** Use 'time' and 'clock' as sources of "randomness". Because we don't
+** know the types 'clock_t' and 'time_t', we cannot cast them to
+** anything without risking overflows. A safe way to use their values
+** is to copy them to an array of a known type and use the array values.
+*/
+static unsigned int l_randomizePivot (void) {
+  clock_t c = clock();
+  time_t t = time(NULL);
+  unsigned int buff[sof(c) + sof(t)];
+  unsigned int i, rnd = 0;
+  memcpy(buff, &c, sof(c) * sizeof(unsigned int));
+  memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
+  for (i = 0; i < sof(buff); i++)
+    rnd += buff[i];
+  return rnd;
+}
+
+#endif                                 /* } */
+
+
+/* arrays larger than 'RANLIMIT' may use randomized pivots */
+#define RANLIMIT       100u
+
+
+static void set2 (lua_State *L, IdxT i, IdxT j) {
+  lua_seti(L, 1, i);
+  lua_seti(L, 1, j);
 }
 
+
+/*
+** Return true iff value at stack index 'a' is less than the value at
+** index 'b' (according to the order of the sort).
+*/
 static int sort_comp (lua_State *L, int a, int b) {
-  if (!lua_isnil(L, 2)) {  /* function? */
+  if (lua_isnil(L, 2))  /* no function? */
+    return lua_compare(L, a, b, LUA_OPLT);  /* a < b */
+  else {  /* function */
     int res;
-    lua_pushvalue(L, 2);
+    lua_pushvalue(L, 2);    /* push function */
     lua_pushvalue(L, a-1);  /* -1 to compensate function */
-    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */
-    lua_call(L, 2, 1);
-    res = lua_toboolean(L, -1);
-    lua_pop(L, 1);
+    lua_pushvalue(L, b-2);  /* -2 to compensate function and 'a' */
+    lua_call(L, 2, 1);      /* call function */
+    res = lua_toboolean(L, -1);  /* get result */
+    lua_pop(L, 1);          /* pop result */
     return res;
   }
-  else  /* a < b? */
-    return lua_compare(L, a, b, LUA_OPLT);
 }
 
-static void auxsort (lua_State *L, int l, int u) {
-  while (l < u) {  /* for tail recursion */
-    int i, j;
-    /* sort elements a[l], a[(l+u)/2] and a[u] */
-    lua_rawgeti(L, 1, l);
-    lua_rawgeti(L, 1, u);
-    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */
-      set2(L, l, u);  /* swap a[l] - a[u] */
+
+/*
+** Does the partition: Pivot P is at the top of the stack.
+** precondition: a[lo] <= P == a[up-1] <= a[up],
+** so it only needs to do the partition from lo + 1 to up - 2.
+** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
+** returns 'i'.
+*/
+static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
+  IdxT i = lo;  /* will be incremented before first use */
+  IdxT j = up - 1;  /* will be decremented before first use */
+  /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
+  for (;;) {
+    /* next loop: repeat ++i while a[i] < P */
+    while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
+      if (i == up - 1)  /* a[i] < P  but a[up - 1] == P  ?? */
+        luaL_error(L, "invalid order function for sorting");
+      lua_pop(L, 1);  /* remove a[i] */
+    }
+    /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
+    /* next loop: repeat --j while P < a[j] */
+    while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
+      if (j < i)  /* j < i  but  a[j] > P ?? */
+        luaL_error(L, "invalid order function for sorting");
+      lua_pop(L, 1);  /* remove a[j] */
+    }
+    /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
+    if (j < i) {  /* no elements out of place? */
+      /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
+      lua_pop(L, 1);  /* pop a[j] */
+      /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
+      set2(L, up - 1, i);
+      return i;
+    }
+    /* otherwise, swap a[i] - a[j] to restore invariant and repeat */
+    set2(L, i, j);
+  }
+}
+
+
+/*
+** Choose an element in the middle (2nd-3th quarters) of [lo,up]
+** "randomized" by 'rnd'
+*/
+static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
+  IdxT r4 = (up - lo) / 4;  /* range/4 */
+  IdxT p = rnd % (r4 * 2) + (lo + r4);
+  lua_assert(lo + r4 <= p && p <= up - r4);
+  return p;
+}
+
+
+/*
+** QuickSort algorithm (recursive function)
+*/
+static void auxsort (lua_State *L, IdxT lo, IdxT up,
+                                   unsigned int rnd) {
+  while (lo < up) {  /* loop for tail recursion */
+    IdxT p;  /* Pivot index */
+    IdxT n;  /* to be used later */
+    /* sort elements 'lo', 'p', and 'up' */
+    lua_geti(L, 1, lo);
+    lua_geti(L, 1, up);
+    if (sort_comp(L, -1, -2))  /* a[up] < a[lo]? */
+      set2(L, lo, up);  /* swap a[lo] - a[up] */
     else
-      lua_pop(L, 2);
-    if (u-l == 1) break;  /* only 2 elements */
-    i = (l+u)/2;
-    lua_rawgeti(L, 1, i);
-    lua_rawgeti(L, 1, l);
-    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */
-      set2(L, i, l);
+      lua_pop(L, 2);  /* remove both values */
+    if (up - lo == 1)  /* only 2 elements? */
+      return;  /* already sorted */
+    if (up - lo < RANLIMIT || rnd == 0)  /* small interval or no randomize? */
+      p = (lo + up)/2;  /* middle element is a good pivot */
+    else  /* for larger intervals, it is worth a random pivot */
+      p = choosePivot(lo, up, rnd);
+    lua_geti(L, 1, p);
+    lua_geti(L, 1, lo);
+    if (sort_comp(L, -2, -1))  /* a[p] < a[lo]? */
+      set2(L, p, lo);  /* swap a[p] - a[lo] */
     else {
-      lua_pop(L, 1);  /* remove a[l] */
-      lua_rawgeti(L, 1, u);
-      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */
-        set2(L, i, u);
+      lua_pop(L, 1);  /* remove a[lo] */
+      lua_geti(L, 1, up);
+      if (sort_comp(L, -1, -2))  /* a[up] < a[p]? */
+        set2(L, p, up);  /* swap a[up] - a[p] */
       else
         lua_pop(L, 2);
     }
-    if (u-l == 2) break;  /* only 3 elements */
-    lua_rawgeti(L, 1, i);  /* Pivot */
-    lua_pushvalue(L, -1);
-    lua_rawgeti(L, 1, u-1);
-    set2(L, i, u-1);
-    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
-    i = l; j = u-1;
-    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */
-      /* repeat ++i until a[i] >= P */
-      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
-        if (i>=u) luaL_error(L, "invalid order function for sorting");
-        lua_pop(L, 1);  /* remove a[i] */
-      }
-      /* repeat --j until a[j] <= P */
-      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
-        if (j<=l) luaL_error(L, "invalid order function for sorting");
-        lua_pop(L, 1);  /* remove a[j] */
-      }
-      if (j<i) {
-        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */
-        break;
-      }
-      set2(L, i, j);
-    }
-    lua_rawgeti(L, 1, u-1);
-    lua_rawgeti(L, 1, i);
-    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */
-    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
-    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */
-    if (i-l < u-i) {
-      j=l; i=i-1; l=i+2;
+    if (up - lo == 2)  /* only 3 elements? */
+      return;  /* already sorted */
+    lua_geti(L, 1, p);  /* get middle element (Pivot) */
+    lua_pushvalue(L, -1);  /* push Pivot */
+    lua_geti(L, 1, up - 1);  /* push a[up - 1] */
+    set2(L, p, up - 1);  /* swap Pivot (a[p]) with a[up - 1] */
+    p = partition(L, lo, up);
+    /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
+    if (p - lo < up - p) {  /* lower interval is smaller? */
+      auxsort(L, lo, p - 1, rnd);  /* call recursively for lower interval */
+      n = p - lo;  /* size of smaller interval */
+      lo = p + 1;  /* tail call for [p + 1 .. up] (upper interval) */
     }
     else {
-      j=i+1; i=u; u=j-2;
+      auxsort(L, p + 1, up, rnd);  /* call recursively for upper interval */
+      n = up - p;  /* size of smaller interval */
+      up = p - 1;  /* tail call for [lo .. p - 1]  (lower interval) */
     }
-    auxsort(L, j, i);  /* call recursively the smaller one */
-  }  /* repeat the routine for the larger one */
+    if ((up - lo) / 128 > n) /* partition too imbalanced? */
+      rnd = l_randomizePivot();  /* try a new randomization */
+  }  /* tail call auxsort(L, lo, up, rnd) */
 }
 
+
 static int sort (lua_State *L) {
-  int n = aux_getn(L, 1);
-  luaL_checkstack(L, 40, "");  /* assume array is smaller than 2^40 */
-  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
-    luaL_checktype(L, 2, LUA_TFUNCTION);
-  lua_settop(L, 2);  /* make sure there is two arguments */
-  auxsort(L, 1, n);
+  lua_Integer n = aux_getn(L, 1, TAB_RW);
+  if (n > 1) {  /* non-trivial interval? */
+    luaL_argcheck(L, n < INT_MAX, 1, "array too big");
+    if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */
+      luaL_checktype(L, 2, LUA_TFUNCTION);  /* must be a function */
+    lua_settop(L, 2);  /* make sure there are two arguments */
+    auxsort(L, 1, (IdxT)n, 0);
+  }
   return 0;
 }
 
@@ -268,6 +432,7 @@ static const luaL_Reg tab_funcs[] = {
   {"pack", pack},
   {"unpack", unpack},
   {"remove", tremove},
+  {"move", tmove},
   {"sort", sort},
   {NULL, NULL}
 };
index 69b4ed7..4650cc2 100644 (file)
--- a/src/ltm.c
+++ b/src/ltm.c
@@ -1,22 +1,27 @@
 /*
-** $Id: ltm.c,v 2.14.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltm.c,v 2.37 2016/02/26 19:20:15 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
 
-
-#include <string.h>
-
 #define ltm_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
+#include "ldebug.h"
+#include "ldo.h" 
 #include "lobject.h"
 #include "lstate.h"
 #include "lstring.h"
 #include "ltable.h"
 #include "ltm.h"
+#include "lvm.h"
 
 
 static const char udatatypename[] = "userdata";
@@ -25,7 +30,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
   "no value",
   "nil", "boolean", udatatypename, "number",
   "string", "table", "function", udatatypename, "thread",
-  "proto", "upval"  /* these last two cases are used for tests only */
+  "proto" /* this last case is used for tests only */
 };
 
 
@@ -33,14 +38,16 @@ void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
     "__index", "__newindex",
     "__gc", "__mode", "__len", "__eq",
-    "__add", "__sub", "__mul", "__div", "__mod",
-    "__pow", "__unm", "__lt", "__le",
+    "__add", "__sub", "__mul", "__mod", "__pow",
+    "__div", "__idiv",
+    "__band", "__bor", "__bxor", "__shl", "__shr",
+    "__unm", "__bnot", "__lt", "__le",
     "__concat", "__call"
   };
   int i;
   for (i=0; i<TM_N; i++) {
     G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
-    luaS_fix(G(L)->tmname[i]);  /* never collect these names */
+    luaC_fix(L, obj2gco(G(L)->tmname[i]));  /* never collect these names */
   }
 }
 
@@ -50,7 +57,7 @@ void luaT_init (lua_State *L) {
 ** tag methods
 */
 const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
-  const TValue *tm = luaH_getstr(events, ename);
+  const TValue *tm = luaH_getshortstr(events, ename);
   lua_assert(event <= TM_EQ);
   if (ttisnil(tm)) {  /* no tag method? */
     events->flags |= cast_byte(1u<<event);  /* cache this fact */
@@ -62,7 +69,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
 
 const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
   Table *mt;
-  switch (ttypenv(o)) {
+  switch (ttnov(o)) {
     case LUA_TTABLE:
       mt = hvalue(o)->metatable;
       break;
@@ -70,8 +77,89 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
       mt = uvalue(o)->metatable;
       break;
     default:
-      mt = G(L)->mt[ttypenv(o)];
+      mt = G(L)->mt[ttnov(o)];
+  }
+  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+}
+
+
+/*
+** Return the name of the type of an object. For tables and userdata
+** with metatable, use their '__name' metafield, if present.
+*/
+const char *luaT_objtypename (lua_State *L, const TValue *o) {
+  Table *mt;
+  if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
+      (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
+    const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
+    if (ttisstring(name))  /* is '__name' a string? */
+      return getstr(tsvalue(name));  /* use it as type name */
   }
-  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+  return ttypename(ttnov(o));  /* else use standard type name */
+}
+
+
+void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+                  const TValue *p2, TValue *p3, int hasres) {
+  ptrdiff_t result = savestack(L, p3);
+  StkId func = L->top;
+  setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
+  setobj2s(L, func + 1, p1);  /* 1st argument */
+  setobj2s(L, func + 2, p2);  /* 2nd argument */
+  L->top += 3;
+  if (!hasres)  /* no result? 'p3' is third argument */
+    setobj2s(L, L->top++, p3);  /* 3rd argument */
+  /* metamethod may yield only when called from Lua code */
+  if (isLua(L->ci))
+    luaD_call(L, func, hasres);
+  else
+    luaD_callnoyield(L, func, hasres);
+  if (hasres) {  /* if has result, move it to its place */
+    p3 = restorestack(L, result);
+    setobjs2s(L, p3, --L->top);
+  }
+}
+
+
+int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                    StkId res, TMS event) {
+  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
+  if (ttisnil(tm))
+    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
+  if (ttisnil(tm)) return 0;
+  luaT_callTM(L, tm, p1, p2, res, 1);
+  return 1;
+}
+
+
+void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                    StkId res, TMS event) {
+  if (!luaT_callbinTM(L, p1, p2, res, event)) {
+    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;
+        if (tonumber(p1, &dummy) && tonumber(p2, &dummy))
+          luaG_tointerror(L, p1, p2);
+        else
+          luaG_opinterror(L, p1, p2, "perform bitwise operation on");
+      }
+      /* calls never return, but to avoid warnings: *//* FALLTHROUGH */
+      default:
+        luaG_opinterror(L, p1, p2, "perform arithmetic on");
+    }
+  }
+}
+
+
+int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
+                      TMS event) {
+  if (!luaT_callbinTM(L, p1, p2, L->top, event))
+    return -1;  /* no metamethod */
+  else
+    return !l_isfalse(L->top);
 }
 
index 7f89c84..63db726 100644 (file)
--- a/src/ltm.h
+++ b/src/ltm.h
@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -13,7 +13,7 @@
 
 /*
 * WARNING: if you change the order of this enumeration,
-* grep "ORDER TM"
+* grep "ORDER TM" and "ORDER OP"
 */
 typedef enum {
   TM_INDEX,
@@ -21,14 +21,21 @@ typedef enum {
   TM_GC,
   TM_MODE,
   TM_LEN,
-  TM_EQ,  /* last tag method with `fast' access */
+  TM_EQ,  /* last tag method with fast access */
   TM_ADD,
   TM_SUB,
   TM_MUL,
-  TM_DIV,
   TM_MOD,
   TM_POW,
+  TM_DIV,
+  TM_IDIV,
+  TM_BAND,
+  TM_BOR,
+  TM_BXOR,
+  TM_SHL,
+  TM_SHR,
   TM_UNM,
+  TM_BNOT,
   TM_LT,
   TM_LE,
   TM_CONCAT,
@@ -44,14 +51,26 @@ typedef enum {
 #define fasttm(l,et,e) gfasttm(G(l), et, e)
 
 #define ttypename(x)   luaT_typenames_[(x) + 1]
-#define objtypename(x) ttypename(ttypenv(x))
 
 LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
 
 
+LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
+
 LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
 LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
                                                        TMS event);
 LUAI_FUNC void luaT_init (lua_State *L);
 
+LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
+                            const TValue *p2, TValue *p3, int hasres);
+LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                              StkId res, TMS event);
+LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
+                              StkId res, TMS event);
+LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
+                                const TValue *p2, TMS event);
+
+
+
 #endif
index 4345e55..545d23d 100644 (file)
--- a/src/lua.c
+++ b/src/lua.c
@@ -1,17 +1,19 @@
 /*
-** $Id: lua.c,v 1.206.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lua.c,v 1.226 2015/08/14 19:11:20 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
 
+#define lua_c
+
+#include "lprefix.h"
+
 
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define lua_c
-
 #include "lua.h"
 
 #include "lauxlib.h"
 #define LUA_MAXINPUT           512
 #endif
 
-#if !defined(LUA_INIT)
-#define LUA_INIT               "LUA_INIT"
+#if !defined(LUA_INIT_VAR)
+#define LUA_INIT_VAR           "LUA_INIT"
 #endif
 
-#define LUA_INITVERSION  \
-       LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
+#define LUA_INITVARVERSION  \
+       LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
 
 
 /*
 ** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
 ** is, whether we're running lua interactively).
 */
-#if defined(LUA_USE_ISATTY)
+#if !defined(lua_stdin_is_tty) /* { */
+
+#if defined(LUA_USE_POSIX)     /* { */
+
 #include <unistd.h>
 #define lua_stdin_is_tty()     isatty(0)
-#elif defined(LUA_WIN)
+
+#elif defined(LUA_USE_WINDOWS) /* }{ */
+
 #include <io.h>
-#include <stdio.h>
 #define lua_stdin_is_tty()     _isatty(_fileno(stdin))
-#else
+
+#else                          /* }{ */
+
+/* ISO C definition */
 #define lua_stdin_is_tty()     1  /* assume stdin is a tty */
-#endif
+
+#endif                         /* } */
+
+#endif                         /* } */
 
 
 /*
 ** lua_saveline defines how to "save" a read line in a "history".
 ** lua_freeline defines how to free a line read by lua_readline.
 */
-#if defined(LUA_USE_READLINE)
+#if !defined(lua_readline)     /* { */
+
+#if defined(LUA_USE_READLINE)  /* { */
 
-#include <stdio.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 #define lua_readline(L,b,p)    ((void)L, ((b)=readline(p)) != NULL)
-#define lua_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))
 
-#elif !defined(lua_readline)
+#else                          /* }{ */
 
 #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
+#endif                         /* } */
+
+#endif                         /* } */
 
 
 
@@ -90,33 +103,40 @@ static lua_State *globalL = NULL;
 static const char *progname = LUA_PROGNAME;
 
 
-
+/*
+** Hook set by signal function to stop the interpreter.
+*/
 static void lstop (lua_State *L, lua_Debug *ar) {
   (void)ar;  /* unused arg. */
-  lua_sethook(L, NULL, 0, 0);
+  lua_sethook(L, NULL, 0, 0);  /* reset hook */
   luaL_error(L, "interrupted!");
 }
 
 
+/*
+** Function to be called at a C signal. Because a C signal cannot
+** just change a Lua state (as there is no proper synchronization),
+** this function only sets a hook that, when called, will stop the
+** interpreter.
+*/
 static void laction (int i) {
-  signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
-                              terminate process (default action) */
+  signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
   lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
 }
 
 
 static void print_usage (const char *badoption) {
-  luai_writestringerror("%s: ", progname);
+  lua_writestringerror("%s: ", progname);
   if (badoption[1] == 'e' || badoption[1] == 'l')
-    luai_writestringerror("'%s' needs argument\n", badoption);
+    lua_writestringerror("'%s' needs argument\n", badoption);
   else
-    luai_writestringerror("unrecognized option '%s'\n", badoption);
-  luai_writestringerror(
+    lua_writestringerror("unrecognized option '%s'\n", badoption);
+  lua_writestringerror(
   "usage: %s [options] [script [args]]\n"
   "Available options are:\n"
-  "  -e stat  execute string " LUA_QL("stat") "\n"
-  "  -i       enter interactive mode after executing " LUA_QL("script") "\n"
-  "  -l name  require library " LUA_QL("name") "\n"
+  "  -e stat  execute string 'stat'\n"
+  "  -i       enter interactive mode after executing 'script'\n"
+  "  -l name  require library 'name'\n"
   "  -v       show version information\n"
   "  -E       ignore environment variables\n"
   "  --       stop handling options\n"
@@ -126,101 +146,114 @@ static void print_usage (const char *badoption) {
 }
 
 
+/*
+** Prints an error message, adding the program name in front of it
+** (if present)
+*/
 static void l_message (const char *pname, const char *msg) {
-  if (pname) luai_writestringerror("%s: ", pname);
-  luai_writestringerror("%s\n", msg);
+  if (pname) lua_writestringerror("%s: ", pname);
+  lua_writestringerror("%s\n", msg);
 }
 
 
+/*
+** Check whether 'status' is not OK and, if so, prints the error
+** message on the top of the stack. It assumes that the error object
+** is a string, as it was either generated by Lua or by 'msghandler'.
+*/
 static int report (lua_State *L, int status) {
-  if (status != LUA_OK && !lua_isnil(L, -1)) {
+  if (status != LUA_OK) {
     const char *msg = lua_tostring(L, -1);
-    if (msg == NULL) msg = "(error object is not a string)";
     l_message(progname, msg);
-    lua_pop(L, 1);
-    /* force a complete garbage collection in case of errors */
-    lua_gc(L, LUA_GCCOLLECT, 0);
+    lua_pop(L, 1);  /* remove message */
   }
   return status;
 }
 
 
-/* the next function is called unprotected, so it must avoid errors */
-static void finalreport (lua_State *L, int status) {
-  if (status != LUA_OK) {
-    const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
-                                                       : NULL;
-    if (msg == NULL) msg = "(error object is not a string)";
-    l_message(progname, msg);
-    lua_pop(L, 1);
-  }
-}
-
-
-static int traceback (lua_State *L) {
+/*
+** Message handler used to run all chunks
+*/
+static int msghandler (lua_State *L) {
   const char *msg = lua_tostring(L, 1);
-  if (msg)
-    luaL_traceback(L, L, msg, 1);
-  else if (!lua_isnoneornil(L, 1)) {  /* is there an error object? */
-    if (!luaL_callmeta(L, 1, "__tostring"))  /* try its 'tostring' metamethod */
-      lua_pushliteral(L, "(no error message)");
+  if (msg == NULL) {  /* is error object not a string? */
+    if (luaL_callmeta(L, 1, "__tostring") &&  /* does it have a metamethod */
+        lua_type(L, -1) == LUA_TSTRING)  /* that produces a string? */
+      return 1;  /* that is the message */
+    else
+      msg = lua_pushfstring(L, "(error object is a %s value)",
+                               luaL_typename(L, 1));
   }
-  return 1;
+  luaL_traceback(L, L, msg, 1);  /* append a standard traceback */
+  return 1;  /* return the traceback */
 }
 
 
+/*
+** Interface to 'lua_pcall', which sets appropriate message function
+** and C-signal handler. Used to run all chunks.
+*/
 static int docall (lua_State *L, int narg, int nres) {
   int status;
   int base = lua_gettop(L) - narg;  /* function index */
-  lua_pushcfunction(L, traceback);  /* push traceback function */
-  lua_insert(L, base);  /* put it under chunk and args */
+  lua_pushcfunction(L, msghandler);  /* push message handler */
+  lua_insert(L, base);  /* put it under function and args */
   globalL = L;  /* to be available to 'laction' */
-  signal(SIGINT, laction);
+  signal(SIGINT, laction);  /* set C-signal handler */
   status = lua_pcall(L, narg, nres, base);
-  signal(SIGINT, SIG_DFL);
-  lua_remove(L, base);  /* remove traceback function */
+  signal(SIGINT, SIG_DFL); /* reset C-signal handler */
+  lua_remove(L, base);  /* remove message handler from the stack */
   return status;
 }
 
 
 static void print_version (void) {
-  luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
-  luai_writeline();
+  lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
+  lua_writeline();
 }
 
 
-static int getargs (lua_State *L, char **argv, int n) {
-  int narg;
-  int i;
-  int argc = 0;
-  while (argv[argc]) argc++;  /* count total number of arguments */
-  narg = argc - (n + 1);  /* number of arguments to the script */
-  luaL_checkstack(L, narg + 3, "too many arguments to script");
-  for (i=n+1; i < argc; i++)
-    lua_pushstring(L, argv[i]);
-  lua_createtable(L, narg, n + 1);
-  for (i=0; i < argc; i++) {
+/*
+** Create the 'arg' table, which stores all arguments from the
+** command line ('argv'). It should be aligned so that, at index 0,
+** it has 'argv[script]', which is the script name. The arguments
+** to the script (everything after 'script') go to positive indices;
+** other arguments (before the script name) go to negative indices.
+** If there is no script name, assume interpreter's name as base.
+*/
+static void createargtable (lua_State *L, char **argv, int argc, int script) {
+  int i, narg;
+  if (script == argc) script = 0;  /* no script name? */
+  narg = argc - (script + 1);  /* number of positive indices */
+  lua_createtable(L, narg, script + 1);
+  for (i = 0; i < argc; i++) {
     lua_pushstring(L, argv[i]);
-    lua_rawseti(L, -2, i - n);
+    lua_rawseti(L, -2, i - script);
   }
-  return narg;
+  lua_setglobal(L, "arg");
 }
 
 
-static int dofile (lua_State *L, const char *name) {
-  int status = luaL_loadfile(L, name);
+static int dochunk (lua_State *L, int status) {
   if (status == LUA_OK) status = docall(L, 0, 0);
   return report(L, status);
 }
 
 
+static int dofile (lua_State *L, const char *name) {
+  return dochunk(L, luaL_loadfile(L, name));
+}
+
+
 static int dostring (lua_State *L, const char *s, const char *name) {
-  int status = luaL_loadbuffer(L, s, strlen(s), name);
-  if (status == LUA_OK) status = docall(L, 0, 0);
-  return report(L, status);
+  return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name));
 }
 
 
+/*
+** Calls 'require(name)' and stores the result in a global variable
+** with the given name.
+*/
 static int dolibrary (lua_State *L, const char *name) {
   int status;
   lua_getglobal(L, "require");
@@ -232,6 +265,9 @@ static int dolibrary (lua_State *L, const char *name) {
 }
 
 
+/*
+** Returns the string to be used as a prompt by the interpreter.
+*/
 static const char *get_prompt (lua_State *L, int firstline) {
   const char *p;
   lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
@@ -244,6 +280,12 @@ static const char *get_prompt (lua_State *L, int firstline) {
 #define EOFMARK                "<eof>"
 #define marklen                (sizeof(EOFMARK)/sizeof(char) - 1)
 
+
+/*
+** Check whether 'status' signals a syntax error and the error
+** message at the top of the stack ends with the above mark for
+** incomplete statements.
+*/
 static int incomplete (lua_State *L, int status) {
   if (status == LUA_ERRSYNTAX) {
     size_t lmsg;
@@ -257,163 +299,230 @@ static int incomplete (lua_State *L, int status) {
 }
 
 
+/*
+** Prompt the user, read a line, and push it into the Lua stack.
+*/
 static int pushline (lua_State *L, int firstline) {
   char buffer[LUA_MAXINPUT];
   char *b = buffer;
   size_t l;
   const char *prmt = get_prompt(L, firstline);
   int readstatus = lua_readline(L, b, prmt);
-  lua_pop(L, 1);  /* remove result from 'get_prompt' */
   if (readstatus == 0)
-    return 0;  /* no input */
+    return 0;  /* no input (prompt will be popped by caller) */
+  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 */
-  if (firstline && b[0] == '=')  /* first line starts with `=' ? */
-    lua_pushfstring(L, "return %s", b+1);  /* change it to `return' */
+    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;
 }
 
 
+/*
+** Try to compile line on the stack as 'return <line>;'; on return, stack
+** has either compiled chunk or original line (if compilation failed).
+*/
+static int addreturn (lua_State *L) {
+  const char *line = lua_tostring(L, -1);  /* original line */
+  const char *retline = lua_pushfstring(L, "return %s;", line);
+  int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin");
+  if (status == LUA_OK) {
+    lua_remove(L, -2);  /* remove modified line */
+    if (line[0] != '\0')  /* non empty? */
+      lua_saveline(L, line);  /* keep history */
+  }
+  else
+    lua_pop(L, 2);  /* pop result from 'luaL_loadbuffer' and modified line */
+  return status;
+}
+
+
+/*
+** Read multiple lines until a complete Lua statement
+*/
+static int multiline (lua_State *L) {
+  for (;;) {  /* repeat until gets a complete statement */
+    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)) {
+      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 */
+  }
+}
+
+
+/*
+** Read a line and try to load (compile) it first as an expression (by
+** adding "return " in front of it) and second as a statement. Return
+** the final status of load/call with the resulting function (if any)
+** in the top of the stack.
+*/
 static int loadline (lua_State *L) {
   int status;
   lua_settop(L, 0);
   if (!pushline(L, 1))
     return -1;  /* no input */
-  for (;;) {  /* repeat until gets a complete line */
-    size_t l;
-    const char *line = lua_tolstring(L, 1, &l);
-    status = luaL_loadbuffer(L, line, l, "=stdin");
-    if (!incomplete(L, status)) break;  /* cannot try to add lines? */
-    if (!pushline(L, 0))  /* no more input? */
-      return -1;
-    lua_pushliteral(L, "\n");  /* add a new line... */
-    lua_insert(L, -2);  /* ...between the two lines */
-    lua_concat(L, 3);  /* join them */
-  }
-  lua_saveline(L, 1);
-  lua_remove(L, 1);  /* remove line */
+  if ((status = addreturn(L)) != LUA_OK)  /* 'return ...' did not work? */
+    status = multiline(L);  /* try as command, maybe with continuation lines */
+  lua_remove(L, 1);  /* remove line from the stack */
+  lua_assert(lua_gettop(L) == 1);
   return status;
 }
 
 
-static void dotty (lua_State *L) {
+/*
+** Prints (calling the Lua 'print' function) any values on the stack
+*/
+static void l_print (lua_State *L) {
+  int n = lua_gettop(L);
+  if (n > 0) {  /* any result to be printed? */
+    luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
+    lua_getglobal(L, "print");
+    lua_insert(L, 1);
+    if (lua_pcall(L, n, 0, 0) != LUA_OK)
+      l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)",
+                                             lua_tostring(L, -1)));
+  }
+}
+
+
+/*
+** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and
+** print any results.
+*/
+static void doREPL (lua_State *L) {
   int status;
   const char *oldprogname = progname;
-  progname = NULL;
+  progname = NULL;  /* no 'progname' on errors in interactive mode */
   while ((status = loadline(L)) != -1) {
-    if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET);
-    report(L, status);
-    if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
-      luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
-      lua_getglobal(L, "print");
-      lua_insert(L, 1);
-      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK)
-        l_message(progname, lua_pushfstring(L,
-                               "error calling " LUA_QL("print") " (%s)",
-                               lua_tostring(L, -1)));
-    }
+    if (status == LUA_OK)
+      status = docall(L, 0, LUA_MULTRET);
+    if (status == LUA_OK) l_print(L);
+    else report(L, status);
   }
   lua_settop(L, 0);  /* clear stack */
-  luai_writeline();
+  lua_writeline();
   progname = oldprogname;
 }
 
 
-static int handle_script (lua_State *L, char **argv, int n) {
+/*
+** Push on the stack the contents of table 'arg' from 1 to #arg
+*/
+static int pushargs (lua_State *L) {
+  int i, n;
+  if (lua_getglobal(L, "arg") != LUA_TTABLE)
+    luaL_error(L, "'arg' is not a table");
+  n = (int)luaL_len(L, -1);
+  luaL_checkstack(L, n + 3, "too many arguments to script");
+  for (i = 1; i <= n; i++)
+    lua_rawgeti(L, -i, i);
+  lua_remove(L, -i);  /* remove table from the stack */
+  return n;
+}
+
+
+static int handle_script (lua_State *L, char **argv) {
   int status;
-  const char *fname;
-  int narg = getargs(L, argv, n);  /* collect arguments */
-  lua_setglobal(L, "arg");
-  fname = argv[n];
-  if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0)
+  const char *fname = argv[0];
+  if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
     fname = NULL;  /* stdin */
   status = luaL_loadfile(L, fname);
-  lua_insert(L, -(narg+1));
-  if (status == LUA_OK)
-    status = docall(L, narg, LUA_MULTRET);
-  else
-    lua_pop(L, narg);
+  if (status == LUA_OK) {
+    int n = pushargs(L);  /* push arguments to script */
+    status = docall(L, n, LUA_MULTRET);
+  }
   return report(L, status);
 }
 
 
-/* check that argument has no extra characters at the end */
-#define noextrachars(x)                {if ((x)[2] != '\0') return -1;}
-
-
-/* indices of various argument indicators in array args */
-#define has_i          0       /* -i */
-#define has_v          1       /* -v */
-#define has_e          2       /* -e */
-#define has_E          3       /* -E */
-
-#define num_has                4       /* number of 'has_*' */
 
+/* bits of various argument indicators in 'args' */
+#define has_error      1       /* bad option */
+#define has_i          2       /* -i */
+#define has_v          4       /* -v */
+#define has_e          8       /* -e */
+#define has_E          16      /* -E */
 
-static int collectargs (char **argv, int *args) {
+/*
+** Traverses all arguments from 'argv', returning a mask with those
+** needed before running any Lua code (or an error code if it finds
+** any invalid argument). 'first' returns the first not-handled argument 
+** (either the script name or a bad argument in case of error).
+*/
+static int collectargs (char **argv, int *first) {
+  int args = 0;
   int i;
   for (i = 1; argv[i] != NULL; i++) {
+    *first = i;
     if (argv[i][0] != '-')  /* not an option? */
-        return i;
-    switch (argv[i][1]) {  /* option */
-      case '-':
-        noextrachars(argv[i]);
-        return (argv[i+1] != NULL ? i+1 : 0);
-      case '\0':
-        return i;
+        return args;  /* stop handling options */
+    switch (argv[i][1]) {  /* else check option */
+      case '-':  /* '--' */
+        if (argv[i][2] != '\0')  /* extra characters after '--'? */
+          return has_error;  /* invalid option */
+        *first = i + 1;
+        return args;
+      case '\0':  /* '-' */
+        return args;  /* script "name" is '-' */
       case 'E':
-        args[has_E] = 1;
+        if (argv[i][2] != '\0')  /* extra characters after 1st? */
+          return has_error;  /* invalid option */
+        args |= has_E;
         break;
       case 'i':
-        noextrachars(argv[i]);
-        args[has_i] = 1;  /* go through */
+        args |= has_i;  /* (-i implies -v) *//* FALLTHROUGH */ 
       case 'v':
-        noextrachars(argv[i]);
-        args[has_v] = 1;
+        if (argv[i][2] != '\0')  /* extra characters after 1st? */
+          return has_error;  /* invalid option */
+        args |= has_v;
         break;
       case 'e':
-        args[has_e] = 1;  /* 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' */
           if (argv[i] == NULL || argv[i][0] == '-')
-            return -(i - 1);  /* no next argument or it is another option */
+            return has_error;  /* no next argument or it is another option */
         }
         break;
-      default:  /* invalid option; return its index... */
-        return -i;  /* ...as a negative value */
+      default:  /* invalid option */
+        return has_error;
     }
   }
-  return 0;
+  *first = i;  /* no script name */
+  return args;
 }
 
 
+/*
+** Processes options 'e' and 'l', which involve running Lua code.
+** Returns 0 if some code raises an error.
+*/
 static int runargs (lua_State *L, char **argv, int n) {
   int i;
   for (i = 1; i < n; i++) {
-    lua_assert(argv[i][0] == '-');
-    switch (argv[i][1]) {  /* option */
-      case 'e': {
-        const char *chunk = argv[i] + 2;
-        if (*chunk == '\0') chunk = argv[++i];
-        lua_assert(chunk != NULL);
-        if (dostring(L, chunk, "=(command line)") != LUA_OK)
-          return 0;
-        break;
-      }
-      case 'l': {
-        const char *filename = argv[i] + 2;
-        if (*filename == '\0') filename = argv[++i];
-        lua_assert(filename != NULL);
-        if (dolibrary(L, filename) != LUA_OK)
-          return 0;  /* stop if file fails */
-        break;
-      }
-      default: break;
+    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);
+      status = (option == 'e')
+               ? dostring(L, extra, "=(command line)")
+               : dolibrary(L, extra);
+      if (status != LUA_OK) return 0;
     }
   }
   return 1;
@@ -421,10 +530,10 @@ static int runargs (lua_State *L, char **argv, int n) {
 
 
 static int handle_luainit (lua_State *L) {
-  const char *name = "=" LUA_INITVERSION;
+  const char *name = "=" LUA_INITVARVERSION;
   const char *init = getenv(name + 1);
   if (init == NULL) {
-    name = "=" LUA_INIT;
+    name = "=" LUA_INIT_VAR;
     init = getenv(name + 1);  /* try alternative name */
   }
   if (init == NULL) return LUA_OK;
@@ -435,40 +544,44 @@ static int handle_luainit (lua_State *L) {
 }
 
 
+/*
+** Main body of stand-alone interpreter (to be called in protected mode).
+** Reads the options and handles them all.
+*/
 static int pmain (lua_State *L) {
   int argc = (int)lua_tointeger(L, 1);
   char **argv = (char **)lua_touserdata(L, 2);
   int script;
-  int args[num_has];
-  args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
+  int args = collectargs(argv, &script);
+  luaL_checkversion(L);  /* check that interpreter has correct version */
   if (argv[0] && argv[0][0]) progname = argv[0];
-  script = collectargs(argv, args);
-  if (script < 0) {  /* invalid arg? */
-    print_usage(argv[-script]);
+  if (args == has_error) {  /* bad arg? */
+    print_usage(argv[script]);  /* 'script' has index of bad arg. */
     return 0;
   }
-  if (args[has_v]) print_version();
-  if (args[has_E]) {  /* option '-E'? */
+  if (args & has_v)  /* option '-v'? */
+    print_version();
+  if (args & has_E) {  /* option '-E'? */
     lua_pushboolean(L, 1);  /* signal for libraries to ignore env. vars. */
     lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
   }
-  /* open standard libraries */
-  luaL_checkversion(L);
-  lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
-  luaL_openlibs(L);  /* open libraries */
-  lua_gc(L, LUA_GCRESTART, 0);
-  if (!args[has_E] && handle_luainit(L) != LUA_OK)
-    return 0;  /* error running LUA_INIT */
-  /* execute arguments -e and -l */
-  if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
-  /* execute main script (if there is one) */
-  if (script && handle_script(L, argv, script) != LUA_OK) return 0;
-  if (args[has_i])  /* -i option? */
-    dotty(L);
-  else if (script == 0 && !args[has_e] && !args[has_v]) {  /* no arguments? */
-    if (lua_stdin_is_tty()) {
+  luaL_openlibs(L);  /* open standard libraries */
+  createargtable(L, argv, argc, script);  /* create table 'arg' */
+  if (!(args & has_E)) {  /* no option '-E'? */
+    if (handle_luainit(L) != LUA_OK)  /* run LUA_INIT */
+      return 0;  /* error running LUA_INIT */
+  }
+  if (!runargs(L, argv, script))  /* execute arguments -e and -l */
+    return 0;  /* something failed */
+  if (script < argc &&  /* execute main script (if there is one) */
+      handle_script(L, argv + script) != LUA_OK)
+    return 0;
+  if (args & has_i)  /* -i option? */
+    doREPL(L);  /* do read-eval-print loop */
+  else if (script == argc && !(args & (has_e | has_v))) {  /* no arguments? */
+    if (lua_stdin_is_tty()) {  /* running in interactive mode? */
       print_version();
-      dotty(L);
+      doREPL(L);  /* do read-eval-print loop */
     }
     else dofile(L, NULL);  /* executes stdin as a file */
   }
@@ -484,13 +597,12 @@ int main (int argc, char **argv) {
     l_message(argv[0], "cannot create state: not enough memory");
     return EXIT_FAILURE;
   }
-  /* call 'pmain' in protected mode */
-  lua_pushcfunction(L, &pmain);
+  lua_pushcfunction(L, &pmain);  /* to call 'pmain' in protected mode */
   lua_pushinteger(L, argc);  /* 1st argument */
   lua_pushlightuserdata(L, argv); /* 2nd argument */
-  status = lua_pcall(L, 2, 1, 0);
+  status = lua_pcall(L, 2, 1, 0);  /* do the call */
   result = lua_toboolean(L, -1);  /* get result */
-  finalreport(L, status);
+  report(L, status);
   lua_close(L);
   return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index ff4a108..f78899f 100644 (file)
--- a/src/lua.h
+++ b/src/lua.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.285.1.4 2015/02/21 14:04:50 roberto Exp $
+** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
 
 
 #define LUA_VERSION_MAJOR      "5"
-#define LUA_VERSION_MINOR      "2"
-#define LUA_VERSION_NUM                502
-#define LUA_VERSION_RELEASE    "4"
+#define LUA_VERSION_MINOR      "3"
+#define LUA_VERSION_NUM                503
+#define LUA_VERSION_RELEASE    "3"
 
 #define LUA_VERSION    "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #define LUA_RELEASE    LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT  LUA_RELEASE "  Copyright (C) 1994-2015 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT  LUA_RELEASE "  Copyright (C) 1994-2016 Lua.org, PUC-Rio"
 #define LUA_AUTHORS    "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
 
 
 /* mark for precompiled code ('<esc>Lua') */
-#define LUA_SIGNATURE  "\033Lua"
+#define LUA_SIGNATURE  "\x1bLua"
 
 /* option for multiple returns in 'lua_pcall' and 'lua_call' */
 #define LUA_MULTRET    (-1)
 
 
 /*
-** 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))
 
 
 
 typedef struct lua_State lua_State;
 
-typedef int (*lua_CFunction) (lua_State *L);
-
-
-/*
-** functions that read/write blocks when loading/dumping Lua chunks
-*/
-typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
-
-typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
-
-
-/*
-** prototype for memory-allocation functions
-*/
-typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
-
 
 /*
 ** basic types
@@ -109,6 +95,34 @@ typedef LUA_INTEGER lua_Integer;
 /* unsigned integer type */
 typedef LUA_UNSIGNED lua_Unsigned;
 
+/* type for continuation-function contexts */
+typedef LUA_KCONTEXT lua_KContext;
+
+
+/*
+** Type for C functions registered with Lua
+*/
+typedef int (*lua_CFunction) (lua_State *L);
+
+/*
+** Type for continuation functions
+*/
+typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);
+
+
+/*
+** Type for functions that read/write blocks when loading/dumping Lua chunks
+*/
+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
+
+typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud);
+
+
+/*
+** Type for memory-allocation functions
+*/
+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
+
 
 
 /*
@@ -145,11 +159,9 @@ LUA_API int   (lua_absindex) (lua_State *L, int idx);
 LUA_API int   (lua_gettop) (lua_State *L);
 LUA_API void  (lua_settop) (lua_State *L, int idx);
 LUA_API void  (lua_pushvalue) (lua_State *L, int idx);
-LUA_API void  (lua_remove) (lua_State *L, int idx);
-LUA_API void  (lua_insert) (lua_State *L, int idx);
-LUA_API void  (lua_replace) (lua_State *L, int idx);
+LUA_API void  (lua_rotate) (lua_State *L, int idx, int n);
 LUA_API void  (lua_copy) (lua_State *L, int fromidx, int toidx);
-LUA_API int   (lua_checkstack) (lua_State *L, int sz);
+LUA_API int   (lua_checkstack) (lua_State *L, int n);
 
 LUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);
 
@@ -161,13 +173,13 @@ LUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);
 LUA_API int             (lua_isnumber) (lua_State *L, int idx);
 LUA_API int             (lua_isstring) (lua_State *L, int idx);
 LUA_API int             (lua_iscfunction) (lua_State *L, int idx);
+LUA_API int             (lua_isinteger) (lua_State *L, int idx);
 LUA_API int             (lua_isuserdata) (lua_State *L, int idx);
 LUA_API int             (lua_type) (lua_State *L, int idx);
 LUA_API const char     *(lua_typename) (lua_State *L, int tp);
 
 LUA_API lua_Number      (lua_tonumberx) (lua_State *L, int idx, int *isnum);
 LUA_API lua_Integer     (lua_tointegerx) (lua_State *L, int idx, int *isnum);
-LUA_API lua_Unsigned    (lua_tounsignedx) (lua_State *L, int idx, int *isnum);
 LUA_API int             (lua_toboolean) (lua_State *L, int idx);
 LUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);
 LUA_API size_t          (lua_rawlen) (lua_State *L, int idx);
@@ -181,13 +193,20 @@ LUA_API const void     *(lua_topointer) (lua_State *L, int idx);
 ** Comparison and arithmetic functions
 */
 
-#define LUA_OPADD      0       /* ORDER TM */
+#define LUA_OPADD      0       /* ORDER TM, ORDER OP */
 #define LUA_OPSUB      1
 #define LUA_OPMUL      2
-#define LUA_OPDIV      3
-#define LUA_OPMOD      4
-#define LUA_OPPOW      5
-#define LUA_OPUNM      6
+#define LUA_OPMOD      3
+#define LUA_OPPOW      4
+#define LUA_OPDIV      5
+#define LUA_OPIDIV     6
+#define LUA_OPBAND     7
+#define LUA_OPBOR      8
+#define LUA_OPBXOR     9
+#define LUA_OPSHL      10
+#define LUA_OPSHR      11
+#define LUA_OPUNM      12
+#define LUA_OPBNOT     13
 
 LUA_API void  (lua_arith) (lua_State *L, int op);
 
@@ -205,8 +224,7 @@ LUA_API int   (lua_compare) (lua_State *L, int idx1, int idx2, int op);
 LUA_API void        (lua_pushnil) (lua_State *L);
 LUA_API void        (lua_pushnumber) (lua_State *L, lua_Number n);
 LUA_API void        (lua_pushinteger) (lua_State *L, lua_Integer n);
-LUA_API void        (lua_pushunsigned) (lua_State *L, lua_Unsigned n);
-LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l);
+LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
 LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
 LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
                                                       va_list argp);
@@ -220,26 +238,29 @@ LUA_API int   (lua_pushthread) (lua_State *L);
 /*
 ** get functions (Lua -> stack)
 */
-LUA_API void  (lua_getglobal) (lua_State *L, const char *var);
-LUA_API void  (lua_gettable) (lua_State *L, int idx);
-LUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);
-LUA_API void  (lua_rawget) (lua_State *L, int idx);
-LUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);
-LUA_API void  (lua_rawgetp) (lua_State *L, int idx, const void *p);
+LUA_API int (lua_getglobal) (lua_State *L, const char *name);
+LUA_API int (lua_gettable) (lua_State *L, int idx);
+LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
+LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
+LUA_API int (lua_rawget) (lua_State *L, int idx);
+LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
+LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
+
 LUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);
 LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
 LUA_API int   (lua_getmetatable) (lua_State *L, int objindex);
-LUA_API void  (lua_getuservalue) (lua_State *L, int idx);
+LUA_API int  (lua_getuservalue) (lua_State *L, int idx);
 
 
 /*
 ** set functions (stack -> Lua)
 */
-LUA_API void  (lua_setglobal) (lua_State *L, const char *var);
+LUA_API void  (lua_setglobal) (lua_State *L, const char *name);
 LUA_API void  (lua_settable) (lua_State *L, int idx);
 LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
+LUA_API void  (lua_seti) (lua_State *L, int idx, lua_Integer n);
 LUA_API void  (lua_rawset) (lua_State *L, int idx);
-LUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);
+LUA_API void  (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
 LUA_API void  (lua_rawsetp) (lua_State *L, int idx, const void *p);
 LUA_API int   (lua_setmetatable) (lua_State *L, int objindex);
 LUA_API void  (lua_setuservalue) (lua_State *L, int idx);
@@ -248,31 +269,31 @@ LUA_API void  (lua_setuservalue) (lua_State *L, int idx);
 /*
 ** 'load' and 'call' functions (load and run Lua code)
 */
-LUA_API void  (lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
-                           lua_CFunction k);
+LUA_API void  (lua_callk) (lua_State *L, int nargs, int nresults,
+                           lua_KContext ctx, lua_KFunction k);
 #define lua_call(L,n,r)                lua_callk(L, (n), (r), 0, NULL)
 
-LUA_API int   (lua_getctx) (lua_State *L, int *ctx);
-
 LUA_API int   (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
-                            int ctx, lua_CFunction k);
+                            lua_KContext ctx, lua_KFunction k);
 #define lua_pcall(L,n,r,f)     lua_pcallk(L, (n), (r), (f), 0, NULL)
 
 LUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,
-                                        const char *chunkname,
-                                        const char *mode);
+                          const char *chunkname, const char *mode);
 
-LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
 
 
 /*
 ** coroutine functions
 */
-LUA_API int  (lua_yieldk) (lua_State *L, int nresults, int ctx,
-                           lua_CFunction k);
+LUA_API int  (lua_yieldk)     (lua_State *L, int nresults, lua_KContext ctx,
+                               lua_KFunction k);
+LUA_API int  (lua_resume)     (lua_State *L, lua_State *from, int narg);
+LUA_API int  (lua_status)     (lua_State *L);
+LUA_API int (lua_isyieldable) (lua_State *L);
+
 #define lua_yield(L,n)         lua_yieldk(L, (n), 0, NULL)
-LUA_API int  (lua_resume) (lua_State *L, lua_State *from, int narg);
-LUA_API int  (lua_status) (lua_State *L);
+
 
 /*
 ** garbage-collection function and options
@@ -286,10 +307,7 @@ LUA_API int  (lua_status) (lua_State *L);
 #define LUA_GCSTEP             5
 #define LUA_GCSETPAUSE         6
 #define LUA_GCSETSTEPMUL       7
-#define LUA_GCSETMAJORINC      8
 #define LUA_GCISRUNNING                9
-#define LUA_GCGEN              10
-#define LUA_GCINC              11
 
 LUA_API int (lua_gc) (lua_State *L, int what, int data);
 
@@ -305,20 +323,23 @@ LUA_API int   (lua_next) (lua_State *L, int idx);
 LUA_API void  (lua_concat) (lua_State *L, int n);
 LUA_API void  (lua_len)    (lua_State *L, int idx);
 
+LUA_API size_t   (lua_stringtonumber) (lua_State *L, const char *s);
+
 LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
 LUA_API void      (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
 
 
 
 /*
-** ===============================================================
+** {==============================================================
 ** some useful macros
 ** ===============================================================
 */
 
-#define lua_tonumber(L,i)      lua_tonumberx(L,i,NULL)
-#define lua_tointeger(L,i)     lua_tointegerx(L,i,NULL)
-#define lua_tounsigned(L,i)    lua_tounsignedx(L,i,NULL)
+#define lua_getextraspace(L)   ((void *)((char *)(L) - LUA_EXTRASPACE))
+
+#define lua_tonumber(L,i)      lua_tonumberx(L,(i),NULL)
+#define lua_tointeger(L,i)     lua_tointegerx(L,(i),NULL)
 
 #define lua_pop(L,n)           lua_settop(L, -(n)-1)
 
@@ -337,15 +358,36 @@ 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)
+       ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
 
 #define lua_tostring(L,i)      lua_tolstring(L, (i), NULL)
 
 
+#define lua_insert(L,idx)      lua_rotate(L, (idx), 1)
+
+#define lua_remove(L,idx)      (lua_rotate(L, (idx), -1), lua_pop(L, 1))
+
+#define lua_replace(L,idx)     (lua_copy(L, -1, (idx)), lua_pop(L, 1))
+
+/* }============================================================== */
+
+
+/*
+** {==============================================================
+** compatibility macros for unsigned conversions
+** ===============================================================
+*/
+#if defined(LUA_COMPAT_APIINTCASTS)
+
+#define lua_pushunsigned(L,n)  lua_pushinteger(L, (lua_Integer)(n))
+#define lua_tounsignedx(L,i,is)        ((lua_Unsigned)lua_tointegerx(L,i,is))
+#define lua_tounsigned(L,i)    lua_tounsignedx(L,(i),NULL)
+
+#endif
+/* }============================================================== */
 
 /*
 ** {======================================================================
@@ -390,7 +432,7 @@ LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
 LUA_API void  (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
                                                int fidx2, int n2);
 
-LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
+LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
 LUA_API lua_Hook (lua_gethook) (lua_State *L);
 LUA_API int (lua_gethookmask) (lua_State *L);
 LUA_API int (lua_gethookcount) (lua_State *L);
@@ -418,7 +460,7 @@ struct lua_Debug {
 
 
 /******************************************************************************
-* Copyright (C) 1994-2015 Lua.org, PUC-Rio.
+* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
index 7409706..c0c91d0 100644 (file)
@@ -1,17 +1,20 @@
 /*
-** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $
-** Lua compiler (saves bytecodes to files; also list bytecodes)
+** $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
 */
 
+#define luac_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
+#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define luac_c
-#define LUA_CORE
-
 #include "lua.h"
 #include "lauxlib.h"
 
@@ -47,14 +50,14 @@ static void cannot(const char* what)
 static void usage(const char* message)
 {
  if (*message=='-')
-  fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
+  fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message);
  else
   fprintf(stderr,"%s: %s\n",progname,message);
  fprintf(stderr,
   "usage: %s [options] [filenames]\n"
   "Available options are:\n"
   "  -l       list (use -l -l for full listing)\n"
-  "  -o name  output to file " LUA_QL("name") " (default is \"%s\")\n"
+  "  -o name  output to file 'name' (default is \"%s\")\n"
   "  -p       parse only\n"
   "  -s       strip debug information\n"
   "  -v       show version information\n"
@@ -89,7 +92,7 @@ static int doargs(int argc, char* argv[])
   {
    output=argv[++i];
    if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
-    usage(LUA_QL("-o") " needs argument");
+    usage("'-o' needs argument");
    if (IS("-")) output=NULL;
   }
   else if (IS("-p"))                   /* parse only */
@@ -203,7 +206,7 @@ int main(int argc, char* argv[])
 }
 
 /*
-** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $
+** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
 ** print bytecodes
 ** See Copyright Notice in lua.h
 */
@@ -223,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->tsv.len;
+ size_t i,n=tsslen(ts);
  printf("%c",'"');
  for (i=0; i<n; i++)
  {
@@ -251,7 +254,7 @@ static void PrintString(const TString* ts)
 static void PrintConstant(const Proto* f, int i)
 {
  const TValue* o=&f->k[i];
- switch (ttypenv(o))
+ switch (ttype(o))
  {
   case LUA_TNIL:
        printf("nil");
@@ -259,11 +262,19 @@ static void PrintConstant(const Proto* f, int i)
   case LUA_TBOOLEAN:
        printf(bvalue(o) ? "true" : "false");
        break;
-  case LUA_TNUMBER:
-       printf(LUA_NUMBER_FMT,nvalue(o));
+  case LUA_TNUMFLT:
+       {
+       char buff[100];
+       sprintf(buff,LUA_NUMBER_FMT,fltvalue(o));
+       printf("%s",buff);
+       if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0");
+       break;
+       }
+  case LUA_TNUMINT:
+       printf(LUA_INTEGER_FMT,ivalue(o));
        break;
-  case LUA_TSTRING:
-       PrintString(rawtsvalue(o));
+  case LUA_TSHRSTR: case LUA_TLNGSTR:
+       PrintString(tsvalue(o));
        break;
   default:                             /* cannot happen */
        printf("? type=%d",ttype(o));
@@ -337,8 +348,14 @@ static void PrintCode(const Proto* f)
    case OP_ADD:
    case OP_SUB:
    case OP_MUL:
-   case OP_DIV:
    case OP_POW:
+   case OP_DIV:
+   case OP_IDIV:
+   case OP_BAND:
+   case OP_BOR:
+   case OP_BXOR:
+   case OP_SHL:
+   case OP_SHR:
    case OP_EQ:
    case OP_LT:
    case OP_LE:
index 1b0ff59..fd447cc 100644 (file)
 /*
-** $Id: luaconf.h,v 1.176.1.2 2013/11/21 17:26:16 roberto Exp $
+** $Id: luaconf.h,v 1.255 2016/05/01 20:06:09 roberto Exp $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */
 
 
-#ifndef lconfig_h
-#define lconfig_h
+#ifndef luaconf_h
+#define luaconf_h
 
 #include <limits.h>
 #include <stddef.h>
 
 
 /*
-** ==================================================================
+** ===================================================================
 ** Search for "@@" to find all configurable definitions.
 ** ===================================================================
 */
 
 
 /*
-@@ LUA_ANSI controls the use of non-ansi features.
-** CHANGE it (define it) if you want Lua to avoid the use of any
-** non-ansi feature or library.
+** {====================================================================
+** System Configuration: macros to adapt (if needed) Lua to some
+** particular platform, for instance compiling it with 32-bit numbers or
+** restricting it to C89.
+** =====================================================================
 */
-#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__)
-#define LUA_ANSI
-#endif
+
+/*
+@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You
+** can also define LUA_32BITS in the make file, but changing here you
+** ensure that all software connected to Lua will be compiled with the
+** same configuration.
+*/
+/* #define LUA_32BITS */
 
 
-#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE)
-#define LUA_WIN                /* enable goodies for regular Windows platforms */
-#endif
+/*
+@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
+** Define it if you want Lua to avoid the use of a few C99 features
+** or Windows-specific features on Windows.
+*/
+/* #define LUA_USE_C89 */
 
-#if defined(LUA_WIN)
-#define LUA_DL_DLL
-#define LUA_USE_AFORMAT                /* assume 'printf' handles 'aA' specifiers */
+
+/*
+** By default, Lua on Windows use (some) specific Windows features
+*/
+#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
+#define LUA_USE_WINDOWS  /* enable goodies for regular Windows */
 #endif
 
 
+#if defined(LUA_USE_WINDOWS)
+#define LUA_DL_DLL     /* enable support for DLL */
+#define LUA_USE_C89    /* broadly, Windows is C89 */
+#endif
+
 
 #if defined(LUA_USE_LINUX)
 #define LUA_USE_POSIX
 #define LUA_USE_DLOPEN         /* needs an extra library: -ldl */
 #define LUA_USE_READLINE       /* needs some extra libraries */
-#define LUA_USE_STRTODHEX      /* assume 'strtod' handles hex formats */
-#define LUA_USE_AFORMAT                /* assume 'printf' handles 'aA' specifiers */
-#define LUA_USE_LONGLONG       /* assume support for long long */
 #endif
 
+
 #if defined(LUA_USE_MACOSX)
 #define LUA_USE_POSIX
-#define LUA_USE_DLOPEN         /* does not need -ldl */
+#define LUA_USE_DLOPEN         /* MacOS does not need -ldl */
 #define LUA_USE_READLINE       /* needs an extra library: -lreadline */
-#define LUA_USE_STRTODHEX      /* assume 'strtod' handles hex formats */
-#define LUA_USE_AFORMAT                /* assume 'printf' handles 'aA' specifiers */
-#define LUA_USE_LONGLONG       /* assume support for long long */
+#endif
+
+
+/*
+@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
+** C89 ('long' and 'double'); Windows always has '__int64', so it does
+** not need to use this case.
+*/
+#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
+#define LUA_C89_NUMBERS
 #endif
 
 
 
 /*
-@@ LUA_USE_POSIX includes all functionality listed as X/Open System
-@* Interfaces Extension (XSI).
-** CHANGE it (define it) if your system is XSI compatible.
+@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'.
 */
-#if defined(LUA_USE_POSIX)
-#define LUA_USE_MKSTEMP
-#define LUA_USE_ISATTY
-#define LUA_USE_POPEN
-#define LUA_USE_ULONGJMP
-#define LUA_USE_GMTIME_R
+/* avoid undefined shifts */
+#if ((INT_MAX >> 15) >> 15) >= 1
+#define LUAI_BITSINT   32
+#else
+/* 'int' always must have at least 16 bits */
+#define LUAI_BITSINT   16
 #endif
 
 
+/*
+@@ 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
+** restricted platforms), and 'long'/'double' (for C compilers not
+** 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_TYPE   LUA_INT_INT
+#else  /* otherwise use 'long' */
+#define LUA_INT_TYPE   LUA_INT_LONG
+#endif
+#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
+
+#elif defined(LUA_C89_NUMBERS) /* }{ */
+/*
+** largest types available for C89 ('long' and 'double')
+*/
+#define LUA_INT_TYPE   LUA_INT_LONG
+#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
+
+#endif                         /* } */
+
+
+/*
+** default configuration for 64-bit Lua ('long long' and '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
+
+/* }================================================================== */
+
+
+
+
+/*
+** {==================================================================
+** Configuration for Paths.
+** ===================================================================
+*/
 
 /*
 @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
-@* Lua libraries.
+** Lua libraries.
 @@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
-@* C libraries.
+** C libraries.
 ** CHANGE them if your machine has a non-conventional directory
 ** hierarchy or if you want to install your libraries in
 ** non-conventional directories.
 */
+#define LUA_VDIR       LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #if defined(_WIN32)    /* { */
 /*
 ** In Windows, any exclamation mark ('!') in the path is replaced by the
 */
 #define LUA_LDIR       "!\\lua\\"
 #define LUA_CDIR       "!\\"
+#define LUA_SHRDIR     "!\\..\\share\\lua\\" LUA_VDIR "\\"
 #define LUA_PATH_DEFAULT  \
                LUA_LDIR"?.lua;"  LUA_LDIR"?\\init.lua;" \
-               LUA_CDIR"?.lua;"  LUA_CDIR"?\\init.lua;" ".\\?.lua"
+               LUA_CDIR"?.lua;"  LUA_CDIR"?\\init.lua;" \
+               LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
+               ".\\?.lua;" ".\\?\\init.lua"
 #define LUA_CPATH_DEFAULT \
-               LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll"
+               LUA_CDIR"?.dll;" \
+               LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
+               LUA_CDIR"loadall.dll;" ".\\?.dll"
 
 #else                  /* }{ */
 
-#define LUA_VDIR       LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/"
 #define LUA_ROOT       "/usr/local/"
-#define LUA_LDIR       LUA_ROOT "share/lua/" LUA_VDIR
-#define LUA_CDIR       LUA_ROOT "lib/lua/" LUA_VDIR
+#define LUA_LDIR       LUA_ROOT "share/lua/" LUA_VDIR "/"
+#define LUA_CDIR       LUA_ROOT "lib/lua/" LUA_VDIR "/"
 #define LUA_PATH_DEFAULT  \
                LUA_LDIR"?.lua;"  LUA_LDIR"?/init.lua;" \
-               LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua;" "./?.lua"
+               LUA_CDIR"?.lua;"  LUA_CDIR"?/init.lua;" \
+               "./?.lua;" "./?/init.lua"
 #define LUA_CPATH_DEFAULT \
                LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
 #endif                 /* } */
 #define LUA_DIRSEP     "/"
 #endif
 
+/* }================================================================== */
+
 
 /*
-@@ LUA_ENV is the name of the variable that holds the current
-@@ environment, used to access global names.
-** CHANGE it if you do not like this name.
+** {==================================================================
+** Marks for exported symbols in the C code
+** ===================================================================
 */
-#define LUA_ENV                "_ENV"
-
 
 /*
 @@ LUA_API is a mark for all core API functions.
 
 /*
 @@ LUAI_FUNC is a mark for all extern functions that are not to be
-@* exported to outside modules.
+** exported to outside modules.
 @@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
-@* that are not to be exported to outside modules (LUAI_DDEF for
-@* definitions and LUAI_DDEC for declarations).
+** that are not to be exported to outside modules (LUAI_DDEF for
+** definitions and LUAI_DDEC for declarations).
 ** CHANGE them if you need to mark them in some special way. Elf/gcc
 ** (versions 3.2 and later) mark them as "hidden" to optimize access
 ** when Lua is compiled as a shared library. Not all elf targets support
 #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
     defined(__ELF__)           /* { */
 #define LUAI_FUNC      __attribute__((visibility("hidden"))) extern
-#define LUAI_DDEC      LUAI_FUNC
-#define LUAI_DDEF      /* empty */
-
 #else                          /* }{ */
 #define LUAI_FUNC      extern
-#define LUAI_DDEC      extern
-#define LUAI_DDEF      /* empty */
 #endif                         /* } */
 
+#define LUAI_DDEC      LUAI_FUNC
+#define LUAI_DDEF      /* empty */
+
+/* }================================================================== */
 
 
 /*
-@@ LUA_QL describes how error messages quote program elements.
-** CHANGE it if you want a different appearance.
+** {==================================================================
+** Compatibility with previous versions
+** ===================================================================
 */
-#define LUA_QL(x)      "'" x "'"
-#define LUA_QS         LUA_QL("%s")
-
 
 /*
-@@ LUA_IDSIZE gives the maximum size for the description of the source
-@* of a function in debug information.
-** CHANGE it if you want a different size.
+@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2.
+@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1.
+** You can define it to get all options, or change specific options
+** to fit your specific needs.
 */
-#define LUA_IDSIZE     60
-
+#if defined(LUA_COMPAT_5_2)    /* { */
 
 /*
-@@ luai_writestring/luai_writeline define how 'print' prints its results.
-** They are only used in libraries and the stand-alone program. (The #if
-** avoids including 'stdio.h' everywhere.)
+@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
+** functions in the mathematical library.
 */
-#if defined(LUA_LIB) || defined(lua_c)
-#include <stdio.h>
-#define luai_writestring(s,l)  fwrite((s), sizeof(char), (l), stdout)
-#define luai_writeline()       (luai_writestring("\n", 1), fflush(stdout))
-#endif
+#define LUA_COMPAT_MATHLIB
 
 /*
-@@ luai_writestringerror defines how to print error messages.
-** (A format string with one argument is enough for Lua...)
+@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'.
 */
-#define luai_writestringerror(s,p) \
-       (fprintf(stderr, (s), (p)), fflush(stderr))
+#define LUA_COMPAT_BITLIB
 
+/*
+@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod.
+*/
+#define LUA_COMPAT_IPAIRS
 
 /*
-@@ 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.)
+@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
+** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
+** luaL_checkint, luaL_checklong, etc.)
 */
-#define LUAI_MAXSHORTLEN        40
+#define LUA_COMPAT_APIINTCASTS
 
+#endif                         /* } */
 
 
-/*
-** {==================================================================
-** Compatibility with previous versions
-** ===================================================================
-*/
+#if defined(LUA_COMPAT_5_1)    /* { */
 
-/*
-@@ LUA_COMPAT_ALL controls all compatibility options.
-** You can define it to get all options, or change specific options
-** to fit your specific needs.
-*/
-#if defined(LUA_COMPAT_ALL)    /* { */
+/* Incompatibilities from 5.2 -> 5.3 */
+#define LUA_COMPAT_MATHLIB
+#define LUA_COMPAT_APIINTCASTS
 
 /*
 @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'.
 
 #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 */
+
 /* }================================================================== */
 
 
 
 /*
-@@ LUAI_BITSINT defines the number of bits in an int.
-** CHANGE here if Lua cannot automatically detect the number of bits of
-** your machine. Probably you do not need to change this.
+** {==================================================================
+** Configuration for Numbers.
+** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
+** satisfy your needs.
+** ===================================================================
 */
-/* avoid overflows in comparison */
-#if INT_MAX-20 < 32760         /* { */
-#define LUAI_BITSINT   16
-#elif INT_MAX > 2147483640L    /* }{ */
-/* int has at least 32 bits */
-#define LUAI_BITSINT   32
-#else                          /* }{ */
-#error "you must define LUA_BITSINT with number of bits in an integer"
-#endif                         /* } */
 
+/*
+@@ 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.
+@@ l_floor takes the floor of a float.
+@@ lua_str2number converts a decimal numeric string to a number.
+*/
+
+
+/* The following definitions are good for most cases here */
+
+#define l_floor(x)             (l_mathop(floor)(x))
+
+#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n))
 
 /*
-@@ LUA_INT32 is a signed integer with exactly 32 bits.
-@@ LUAI_UMEM is an unsigned integer big enough to count the total
-@* memory used by Lua.
-@@ LUAI_MEM is a signed integer big enough to count the total memory
-@* used by Lua.
-** CHANGE here if for some weird reason the default definitions are not
-** good enough for your machine. Probably you do not need to change
-** this.
+@@ lua_numbertointeger converts a float number to an integer, or
+** returns 0 if float is not within the range of a lua_Integer.
+** (The range comparisons are tricky because of rounding. The tests
+** here assume a two-complement representation, where MININTEGER always
+** has an exact representation as a float; MAXINTEGER may not have one,
+** and therefore its conversion to float may have an ill-defined value.)
 */
-#if LUAI_BITSINT >= 32         /* { */
-#define LUA_INT32      int
-#define LUAI_UMEM      size_t
-#define LUAI_MEM       ptrdiff_t
-#else                          /* }{ */
-/* 16-bit ints */
-#define LUA_INT32      long
-#define LUAI_UMEM      unsigned long
-#define LUAI_MEM       long
-#endif                         /* } */
+#define lua_numbertointeger(n,p) \
+  ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
+   (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
+      (*(p) = (LUA_INTEGER)(n), 1))
+
+
+/* now the variable definitions */
+
+#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      ""
+#define LUA_NUMBER_FMT         "%.7g"
+
+#define l_mathop(op)           op##f
+
+#define lua_str2number(s,p)    strtof((s), (p))
+
+
+#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"
+#define LUA_NUMBER_FMT         "%.19Lg"
+
+#define l_mathop(op)           op##l
+
+#define lua_str2number(s,p)    strtold((s), (p))
+
+#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      ""
+#define LUA_NUMBER_FMT         "%.14g"
+
+#define l_mathop(op)           op
+
+#define lua_str2number(s,p)    strtod((s), (p))
+
+#else                                          /* }{ */
+
+#error "numeric float type not defined"
+
+#endif                                 /* } */
+
 
 
 /*
-@@ LUAI_MAXSTACK limits the size of the Lua stack.
-** CHANGE it if you need a different limit. This limit is arbitrary;
-** its only purpose is to stop Lua from consuming unlimited stack
-** space (and to reserve some numbers for pseudo-indices).
+@@ LUA_INTEGER is the integer type used by Lua.
+**
+@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
+**
+@@ LUAI_UACINT is the result of an 'usual argument conversion'
+@@ over a lUA_INTEGER.
+@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
+@@ LUA_INTEGER_FMT is the format for writing integers.
+@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
+@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
+@@ lua_integer2str converts an integer to a string.
 */
-#if LUAI_BITSINT >= 32
-#define LUAI_MAXSTACK          1000000
-#else
-#define LUAI_MAXSTACK          15000
-#endif
 
-/* reserve some space for error handling */
-#define LUAI_FIRSTPSEUDOIDX    (-LUAI_MAXSTACK - 1000)
 
+/* The following definitions are good for most cases here */
 
+#define LUA_INTEGER_FMT                "%" LUA_INTEGER_FRMLEN "d"
+#define lua_integer2str(s,sz,n)        l_sprintf((s), sz, LUA_INTEGER_FMT, (n))
 
+#define LUAI_UACINT            LUA_INTEGER
 
 /*
-@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
-** CHANGE it if it uses too much C-stack space.
+** use LUAI_UACINT here to avoid problems with promotions (which
+** can turn a comparison between unsigneds into a signed comparison)
 */
-#define LUAL_BUFFERSIZE                BUFSIZ
+#define LUA_UNSIGNED           unsigned LUAI_UACINT
+
 
+/* now the variable definitions */
 
+#if LUA_INT_TYPE == LUA_INT_INT                /* { int */
+
+#define LUA_INTEGER            int
+#define LUA_INTEGER_FRMLEN     ""
+
+#define LUA_MAXINTEGER         INT_MAX
+#define LUA_MININTEGER         INT_MIN
+
+#elif LUA_INT_TYPE == LUA_INT_LONG     /* }{ long */
+
+#define LUA_INTEGER            long
+#define LUA_INTEGER_FRMLEN     "l"
+
+#define LUA_MAXINTEGER         LONG_MAX
+#define LUA_MININTEGER         LONG_MIN
+
+#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
+
+/* use presence of macro LLONG_MAX as proxy for C99 compliance */
+#if defined(LLONG_MAX)         /* { */
+/* use ISO C99 stuff */
+
+#define LUA_INTEGER            long long
+#define LUA_INTEGER_FRMLEN     "ll"
+
+#define LUA_MAXINTEGER         LLONG_MAX
+#define LUA_MININTEGER         LLONG_MIN
+
+#elif defined(LUA_USE_WINDOWS) /* }{ */
+/* in Windows, can use specific Windows types */
+
+#define LUA_INTEGER            __int64
+#define LUA_INTEGER_FRMLEN     "I64"
+
+#define LUA_MAXINTEGER         _I64_MAX
+#define LUA_MININTEGER         _I64_MIN
+
+#else                          /* }{ */
+
+#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
+  or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
+
+#endif                         /* } */
+
+#else                          /* }{ */
+
+#error "numeric integer type not defined"
+
+#endif                         /* } */
+
+/* }================================================================== */
 
 
 /*
 ** {==================================================================
-@@ LUA_NUMBER is the type of numbers in Lua.
-** CHANGE the following definitions only if you want to build Lua
-** with a number type different from double. You may also need to
-** change lua_number2int & lua_number2integer.
+** Dependencies with C99 and other C details
 ** ===================================================================
 */
 
-#define LUA_NUMBER_DOUBLE
-#define LUA_NUMBER     double
-
 /*
-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
-@* over a number.
+@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
+** (All uses in Lua have only one format item.)
 */
-#define LUAI_UACNUMBER double
+#if !defined(LUA_USE_C89)
+#define l_sprintf(s,sz,f,i)    snprintf(s,sz,f,i)
+#else
+#define l_sprintf(s,sz,f,i)    ((void)(sz), sprintf(s,f,i))
+#endif
 
 
 /*
-@@ LUA_NUMBER_SCAN is the format for reading numbers.
-@@ LUA_NUMBER_FMT is the format for writing numbers.
-@@ lua_number2str converts a number to a string.
-@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
+@@ lua_strx2number converts an hexadecimal numeric string to a number.
+** In C99, 'strtod' does that conversion. Otherwise, you can
+** leave 'lua_strx2number' undefined and Lua will provide its own
+** implementation.
 */
-#define LUA_NUMBER_SCAN                "%lf"
-#define LUA_NUMBER_FMT         "%.14g"
-#define lua_number2str(s,n)    sprintf((s), LUA_NUMBER_FMT, (n))
-#define LUAI_MAXNUMBER2STR     32 /* 16 digits, sign, point, and \0 */
+#if !defined(LUA_USE_C89)
+#define lua_strx2number(s,p)           lua_str2number(s,p)
+#endif
 
 
 /*
-@@ l_mathop allows the addition of an 'l' or 'f' to all math operations
+@@ 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.
 */
-#define l_mathop(x)            (x)
+#if !defined(LUA_USE_C89)
+#define lua_number2strx(L,b,sz,f,n)    ((void)L, l_sprintf(b,sz,f,n))
+#endif
 
 
 /*
-@@ lua_str2number converts a decimal numeric string to a number.
-@@ lua_strx2number converts an hexadecimal numeric string to a number.
-** In C99, 'strtod' does both conversions. C89, however, has no function
-** to convert floating hexadecimal strings to numbers. For these
-** systems, you can leave 'lua_strx2number' undefined and Lua will
-** provide its own implementation.
+** 'strtof' and 'opf' variants for math functions are not valid in
+** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
+** availability of these variants. ('math.h' is already included in
+** all files that use these macros.)
 */
-#define lua_str2number(s,p)    strtod((s), (p))
-
-#if defined(LUA_USE_STRTODHEX)
-#define lua_strx2number(s,p)   strtod((s), (p))
+#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
+#undef l_mathop  /* variants not available */
+#undef lua_str2number
+#define l_mathop(op)           (lua_Number)op  /* no variant */
+#define lua_str2number(s,p)    ((lua_Number)strtod((s), (p)))
 #endif
 
 
 /*
-@@ The luai_num* macros define the primitive operations over numbers.
+@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
+** functions.  It must be a numerical type; Lua will use 'intptr_t' if
+** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
+** 'intptr_t' in C89)
 */
+#define LUA_KCONTEXT   ptrdiff_t
 
-/* the following operations need the math library */
-#if defined(lobject_c) || defined(lvm_c)
-#include <math.h>
-#define luai_nummod(L,a,b)     ((a) - l_mathop(floor)((a)/(b))*(b))
-#define luai_numpow(L,a,b)     (l_mathop(pow)(a,b))
+#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 */
+#undef LUA_KCONTEXT
+#define LUA_KCONTEXT   intptr_t
 #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(L,a,b)      ((a)<(b))
-#define luai_numle(L,a,b)      ((a)<=(b))
-#define luai_numisnan(L,a)     (!luai_numeq((a), (a)))
 #endif
 
 
-
-/*
-@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
-** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
-** machines, ptrdiff_t gives a good choice between int or long.)
-*/
-#define LUA_INTEGER    ptrdiff_t
-
 /*
-@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
-** It must have at least 32 bits.
+@@ 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'.)
 */
-#define LUA_UNSIGNED   unsigned LUA_INT32
+#if !defined(lua_getlocaledecpoint)
+#define lua_getlocaledecpoint()                (localeconv()->decimal_point[0])
+#endif
 
+/* }================================================================== */
 
 
 /*
-** Some tricks with doubles
+** {==================================================================
+** Language Variations
+** =====================================================================
 */
 
-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI)   /* { */
 /*
-** The next definitions activate some tricks to speed up the
-** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
-**
-@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a
-** DirectX idiosyncrasy.
-**
-@@ LUA_IEEE754TRICK uses a trick that should work on any machine
-** using IEEE754 with a 32-bit integer type.
-**
-@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
-** defined when LUA_INTEGER is a 32-bit integer.
-**
-@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
-** (0 for little endian, 1 for big endian); if not defined, Lua will
-** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
-**
-@@ LUA_NANTRICK controls the use of a trick to pack all types into
-** a single double value, using NaN values to represent non-number
-** values. The trick only works on 32-bit machines (ints and pointers
-** are 32-bit values) with numbers represented as IEEE 754-2008 doubles
-** with conventional endianess (12345678 or 87654321), in CPUs that do
-** not produce signaling NaN values (all NaNs are quiet).
+@@ 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 */
 
-/* Microsoft compiler on a Pentium (32 bit) ? */
-#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86)  /* { */
-
-#define LUA_MSASMTRICK
-#define LUA_IEEEENDIAN         0
-#define LUA_NANTRICK
 
+/*
+@@ 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
 
-/* pentium 32 bits? */
-#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
+/* }================================================================== */
 
-#define LUA_IEEE754TRICK
-#define LUA_IEEELL
-#define LUA_IEEEENDIAN         0
-#define LUA_NANTRICK
 
-/* pentium 64 bits? */
-#elif defined(__x86_64)                                                /* }{ */
+/*
+** {==================================================================
+** Macros that affect the API and must be stable (that is, must be the
+** same when you compile Lua and when you compile code that links to
+** Lua). You probably do not want/need to change them.
+** =====================================================================
+*/
 
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN         0
+/*
+@@ LUAI_MAXSTACK limits the size of the Lua stack.
+** CHANGE it if you need a different limit. This limit is arbitrary;
+** its only purpose is to stop Lua from consuming unlimited stack
+** space (and to reserve some numbers for pseudo-indices).
+*/
+#if LUAI_BITSINT >= 32
+#define LUAI_MAXSTACK          1000000
+#else
+#define LUAI_MAXSTACK          15000
+#endif
 
-#elif defined(__POWERPC__) || defined(__ppc__)                 /* }{ */
 
-#define LUA_IEEE754TRICK
-#define LUA_IEEEENDIAN         1
+/*
+@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
+** a Lua state with very fast access.
+** CHANGE it if you need a different size.
+*/
+#define LUA_EXTRASPACE         (sizeof(void *))
 
-#else                                                          /* }{ */
 
-/* assume IEEE754 and a 32-bit integer type */
-#define LUA_IEEE754TRICK
+/*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@@ of a function in debug information.
+** CHANGE it if you want a different size.
+*/
+#define LUA_IDSIZE     60
 
-#endif                                                         /* } */
 
-#endif                                                 /* } */
+/*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+** 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'.)
+*/
+#if defined(LUA_FLOAT_LONGDOUBLE)
+#define LUAL_BUFFERSIZE                8192
+#else
+#define LUAL_BUFFERSIZE   ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer)))
+#endif
 
 /* }================================================================== */
 
 
+/*
+@@ LUA_QL describes how error messages quote program elements.
+** Lua does not use these macros anymore; they are here for
+** compatibility only.
+*/
+#define LUA_QL(x)      "'" x "'"
+#define LUA_QS         LUA_QL("%s")
+
+
 
 
 /* =================================================================== */
 
 
 
+
+
 #endif
 
index da82005..5165c0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $
 ** Lua standard libraries
 ** See Copyright Notice in lua.h
 */
@@ -29,6 +29,9 @@ LUAMOD_API int (luaopen_os) (lua_State *L);
 #define LUA_STRLIBNAME "string"
 LUAMOD_API int (luaopen_string) (lua_State *L);
 
+#define LUA_UTF8LIBNAME        "utf8"
+LUAMOD_API int (luaopen_utf8) (lua_State *L);
+
 #define LUA_BITLIBNAME "bit32"
 LUAMOD_API int (luaopen_bit32) (lua_State *L);
 
index 4163cb5..4080af9 100644 (file)
@@ -1,14 +1,17 @@
 /*
-** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
 
-#include <string.h>
-
 #define lundump_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
 #include "ldebug.h"
 #include "lundump.h"
 #include "lzio.h"
 
+
+#if !defined(luai_verifycode)
+#define luai_verifycode(L,b,f)  /* empty */
+#endif
+
+
 typedef struct {
- lua_State* L;
- ZIO* Z;
- Mbuffer* b;
- const char* name;
+  lua_State *L;
+  ZIO *Z;
+  const char *name;
 } LoadState;
 
-static l_noret error(LoadState* S, const char* why)
-{
luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why);
luaD_throw(S->L,LUA_ERRSYNTAX);
+
+static l_noret error(LoadState *S, const char *why) {
 luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
 luaD_throw(S->L, LUA_ERRSYNTAX);
 }
 
-#define LoadMem(S,b,n,size)    LoadBlock(S,b,(n)*(size))
-#define LoadByte(S)            (lu_byte)LoadChar(S)
-#define LoadVar(S,x)           LoadMem(S,&x,1,sizeof(x))
-#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
 
-#if !defined(luai_verifycode)
-#define luai_verifycode(L,b,f) /* empty */
-#endif
+/*
+** All high-level loads go through LoadVector; you can change it to
+** adapt to the endianness of the input
+*/
+#define LoadVector(S,b,n)      LoadBlock(S,b,(n)*sizeof((b)[0]))
 
-static void LoadBlock(LoadState* S, void* b, size_t size)
-{
if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated");
+static void LoadBlock (LoadState *S, void *b, size_t size) {
+  if (luaZ_read(S->Z, b, size) != 0)
   error(S, "truncated");
 }
 
-static int LoadChar(LoadState* S)
-{
- char x;
- LoadVar(S,x);
- return x;
+
+#define LoadVar(S,x)           LoadVector(S,&x,1)
+
+
+static lu_byte LoadByte (LoadState *S) {
+  lu_byte x;
+  LoadVar(S, x);
+  return x;
 }
 
-static int LoadInt(LoadState* S)
-{
- int x;
- LoadVar(S,x);
- if (x<0) error(S,"corrupted");
- return x;
+
+static int LoadInt (LoadState *S) {
+  int x;
+  LoadVar(S, x);
+  return x;
 }
 
-static lua_Number LoadNumber(LoadState* S)
-{
- lua_Number x;
LoadVar(S,x);
- return x;
+
+static lua_Number LoadNumber (LoadState *S) {
 lua_Number x;
 LoadVar(S, x);
 return x;
 }
 
-static TString* LoadString(LoadState* S)
-{
- size_t size;
- LoadVar(S,size);
- if (size==0)
-  return NULL;
- else
- {
-  char* s=luaZ_openspace(S->L,S->b,size);
-  LoadBlock(S,s,size*sizeof(char));
-  return luaS_newlstr(S->L,s,size-1);          /* remove trailing '\0' */
- }
+
+static lua_Integer LoadInteger (LoadState *S) {
+  lua_Integer x;
+  LoadVar(S, x);
+  return x;
 }
 
-static void LoadCode(LoadState* S, Proto* f)
-{
- int n=LoadInt(S);
- f->code=luaM_newvector(S->L,n,Instruction);
- f->sizecode=n;
- LoadVector(S,f->code,n,sizeof(Instruction));
+
+static TString *LoadString (LoadState *S) {
+  size_t size = LoadByte(S);
+  if (size == 0xFF)
+    LoadVar(S, size);
+  if (size == 0)
+    return NULL;
+  else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
+    char buff[LUAI_MAXSHORTLEN];
+    LoadVector(S, buff, size);
+    return luaS_newlstr(S->L, buff, size);
+  }
+  else {  /* long string */
+    TString *ts = luaS_createlngstrobj(S->L, size);
+    LoadVector(S, getstr(ts), size);  /* load directly in final place */
+    return ts;
+  }
 }
 
-static void LoadFunction(LoadState* S, Proto* f);
-
-static void LoadConstants(LoadState* S, Proto* f)
-{
- int i,n;
- n=LoadInt(S);
- f->k=luaM_newvector(S->L,n,TValue);
- f->sizek=n;
- for (i=0; i<n; i++) setnilvalue(&f->k[i]);
- for (i=0; i<n; i++)
- {
-  TValue* o=&f->k[i];
-  int t=LoadChar(S);
-  switch (t)
-  {
-   case LUA_TNIL:
-       setnilvalue(o);
-       break;
-   case LUA_TBOOLEAN:
-       setbvalue(o,LoadChar(S));
-       break;
-   case LUA_TNUMBER:
-       setnvalue(o,LoadNumber(S));
-       break;
-   case LUA_TSTRING:
-       setsvalue2n(S->L,o,LoadString(S));
-       break;
-    default: lua_assert(0);
+
+static void LoadCode (LoadState *S, Proto *f) {
+  int n = LoadInt(S);
+  f->code = luaM_newvector(S->L, n, Instruction);
+  f->sizecode = n;
+  LoadVector(S, f->code, n);
+}
+
+
+static void LoadFunction(LoadState *S, Proto *f, TString *psource);
+
+
+static void LoadConstants (LoadState *S, Proto *f) {
+  int i;
+  int n = LoadInt(S);
+  f->k = luaM_newvector(S->L, n, TValue);
+  f->sizek = n;
+  for (i = 0; i < n; i++)
+    setnilvalue(&f->k[i]);
+  for (i = 0; i < n; i++) {
+    TValue *o = &f->k[i];
+    int t = LoadByte(S);
+    switch (t) {
+    case LUA_TNIL:
+      setnilvalue(o);
+      break;
+    case LUA_TBOOLEAN:
+      setbvalue(o, LoadByte(S));
+      break;
+    case LUA_TNUMFLT:
+      setfltvalue(o, LoadNumber(S));
+      break;
+    case LUA_TNUMINT:
+      setivalue(o, LoadInteger(S));
+      break;
+    case LUA_TSHRSTR:
+    case LUA_TLNGSTR:
+      setsvalue2n(S->L, o, LoadString(S));
+      break;
+    default:
+      lua_assert(0);
+    }
   }
- }
- n=LoadInt(S);
- f->p=luaM_newvector(S->L,n,Proto*);
- f->sizep=n;
- for (i=0; i<n; i++) f->p[i]=NULL;
- for (i=0; i<n; i++)
- {
-  f->p[i]=luaF_newproto(S->L);
-  LoadFunction(S,f->p[i]);
- }
 }
 
-static void LoadUpvalues(LoadState* S, Proto* f)
-{
int i,n;
n=LoadInt(S);
f->upvalues=luaM_newvector(S->L,n,Upvaldesc);
f->sizeupvalues=n;
- for (i=0; i<n; i++) f->upvalues[i].name=NULL;
- for (i=0; i<n; i++)
- {
-  f->upvalues[i].instack=LoadByte(S);
-  f->upvalues[i].idx=LoadByte(S);
- }
+
+static void LoadProtos (LoadState *S, Proto *f) {
 int i;
 int n = LoadInt(S);
 f->p = luaM_newvector(S->L, n, Proto *);
 f->sizep = n;
+  for (i = 0; i < n; i++)
+    f->p[i] = NULL;
 for (i = 0; i < n; i++) {
+    f->p[i] = luaF_newproto(S->L);
+    LoadFunction(S, f->p[i], f->source);
 }
 }
 
-static void LoadDebug(LoadState* S, Proto* f)
-{
- int i,n;
- f->source=LoadString(S);
- n=LoadInt(S);
- f->lineinfo=luaM_newvector(S->L,n,int);
- f->sizelineinfo=n;
- LoadVector(S,f->lineinfo,n,sizeof(int));
- n=LoadInt(S);
- f->locvars=luaM_newvector(S->L,n,LocVar);
- f->sizelocvars=n;
- for (i=0; i<n; i++) f->locvars[i].varname=NULL;
- for (i=0; i<n; i++)
- {
-  f->locvars[i].varname=LoadString(S);
-  f->locvars[i].startpc=LoadInt(S);
-  f->locvars[i].endpc=LoadInt(S);
- }
- n=LoadInt(S);
- for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
+
+static void LoadUpvalues (LoadState *S, Proto *f) {
+  int i, n;
+  n = LoadInt(S);
+  f->upvalues = luaM_newvector(S->L, n, Upvaldesc);
+  f->sizeupvalues = n;
+  for (i = 0; i < n; i++)
+    f->upvalues[i].name = NULL;
+  for (i = 0; i < n; i++) {
+    f->upvalues[i].instack = LoadByte(S);
+    f->upvalues[i].idx = LoadByte(S);
+  }
 }
 
-static void LoadFunction(LoadState* S, Proto* f)
-{
- f->linedefined=LoadInt(S);
- f->lastlinedefined=LoadInt(S);
- f->numparams=LoadByte(S);
- f->is_vararg=LoadByte(S);
- f->maxstacksize=LoadByte(S);
- LoadCode(S,f);
- LoadConstants(S,f);
- LoadUpvalues(S,f);
- LoadDebug(S,f);
+
+static void LoadDebug (LoadState *S, Proto *f) {
+  int i, n;
+  n = LoadInt(S);
+  f->lineinfo = luaM_newvector(S->L, n, int);
+  f->sizelineinfo = n;
+  LoadVector(S, f->lineinfo, n);
+  n = LoadInt(S);
+  f->locvars = luaM_newvector(S->L, n, LocVar);
+  f->sizelocvars = n;
+  for (i = 0; i < n; i++)
+    f->locvars[i].varname = NULL;
+  for (i = 0; i < n; i++) {
+    f->locvars[i].varname = LoadString(S);
+    f->locvars[i].startpc = LoadInt(S);
+    f->locvars[i].endpc = LoadInt(S);
+  }
+  n = LoadInt(S);
+  for (i = 0; i < n; i++)
+    f->upvalues[i].name = LoadString(S);
 }
 
-/* the code below must be consistent with the code in luaU_header */
-#define N0     LUAC_HEADERSIZE
-#define N1     (sizeof(LUA_SIGNATURE)-sizeof(char))
-#define N2     N1+2
-#define N3     N2+6
-
-static void LoadHeader(LoadState* S)
-{
- lu_byte h[LUAC_HEADERSIZE];
- lu_byte s[LUAC_HEADERSIZE];
- luaU_header(h);
- memcpy(s,h,sizeof(char));                     /* first char already read */
- LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char));
- if (memcmp(h,s,N0)==0) return;
- if (memcmp(h,s,N1)!=0) error(S,"not a");
- if (memcmp(h,s,N2)!=0) error(S,"version mismatch in");
- if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted");
+
+static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
+  f->source = LoadString(S);
+  if (f->source == NULL)  /* no source in dump? */
+    f->source = psource;  /* reuse parent's source */
+  f->linedefined = LoadInt(S);
+  f->lastlinedefined = LoadInt(S);
+  f->numparams = LoadByte(S);
+  f->is_vararg = LoadByte(S);
+  f->maxstacksize = LoadByte(S);
+  LoadCode(S, f);
+  LoadConstants(S, f);
+  LoadUpvalues(S, f);
+  LoadProtos(S, f);
+  LoadDebug(S, f);
 }
 
-/*
-** load precompiled chunk
-*/
-Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
-{
- LoadState S;
- Closure* cl;
- if (*name=='@' || *name=='=')
-  S.name=name+1;
- else if (*name==LUA_SIGNATURE[0])
-  S.name="binary string";
- else
-  S.name=name;
- S.L=L;
- S.Z=Z;
- S.b=buff;
- LoadHeader(&S);
- cl=luaF_newLclosure(L,1);
- setclLvalue(L,L->top,cl); incr_top(L);
- cl->l.p=luaF_newproto(L);
- LoadFunction(&S,cl->l.p);
- if (cl->l.p->sizeupvalues != 1)
- {
-  Proto* p=cl->l.p;
-  cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
-  cl->l.p=p;
-  setclLvalue(L,L->top-1,cl);
- }
- luai_verifycode(L,buff,cl->l.p);
- return cl;
+
+static void checkliteral (LoadState *S, const char *s, const char *msg) {
+  char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
+  size_t len = strlen(s);
+  LoadVector(S, buff, len);
+  if (memcmp(s, buff, len) != 0)
+    error(S, msg);
+}
+
+
+static void fchecksize (LoadState *S, size_t size, const char *tname) {
+  if (LoadByte(S) != size)
+    error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname));
+}
+
+
+#define checksize(S,t) fchecksize(S,sizeof(t),#t)
+
+static void checkHeader (LoadState *S) {
+  checkliteral(S, LUA_SIGNATURE + 1, "not a");  /* 1st char already checked */
+  if (LoadByte(S) != LUAC_VERSION)
+    error(S, "version mismatch in");
+  if (LoadByte(S) != LUAC_FORMAT)
+    error(S, "format mismatch in");
+  checkliteral(S, LUAC_DATA, "corrupted");
+  checksize(S, int);
+  checksize(S, size_t);
+  checksize(S, Instruction);
+  checksize(S, lua_Integer);
+  checksize(S, lua_Number);
+  if (LoadInteger(S) != LUAC_INT)
+    error(S, "endianness mismatch in");
+  if (LoadNumber(S) != LUAC_NUM)
+    error(S, "float format mismatch in");
 }
 
-#define MYINT(s)       (s[0]-'0')
-#define VERSION                MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)
-#define FORMAT         0               /* this is the official format */
 
 /*
-* make header for precompiled chunks
-* if you change the code below be sure to update LoadHeader and FORMAT above
-* and LUAC_HEADERSIZE in lundump.h
+** load precompiled chunk
 */
-void luaU_header (lu_byte* h)
-{
- int x=1;
- memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char));
- h+=sizeof(LUA_SIGNATURE)-sizeof(char);
- *h++=cast_byte(VERSION);
- *h++=cast_byte(FORMAT);
- *h++=cast_byte(*(char*)&x);                   /* endianness */
- *h++=cast_byte(sizeof(int));
- *h++=cast_byte(sizeof(size_t));
- *h++=cast_byte(sizeof(Instruction));
- *h++=cast_byte(sizeof(lua_Number));
- *h++=cast_byte(((lua_Number)0.5)==0);         /* is lua_Number integral? */
- memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char));
+LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
+  LoadState S;
+  LClosure *cl;
+  if (*name == '@' || *name == '=')
+    S.name = name + 1;
+  else if (*name == LUA_SIGNATURE[0])
+    S.name = "binary string";
+  else
+    S.name = name;
+  S.L = L;
+  S.Z = Z;
+  checkHeader(&S);
+  cl = luaF_newLclosure(L, LoadByte(&S));
+  setclLvalue(L, L->top, cl);
+  luaD_inctop(L);
+  cl->p = luaF_newproto(L);
+  LoadFunction(&S, cl->p, NULL);
+  lua_assert(cl->nupvalues == cl->p->sizeupvalues);
+  luai_verifycode(L, buff, cl->p);
+  return cl;
 }
+
index 5255db2..aa5cc82 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -7,22 +7,26 @@
 #ifndef lundump_h
 #define lundump_h
 
+#include "llimits.h"
 #include "lobject.h"
 #include "lzio.h"
 
-/* load one chunk; from lundump.c */
-LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
 
-/* make header; from lundump.c */
-LUAI_FUNC void luaU_header (lu_byte* h);
+/* data to catch conversion errors */
+#define LUAC_DATA      "\x19\x93\r\n\x1a\n"
 
-/* dump one chunk; from ldump.c */
-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+#define LUAC_INT       0x5678
+#define LUAC_NUM       cast_num(370.5)
 
-/* data to catch conversion errors */
-#define LUAC_TAIL              "\x19\x93\r\n\x1a\n"
+#define MYINT(s)       (s[0]-'0')
+#define LUAC_VERSION   (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
+#define LUAC_FORMAT    0       /* this is the official format */
 
-/* size in bytes of header of binary files */
-#define LUAC_HEADERSIZE                (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char))
+/* load one chunk; from lundump.c */
+LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
+
+/* dump one chunk; from ldump.c */
+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
+                         void* data, int strip);
 
 #endif
diff --git a/src/lutf8lib.c b/src/lutf8lib.c
new file mode 100644 (file)
index 0000000..9042582
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+** $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
+*/
+
+#define lutf8lib_c
+#define LUA_LIB
+
+#include "lprefix.h"
+
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+
+#define MAXUNICODE     0x10FFFF
+
+#define iscont(p)      ((*(p) & 0xC0) == 0x80)
+
+
+/* from strlib */
+/* translate a relative string position: negative means back from end */
+static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
+  if (pos >= 0) return pos;
+  else if (0u - (size_t)pos > len) return 0;
+  else return (lua_Integer)len + pos + 1;
+}
+
+
+/*
+** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
+*/
+static const char *utf8_decode (const char *o, int *val) {
+  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 */
+  if (c < 0x80)  /* ascii? */
+    res = c;
+  else {
+    int count = 0;  /* to count number of continuation bytes */
+    while (c & 0x40) {  /* still have continuation bytes? */
+      int cc = s[++count];  /* read next byte */
+      if ((cc & 0xC0) != 0x80)  /* not a continuation byte? */
+        return NULL;  /* invalid byte sequence */
+      res = (res << 6) | (cc & 0x3F);  /* add lower 6 bits from cont. byte */
+      c <<= 1;  /* to test next bit */
+    }
+    res |= ((c & 0x7F) << (count * 5));  /* add first byte */
+    if (count > 3 || res > MAXUNICODE || res <= limits[count])
+      return NULL;  /* invalid byte sequence */
+    s += count;  /* skip continuation bytes read */
+  }
+  if (val) *val = res;
+  return (const char *)s + 1;  /* +1 to include first byte */
+}
+
+
+/*
+** utf8len(s [, i [, j]]) --> number of characters that start in the
+** range [i,j], or nil + current position if 's' is not well formed in
+** that interval
+*/
+static int utflen (lua_State *L) {
+  int n = 0;
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+  lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
+  luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
+                   "initial position out of string");
+  luaL_argcheck(L, --posj < (lua_Integer)len, 3,
+                   "final position out of string");
+  while (posi <= posj) {
+    const char *s1 = utf8_decode(s + posi, NULL);
+    if (s1 == NULL) {  /* conversion error? */
+      lua_pushnil(L);  /* return nil ... */
+      lua_pushinteger(L, posi + 1);  /* ... and current position */
+      return 2;
+    }
+    posi = s1 - s;
+    n++;
+  }
+  lua_pushinteger(L, n);
+  return 1;
+}
+
+
+/*
+** codepoint(s, [i, [j]])  -> returns codepoints for all characters
+** that start in the range [i,j]
+*/
+static int codepoint (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
+  lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
+  int n;
+  const char *se;
+  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 */
+  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;
+  for (s += posi - 1; s < se;) {
+    int code;
+    s = utf8_decode(s, &code);
+    if (s == NULL)
+      return luaL_error(L, "invalid UTF-8 code");
+    lua_pushinteger(L, code);
+    n++;
+  }
+  return n;
+}
+
+
+static void pushutfchar (lua_State *L, int arg) {
+  lua_Integer code = luaL_checkinteger(L, arg);
+  luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
+  lua_pushfstring(L, "%U", (long)code);
+}
+
+
+/*
+** utfchar(n1, n2, ...)  -> char(n1)..char(n2)...
+*/
+static int utfchar (lua_State *L) {
+  int n = lua_gettop(L);  /* number of arguments */
+  if (n == 1)  /* optimize common case of single char */
+    pushutfchar(L, 1);
+  else {
+    int i;
+    luaL_Buffer b;
+    luaL_buffinit(L, &b);
+    for (i = 1; i <= n; i++) {
+      pushutfchar(L, i);
+      luaL_addvalue(&b);
+    }
+    luaL_pushresult(&b);
+  }
+  return 1;
+}
+
+
+/*
+** offset(s, n, [i])  -> index where n-th character counting from
+**   position 'i' starts; 0 means character at 'i'.
+*/
+static int byteoffset (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer n  = luaL_checkinteger(L, 2);
+  lua_Integer posi = (n >= 0) ? 1 : len + 1;
+  posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
+  luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
+                   "position out of range");
+  if (n == 0) {
+    /* find beginning of current byte sequence */
+    while (posi > 0 && iscont(s + posi)) posi--;
+  }
+  else {
+    if (iscont(s + posi))
+      luaL_error(L, "initial position is a continuation byte");
+    if (n < 0) {
+       while (n < 0 && posi > 0) {  /* move back */
+         do {  /* find beginning of previous character */
+           posi--;
+         } while (posi > 0 && iscont(s + posi));
+         n++;
+       }
+     }
+     else {
+       n--;  /* do not move for 1st character */
+       while (n > 0 && posi < (lua_Integer)len) {
+         do {  /* find beginning of next character */
+           posi++;
+         } while (iscont(s + posi));  /* (cannot pass final '\0') */
+         n--;
+       }
+     }
+  }
+  if (n == 0)  /* did it find given character? */
+    lua_pushinteger(L, posi + 1);
+  else  /* no such character */
+    lua_pushnil(L);
+  return 1;  
+}
+
+
+static int iter_aux (lua_State *L) {
+  size_t len;
+  const char *s = luaL_checklstring(L, 1, &len);
+  lua_Integer n = lua_tointeger(L, 2) - 1;
+  if (n < 0)  /* first iteration? */
+    n = 0;  /* start from here */
+  else if (n < (lua_Integer)len) {
+    n++;  /* skip current byte */
+    while (iscont(s + n)) n++;  /* and its continuations */
+  }
+  if (n >= (lua_Integer)len)
+    return 0;  /* no more codepoints */
+  else {
+    int code;
+    const char *next = utf8_decode(s + n, &code);
+    if (next == NULL || iscont(next))
+      return luaL_error(L, "invalid UTF-8 code");
+    lua_pushinteger(L, n + 1);
+    lua_pushinteger(L, code);
+    return 2;
+  }
+}
+
+
+static int iter_codes (lua_State *L) {
+  luaL_checkstring(L, 1);
+  lua_pushcfunction(L, iter_aux);
+  lua_pushvalue(L, 1);
+  lua_pushinteger(L, 0);
+  return 3;
+}
+
+
+/* pattern to match a single UTF-8 character */
+#define UTF8PATT       "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
+
+
+static const luaL_Reg funcs[] = {
+  {"offset", byteoffset},
+  {"codepoint", codepoint},
+  {"char", utfchar},
+  {"len", utflen},
+  {"codes", iter_codes},
+  /* placeholders */
+  {"charpattern", NULL},
+  {NULL, NULL}
+};
+
+
+LUAMOD_API int luaopen_utf8 (lua_State *L) {
+  luaL_newlib(L, funcs);
+  lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
+  lua_setfield(L, -2, "charpattern");
+  return 1;
+}
+
index 141b9fd..84ade6b 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,17 +1,21 @@
 /*
-** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lvm.c,v 2.268 2016/02/05 19:59:14 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
 
+#define lvm_c
+#define LUA_CORE
+
+#include "lprefix.h"
 
+#include <float.h>
+#include <limits.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#define lvm_c
-#define LUA_CORE
-
 #include "lua.h"
 
 #include "ldebug.h"
 #include "lvm.h"
 
 
-
 /* limit for table tag-method chains (to avoid loops) */
-#define MAXTAGLOOP     100
+#define MAXTAGLOOP     2000
 
 
-const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
-  lua_Number num;
-  if (ttisnumber(obj)) return obj;
-  if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
-    setnvalue(n, num);
-    return n;
-  }
-  else
-    return NULL;
-}
 
+/*
+** '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.
+*/
+#if !defined(l_intfitsf)
 
-int luaV_tostring (lua_State *L, StkId obj) {
-  if (!ttisnumber(obj))
-    return 0;
-  else {
-    char s[LUAI_MAXNUMBER2STR];
-    lua_Number n = nvalue(obj);
-    int l = lua_number2str(s, n);
-    setsvalue2s(L, obj, luaS_newlstr(L, s, l));
+/* 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
+
+
+
+/*
+** Try to convert a value to a float. The float case is already handled
+** by the macro 'tonumber'.
+*/
+int luaV_tonumber_ (const TValue *obj, lua_Number *n) {
+  TValue v;
+  if (ttisinteger(obj)) {
+    *n = cast_num(ivalue(obj));
+    return 1;
+  }
+  else if (cvt2num(obj) &&  /* string convertible to number? */
+            luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
+    *n = nvalue(&v);  /* convert result of 'luaO_str2num' to a float */
     return 1;
   }
+  else
+    return 0;  /* conversion failed */
 }
 
 
-static void traceexec (lua_State *L) {
-  CallInfo *ci = L->ci;
-  lu_byte mask = L->hookmask;
-  int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
-  if (counthook)
-    resethookcount(L);  /* reset count */
-  if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
-    ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
-    return;  /* do not call hook again (VM yielded, so it did not move) */
+/*
+** try to convert a value to an integer, rounding according to 'mode':
+** mode == 0: accepts only integral values
+** mode == 1: takes the floor of the number
+** mode == 2: takes the ceil of the number
+*/
+int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) {
+  TValue v;
+ again:
+  if (ttisfloat(obj)) {
+    lua_Number n = fltvalue(obj);
+    lua_Number f = l_floor(n);
+    if (n != f) {  /* not an integral value? */
+      if (mode == 0) return 0;  /* fails if mode demands integral value */
+      else if (mode > 1)  /* needs ceil? */
+        f += 1;  /* convert floor to ceil (remember: n != f) */
+    }
+    return lua_numbertointeger(f, p);
   }
-  if (counthook)
-    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
-  if (mask & LUA_MASKLINE) {
-    Proto *p = ci_func(ci)->p;
-    int npc = pcRel(ci->u.l.savedpc, p);
-    int newline = getfuncline(p, npc);
-    if (npc == 0 ||  /* call linehook when enter a new function, */
-        ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
-        newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
-      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
+  else if (ttisinteger(obj)) {
+    *p = ivalue(obj);
+    return 1;
   }
-  L->oldpc = ci->u.l.savedpc;
-  if (L->status == LUA_YIELD) {  /* did hook yield? */
-    if (counthook)
-      L->hookcount = 1;  /* undo decrement to zero */
-    ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
-    ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
-    ci->func = L->top - 1;  /* protect stack below results */
-    luaD_throw(L, LUA_YIELD);
+  else if (cvt2num(obj) &&
+            luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) {
+    obj = &v;
+    goto again;  /* convert result from 'luaO_str2num' to an integer */
   }
+  return 0;  /* conversion failed */
 }
 
 
-static void callTM (lua_State *L, const TValue *f, const TValue *p1,
-                    const TValue *p2, TValue *p3, int hasres) {
-  ptrdiff_t result = savestack(L, p3);
-  setobj2s(L, L->top++, f);  /* push function */
-  setobj2s(L, L->top++, p1);  /* 1st argument */
-  setobj2s(L, L->top++, p2);  /* 2nd argument */
-  if (!hasres)  /* no result? 'p3' is third argument */
-    setobj2s(L, L->top++, p3);  /* 3rd argument */
-  /* metamethod may yield only when called from Lua code */
-  luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
-  if (hasres) {  /* if has result, move it to its place */
-    p3 = restorestack(L, result);
-    setobjs2s(L, p3, --L->top);
+/*
+** Try to convert a 'for' limit to an integer, preserving the
+** semantics of the loop.
+** (The following explanation assumes a non-negative step; it is valid
+** for negative steps mutatis mutandis.)
+** If the limit can be converted to an integer, rounding down, that is
+** it.
+** Otherwise, check whether the limit can be converted to a number.  If
+** the number is too large, it is OK to set the limit as LUA_MAXINTEGER,
+** which means no limit.  If the number is too negative, the loop
+** should not run, because any initial integer value is larger than the
+** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects
+** the extreme case when the initial value is LUA_MININTEGER, in which
+** case the LUA_MININTEGER limit would still run the loop once.
+*/
+static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
+                     int *stopnow) {
+  *stopnow = 0;  /* usually, let loops run */
+  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 (luai_numlt(0, n)) {  /* if true, float is larger than max integer */
+      *p = LUA_MAXINTEGER;
+      if (step < 0) *stopnow = 1;
+    }
+    else {  /* float is smaller than min integer */
+      *p = LUA_MININTEGER;
+      if (step >= 0) *stopnow = 1;
+    }
   }
+  return 1;
 }
 
 
-void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
-  int loop;
+/*
+** Finish the table access 'val = t[key]'.
+** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to
+** t[k] entry (which must be nil).
+*/
+void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
+                      const TValue *slot) {
+  int loop;  /* counter to avoid infinite loops */
+  const TValue *tm;  /* metamethod */
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
-    const TValue *tm;
-    if (ttistable(t)) {  /* `t' is a table? */
-      Table *h = hvalue(t);
-      const TValue *res = luaH_get(h, key); /* do a primitive get */
-      if (!ttisnil(res) ||  /* result is not nil? */
-          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
-        setobj2s(L, val, res);
+    if (slot == NULL) {  /* 't' is not a table? */
+      lua_assert(!ttistable(t));
+      tm = luaT_gettmbyobj(L, t, TM_INDEX);
+      if (ttisnil(tm))
+        luaG_typeerror(L, t, "index");  /* no metamethod */
+      /* else will try the metamethod */
+    }
+    else {  /* 't' is a table */
+      lua_assert(ttisnil(slot));
+      tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);  /* table's metamethod */
+      if (tm == NULL) {  /* no metamethod? */
+        setnilvalue(val);  /* result is nil */
         return;
       }
-      /* else will try the tag method */
+      /* else will try the metamethod */
     }
-    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
-      luaG_typeerror(L, t, "index");
-    if (ttisfunction(tm)) {
-      callTM(L, tm, t, key, val, 1);
+    if (ttisfunction(tm)) {  /* is metamethod a function? */
+      luaT_callTM(L, tm, t, key, val, 1);  /* call it */
+      return;
+    }
+    t = tm;  /* else try to access 'tm[key]' */
+    if (luaV_fastget(L,t,key,slot,luaH_get)) {  /* fast track? */
+      setobj2s(L, val, slot);  /* done */
       return;
     }
-    t = tm;  /* else repeat with 'tm' */
+    /* else repeat (tail call 'luaV_finishget') */
   }
-  luaG_runerror(L, "loop in gettable");
+  luaG_runerror(L, "'__index' chain too long; possible loop");
 }
 
 
-void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
-  int loop;
+/*
+** Finish a table assignment 't[key] = val'.
+** If 'slot' is NULL, 't' is not a table.  Otherwise, 'slot' points
+** to the entry 't[key]', or to 'luaO_nilobject' if there is no such
+** entry.  (The value at 'slot' must be nil, otherwise 'luaV_fastset'
+** would have done the job.)
+*/
+void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                     StkId val, const TValue *slot) {
+  int loop;  /* counter to avoid infinite loops */
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
-    const TValue *tm;
-    if (ttistable(t)) {  /* `t' is a table? */
-      Table *h = hvalue(t);
-      TValue *oldval = cast(TValue *, luaH_get(h, key));
-      /* if previous value is not nil, there must be a previous entry
-         in the table; moreover, a metamethod has no relevance */
-      if (!ttisnil(oldval) ||
-         /* previous value is nil; must check the metamethod */
-         ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
-         /* no metamethod; is there a previous entry in the table? */
-         (oldval != luaO_nilobject ||
-         /* no previous entry; must create one. (The next test is
-            always true; we only need the assignment.) */
-         (oldval = luaH_newkey(L, h, key), 1)))) {
+    const TValue *tm;  /* '__newindex' metamethod */
+    if (slot != NULL) {  /* is 't' a table? */
+      Table *h = hvalue(t);  /* save 't' table */
+      lua_assert(ttisnil(slot));  /* old value must be nil */
+      tm = fasttm(L, h->metatable, TM_NEWINDEX);  /* get metamethod */
+      if (tm == NULL) {  /* no metamethod? */
+        if (slot == luaO_nilobject)  /* no previous entry? */
+          slot = luaH_newkey(L, h, key);  /* create one */
         /* no metamethod and (now) there is an entry with given key */
-        setobj2t(L, oldval, val);  /* assign new value to that entry */
+        setobj2t(L, cast(TValue *, slot), val);  /* set its new value */
         invalidateTMcache(h);
-        luaC_barrierback(L, obj2gco(h), val);
+        luaC_barrierback(L, h, val);
         return;
       }
       /* else will try the metamethod */
     }
-    else  /* not a table; check metamethod */
+    else  /* not a table; check metamethod */
       if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
         luaG_typeerror(L, t, "index");
-    /* there is a metamethod */
+    }
+    /* try the metamethod */
     if (ttisfunction(tm)) {
-      callTM(L, tm, t, key, val, 0);
+      luaT_callTM(L, tm, t, key, val, 0);
       return;
     }
-    t = tm;  /* else repeat with 'tm' */
+    t = tm;  /* else repeat assignment over 'tm' */
+    if (luaV_fastset(L, t, key, slot, luaH_get, val))
+      return;  /* done */
+    /* else loop */
   }
-  luaG_runerror(L, "loop in settable");
+  luaG_runerror(L, "'__newindex' chain too long; possible loop");
 }
 
 
-static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
-                       StkId res, TMS event) {
-  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
-  if (ttisnil(tm))
-    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
-  if (ttisnil(tm)) return 0;
-  callTM(L, tm, p1, p2, res, 1);
-  return 1;
+/*
+** Compare two strings 'ls' x 'rs', returning an integer smaller-equal-
+** -larger than zero if 'ls' is smaller-equal-larger than 'rs'.
+** The code is a little tricky because it allows '\0' in the strings
+** and it uses 'strcoll' (to respect locales) for each segments
+** of the strings.
+*/
+static int l_strcmp (const TString *ls, const TString *rs) {
+  const char *l = getstr(ls);
+  size_t ll = tsslen(ls);
+  const char *r = getstr(rs);
+  size_t lr = tsslen(rs);
+  for (;;) {  /* for each segment */
+    int temp = strcoll(l, r);
+    if (temp != 0)  /* not equal? */
+      return temp;  /* done */
+    else {  /* strings are equal up to a '\0' */
+      size_t len = strlen(l);  /* index of first '\0' in both strings */
+      if (len == lr)  /* 'rs' is finished? */
+        return (len == ll) ? 0 : 1;  /* check 'ls' */
+      else if (len == ll)  /* 'ls' is finished? */
+        return -1;  /* 'ls' is smaller than 'rs' ('rs' is not finished) */
+      /* both strings longer than 'len'; go on comparing after the '\0' */
+      len++;
+      l += len; ll -= len; r += len; lr -= len;
+    }
+  }
 }
 
 
-static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
-                                  TMS event) {
-  const TValue *tm1 = fasttm(L, mt1, event);
-  const TValue *tm2;
-  if (tm1 == NULL) return NULL;  /* no metamethod */
-  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
-  tm2 = fasttm(L, mt2, event);
-  if (tm2 == NULL) return NULL;  /* no metamethod */
-  if (luaV_rawequalobj(tm1, tm2))  /* same metamethods? */
-    return tm1;
-  return NULL;
+/*
+** 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 */
 }
 
 
-static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
-                         TMS event) {
-  if (!call_binTM(L, p1, p2, L->top, event))
-    return -1;  /* no metamethod */
-  else
-    return !l_isfalse(L->top);
+/*
+** 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 */
 }
 
 
-static int l_strcmp (const TString *ls, const TString *rs) {
-  const char *l = getstr(ls);
-  size_t ll = ls->tsv.len;
-  const char *r = getstr(rs);
-  size_t lr = rs->tsv.len;
-  for (;;) {
-    int temp = strcoll(l, r);
-    if (temp != 0) return temp;
-    else {  /* strings are equal up to a `\0' */
-      size_t len = strlen(l);  /* index of first `\0' in both strings */
-      if (len == lr)  /* r is finished? */
-        return (len == ll) ? 0 : 1;
-      else if (len == ll)  /* l is finished? */
-        return -1;  /* l is smaller than r (because r is not finished) */
-      /* both strings longer than `len'; go on comparing (after the `\0') */
-      len++;
-      l += len; ll -= len; r += len; lr -= len;
-    }
+/*
+** 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;
-  if (ttisnumber(l) && ttisnumber(r))
-    return luai_numlt(L, nvalue(l), nvalue(r));
-  else if (ttisstring(l) && ttisstring(r))
-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
-  else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
-    luaG_ordererror(L, l, r);
+  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? */
+    luaG_ordererror(L, l, r);  /* error */
   return res;
 }
 
 
+/*
+** 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;
-  if (ttisnumber(l) && ttisnumber(r))
-    return luai_numle(L, nvalue(l), nvalue(r));
-  else if (ttisstring(l) && ttisstring(r))
-    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
-  else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0)  /* first try `le' */
+  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)  /* try 'le' */
     return res;
-  else if ((res = call_orderTM(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 */
+  }
 }
 
 
 /*
-** equality of Lua values. L == NULL means raw equality (no metamethods)
+** 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) {
+int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
   const TValue *tm;
-  lua_assert(ttisequal(t1, t2));
+  if (ttype(t1) != ttype(t2)) {  /* not the same variant? */
+    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_Integer i1, i2;  /* compare them as integers */
+      return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2);
+    }
+  }
+  /* values have same type and same variant */
   switch (ttype(t1)) {
     case LUA_TNIL: return 1;
-    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
+    case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2));
+    case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
     case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
     case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
     case LUA_TLCF: return fvalue(t1) == fvalue(t2);
-    case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
-    case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
+    case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
+    case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
     case LUA_TUSERDATA: {
       if (uvalue(t1) == uvalue(t2)) return 1;
       else if (L == NULL) return 0;
-      tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
+      tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
+      if (tm == NULL)
+        tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
       break;  /* will try TM */
     }
     case LUA_TTABLE: {
       if (hvalue(t1) == hvalue(t2)) return 1;
       else if (L == NULL) return 0;
-      tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
+      tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
+      if (tm == NULL)
+        tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
       break;  /* will try TM */
     }
     default:
-      lua_assert(iscollectable(t1));
       return gcvalue(t1) == gcvalue(t2);
   }
-  if (tm == NULL) return 0;  /* no TM? */
-  callTM(L, tm, t1, t2, L->top, 1);  /* call TM */
+  if (tm == NULL)  /* no TM? */
+    return 0;  /* objects are different */
+  luaT_callTM(L, tm, t1, t2, L->top, 1);  /* call TM */
   return !l_isfalse(L->top);
 }
 
 
+/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */
+#define tostring(L,o)  \
+       (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1)))
+
+#define isemptystr(o)  (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
+
+/* copy strings in stack from top - n up to top - 1 to buffer */
+static void copy2buff (StkId top, int n, char *buff) {
+  size_t tl = 0;  /* size already copied */
+  do {
+    size_t l = vslen(top - n);  /* length of string being copied */
+    memcpy(buff + tl, svalue(top - n), l * sizeof(char));
+    tl += l;
+  } while (--n > 0);
+}
+
+
+/*
+** Main operation for concatenation: concat 'total' values in the stack,
+** from 'L->top - total' up to 'L->top - 1'.
+*/
 void luaV_concat (lua_State *L, int total) {
   lua_assert(total >= 2);
   do {
     StkId top = L->top;
     int n = 2;  /* number of elements handled in this pass (at least 2) */
-    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
-      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
-        luaG_concaterror(L, top-2, top-1);
-    }
-    else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
-      (void)tostring(L, top - 2);  /* result is first operand */
-    else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
+    if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1))
+      luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
+    else if (isemptystr(top - 1))  /* second operand is empty? */
+      cast_void(tostring(L, top - 2));  /* result is first operand */
+    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;
-      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;
-        if (l >= (MAX_SIZET/sizeof(char)) - tl)
+      size_t tl = vslen(top - 1);
+      TString *ts;
+      /* collect total length and number of strings */
+      for (n = 1; n < total && tostring(L, top - n - 1); n++) {
+        size_t l = vslen(top - n - 1);
+        if (l >= (MAX_SIZE/sizeof(char)) - tl)
           luaG_runerror(L, "string length overflow");
         tl += l;
       }
-      buffer = luaZ_openspace(L, &G(L)->buff, tl);
-      tl = 0;
-      n = i;
-      do {  /* concat all strings */
-        size_t l = tsvalue(top-i)->len;
-        memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
-        tl += l;
-      } while (--i > 0);
-      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
+      if (tl <= LUAI_MAXSHORTLEN) {  /* is result a short string? */
+        char buff[LUAI_MAXSHORTLEN];
+        copy2buff(top, n, buff);  /* copy strings to buffer */
+        ts = luaS_newlstr(L, buff, tl);
+      }
+      else {  /* long string; copy strings directly to final result */
+        ts = luaS_createlngstrobj(L, tl);
+        copy2buff(top, n, getstr(ts));
+      }
+      setsvalue2s(L, top - n, ts);  /* create result */
     }
     total -= n-1;  /* got 'n' strings to create 1 new */
     L->top -= n-1;  /* popped 'n' strings and pushed one */
@@ -332,18 +511,25 @@ void luaV_concat (lua_State *L, int total) {
 }
 
 
+/*
+** Main operation 'ra' = #rb'.
+*/
 void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
   const TValue *tm;
-  switch (ttypenv(rb)) {
+  switch (ttype(rb)) {
     case LUA_TTABLE: {
       Table *h = hvalue(rb);
       tm = fasttm(L, h->metatable, TM_LEN);
       if (tm) break;  /* metamethod? break switch to call it */
-      setnvalue(ra, cast_num(luaH_getn(h)));  /* else primitive len */
+      setivalue(ra, luaH_getn(h));  /* else primitive len */
       return;
     }
-    case LUA_TSTRING: {
-      setnvalue(ra, cast_num(tsvalue(rb)->len));
+    case LUA_TSHRSTR: {
+      setivalue(ra, tsvalue(rb)->shrlen);
+      return;
+    }
+    case LUA_TLNGSTR: {
+      setivalue(ra, tsvalue(rb)->u.lnglen);
       return;
     }
     default: {  /* try metamethod */
@@ -353,21 +539,66 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
       break;
     }
   }
-  callTM(L, tm, rb, rb, ra, 1);
+  luaT_callTM(L, tm, rb, rb, ra, 1);
+}
+
+
+/*
+** Integer division; return 'm // n', that is, floor(m/n).
+** C division truncates its result (rounds towards zero).
+** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer,
+** otherwise 'floor(q) == trunc(q) - 1'.
+*/
+lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
+  if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
+    if (n == 0)
+      luaG_runerror(L, "attempt to divide by zero");
+    return intop(-, 0, m);   /* n==-1; avoid overflow with 0x80000...//-1 */
+  }
+  else {
+    lua_Integer q = m / n;  /* perform C division */
+    if ((m ^ n) < 0 && m % n != 0)  /* 'm/n' would be negative non-integer? */
+      q -= 1;  /* correct result for different rounding */
+    return q;
+  }
+}
+
+
+/*
+** Integer modulus; return 'm % n'. (Assume that C '%' with
+** negative operands follows C99 behavior. See previous comment
+** about luaV_div.)
+*/
+lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
+  if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
+    if (n == 0)
+      luaG_runerror(L, "attempt to perform 'n%%0'");
+    return 0;   /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
+  }
+  else {
+    lua_Integer r = m % n;
+    if (r != 0 && (m ^ n) < 0)  /* 'm/n' would be non-integer negative? */
+      r += n;  /* correct result for different rounding */
+    return r;
+  }
 }
 
 
-void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
-                 const TValue *rc, TMS op) {
-  TValue tempb, tempc;
-  const TValue *b, *c;
-  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
-      (c = luaV_tonumber(rc, &tempc)) != NULL) {
-    lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
-    setnvalue(ra, res);
+/* number of bits in an integer */
+#define NBITS  cast_int(sizeof(lua_Integer) * CHAR_BIT)
+
+/*
+** Shift left operation. (Shift right just negates 'y'.)
+*/
+lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
+  if (y < 0) {  /* shift right? */
+    if (y <= -NBITS) return 0;
+    else return intop(>>, x, -y);
+  }
+  else {  /* shift left */
+    if (y >= NBITS) return 0;
+    else return intop(<<, x, y);
   }
-  else if (!call_binTM(L, rb, rc, ra, op))
-    luaG_aritherror(L, rb, rc);
 }
 
 
@@ -376,15 +607,15 @@ void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
 ** whether there is a cached closure with the same upvalues needed by
 ** new closure to be created.
 */
-static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
-  Closure *c = p->cache;
+static LClosure *getcached (Proto *p, UpVal **encup, StkId base) {
+  LClosure *c = p->cache;
   if (c != NULL) {  /* is there a cached closure? */
     int nup = p->sizeupvalues;
     Upvaldesc *uv = p->upvalues;
     int i;
     for (i = 0; i < nup; i++) {  /* check whether it has right upvalues */
       TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
-      if (c->l.upvals[i]->v != v)
+      if (c->upvals[i]->v != v)
         return NULL;  /* wrong upvalue; cannot reuse closure */
     }
   }
@@ -394,26 +625,28 @@ static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
 
 /*
 ** create a new Lua closure, push it in the stack, and initialize
-** its upvalues. Note that the call to 'luaC_barrierproto' must come
-** before the assignment to 'p->cache', as the function needs the
-** original value of that field.
+** its upvalues. Note that the closure is not cached if prototype is
+** already black (which means that 'cache' was already cleared by the
+** GC).
 */
 static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
                          StkId ra) {
   int nup = p->sizeupvalues;
   Upvaldesc *uv = p->upvalues;
   int i;
-  Closure *ncl = luaF_newLclosure(L, nup);
-  ncl->l.p = p;
+  LClosure *ncl = luaF_newLclosure(L, nup);
+  ncl->p = p;
   setclLvalue(L, ra, ncl);  /* anchor new closure in stack */
   for (i = 0; i < nup; i++) {  /* fill in its upvalues */
     if (uv[i].instack)  /* upvalue refers to local variable? */
-      ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
+      ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
     else  /* get upvalue from enclosing function */
-      ncl->l.upvals[i] = encup[uv[i].idx];
+      ncl->upvals[i] = encup[uv[i].idx];
+    ncl->upvals[i]->refcount++;
+    /* new closure is white, so we do not need a barrier here */
   }
-  luaC_barrierproto(L, p, ncl);
-  p->cache = ncl;  /* save it on cache for reuse */
+  if (!isblack(p))  /* cache will not break GC invariant? */
+    p->cache = ncl;  /* save it on cache for reuse */
 }
 
 
@@ -426,8 +659,10 @@ void luaV_finishOp (lua_State *L) {
   Instruction inst = *(ci->u.l.savedpc - 1);  /* interrupted instruction */
   OpCode op = GET_OPCODE(inst);
   switch (op) {  /* finish its execution */
-    case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
-    case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
+    case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
+    case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
+    case OP_MOD: case OP_POW:
+    case OP_UNM: case OP_BNOT: case OP_LEN:
     case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
       setobjs2s(L, base + GETARG_A(inst), --L->top);
       break;
@@ -435,18 +670,18 @@ 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 */
       break;
     }
     case OP_CONCAT: {
-      StkId top = L->top - 1;  /* top when 'call_binTM' was called */
+      StkId top = L->top - 1;  /* top when 'luaT_trybinTM' was called */
       int b = GETARG_B(inst);      /* first element to concatenate */
       int total = cast_int(top - 1 - (base + b));  /* yet to concatenate */
       setobj2s(L, top - 2, top);  /* put TM result in proper position */
@@ -477,31 +712,32 @@ void luaV_finishOp (lua_State *L) {
 
 
 
+
 /*
-** some macros for common tasks in `luaV_execute'
+** {==================================================================
+** Function 'luaV_execute': main interpreter loop
+** ===================================================================
 */
 
-#if !defined luai_runtimecheck
-#define luai_runtimecheck(L, c)                /* void */
-#endif
+
+/*
+** some macros for common tasks in 'luaV_execute'
+*/
 
 
 #define RA(i)  (base+GETARG_A(i))
-/* to be used after possible stack reallocation */
 #define RB(i)  check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
 #define RC(i)  check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
 #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
        ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
 #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
        ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
-#define KBx(i)  \
-  (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
 
 
 /* execute a jump instruction */
 #define dojump(ci,i,e) \
   { int a = GETARG_A(i); \
-    if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
+    if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
     ci->u.l.savedpc += GETARG_sBx(i) + e; }
 
 /* for test instructions, execute the jump instruction that follows it */
@@ -511,96 +747,124 @@ void luaV_finishOp (lua_State *L) {
 #define Protect(x)     { {x;}; base = ci->u.l.base; }
 
 #define checkGC(L,c)  \
-  Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
-                          luaC_step(L); \
-                          L->top = ci->top;})  /* restore top */ \
-           luai_threadyield(L); )
+       { luaC_condGC(L, L->top = (c),  /* limit of live values */ \
+                         Protect(L->top = ci->top));  /* restore top */ \
+           luai_threadyield(L); }
+
+
+/* fetch an instruction and prepare its execution */
+#define vmfetch()      { \
+  i = *(ci->u.l.savedpc++); \
+  if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \
+    Protect(luaG_traceexec(L)); \
+  ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
+  lua_assert(base == ci->u.l.base); \
+  lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \
+}
 
+#define vmdispatch(o)  switch(o)
+#define vmcase(l)      case l:
+#define vmbreak                break
 
-#define arith_op(op,tm) { \
-        TValue *rb = RKB(i); \
-        TValue *rc = RKC(i); \
-        if (ttisnumber(rb) && ttisnumber(rc)) { \
-          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
-          setnvalue(ra, op(L, nb, nc)); \
-        } \
-        else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
+
+/*
+** copy of 'luaV_gettable', but protecting the call to potential
+** metamethod (which can reallocate the stack)
+*/
+#define gettableProtected(L,t,k,v)  { const TValue *slot; \
+  if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
+  else Protect(luaV_finishget(L,t,k,v,slot)); }
+
+
+/* same for 'luaV_settable' */
+#define settableProtected(L,t,k,v) { const TValue *slot; \
+  if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
+    Protect(luaV_finishset(L,t,k,v,slot)); }
 
 
-#define vmdispatch(o)  switch(o)
-#define vmcase(l,b)    case l: {b}  break;
-#define vmcasenb(l,b)  case l: {b}             /* nb = no break */
 
 void luaV_execute (lua_State *L) {
   CallInfo *ci = L->ci;
   LClosure *cl;
   TValue *k;
   StkId base;
+  ci->callstatus |= CIST_FRESH;  /* fresh invocation of 'luaV_execute" */
  newframe:  /* reentry point when frame changes (call/return) */
   lua_assert(ci == L->ci);
-  cl = clLvalue(ci->func);
-  k = cl->p->k;
-  base = ci->u.l.base;
+  cl = clLvalue(ci->func);  /* local reference to function's closure */
+  k = cl->p->k;  /* local reference to function's constant table */
+  base = ci->u.l.base;  /* local copy of function's base */
   /* main loop of interpreter */
   for (;;) {
-    Instruction i = *(ci->u.l.savedpc++);
+    Instruction i;
     StkId ra;
-    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
-        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
-      Protect(traceexec(L));
-    }
-    /* WARNING: several calls may realloc the stack and invalidate `ra' */
-    ra = RA(i);
-    lua_assert(base == ci->u.l.base);
-    lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
+    vmfetch();
     vmdispatch (GET_OPCODE(i)) {
-      vmcase(OP_MOVE,
+      vmcase(OP_MOVE) {
         setobjs2s(L, ra, RB(i));
-      )
-      vmcase(OP_LOADK,
+        vmbreak;
+      }
+      vmcase(OP_LOADK) {
         TValue *rb = k + GETARG_Bx(i);
         setobj2s(L, ra, rb);
-      )
-      vmcase(OP_LOADKX,
+        vmbreak;
+      }
+      vmcase(OP_LOADKX) {
         TValue *rb;
         lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
         rb = k + GETARG_Ax(*ci->u.l.savedpc++);
         setobj2s(L, ra, rb);
-      )
-      vmcase(OP_LOADBOOL,
+        vmbreak;
+      }
+      vmcase(OP_LOADBOOL) {
         setbvalue(ra, GETARG_B(i));
         if (GETARG_C(i)) ci->u.l.savedpc++;  /* skip next instruction (if C) */
-      )
-      vmcase(OP_LOADNIL,
+        vmbreak;
+      }
+      vmcase(OP_LOADNIL) {
         int b = GETARG_B(i);
         do {
           setnilvalue(ra++);
         } while (b--);
-      )
-      vmcase(OP_GETUPVAL,
+        vmbreak;
+      }
+      vmcase(OP_GETUPVAL) {
         int b = GETARG_B(i);
         setobj2s(L, ra, cl->upvals[b]->v);
-      )
-      vmcase(OP_GETTABUP,
-        int b = GETARG_B(i);
-        Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
-      )
-      vmcase(OP_GETTABLE,
-        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
-      )
-      vmcase(OP_SETTABUP,
-        int a = GETARG_A(i);
-        Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
-      )
-      vmcase(OP_SETUPVAL,
+        vmbreak;
+      }
+      vmcase(OP_GETTABUP) {
+        TValue *upval = cl->upvals[GETARG_B(i)]->v;
+        TValue *rc = RKC(i);
+        gettableProtected(L, upval, rc, ra);
+        vmbreak;
+      }
+      vmcase(OP_GETTABLE) {
+        StkId rb = RB(i);
+        TValue *rc = RKC(i);
+        gettableProtected(L, rb, rc, ra);
+        vmbreak;
+      }
+      vmcase(OP_SETTABUP) {
+        TValue *upval = cl->upvals[GETARG_A(i)]->v;
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        settableProtected(L, upval, rb, rc);
+        vmbreak;
+      }
+      vmcase(OP_SETUPVAL) {
         UpVal *uv = cl->upvals[GETARG_B(i)];
         setobj(L, uv->v, ra);
-        luaC_barrier(L, uv, ra);
-      )
-      vmcase(OP_SETTABLE,
-        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
-      )
-      vmcase(OP_NEWTABLE,
+        luaC_upvalbarrier(L, uv);
+        vmbreak;
+      }
+      vmcase(OP_SETTABLE) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        settableProtected(L, ra, rb, rc);
+        vmbreak;
+      }
+      vmcase(OP_NEWTABLE) {
         int b = GETARG_B(i);
         int c = GETARG_C(i);
         Table *t = luaH_new(L);
@@ -608,96 +872,252 @@ void luaV_execute (lua_State *L) {
         if (b != 0 || c != 0)
           luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
         checkGC(L, ra + 1);
-      )
-      vmcase(OP_SELF,
+        vmbreak;
+      }
+      vmcase(OP_SELF) {
+        const TValue *aux;
         StkId rb = RB(i);
-        setobjs2s(L, ra+1, rb);
-        Protect(luaV_gettable(L, rb, RKC(i), ra));
-      )
-      vmcase(OP_ADD,
-        arith_op(luai_numadd, TM_ADD);
-      )
-      vmcase(OP_SUB,
-        arith_op(luai_numsub, TM_SUB);
-      )
-      vmcase(OP_MUL,
-        arith_op(luai_nummul, TM_MUL);
-      )
-      vmcase(OP_DIV,
-        arith_op(luai_numdiv, TM_DIV);
-      )
-      vmcase(OP_MOD,
-        arith_op(luai_nummod, TM_MOD);
-      )
-      vmcase(OP_POW,
-        arith_op(luai_numpow, TM_POW);
-      )
-      vmcase(OP_UNM,
+        TValue *rc = RKC(i);
+        TString *key = tsvalue(rc);  /* key must be a string */
+        setobjs2s(L, ra + 1, rb);
+        if (luaV_fastget(L, rb, key, aux, luaH_getstr)) {
+          setobj2s(L, ra, aux);
+        }
+        else Protect(luaV_finishget(L, rb, rc, ra, aux));
+        vmbreak;
+      }
+      vmcase(OP_ADD) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (ttisinteger(rb) && ttisinteger(rc)) {
+          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+          setivalue(ra, intop(+, ib, ic));
+        }
+        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_numadd(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
+        vmbreak;
+      }
+      vmcase(OP_SUB) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (ttisinteger(rb) && ttisinteger(rc)) {
+          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+          setivalue(ra, intop(-, ib, ic));
+        }
+        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_numsub(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); }
+        vmbreak;
+      }
+      vmcase(OP_MUL) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (ttisinteger(rb) && ttisinteger(rc)) {
+          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+          setivalue(ra, intop(*, ib, ic));
+        }
+        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_nummul(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); }
+        vmbreak;
+      }
+      vmcase(OP_DIV) {  /* float division (always with floats) */
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_numdiv(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
+        vmbreak;
+      }
+      vmcase(OP_BAND) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(&, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); }
+        vmbreak;
+      }
+      vmcase(OP_BOR) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(|, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); }
+        vmbreak;
+      }
+      vmcase(OP_BXOR) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(^, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); }
+        vmbreak;
+      }
+      vmcase(OP_SHL) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, luaV_shiftl(ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); }
+        vmbreak;
+      }
+      vmcase(OP_SHR) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, luaV_shiftl(ib, -ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); }
+        vmbreak;
+      }
+      vmcase(OP_MOD) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (ttisinteger(rb) && ttisinteger(rc)) {
+          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+          setivalue(ra, luaV_mod(L, ib, ic));
+        }
+        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          lua_Number m;
+          luai_nummod(L, nb, nc, m);
+          setfltvalue(ra, m);
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); }
+        vmbreak;
+      }
+      vmcase(OP_IDIV) {  /* floor division */
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (ttisinteger(rb) && ttisinteger(rc)) {
+          lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
+          setivalue(ra, luaV_div(L, ib, ic));
+        }
+        else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_numidiv(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
+        vmbreak;
+      }
+      vmcase(OP_POW) {
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Number nb; lua_Number nc;
+        if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
+          setfltvalue(ra, luai_numpow(L, nb, nc));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
+        vmbreak;
+      }
+      vmcase(OP_UNM) {
         TValue *rb = RB(i);
-        if (ttisnumber(rb)) {
-          lua_Number nb = nvalue(rb);
-          setnvalue(ra, luai_numunm(L, nb));
+        lua_Number nb;
+        if (ttisinteger(rb)) {
+          lua_Integer ib = ivalue(rb);
+          setivalue(ra, intop(-, 0, ib));
+        }
+        else if (tonumber(rb, &nb)) {
+          setfltvalue(ra, luai_numunm(L, nb));
         }
         else {
-          Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
+          Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
         }
-      )
-      vmcase(OP_NOT,
+        vmbreak;
+      }
+      vmcase(OP_BNOT) {
+        TValue *rb = RB(i);
+        lua_Integer ib;
+        if (tointeger(rb, &ib)) {
+          setivalue(ra, intop(^, ~l_castS2U(0), ib));
+        }
+        else {
+          Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));
+        }
+        vmbreak;
+      }
+      vmcase(OP_NOT) {
         TValue *rb = RB(i);
         int res = l_isfalse(rb);  /* next assignment may change this value */
         setbvalue(ra, res);
-      )
-      vmcase(OP_LEN,
+        vmbreak;
+      }
+      vmcase(OP_LEN) {
         Protect(luaV_objlen(L, ra, RB(i)));
-      )
-      vmcase(OP_CONCAT,
+        vmbreak;
+      }
+      vmcase(OP_CONCAT) {
         int b = GETARG_B(i);
         int c = GETARG_C(i);
         StkId rb;
         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;
+        ra = RA(i);  /* 'luaV_concat' may invoke TMs and move the stack */
+        rb = base + b;
         setobjs2s(L, ra, rb);
         checkGC(L, (ra >= rb ? ra + 1 : rb));
         L->top = ci->top;  /* restore top */
-      )
-      vmcase(OP_JMP,
+        vmbreak;
+      }
+      vmcase(OP_JMP) {
         dojump(ci, i, 0);
-      )
-      vmcase(OP_EQ,
+        vmbreak;
+      }
+      vmcase(OP_EQ) {
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);
         Protect(
-          if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
+          if (luaV_equalobj(L, rb, rc) != GETARG_A(i))
             ci->u.l.savedpc++;
           else
             donextjump(ci);
         )
-      )
-      vmcase(OP_LT,
+        vmbreak;
+      }
+      vmcase(OP_LT) {
         Protect(
           if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
             ci->u.l.savedpc++;
           else
             donextjump(ci);
         )
-      )
-      vmcase(OP_LE,
+        vmbreak;
+      }
+      vmcase(OP_LE) {
         Protect(
           if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
             ci->u.l.savedpc++;
           else
             donextjump(ci);
         )
-      )
-      vmcase(OP_TEST,
+        vmbreak;
+      }
+      vmcase(OP_TEST) {
         if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
             ci->u.l.savedpc++;
           else
           donextjump(ci);
-      )
-      vmcase(OP_TESTSET,
+        vmbreak;
+      }
+      vmcase(OP_TESTSET) {
         TValue *rb = RB(i);
         if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
           ci->u.l.savedpc++;
@@ -705,27 +1125,30 @@ void luaV_execute (lua_State *L) {
           setobjs2s(L, ra, rb);
           donextjump(ci);
         }
-      )
-      vmcase(OP_CALL,
+        vmbreak;
+      }
+      vmcase(OP_CALL) {
         int b = GETARG_B(i);
         int nresults = GETARG_C(i) - 1;
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         if (luaD_precall(L, ra, nresults)) {  /* C function? */
-          if (nresults >= 0) L->top = ci->top;  /* adjust results */
-          base = ci->u.l.base;
+          if (nresults >= 0)
+            L->top = ci->top;  /* adjust results */
+          Protect((void)0);  /* update 'base' */
         }
         else {  /* Lua function */
           ci = L->ci;
-          ci->callstatus |= CIST_REENTRY;
           goto newframe;  /* restart luaV_execute over new Lua function */
         }
-      )
-      vmcase(OP_TAILCALL,
+        vmbreak;
+      }
+      vmcase(OP_TAILCALL) {
         int b = GETARG_B(i);
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
-        if (luaD_precall(L, ra, LUA_MULTRET))  /* C function? */
-          base = ci->u.l.base;
+        if (luaD_precall(L, ra, LUA_MULTRET)) {  /* C function? */
+          Protect((void)0);  /* update 'base' */
+        }
         else {
           /* tail call: put called frame (n) in place of caller one (o) */
           CallInfo *nci = L->ci;  /* called frame */
@@ -748,13 +1171,13 @@ void luaV_execute (lua_State *L) {
           lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
           goto newframe;  /* restart luaV_execute over new Lua function */
         }
-      )
-      vmcasenb(OP_RETURN,
+        vmbreak;
+      }
+      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);
-        if (!(ci->callstatus & CIST_REENTRY))  /* 'ci' still the called one */
+        b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
+        if (ci->callstatus & CIST_FRESH)  /* local 'ci' still from callee */
           return;  /* external invocation: return */
         else {  /* invocation via reentry: continue execution */
           ci = L->ci;
@@ -763,105 +1186,137 @@ void luaV_execute (lua_State *L) {
           lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
           goto newframe;  /* restart luaV_execute over new Lua function */
         }
-      )
-      vmcase(OP_FORLOOP,
-        lua_Number step = nvalue(ra+2);
-        lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
-        lua_Number limit = nvalue(ra+1);
-        if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
-                                   : luai_numle(L, limit, idx)) {
-          ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
-          setnvalue(ra, idx);  /* update internal index... */
-          setnvalue(ra+3, idx);  /* ...and external index */
-        }
-      )
-      vmcase(OP_FORPREP,
-        const TValue *init = ra;
-        const TValue *plimit = ra+1;
-        const TValue *pstep = ra+2;
-        if (!tonumber(init, ra))
-          luaG_runerror(L, LUA_QL("for") " initial value must be a number");
-        else if (!tonumber(plimit, ra+1))
-          luaG_runerror(L, LUA_QL("for") " limit must be a number");
-        else if (!tonumber(pstep, ra+2))
-          luaG_runerror(L, LUA_QL("for") " step must be a number");
-        setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
+      }
+      vmcase(OP_FORLOOP) {
+        if (ttisinteger(ra)) {  /* integer loop? */
+          lua_Integer step = ivalue(ra + 2);
+          lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */
+          lua_Integer limit = ivalue(ra + 1);
+          if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
+            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
+            chgivalue(ra, idx);  /* update internal index... */
+            setivalue(ra + 3, idx);  /* ...and external index */
+          }
+        }
+        else {  /* floating loop */
+          lua_Number step = fltvalue(ra + 2);
+          lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */
+          lua_Number limit = fltvalue(ra + 1);
+          if (luai_numlt(0, step) ? luai_numle(idx, limit)
+                                  : luai_numle(limit, idx)) {
+            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
+            chgfltvalue(ra, idx);  /* update internal index... */
+            setfltvalue(ra + 3, idx);  /* ...and external index */
+          }
+        }
+        vmbreak;
+      }
+      vmcase(OP_FORPREP) {
+        TValue *init = ra;
+        TValue *plimit = ra + 1;
+        TValue *pstep = ra + 2;
+        lua_Integer ilimit;
+        int stopnow;
+        if (ttisinteger(init) && ttisinteger(pstep) &&
+            forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) {
+          /* all values are integer */
+          lua_Integer initv = (stopnow ? 0 : ivalue(init));
+          setivalue(plimit, ilimit);
+          setivalue(init, intop(-, initv, ivalue(pstep)));
+        }
+        else {  /* try making all values floats */
+          lua_Number ninit; lua_Number nlimit; lua_Number nstep;
+          if (!tonumber(plimit, &nlimit))
+            luaG_runerror(L, "'for' limit must be a number");
+          setfltvalue(plimit, nlimit);
+          if (!tonumber(pstep, &nstep))
+            luaG_runerror(L, "'for' step must be a number");
+          setfltvalue(pstep, nstep);
+          if (!tonumber(init, &ninit))
+            luaG_runerror(L, "'for' initial value must be a number");
+          setfltvalue(init, luai_numsub(L, ninit, nstep));
+        }
         ci->u.l.savedpc += GETARG_sBx(i);
-      )
-      vmcasenb(OP_TFORCALL,
+        vmbreak;
+      }
+      vmcase(OP_TFORCALL) {
         StkId cb = ra + 3;  /* call base */
         setobjs2s(L, cb+2, ra+2);
         setobjs2s(L, cb+1, ra+1);
         setobjs2s(L, cb, ra);
         L->top = cb + 3;  /* func. + 2 args (state and index) */
-        Protect(luaD_call(L, cb, GETARG_C(i), 1));
+        Protect(luaD_call(L, cb, GETARG_C(i)));
         L->top = ci->top;
         i = *(ci->u.l.savedpc++);  /* go to next instruction */
         ra = RA(i);
         lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
         goto l_tforloop;
-      )
-      vmcase(OP_TFORLOOP,
+      }
+      vmcase(OP_TFORLOOP) {
         l_tforloop:
         if (!ttisnil(ra + 1)) {  /* continue loop? */
           setobjs2s(L, ra, ra + 1);  /* save control variable */
            ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
         }
-      )
-      vmcase(OP_SETLIST,
+        vmbreak;
+      }
+      vmcase(OP_SETLIST) {
         int n = GETARG_B(i);
         int c = GETARG_C(i);
-        int last;
+        unsigned int last;
         Table *h;
         if (n == 0) n = cast_int(L->top - ra) - 1;
         if (c == 0) {
           lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
           c = GETARG_Ax(*ci->u.l.savedpc++);
         }
-        luai_runtimecheck(L, ttistable(ra));
         h = hvalue(ra);
         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
         if (last > h->sizearray)  /* needs more space? */
-          luaH_resizearray(L, h, last);  /* pre-allocate it at once */
+          luaH_resizearray(L, h, last);  /* preallocate it at once */
         for (; n > 0; n--) {
           TValue *val = ra+n;
           luaH_setint(L, h, last--, val);
-          luaC_barrierback(L, obj2gco(h), val);
+          luaC_barrierback(L, h, val);
         }
         L->top = ci->top;  /* correct top (in case of previous open call) */
-      )
-      vmcase(OP_CLOSURE,
+        vmbreak;
+      }
+      vmcase(OP_CLOSURE) {
         Proto *p = cl->p->p[GETARG_Bx(i)];
-        Closure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
+        LClosure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
         if (ncl == NULL)  /* no match? */
           pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
         else
           setclLvalue(L, ra, ncl);  /* push cashed closure */
         checkGC(L, ra + 1);
-      )
-      vmcase(OP_VARARG,
-        int b = GETARG_B(i) - 1;
+        vmbreak;
+      }
+      vmcase(OP_VARARG) {
+        int b = GETARG_B(i) - 1;  /* required results */
         int j;
         int n = cast_int(base - ci->func) - cl->p->numparams - 1;
+        if (n < 0)  /* less arguments than parameters? */
+          n = 0;  /* no vararg arguments */
         if (b < 0) {  /* B == 0? */
           b = n;  /* get all var. arguments */
           Protect(luaD_checkstack(L, n));
           ra = RA(i);  /* previous call may change the stack */
           L->top = ra + n;
         }
-        for (j = 0; j < b; j++) {
-          if (j < n) {
-            setobjs2s(L, ra + j, base - n + j);
-          }
-          else {
-            setnilvalue(ra + j);
-          }
-        }
-      )
-      vmcase(OP_EXTRAARG,
+        for (j = 0; j < b && j < n; j++)
+          setobjs2s(L, ra + j, base - n + j);
+        for (; j < b; j++)  /* complete required results with nil */
+          setnilvalue(ra + j);
+        vmbreak;
+      }
+      vmcase(OP_EXTRAARG) {
         lua_assert(0);
-      )
+        vmbreak;
+      }
     }
   }
 }
 
+/* }================================================================== */
+
index 5380270..bcf52d2 100644 (file)
--- a/src/lvm.h
+++ b/src/lvm.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lvm.h,v 2.40 2016/01/05 16:07:21 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
 #include "ltm.h"
 
 
-#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o)))
+#if !defined(LUA_NOCVTN2S)
+#define cvt2str(o)     ttisnumber(o)
+#else
+#define cvt2str(o)     0       /* no conversion from numbers to strings */
+#endif
+
+
+#if !defined(LUA_NOCVTS2N)
+#define cvt2num(o)     ttisstring(o)
+#else
+#define cvt2num(o)     0       /* no conversion from strings to numbers */
+#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 tonumber(o,n)  (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+#define tointeger(o,i) \
+    (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
 
-#define equalobj(L,o1,o2)  (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2))
+#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
 
-#define luaV_rawequalobj(o1,o2)                equalobj(NULL,o1,o2)
+#define luaV_rawequalobj(t1,t2)                luaV_equalobj(NULL,t1,t2)
+
+
+/*
+** fast track for 'gettable': if 't' is a table and 't[k]' is not nil,
+** return 1 with 'slot' pointing to 't[k]' (final result).  Otherwise,
+** return 0 (meaning it will have to check metamethod) with 'slot'
+** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise).
+** 'f' is the raw get function to use.
+*/
+#define luaV_fastget(L,t,k,slot,f) \
+  (!ttistable(t)  \
+   ? (slot = NULL, 0)  /* not a table; 'slot' is NULL and result is 0 */  \
+   : (slot = f(hvalue(t), k),  /* else, do raw access */  \
+      !ttisnil(slot)))  /* result not nil? */
+
+/*
+** standard implementation for 'gettable'
+*/
+#define luaV_gettable(L,t,k,v) { const TValue *slot; \
+  if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \
+  else luaV_finishget(L,t,k,v,slot); }
+
+
+/*
+** Fast track for set table. If 't' is a table and 't[k]' is not nil,
+** call GC barrier, do a raw 't[k]=v', and return true; otherwise,
+** return false with 'slot' equal to NULL (if 't' is not a table) or
+** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro
+** returns true, there is no need to 'invalidateTMcache', because the
+** call is not creating a new entry.
+*/
+#define luaV_fastset(L,t,k,slot,f,v) \
+  (!ttistable(t) \
+   ? (slot = NULL, 0) \
+   : (slot = f(hvalue(t), k), \
+     ttisnil(slot) ? 0 \
+     : (luaC_barrierback(L, hvalue(t), v), \
+        setobj2t(L, cast(TValue *,slot), v), \
+        1)))
 
 
-/* not to called directly */
-LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2);
+#define luaV_settable(L,t,k,v) { const TValue *slot; \
+  if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
+    luaV_finishset(L,t,k,v,slot); }
+  
 
 
+LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
 LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
 LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
-LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
-LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
-LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
-                                            StkId val);
-LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
-                                            StkId val);
+LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
+LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
+LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
+                               StkId val, const TValue *slot);
+LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                               StkId val, const TValue *slot);
 LUAI_FUNC void luaV_finishOp (lua_State *L);
 LUAI_FUNC void luaV_execute (lua_State *L);
 LUAI_FUNC void luaV_concat (lua_State *L, int total);
-LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
-                           const TValue *rc, TMS op);
+LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
 LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
 
 #endif
index 20efea9..c9e1f49 100644 (file)
@@ -1,15 +1,17 @@
 /*
-** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
 
-
-#include <string.h>
-
 #define lzio_c
 #define LUA_CORE
 
+#include "lprefix.h"
+
+
+#include <string.h>
+
 #include "lua.h"
 
 #include "llimits.h"
@@ -64,13 +66,3 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
   return 0;
 }
 
-/* ------------------------------------------------------------------------ */
-char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
-  if (n > buff->buffsize) {
-    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
-    luaZ_resizebuffer(L, buff, n);
-  }
-  return buff->buffer;
-}
-
-
index 441f747..e7b6f34 100644 (file)
@@ -1,5 +1,5 @@
 /*
-** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 roberto Exp $
+** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $
 ** Buffered streams
 ** See Copyright Notice in lua.h
 */
@@ -32,20 +32,21 @@ typedef struct Mbuffer {
 #define luaZ_sizebuffer(buff)  ((buff)->buffsize)
 #define luaZ_bufflen(buff)     ((buff)->n)
 
+#define luaZ_buffremove(buff,i)        ((buff)->n -= (i))
 #define luaZ_resetbuffer(buff) ((buff)->n = 0)
 
 
 #define luaZ_resizebuffer(L, buff, size) \
-       (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \
+       ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \
+                               (buff)->buffsize, size), \
        (buff)->buffsize = size)
 
 #define luaZ_freebuffer(L, buff)       luaZ_resizebuffer(L, buff, 0)
 
 
-LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
 LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
                                         void *data);
-LUAI_FUNC size_t luaZ_read (ZIO* z, voidb, size_t n);        /* read next n bytes */
+LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n);        /* read next n bytes */
 
 
 
@@ -55,7 +56,7 @@ struct Zio {
   size_t n;                    /* bytes still unread */
   const char *p;               /* current position in buffer */
   lua_Reader reader;           /* reader function */
-  voiddata;                  /* additional data */
+  void *data;                  /* additional data */
   lua_State *L;                        /* Lua state (for reader) */
 };