Index: vendor/lua/dist/Makefile
===================================================================
--- vendor/lua/dist/Makefile (revision 326343)
+++ vendor/lua/dist/Makefile (revision 326344)
@@ -1,114 +1,114 @@
# Makefile for installing Lua
# See doc/readme.html for installation and customization instructions.
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
# Where to install. The installation starts in the src and doc directories,
# so take care if INSTALL_TOP is not an absolute path. See the local target.
# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
INSTALL_TOP= /usr/local
INSTALL_BIN= $(INSTALL_TOP)/bin
INSTALL_INC= $(INSTALL_TOP)/include
INSTALL_LIB= $(INSTALL_TOP)/lib
INSTALL_MAN= $(INSTALL_TOP)/man/man1
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
# How to install. If your install program does not support "-p", then
# you may have to run ranlib on the installed liblua.a.
INSTALL= install -p
INSTALL_EXEC= $(INSTALL) -m 0755
INSTALL_DATA= $(INSTALL) -m 0644
#
# If you don't have "install" you can use "cp" instead.
# INSTALL= cp -p
# INSTALL_EXEC= $(INSTALL)
# INSTALL_DATA= $(INSTALL)
# Other utilities.
MKDIR= mkdir -p
RM= rm -f
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
# Convenience platforms targets.
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
# What to install.
TO_BIN= lua luac
TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
TO_LIB= liblua.a
TO_MAN= lua.1 luac.1
# Lua version and release.
V= 5.3
-R= $V.0
+R= $V.4
# Targets start here.
all: $(PLAT)
$(PLATS) clean:
cd src && $(MAKE) $@
test: dummy
src/lua -v
install: dummy
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
uninstall:
cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN)
cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC)
cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB)
cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN)
local:
$(MAKE) install INSTALL_TOP=../install
none:
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
@echo " $(PLATS)"
@echo "See doc/readme.html for complete instructions."
# make may get confused with test/ and install/
dummy:
# echo config parameters
echo:
@cd src && $(MAKE) -s echo
@echo "PLAT= $(PLAT)"
@echo "V= $V"
@echo "R= $R"
@echo "TO_BIN= $(TO_BIN)"
@echo "TO_INC= $(TO_INC)"
@echo "TO_LIB= $(TO_LIB)"
@echo "TO_MAN= $(TO_MAN)"
@echo "INSTALL_TOP= $(INSTALL_TOP)"
@echo "INSTALL_BIN= $(INSTALL_BIN)"
@echo "INSTALL_INC= $(INSTALL_INC)"
@echo "INSTALL_LIB= $(INSTALL_LIB)"
@echo "INSTALL_MAN= $(INSTALL_MAN)"
@echo "INSTALL_LMOD= $(INSTALL_LMOD)"
@echo "INSTALL_CMOD= $(INSTALL_CMOD)"
@echo "INSTALL_EXEC= $(INSTALL_EXEC)"
@echo "INSTALL_DATA= $(INSTALL_DATA)"
# echo pkg-config data
pc:
@echo "version=$R"
@echo "prefix=$(INSTALL_TOP)"
@echo "libdir=$(INSTALL_LIB)"
@echo "includedir=$(INSTALL_INC)"
# list targets that do not create files (but not all makes understand .PHONY)
.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
# (end of Makefile)
Index: vendor/lua/dist/README
===================================================================
--- vendor/lua/dist/README (revision 326343)
+++ vendor/lua/dist/README (revision 326344)
@@ -1,6 +1,6 @@
-This is Lua 5.3.0, released on 06 Jan 2015.
+This is Lua 5.3.4, released on 12 Jan 2017.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
Index: vendor/lua/dist/doc/contents.html
===================================================================
--- vendor/lua/dist/doc/contents.html (revision 326343)
+++ vendor/lua/dist/doc/contents.html (revision 326344)
@@ -1,619 +1,619 @@
Lua 5.3 Reference Manual - contents
+
-
-
-
+
Lua 5.3 Reference Manual
The reference manual is the official definition of the Lua language.
+
For a complete introduction to Lua programming, see the book
Programming in Lua.
-
-Lua is an extension programming language designed to support
-general procedural programming with data description
-facilities.
-Lua 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.
+
+
+
+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.
+
+
+
Lua is implemented as a library, written in clean C,
the common subset of Standard C and C++.
+The Lua distribution includes a host program called lua,
+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.
As an extension language, Lua has no notion of a "main" program:
-it only works embedded in a host client,
+it works embedded in a host client,
called the embedding program or simply the host.
+(Frequently, this host is the stand-alone lua program.)
The host program can invoke functions to execute a piece of Lua code,
can write and read Lua variables,
and can register C functions to be called by Lua code.
Through the use of C 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 lua,
-which uses the Lua library to offer a complete, standalone Lua interpreter,
-for interactive or batch use.
Lua is free software,
and is provided as usual with no guarantees,
as stated in its license.
The implementation described in this manual is available
at Lua's official web site, www.lua.org.
Like any other reference manual,
this document is dry in places.
For a discussion of the decisions behind the design of Lua,
see the technical papers available at Lua's web site.
For a detailed introduction to programming in Lua,
see Roberto's book, Programming in Lua.
Lua is a dynamically typed language.
This means that
variables do not have types; only values do.
There are no type definitions in the language.
All values carry their own type.
All values in Lua are first-class values.
This means that all values can be stored in variables,
passed as arguments to other functions, and returned as results.
There are eight basic types in Lua:
nil, boolean, number,
string, function, userdata,
thread, and table.
-Nil is the type of the value nil,
+The type nil has one single value, nil,
whose main property is to be different from any other value;
it usually represents the absence of a useful value.
-Boolean is the type of the values false and true.
+The type boolean has two values, false and true.
Both nil and false make a condition false;
any other value makes it true.
-Number represents both
+The type number represents both
integer numbers and real (floating-point) numbers.
-String represents immutable sequences of bytes.
+The type string represents immutable sequences of bytes.
Lua is 8-bit clean:
strings can contain any 8-bit value,
including embedded zeros ('\0').
Lua is also encoding-agnostic;
it makes no assumptions about the contents of a string.
The type number uses two internal representations,
+or two subtypes,
one called integer and the other called float.
Lua has explicit rules about when each representation is used,
but it also converts between them automatically as needed (see §3.4.3).
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
+The option with 32 bits for both integers and floats
is particularly attractive
for small machines and embedded systems.
(See macro LUA_32BITS in file luaconf.h.)
Lua can call (and manipulate) functions written in Lua and
functions written in C (see §3.4.10).
Both are represented by the type function.
The type userdata is provided to allow arbitrary C data to
be stored in Lua variables.
A userdata value represents a block of raw memory.
There are two kinds of userdata:
full userdata,
which is an object with a block of memory managed by Lua,
and light userdata,
which is simply a C pointer value.
Userdata has no predefined operations in Lua,
except assignment and identity test.
By using metatables,
the programmer can define operations for full userdata values
(see §2.4).
Userdata values cannot be created or modified in Lua,
only through the C API.
This guarantees the integrity of data owned by the host program.
The type thread represents independent threads of execution
and it is used to implement coroutines (see §2.6).
Lua threads are not related to operating-system threads.
Lua supports coroutines on all systems,
even those that do not support threads natively.
The type table implements associative arrays,
that is, arrays that can be indexed not only with numbers,
but with any Lua value except nil and NaN.
-(Not a Number is a special numeric value used to represent
-undefined or unrepresentable results, such as 0/0.)
+(Not a Number is a special value used to represent
+undefined or unrepresentable numerical results, such as 0/0.)
Tables can be heterogeneous;
that is, they can contain values of all types (except nil).
Any key with value nil is not considered part of the table.
Conversely, any key that is not part of a table has
an associated value nil.
Tables are the sole data-structuring mechanism in Lua;
-they can be used to represent ordinary arrays, sequences,
+they can be used to represent ordinary arrays, lists,
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 a.name as syntactic sugar for a["name"].
There are several convenient ways to create tables in Lua
(see §3.4.9).
-We use the term sequence to denote a table where
-the set of all positive numeric keys is equal to {1..n}
-for some non-negative integer n,
-which is called the length of the sequence (see §3.4.7).
-
-
-
Like indices,
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 methods (see §3.4.11).
The indexing of tables follows
the definition of raw equality in the language.
The expressions a[i] and a[j]
denote the same table element
if and only if i and j are raw equal
(that is, equal without metamethods).
In particular, floats with integral values
are equal to their respective integers
(e.g., 1.0 == 1).
To avoid ambiguities,
any float with integral value used as a key
is converted to its respective integer.
For instance, if you write a[2.0] = true,
the actual key inserted into the table will be the
integer 2.
(On the other hand,
2 and "2" are different Lua values and therefore
denote different table entries.)
Tables, functions, threads, and (full) userdata values are objects:
variables do not actually contain these values,
only references to them.
Assignment, parameter passing, and function returns
always manipulate references to such values;
these operations do not imply any kind of copy.
The library function type returns a string describing the type
of a given value (see §6.1).
As will be discussed in §3.2 and §3.3.3,
any reference to a free name
(that is, a name not bound to any declaration) var
is syntactically translated to _ENV.var.
Moreover, every chunk is compiled in the scope of
an external local variable named _ENV (see §3.3.2),
so _ENV itself is never a free name in a chunk.
Despite the existence of this external _ENV variable and
the translation of free names,
_ENV is a completely regular name.
In particular,
you can define new variables and parameters with that name.
Each reference to a free name uses the _ENV that is
visible at that point in the program,
following the usual visibility rules of Lua (see §3.5).
Any table used as the value of _ENV is called an environment.
Lua keeps a distinguished environment called the global environment.
This value is kept at a special index in the C registry (see §4.5).
In Lua, the global variable _G is initialized with this same value.
(_G is never used internally.)
When Lua loads a chunk,
the default value for its _ENV upvalue
is the global environment (see load).
Therefore, by default,
free names in Lua code refer to entries in the global environment
(and, therefore, they are also called global variables).
Moreover, all standard libraries are loaded in the global environment
and some functions there operate on that environment.
You can use load (or loadfile)
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.)
Because Lua is an embedded extension language,
all Lua actions start from C code in the host program
calling a function from the Lua library.
(When you use Lua standalone,
the lua application is the host program.)
Whenever an error occurs during
the compilation or execution of a Lua chunk,
control returns to the host,
which can take appropriate measures
(such as printing an error message).
Lua code can explicitly generate an error by calling the
error function.
If you need to catch errors in Lua,
you can use pcall or xpcall
to call a given function in protected mode.
Whenever there is an error,
an error object (also called an error message)
is propagated with information about the error.
Lua itself only generates errors whose error object is a string,
but programs may generate errors with
any value as the error object.
It is up to the Lua program or its host to handle such error objects.
When you use xpcall or lua_pcall,
you may give a message handler
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 for too long,
Lua breaks it and returns an appropriate message.
+(The message handler is called only for regular runtime errors.
+It is not called for memory-allocation errors
+nor for errors while running finalizers.)
Every value in Lua can have a metatable.
This metatable is an ordinary Lua table
that defines the behavior of the original value
under certain special operations.
You can change several aspects of the behavior
of operations over a value by setting specific fields in its metatable.
For instance, when a non-numeric value is the operand of an addition,
Lua checks for a function in the field "__add" of the value's metatable.
If it finds one,
Lua calls this function to perform the addition.
-The keys in a metatable are derived from the event 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 metamethods.
-In the previous example, the event is "add"
+In the previous example, the key is "__add"
and the metamethod is the function that performs the addition.
You can query the metatable of any value
using the getmetatable function.
+Lua queries metamethods in metatables using a raw access (see rawget).
+So, to retrieve the metamethod for event ev in object o,
+Lua does the equivalent to the following code:
+
+ rawget(getmetatable(o) or {}, "__ev")
+
You can replace the metatable of tables
using the setmetatable function.
-You cannot change the metatable of other types from Lua
+You cannot change the metatable of other types from Lua code
(except by using the debug library (§6.10));
-you must use the C API for that.
+you should use the C API for that.
Tables and full userdata have individual metatables
(although multiple tables and userdata can share their metatables).
Values of all other types share one single metatable per type;
that is, there is one single metatable for all numbers,
one for all strings, etc.
By default, a value has no metatable,
but the string library sets a metatable for the string type (see §6.4).
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 (§2.5).
-A detailed list of events controlled by metatables is given next.
-Each operation is identified by its corresponding event name.
-The key for each event is a string with its name prefixed by
-two underscores, '__';
-for instance, the key for operation "add" is the
-string "__add".
-Note that queries for metamethods are always raw;
-the access to a metamethod does not invoke other metamethods.
-You can emulate how Lua queries a metamethod for an object obj
-with the following code:
-
-
- rawget(getmetatable(obj) or {}, "__" .. event_name)
-
-
-
-For the unary operators (negation, length, and bitwise not),
+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.)
+
+A detailed list of events controlled by metatables is given next.
+Each operation is identified by its corresponding key.
-
-
"add":
-the + operation.
+
+
+
__add:
+the addition (+) 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 the "__add" event,
+If that operand does not define a metamethod for __add,
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.
-
"sub":
-the - operation.
-
-Behavior similar to the "add" operation.
+
__sub:
+the subtraction (-) operation.
+Behavior similar to the addition operation.
-
"mul":
-the * operation.
-
-Behavior similar to the "add" operation.
+
__mul:
+the multiplication (*) operation.
+Behavior similar to the addition operation.
-
"div":
-the / operation.
-
-Behavior similar to the "add" operation.
+
__div:
+the division (/) operation.
+Behavior similar to the addition operation.
-
"mod":
-the % operation.
-
-Behavior similar to the "add" operation.
+
__mod:
+the modulo (%) operation.
+Behavior similar to the addition operation.
-
"pow":
-the ^ (exponentiation) operation.
-
-Behavior similar to the "add" operation.
+
__pow:
+the exponentiation (^) operation.
+Behavior similar to the addition operation.
-
"unm":
-the - (unary minus) operation.
-
-Behavior similar to the "add" operation.
+
__unm:
+the negation (unary -) operation.
+Behavior similar to the addition operation.
-
"idiv":
-the // (floor division) operation.
-
-Behavior similar to the "add" operation.
+
__idiv:
+the floor division (//) operation.
+Behavior similar to the addition operation.
-
"band":
-the & (bitwise and) operation.
-
-Behavior similar to the "add" operation,
+
__band:
+the bitwise AND (&) operation.
+Behavior similar to the addition operation,
except that Lua will try a metamethod
-if any operator is neither an integer
+if any operand is neither an integer
nor a value coercible to an integer (see §3.4.3).
-
"bor":
-the | (bitwise or) operation.
-
-Behavior similar to the "band" operation.
+
__bor:
+the bitwise OR (|) operation.
+Behavior similar to the bitwise AND operation.
-
"bxor":
-the ~ (bitwise exclusive or) operation.
-
-Behavior similar to the "band" operation.
+
__bxor:
+the bitwise exclusive OR (binary ~) operation.
+Behavior similar to the bitwise AND operation.
-
"bnot":
-the ~ (bitwise unary not) operation.
-
-Behavior similar to the "band" operation.
+
__bnot:
+the bitwise NOT (unary ~) operation.
+Behavior similar to the bitwise AND operation.
-
"shl":
-the << (bitwise left shift) operation.
-
-Behavior similar to the "band" operation.
+
__shl:
+the bitwise left shift (<<) operation.
+Behavior similar to the bitwise AND operation.
-
"shr":
-the >> (bitwise right shift) operation.
-
-Behavior similar to the "band" operation.
+
__shr:
+the bitwise right shift (>>) operation.
+Behavior similar to the bitwise AND operation.
-
"concat":
-the .. (concatenation) operation.
-
-Behavior similar to the "add" operation,
+
__concat:
+the concatenation (..) operation.
+Behavior similar to the addition operation,
except that Lua will try a metamethod
-if any operator is neither a string nor a number
+if any operand is neither a string nor a number
(which is always coercible to a string).
-
"len":
-the # (length) operation.
-
+
__len:
+the length (#) 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 §3.4.7).
Otherwise, Lua raises an error.
-
"eq":
-the == (equal) operation.
-
-Behavior similar to the "add" operation,
+
__eq:
+the equal (==) 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.
-
"lt":
-the < (less than) operation.
-
-Behavior similar to the "add" operation,
+
__lt:
+the less than (<) 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.
-
"le":
-the <= (less equal) operation.
-
+
__le:
+the less equal (<=) operation.
Unlike other operations,
-The less-equal operation can use two different events.
-First, Lua looks for the "__le" metamethod in both operands,
-like in the "lt" operation.
+the less-equal operation can use two different events.
+First, Lua looks for the __le metamethod in both operands,
+like in the less than operation.
If it cannot find such a metamethod,
-then it will try the "__lt" event,
+then it will try the __lt metamethod,
assuming that a <= b is equivalent to not (b < a).
As with the other comparison operators,
the result is always a boolean.
+(This use of the __lt event can be removed in future versions;
+it is also slower than a real __le metamethod.)
-
"index":
+
__index:
The indexing access table[key].
-
This event happens when table is not a table or
when key is not present in table.
The metamethod is looked up in table.
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 table and key as arguments.
+it is called with table and key 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 key.
(This indexing is regular, not raw,
and therefore can trigger another metamethod.)
-
"newindex":
+
__newindex:
The indexing assignment table[key] = value.
-
Like the index event,
this event happens when table is not a table or
when key is not present in table.
The metamethod is looked up in table.
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 table, key, and value 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.)
-Whenever there is a "newindex" metamethod,
+Whenever there is a __newindex metamethod,
Lua does not perform the primitive assignment.
(If necessary,
the metamethod itself can call rawset
to do the assignment.)
-
"call":
+
__call:
The call operation func(args).
-
This event happens when Lua tries to call a non-function value
(that is, func is not a function).
The metamethod is looked up in func.
If present,
the metamethod is called with func as its first argument,
followed by the arguments of the original call (args).
+All results of the call
+are the result of the operation.
+(This is the only metamethod that allows multiple results.)
+
+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 __gc metamethod works only when this order
+is followed (see §2.5.1).
+
+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., tostring)
+use other fields in metatables for their own purposes.
+
+
+
+
Lua performs automatic memory management.
This means that
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 garbage collector to collect all dead objects
(that is, objects that are no longer accessible from Lua).
All memory used by Lua is subject to automatic management:
strings, tables, userdata, functions, threads, internal structures, etc.
Lua implements an incremental mark-and-sweep collector.
It uses two numbers to control its garbage-collection cycles:
the garbage-collector pause and
the garbage-collector step multiplier.
Both use percentage points as units
(e.g., a value of 100 means an internal value of 1).
The garbage-collector pause
controls how long the collector waits before starting a new cycle.
Larger values make the collector less aggressive.
Values smaller than 100 mean the collector will not wait to
start a new cycle.
A value of 200 means that the collector waits for the total memory in use
to double before starting a new cycle.
The garbage-collector step multiplier
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.
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"
the speed of memory allocation.
If you set the step multiplier to a very large number
(larger than 10% of the maximum number of
bytes that the program may use),
the collector behaves like a stop-the-world collector.
If you then set the pause to 200,
the collector behaves as in old Lua versions,
doing a complete collection every time Lua doubles its
memory usage.
You can change these numbers by calling lua_gc in C
or collectgarbage in Lua.
You can also use these functions to control
the collector directly (e.g., stop and restart it).
You can set garbage-collector metamethods for tables
and, using the C API,
for full userdata (see §2.4).
These metamethods are also called finalizers.
Finalizers allow you to coordinate Lua's garbage collection
with external resource management
(such as closing files, network or database connections,
or freeing your own memory).
For an object (table or userdata) to be finalized when collected,
you must mark it for finalization.
You mark an object for finalization when you set its metatable
and the metatable has a field indexed by the string "__gc".
Note that if you set a metatable without a __gc field
and later create that field in the metatable,
the object will not be marked for finalization.
-However, after an object has been marked,
-you can freely change the __gc field of its metatable.
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 goes through that list.
For each object in the list,
it checks the object's __gc 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.
At the end of each garbage-collection cycle,
the finalizers for objects are called in
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.
The execution of each finalizer may occur at any point during
the execution of the regular code.
Because the object being collected must still be used by the finalizer,
that object (and other objects accessible only through it)
must be resurrected 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 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 in the GC cycle where
+the object memory is freed only in a GC cycle where
the object is unreachable and not marked for finalization.
When you close a state (see lua_close),
Lua calls the finalizers of all objects marked for finalization,
following the reverse order that they were marked.
If any finalizer marks objects for collection during that phase,
these marks have no effect.
A weak table is a table whose elements are
weak references.
A weak reference is ignored by the garbage collector.
In other words,
if the only references to an object are weak references,
then the garbage collector will collect that object.
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,
the whole pair is removed from the table.
The weakness of a table is controlled by the
__mode field of its metatable.
If the __mode field is a string containing the character 'k',
the keys in the table are weak.
If __mode contains 'v',
the values in the table are weak.
A table with weak keys and strong values
is also called an ephemeron table.
In an ephemeron table,
a value is considered reachable only if its key is reachable.
In particular,
if the only reference to a key comes through its value,
the pair is removed.
Any change in the weakness of a table may take effect only
at the next collect cycle.
In particular, if you change the weakness to a stronger mode,
Lua may still collect some items from that table
before the change takes effect.
Only objects that have an explicit construction
are removed from weak tables.
-Values, such as numbers and light C functions,
+Values, such as numbers and light C functions,
are not subject to garbage collection,
and therefore are not removed from weak tables
(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.
Resurrected objects
(that is, objects being finalized
and objects accessible only through objects being finalized)
have a special behavior in weak tables.
They are removed from weak values before running their finalizers,
but are removed from weak keys only in the next collection
after running their finalizers, when such objects are actually freed.
This behavior allows the finalizer to access properties
associated with the object through weak tables.
If a weak table is among the resurrected objects in a collection cycle,
it may not be properly cleared until the next cycle.
Lua supports coroutines,
also called collaborative multithreading.
A coroutine in Lua represents an independent thread of execution.
Unlike threads in multithread systems, however,
a coroutine only suspends its execution by explicitly calling
a yield function.
You create a coroutine by calling coroutine.create.
Its sole argument is a function
that is the main function of the coroutine.
The create function only creates a new coroutine and
returns a handle to it (an object of type thread);
it does not start the coroutine.
You execute a coroutine by calling coroutine.resume.
When you first call coroutine.resume,
passing as its first argument
a thread returned by coroutine.create,
-the coroutine starts its execution,
-at the first line of its main function.
+the coroutine starts its execution by
+calling its main function.
Extra arguments passed to coroutine.resume are passed
-as arguments to the coroutine's main function.
+as arguments to that function.
After the coroutine starts running,
it runs until it terminates or yields.
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 case of normal termination,
coroutine.resume returns true,
plus any values returned by the coroutine main function.
In case of errors, coroutine.resume returns false
-plus an error message.
+plus an error object.
A coroutine yields by calling coroutine.yield.
When a coroutine yields,
the corresponding coroutine.resume returns immediately,
even if the yield happens inside nested function calls
(that is, not in the main function,
but in a function directly or indirectly called by the main function).
In the case of a yield, coroutine.resume also returns true,
plus any values passed to coroutine.yield.
The next time you resume the same coroutine,
it continues its execution from the point where it yielded,
with the call to coroutine.yield returning any extra
arguments passed to coroutine.resume.
Like coroutine.create,
the coroutine.wrap function also creates a coroutine,
but instead of returning the coroutine itself,
it returns a function that, when called, resumes the coroutine.
Any arguments passed to this function
go as extra arguments to coroutine.resume.
coroutine.wrap returns all the values returned by coroutine.resume,
except the first one (the boolean error code).
Unlike coroutine.resume,
coroutine.wrap does not catch errors;
any error is propagated to the caller.
As an example of how coroutines work,
consider the following code:
function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))
When you run it, it produces the following output:
co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine
This section describes the lexis, the syntax, and the semantics of Lua.
In other words,
this section describes
which tokens are valid,
how they can be combined,
and what their combinations mean.
Language constructs will be explained using the usual extended BNF notation,
in which
{a} means 0 or more a's, and
[a] means an optional a.
Non-terminals are shown like non-terminal,
keywords are shown like kword,
and other terminal symbols are shown like ‘=’.
The complete syntax of Lua can be found in §9
at the end of this manual.
Lua is a free-form language.
It ignores spaces (including new lines) and comments
between lexical elements (tokens),
except as delimiters between names and keywords.
Names
(also called identifiers)
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.
The following keywords are reserved
and cannot be used as names:
and break do else elseif end
false for function goto if in
local nil not or repeat return
then true until while
Lua is a case-sensitive language:
and is a reserved word, but And and AND
are two different, valid names.
As a convention,
-programs should avoid creating
+programs should avoid creating
names that start with an underscore followed by
one or more uppercase letters (such as _VERSION).
-Literal strings
+A short literal string
can be delimited by matching single or double quotes,
and can contain the following C-like escape sequences:
'\a' (bell),
'\b' (backspace),
'\f' (form feed),
'\n' (newline),
'\r' (carriage return),
'\t' (horizontal tab),
'\v' (vertical tab),
'\\' (backslash),
'\"' (quotation mark [double quote]),
and '\'' (apostrophe [single quote]).
-A backslash followed by a real newline
+A backslash followed by a line break
results in a newline in the string.
The escape sequence '\z' skips the following span
of white-space characters,
including line breaks;
it is particularly useful to break and indent a long literal string
into multiple lines without adding the newlines and spaces
into the string contents.
+A short literal string cannot contain unescaped line breaks
+nor escapes not forming a valid escape sequence.
-Strings in Lua can contain any 8-bit value, including embedded zeros,
-which can be specified as '\0'.
-More generally,
-we can specify any byte in a literal string by its numerical value.
+We can specify any byte in a short literal string by its numeric value
+(including embedded zeros).
This can be done
with the escape sequence \xXX,
where XX is a sequence of exactly two hexadecimal digits,
or with the escape sequence \ddd,
where ddd is a sequence of up to three decimal digits.
(Note that if a decimal escape sequence is to be followed by a digit,
it must be expressed using exactly three digits.)
The UTF-8 encoding of a Unicode character
can be inserted in a literal string with
the escape sequence \u{XXX}
(note the mandatory enclosing brackets),
where XXX is a sequence of one or more hexadecimal digits
representing the character code point.
Literal strings can also be defined using a long format
enclosed by long brackets.
We define an opening long bracket of level n as an opening
square bracket followed by n equal signs followed by another
opening square bracket.
So, an opening long bracket of level 0 is written as [[,
an opening long bracket of level 1 is written as [=[,
and so on.
A closing long bracket is defined similarly;
for instance,
a closing long bracket of level 4 is written as ]====].
A long literal 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 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.
Any kind of end-of-line sequence
(carriage return, newline, carriage return followed by newline,
or newline followed by carriage return)
is converted to a simple newline.
-Any byte in a literal string not
-explicitly affected by the previous rules represents itself.
-However, Lua opens files for parsing in text mode,
-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.
-
-
-
For convenience,
when the opening long bracket is immediately followed by a newline,
the newline is not included in the string.
As an example, in a system using ASCII
(in which 'a' is coded as 97,
newline is coded as 10, and '1' is coded as 49),
the five literal strings below denote the same string:
a = 'alo\n123"'
a = "alo\n123\""
a = '\97lo\10\04923"'
a = [[alo
123"]]
a = [==[
alo
123"]==]
-A numerical constant (or numeral)
+Any byte in a literal string not
+explicitly affected by the previous rules represents itself.
+However, Lua opens files for parsing in text mode,
+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 the non-text characters.
+
+
+
+A numeric constant (or numeral)
can be written with an optional fractional part
and an optional decimal exponent,
marked by a letter 'e' or 'E'.
Lua also accepts hexadecimal constants,
which start with 0x or 0X.
Hexadecimal constants also accept an optional fractional part
plus an optional binary exponent,
marked by a letter 'p' or 'P'.
-A numeric constant with a fractional dot or an exponent
+A numeric constant with a radix point or an exponent
denotes a float;
-otherwise it denotes an integer.
+otherwise,
+if its value fits in an integer,
+it denotes an integer.
Examples of valid integer constants are
A comment starts with a double hyphen (--)
anywhere outside a string.
If the text immediately after -- is not an opening long bracket,
the comment is a short comment,
which runs until the end of the line.
Otherwise, it is a long comment,
which runs until the corresponding closing long bracket.
Long comments are frequently used to disable code temporarily.
Any variable name is assumed to be global unless explicitly declared
as a local (see §3.3.7).
Local variables are lexically scoped:
local variables can be freely accessed by functions
defined inside their scope (see §3.5).
Before the first assignment to a variable, its value is nil.
Square brackets are used to index a table:
var ::= prefixexp ‘[’ exp ‘]’
The meaning of accesses to table fields can be changed via metatables.
An access to an indexed variable t[i] is equivalent to
a call gettable_event(t,i).
(See §2.4 for a complete description of the
gettable_event function.
This function is not defined or callable in Lua.
We use it here only for explanatory purposes.)
The syntax var.Name is just syntactic sugar for
var["Name"]:
var ::= prefixexp ‘.’ Name
An access to a global variable x
is equivalent to _ENV.x.
Due to the way that chunks are compiled,
_ENV is never a global name (see §2.2).
Lua supports an almost conventional set of statements,
similar to those in Pascal or C.
This set includes
assignments, control structures, function calls,
and variable declarations.
A block is a list of statements,
which are executed sequentially:
block ::= {stat}
Lua has empty statements
that allow you to separate statements with semicolons,
start a block with a semicolon
or write two semicolons in sequence:
stat ::= ‘;’
Function calls and assignments
can start with an open parenthesis.
This possibility leads to an ambiguity in Lua's grammar.
Consider the following fragment:
a = b + c
(print or io.write)('done')
The grammar could see it in two ways:
a = b + c(print or io.write)('done')
a = b + c; (print or io.write)('done')
The current parser always sees such constructions
in the first way,
interpreting the open parenthesis
as the start of the arguments to a call.
To avoid this ambiguity,
it is a good practice to always precede with a semicolon
statements that start with a parenthesis:
;(print or io.write)('done')
A block can be explicitly delimited to produce a single statement:
stat ::= do block end
Explicit blocks are useful
to control the scope of variable declarations.
Explicit blocks are also sometimes used to
add a return statement in the middle
of another block (see §3.3.4).
The unit of compilation of Lua is called a chunk.
Syntactically,
a chunk is simply a block:
chunk ::= block
Lua handles a chunk as the body of an anonymous function
with a variable number of arguments
(see §3.4.11).
As such, chunks can define local variables,
receive arguments, and return values.
Moreover, such anonymous function is compiled as in the
scope of an external local variable called _ENV (see §2.2).
The resulting function always has _ENV as its only upvalue,
even if it does not use that variable.
A chunk can be stored in a file or in a string inside the host program.
To execute a chunk,
Lua first loads 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.
Chunks can also be precompiled into binary form;
see program luac and function string.dump for details.
Programs in source and compiled forms are interchangeable;
Lua automatically detects the file type and acts accordingly (see load).
Lua allows multiple assignments.
Therefore, the syntax for assignment
defines a list of variables on the left side
and a list of expressions on the right side.
The elements in both lists are separated by commas:
stat ::= varlist ‘=’ explist
varlist ::= var {‘,’ var}
explist ::= exp {‘,’ exp}
Before the assignment,
the list of values is adjusted to the length of
the list of variables.
If there are more values than needed,
the excess values are thrown away.
If there are fewer values than needed,
the list is extended with as many nil's as needed.
If the list of expressions ends with a function call,
then all values returned by that call enter the list of values,
before the adjustment
(except when the call is enclosed in parentheses; see §3.4).
The assignment statement first evaluates all its expressions
and only then the assignments are performed.
Thus the code
i = 3
i, a[i] = i+1, 20
sets a[3] to 20, without affecting a[4]
because the i in a[i] is evaluated (to 3)
before it is assigned 4.
Similarly, the line
x, y = y, x
exchanges the values of x and y,
and
x, y, z = y, z, x
cyclically permutes the values of x, y, and z.
The meaning of assignments to global variables
and table fields can be changed via metatables.
An assignment to an indexed variable t[i] = val is equivalent to
settable_event(t,i,val).
(See §2.4 for a complete description of the
settable_event function.
This function is not defined or callable in Lua.
We use it here only for explanatory purposes.)
An assignment to a global name x = val
is equivalent to the assignment
_ENV.x = val (see §2.2).
The control structures
if, while, and repeat have the usual meaning and
familiar syntax:
stat ::= while exp do block end
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end
Lua also has a for statement, in two flavors (see §3.3.5).
The condition expression of a
control structure can return any value.
Both false and nil are considered false.
All values different from nil and false are considered true
(in particular, the number 0 and the empty string are also true).
In the repeat–until loop,
the inner block does not end at the until keyword,
but only after the condition.
So, the condition can refer to local variables
declared inside the loop block.
The goto statement transfers the program control to a label.
For syntactical reasons,
labels in Lua are considered statements too:
stat ::= goto Name
stat ::= label
label ::= ‘::’ Name ‘::’
A label is visible in the entire block where it is defined,
except
inside nested blocks where a label with the same name is defined and
inside nested functions.
A goto may jump to any visible label as long as it does not
enter into the scope of a local variable.
Labels and empty statements are called void statements,
as they perform no actions.
The break statement terminates the execution of a
while, repeat, or for loop,
skipping to the next statement after the loop:
stat ::= break
A break ends the innermost enclosing loop.
The return statement is used to return values
from a function or a chunk
(which is an anonymous function).
Functions can return more than one value,
so the syntax for the return statement is
stat ::= return [explist] [‘;’]
The return statement can only be written
as the last statement of a block.
If it is really necessary to return in the middle of a block,
then an explicit inner block can be used,
as in the idiom do return end,
because now return is the last statement in its (inner) block.
The for statement has two forms:
-one numeric and one generic.
+one numerical and one generic.
-The numeric for loop repeats a block of code while a
+The numerical for loop repeats a block of code while a
control variable runs through an arithmetic progression.
It has the following syntax:
stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
The block is repeated for name starting at the value of
the first exp, until it passes the second exp by steps of the
third exp.
More precisely, a for statement like
for v = e1, e2, e3 do block end
is equivalent to the code:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
var = var - step
while true do
var = var + step
if (step >= 0 and var > limit) or (step < 0 and var < limit) then
break
end
local v = varblock
end
end
Note the following:
All three control expressions are evaluated only once,
before the loop starts.
They must all result in numbers.
var, limit, and step are invisible variables.
The names shown here are for explanatory purposes only.
If the third expression (the step) is absent,
then a step of 1 is used.
You can use break and goto to exit a for loop.
The loop variable v is local to the loop body.
If you need its value after the loop,
assign it to another variable before exiting the loop.
The generic for statement works over functions,
called iterators.
On each iteration, the iterator function is called to produce a new value,
stopping when this new value is nil.
The generic for loop has the following syntax:
stat ::= for namelist in explist do block end
namelist ::= Name {‘,’ Name}
A for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
do
local f, s, var = explist
while true do
local var_1, ···, var_n = f(s, var)
if var_1 == nil then break end
var = var_1block
end
end
Note the following:
explist is evaluated only once.
Its results are an iterator function,
a state,
and an initial value for the first iterator variable.
f, s, and var are invisible variables.
The names are here for explanatory purposes only.
You can use break to exit a for loop.
The loop variables var_i are local to the loop;
you cannot use their values after the for ends.
If you need these values,
then assign them to other variables before breaking or exiting the loop.
Numerals and literal strings are explained in §3.1;
variables are explained in §3.2;
function definitions are explained in §3.4.11;
function calls are explained in §3.4.10;
table constructors are explained in §3.4.9.
Vararg expressions,
denoted by three dots ('...'), can only be used when
directly inside a vararg function;
they are explained in §3.4.11.
Binary operators comprise arithmetic operators (see §3.4.1),
bitwise operators (see §3.4.2),
relational operators (see §3.4.4), logical operators (see §3.4.5),
and the concatenation operator (see §3.4.6).
Unary operators comprise the unary minus (see §3.4.1),
-the unary bitwise not (see §3.4.2),
+the unary bitwise NOT (see §3.4.2),
the unary logical not (see §3.4.5),
and the unary length operator (see §3.4.7).
Both function calls and vararg expressions can result in multiple values.
If a function call is used as a statement (see §3.3.6),
then its return list is adjusted to zero elements,
thus discarding all returned values.
If an expression is used as the last (or the only) element
of a list of expressions,
then no adjustment is made
(unless the expression is enclosed in parentheses).
In all other contexts,
Lua adjusts the result list to one element,
either discarding all values except the first one
or adding a single nil if there are no values.
Here are some examples:
f() -- adjusted to 0 results
g(f(), x) -- f() is adjusted to 1 result
g(x, f()) -- g gets x plus all results from f()
a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil)
a,b = ... -- a gets the first vararg parameter, b gets
-- the second (both a and b can get nil if there
-- is no corresponding vararg parameter)
a,b,c = x, f() -- f() is adjusted to 2 results
a,b,c = f() -- f() is adjusted to 3 results
return f() -- returns all results from f()
return ... -- returns all received vararg parameters
return x,y,f() -- returns x, y, and all results from f()
{f()} -- creates a list with all results from f()
{...} -- creates a list with all vararg parameters
{f(), nil} -- f() is adjusted to 1 result
Any expression enclosed in parentheses always results in only one value.
Thus,
(f(x,y,z)) is always a single value,
even if f returns several values.
(The value of (f(x,y,z)) is the first value returned by f
or nil if f does not return any values.)
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 §3.4.3),
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.
Exponentiation and float division (/)
always convert their operands to floats
and the result is always a float.
Exponentiation uses the ISO C function pow,
so that it works for non-integer exponents too.
-Floor division (//) is a division
-that rounds the quotient towards minus infinite,
+Floor division (//) is a division
+that rounds the quotient towards minus infinity,
that is, the floor of the division of its operands.
Modulo is defined as the remainder of a division
-that rounds the quotient towards minus infinite (floor division).
+that rounds the quotient towards minus infinity (floor division).
In case of overflows in integer arithmetic,
all operations wrap around,
according to the usual rules of two-complement arithmetic.
(In other words,
they return the unique representable integer
that is equal modulo 264 to the mathematical result.)
All bitwise operations convert its operands to integers
(see §3.4.3),
operate on all bits of those integers,
and result in an integer.
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).
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 usual rule.
The C API also converts both integers to floats and
floats to integers, as needed.
Moreover, string concatenation accepts numbers as arguments,
-besides strings.
+besides strings.
Lua also converts strings to numbers,
whenever a number is expected.
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.
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.
The conversion from strings to numbers goes as follows:
First, the string is converted to an integer or a float,
following its syntax and the rules of the Lua lexer.
(The string may have also leading and trailing spaces and a sign.)
-Then, the resulting number is converted to the required type
-(float or integer) according to the previous rules.
+Then, the resulting number (float or integer)
+is converted to the type (float or integer) required by the context
+(e.g., the operation that forced the conversion).
+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.)
+
+
+
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 format function from the string library
(see string.format).
Equality (==) first compares the type of its operands.
If the types are different, then the result is false.
Otherwise, the values of the operands are compared.
Strings are compared in the obvious way.
-Numbers follow the usual rule for binary operations:
-if both operands are integers,
-they are compared as integers;
-otherwise, they are converted to floats
-and compared as such.
+Numbers are equal if they denote the same mathematical value.
Tables, userdata, and threads
are compared by reference:
two objects are considered equal only if they are the same object.
Every time you create a new object
(a table, userdata, or thread),
this new object is different from any previously existing object.
Closures with the same reference are always equal.
Closures with any detectable difference
(different behavior, different definition) are always different.
You can change the way that Lua compares tables and userdata
by using the "eq" metamethod (see §2.4).
Equality comparisons do not convert strings to numbers
or vice versa.
Thus, "0"==0 evaluates to false,
and t[0] and t["0"] denote different
entries in a table.
The operator ~= is exactly the negation of equality (==).
The order operators work as follows.
If both arguments are numbers,
-then they are compared following
-the usual rule for binary operations.
+then they are compared according to their mathematical values
+(regardless of their subtypes).
Otherwise, if both arguments are strings,
then their values are compared according to the current locale.
Otherwise, Lua tries to call the "lt" or the "le"
metamethod (see §2.4).
A comparison a > b is translated to b < a
and a >= b is translated to b <= a.
+
+Following the IEEE 754 standard,
+NaN is considered neither smaller than,
+nor equal to, nor greater than any value (including itself).
+
+
The logical operators in Lua are
and, or, and not.
Like the control structures (see §3.3.4),
all logical operators consider both false and nil as false
and anything else as true.
The negation operator not always returns false or true.
The conjunction operator and returns its first argument
if this value is false or nil;
otherwise, and returns its second argument.
The disjunction operator or returns its first argument
if this value is different from nil and false;
otherwise, or returns its second argument.
Both and and or use short-circuit evaluation;
that is,
the second operand is evaluated only if necessary.
Here are some examples:
10 or 20 --> 10
10 or error() --> 10
nil or "a" --> "a"
nil and 10 --> nil
false and error() --> false
false and nil --> false
false or nil --> nil
10 and 20 --> 20
(In this manual,
--> indicates the result of the preceding expression.)
The string concatenation operator in Lua is
denoted by two dots ('..').
If both operands are strings or numbers, then they are converted to
strings according to the rules described in §3.4.3.
Otherwise, the __concat metamethod is called (see §2.4).
The length operator is denoted by the unary prefix operator #.
+
+
+
The length of a string is its number of bytes
(that is, the usual meaning of string length when each
character is one byte).
-A program can modify the behavior of the length operator for
-any value but strings through the __len metamethod (see §2.4).
+The length operator applied on a table
+returns a border in that table.
+A border in a table t is any natural number
+that satisfies the following condition:
-
-
-Unless a __len metamethod is given,
-the length of a table t is only defined if the
-table is a sequence,
-that is,
-the set of its positive numeric keys is equal to {1..n}
-for some non-negative integer n.
-In that case, n is its length.
-Note that a table like
-
- {10, 20, nil, 40}
+ (border == 0 or t[border] ~= nil) and t[border + 1] == nil
-is not a sequence, because it has the key 4
-but does not have the key 3.
-(So, there is no n such that the set {1..n} is equal
-to the set of positive numeric keys of that table.)
-Note, however, that non-numeric keys do not interfere
+In words,
+a border is any (natural) index in a table
+where a non-nil value is followed by a nil value
+(or zero, when index 1 is nil).
+
+
+
+A table with exactly one border is called a sequence.
+For instance, the table {10, 20, 30, 40, 50} is a sequence,
+as it has only one border (5).
+The table {10, 20, 30, nil, 50} has two borders (3 and 5),
+and therefore it is not a sequence.
+The table {nil, 20, 30, nil, nil, 60, nil}
+has three borders (0, 3, and 6),
+so it is not a sequence, too.
+The table {} is a sequence with border 0.
+Note that non-natural keys do not interfere
with whether a table is a sequence.
+
+When t is a sequence,
+#t returns its only border,
+which corresponds to the intuitive notion of the length of the sequence.
+When t is not a sequence,
+#t can return any of its borders.
+(The exact one depends on details of
+the internal representation of the table,
+which in turn can depend on how the table was populated and
+the memory addresses of its non-numeric keys.)
+
+The computation of the length of a table
+has a guaranteed worst time of O(log n),
+where n is the largest natural key in the table.
+
+
+A program can modify the behavior of the length operator for
+any value but strings through the __len metamethod (see §2.4).
+
+
+
+
+
As usual,
you can use parentheses to change the precedences of an expression.
The concatenation ('..') and exponentiation ('^')
operators are right associative.
All other binary operators are left associative.
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
or to create a table and initialize some of its fields.
The general syntax for constructors is
tableconstructor ::= ‘{’ [fieldlist] ‘}’
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
fieldsep ::= ‘,’ | ‘;’
Each field of the form [exp1] = exp2 adds to the new table an entry
with key exp1 and value exp2.
A field of the form name = exp is equivalent to
["name"] = exp.
Finally, fields of the form exp are equivalent to
[i] = exp, where i are consecutive integers
starting with 1.
Fields in the other formats do not affect this counting.
For example,
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
is equivalent to
do
local t = {}
t[f(1)] = g
t[1] = "x" -- 1st exp
t[2] = "y" -- 2nd exp
t.x = 1 -- t["x"] = 1
t[3] = f(x) -- 3rd exp
t[30] = 23
t[4] = 45 -- 4th exp
a = t
end
The order of the assignments in a constructor is undefined.
(This order would be relevant only when there are repeated keys.)
If the last field in the list has the form exp
and the expression is a function call or a vararg expression,
then all values returned by this expression enter the list consecutively
(see §3.4.10).
The field list can have an optional trailing separator,
as a convenience for machine-generated code.
In a function call,
first prefixexp and args are evaluated.
If the value of prefixexp has type function,
then this function is called
with the given arguments.
Otherwise, the prefixexp "call" metamethod is called,
having as first parameter the value of prefixexp,
followed by the original call arguments
(see §2.4).
The form
functioncall ::= prefixexp ‘:’ Name args
can be used to call "methods".
A call v:name(args)
is syntactic sugar for v.name(v,args),
except that v is evaluated only once.
All argument expressions are evaluated before the call.
A call of the form f{fields} is
syntactic sugar for f({fields});
that is, the argument list is a single new table.
A call of the form f'string'
(or f"string" or f[[string]])
is syntactic sugar for f('string');
that is, the argument list is a single literal string.
A call of the form return functioncall is called
a tail call.
Lua implements proper tail calls
(or proper tail recursion):
in a tail call,
the called function reuses the stack entry of the calling function.
Therefore, there is no limit on the number of nested tail calls that
a program can execute.
However, a tail call erases any debug information about the
calling function.
Note that a tail call only happens with a particular syntax,
where the return has one single function call as argument;
this syntax makes the calling function return exactly
the returns of the called function.
So, none of the following examples are tail calls:
return (f(x)) -- results adjusted to 1
return 2 * f(x)
return x, f(x) -- additional results
f(x); return -- results discarded
return x or f(x) -- results adjusted to 1
functiondef ::= function funcbody
funcbody ::= ‘(’ [parlist] ‘)’ block end
The following syntactic sugar simplifies function definitions:
stat ::= function funcname funcbody
stat ::= localfunction Name funcbody
funcname ::= Name {‘.’ Name} [‘:’ Name]
The statement
function f () body end
translates to
f = function () body end
The statement
function t.a.b.c.f () body end
translates to
t.a.b.c.f = function () body end
The statement
local function f () body end
translates to
local f; f = function () body end
not to
local f = function () body end
(This only makes a difference when the body of the function
contains references to f.)
A function definition is an executable expression,
whose value has type function.
When Lua precompiles a chunk,
all its function bodies are precompiled too.
Then, whenever Lua executes the function definition,
the function is instantiated (or closed).
This function instance (or closure)
is the final value of the expression.
Parameters act as local variables that are
initialized with the argument values:
parlist ::= namelist [‘,’ ‘...’] | ‘...’
When a function is called,
the list of arguments is adjusted to
the length of the list of parameters,
unless the function is a vararg function,
which is indicated by three dots ('...')
at the end of its parameter list.
A vararg function does not adjust its argument list;
instead, it collects all extra arguments and supplies them
to the function through a vararg expression,
which is also written as three dots.
The value of this expression is a list of all actual extra arguments,
similar to a function with multiple results.
If a vararg expression is used inside another expression
or in the middle of a list of expressions,
then its return list is adjusted to one element.
If the expression is used as the last element of a list of expressions,
then no adjustment is made
(unless that last expression is enclosed in parentheses).
As an example, consider the following definitions:
function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end
Then, we have the following mapping from arguments to parameters and
to the vararg expression:
Results are returned using the return statement (see §3.3.4).
If control reaches the end of a function
without encountering a return statement,
then the function returns with no results.
There is a system-dependent limit on the number of values
that a function may return.
This limit is guaranteed to be larger than 1000.
The colon syntax
is used for defining methods,
that is, functions that have an implicit extra parameter self.
Thus, the statement
Lua is a lexically scoped language.
The scope of a local variable begins at the first statement after
its declaration and lasts until the last non-void statement
of the innermost block that includes the declaration.
Consider the following example:
x = 10 -- global variable
do -- new block
local x = x -- new 'x', with value 10
print(x) --> 10
x = x+1
do -- another block
local x = x+1 -- another 'x'
print(x) --> 12
end
print(x) --> 11
end
print(x) --> 10 (the global one)
Notice that, in a declaration like local x = x,
the new x being declared is not in scope yet,
and so the second x refers to the outside variable.
Because of the lexical scoping rules,
local variables can be freely accessed by functions
defined inside their scope.
A local variable used by an inner function is called
an upvalue, or external local variable,
inside the inner function.
Notice that each execution of a local statement
defines new local variables.
Consider the following example:
a = {}
local x = 20
for i=1,10 do
local y = 0
a[i] = function () y=y+1; return x+y end
end
The loop creates ten closures
(that is, ten instances of the anonymous function).
Each of these closures uses a different y variable,
while all of them share the same x.
This section describes the C API for Lua, that is,
the set of C functions available to the host program to communicate
with Lua.
All API functions and related types and constants
are declared in the header file lua.h.
Even when we use the term "function",
any facility in the API may be provided as a macro instead.
Except where stated otherwise,
all such macros use each of their arguments exactly once
(except for the first argument, which is always a Lua state),
and so do not generate any hidden side-effects.
As in most C libraries,
the Lua API functions do not check their arguments for validity or consistency.
However, you can change this behavior by compiling Lua
with the macro LUA_USE_APICHECK defined.
+
+The Lua library is fully reentrant:
+it has no global variables.
+It keeps all information it needs in a dynamic structure,
+called the Lua state.
+
+
+Each Lua state has one or more threads,
+which correspond to independent, cooperative lines of execution.
+The type lua_State (despite its name) refers to a thread.
+(Indirectly, through the thread, it also refers to the
+Lua state associated to the thread.)
+
+
+
+A pointer to a thread must be passed as the first argument to
+every function in the library, except to lua_newstate,
+which creates a Lua state from scratch and returns a pointer
+to the main thread in the new state.
+
+
+
Lua uses a virtual stack to pass values to and from C.
Each element in this stack represents a Lua value
(nil, number, string, etc.).
+Functions in the API can access this stack through the
+Lua state parameter that they receive.
Whenever Lua calls C, the called function gets a new stack,
which is independent of previous stacks and of stacks of
C functions that are still active.
This stack initially contains any arguments to the C function
-and it is where the C function pushes its results
+and it is where the C function can store temporary
+Lua values and must push its results
to be returned to the caller (see lua_CFunction).
For convenience,
most query operations in the API do not follow a strict stack discipline.
Instead, they can refer to any element in the stack
by using an index:
A positive index represents an absolute stack position
(starting at 1);
a negative index represents an offset relative to the top of the stack.
More specifically, if the stack has n elements,
then index 1 represents the first element
(that is, the element that was pushed onto the stack first)
and
index n represents the last element;
index -1 also represents the last element
(that is, the element at the top)
and index -n represents the first element.
When you interact with the Lua API,
you are responsible for ensuring consistency.
In particular,
you are responsible for controlling stack overflow.
You can use the function lua_checkstack
to ensure that the stack has enough space for pushing new elements.
Whenever Lua calls C,
it ensures that the stack has space for
at least LUA_MINSTACK extra slots.
LUA_MINSTACK 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.
When you call a Lua function
without a fixed number of results (see lua_call),
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 lua_checkstack.
Any function in the API that receives stack indices
works only with valid indices or acceptable indices.
A valid index is an index that refers to a
-real position within the stack, that is,
-its position lies between 1 and the stack top
-(1 ≤ abs(index) ≤ top).
+position that stores a modifiable Lua value.
+It comprises stack indices between 1 and the stack top
+(1 ≤ abs(index) ≤ top)
-Usually, functions that can modify the value at an index
-require valid indices.
-
-
-
-Unless otherwise noted,
-any function that accepts valid indices also accepts pseudo-indices,
-which represent some Lua values that are accessible to C code
-but which are not in the stack.
-Pseudo-indices are used to access the registry
+plus pseudo-indices,
+which represent some positions that are accessible to C code
+but that are not in the stack.
+Pseudo-indices are used to access the registry (see §4.5)
and the upvalues of a C function (see §4.4).
-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 acceptable index 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.
(Note that 0 is never an acceptable index.)
Except when noted otherwise,
functions in the API work with acceptable indices.
Acceptable indices serve to avoid extra tests
against the stack top when querying the stack.
For instance, a C function can query its third argument
without the need to first check whether there is a third argument,
that is, without the need to check whether 3 is a valid index.
For functions that can be called with acceptable indices,
any non-valid index is treated as if it
contains a value of a virtual type LUA_TNONE,
which behaves like a nil value.
When a C function is created,
it is possible to associate some values with it,
thus creating a C closure
(see lua_pushcclosure);
these values are called upvalues and are
accessible to the function whenever it is called.
Whenever a C function is called,
its upvalues are located at specific pseudo-indices.
These pseudo-indices are produced by the macro
lua_upvalueindex.
-The first value associated with a function is at position
+The first upvalue associated with a function is at index
lua_upvalueindex(1), and so on.
Any access to lua_upvalueindex(n),
where n 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.
Lua provides a registry,
a predefined table that can be used by any C code to
store whatever Lua values it needs to store.
The registry table is always located at pseudo-index
-LUA_REGISTRYINDEX,
-which is a valid index.
+LUA_REGISTRYINDEX.
Any C library can store data into this table,
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 object in your code,
or any Lua object created by your code.
As with variable names,
string keys starting with an underscore followed by
uppercase letters are reserved for Lua.
The integer keys in the registry are used
by the reference mechanism (see luaL_ref)
and by some predefined values.
Therefore, integer keys must not be used for other purposes.
When you create a new Lua state,
its registry comes with some predefined values.
These predefined values are indexed with integer keys
defined as constants in lua.h.
The following constants are defined:
LUA_RIDX_MAINTHREAD: At this index the registry has
the main thread of the state.
(The main thread is the one created together with the state.)
LUA_RIDX_GLOBALS: At this index the registry has
the global environment.
Internally, Lua uses the C longjmp facility to handle errors.
(Lua will use exceptions if you compile it as C++;
search for LUAI_THROW in the source code for details.)
When Lua faces any error
-(such as a memory allocation error, type errors, syntax errors,
-and runtime errors)
+(such as a memory allocation error or a type error)
it raises an error;
that is, it does a long jump.
A protected environment uses setjmp
to set a recovery point;
any error jumps to the most recent active recovery point.
+Inside a C function you can raise an error by calling lua_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 raise errors.
+
+
+
If an error happens outside any protected environment,
Lua calls a panic function (see lua_atpanic)
and then calls abort,
thus exiting the host application.
Your panic function can avoid this exit by
never returning
(e.g., doing a long jump to your own recovery point outside Lua).
+The panic function,
+as its name implies,
+is a mechanism of last resort.
+Programs should avoid it.
+As a general rule,
+when a C function is called by Lua with a Lua state,
+it can do whatever it wants on that Lua state,
+as it should be already protected.
+However,
+when C code operates on other Lua states
+(e.g., a Lua parameter to the function,
+a Lua state stored in the registry, or
+the result of lua_newthread),
+it should use them only in API calls that cannot raise errors.
+
+
+
The panic function runs as if it were a message handler (see §2.3);
-in particular, the error message is at the top of the stack.
+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 must first check the available space (see §4.2).
-
-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 raise errors.
-
-Inside a C function you can raise an error by calling lua_error.
-
-
-
-
Internally, Lua uses the C longjmp facility to yield a coroutine.
-Therefore, if a C function foo calls an API function
+Therefore, if a C function foo calls an API function
and this API function yields
(directly or indirectly by calling another function that yields),
Lua cannot return to foo any more,
because the longjmp removes its frame from the C stack.
To avoid this kind of problem,
Lua raises an error whenever it tries to yield across an API call,
except for three functions:
lua_yieldk, lua_callk, and lua_pcallk.
All those functions receive a continuation function
(as a parameter named k) to continue execution after a yield.
We need to set some terminology to explain continuations.
-We have a C function called from Lua which we will call
+We have a C function called from Lua which we will call
the original function.
This original function then calls one of those three functions in the C API,
which we will call the callee function,
that then yields the current thread.
(This can happen when the callee function is lua_yieldk,
or when the callee function is either lua_callk or lua_pcallk
and the function called by them yields.)
Suppose the running thread yields while executing the callee function.
After the thread resumes,
it eventually will finish running the callee function.
However,
the callee function cannot return to the original function,
because its frame in the C stack was destroyed by the yield.
Instead, Lua calls a continuation function,
which was given as an argument to the callee function.
As the name implies,
the continuation function should continue the task
of the original function.
As an illustration, consider the following function:
int original_function (lua_State *L) {
... /* code 1 */
status = lua_pcall(L, n, m, h); /* calls Lua */
... /* code 2 */
}
Now we want to allow
the Lua code being run by lua_pcall to yield.
First, we can rewrite our function like here:
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);
}
In the above code,
the new function k is a
continuation function (with type lua_KFunction),
which should do all the work that the original function
was doing after calling lua_pcall.
Now, we must inform Lua that it must call k if the Lua code
being executed by lua_pcall gets interrupted in some way
(errors or yielding),
so we rewrite the code as here,
replacing lua_pcall by lua_pcallk:
int original_function (lua_State *L) {
... /* code 1 */
return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1);
}
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,
lua_pcallk (and lua_callk) 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.)
Besides the Lua state,
the continuation function has two other parameters:
the final status of the call plus the context value (ctx) that
was passed originally to lua_pcallk.
(Lua does not use this context value;
it only passes this value from the original function to the
continuation function.)
For lua_pcallk,
the status is the same value that would be returned by lua_pcallk,
except that it is LUA_YIELD when being executed after a yield
(instead of LUA_OK).
For lua_yieldk and lua_callk,
the status is always LUA_YIELD 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 lua_callk,
you should call the continuation function
with LUA_OK as the status.
(For lua_yieldk, there is not much point in calling
directly the continuation function,
because lua_yieldk usually does not return.)
Lua treats the continuation function as if it were the original function.
The continuation function receives the same Lua stack
from the original function,
in the same state it would be if the callee function had returned.
(For instance,
after a lua_callk the function and its arguments are
removed from the stack and replaced by the results from the call.)
It also has the same upvalues.
Whatever it returns is handled by Lua as if it were the return
of the original function.
Here we list all functions and types from the C API in
alphabetical order.
Each function has an indicator like this:
[-o, +p, x]
The first field, o,
is how many elements the function pops from the stack.
The second field, p,
is how many elements the function pushes onto the stack.
(Any function always pushes its results after popping its arguments.)
A field in the form x|y means the function can push (or pop)
x or y elements,
depending on the situation;
an interrogation mark '?' means that
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, x,
tells whether the function may raise errors:
'-' means the function never raises any error;
-'e' means the function may raise errors;
+'m' means the function may raise out-of-memory errors
+and errors running a __gc metamethod;
+'e' means the function may raise any errors
+(it can run arbitrary Lua code,
+either directly or through metamethods);
'v' means the function may raise an error on purpose.
-Converts the acceptable index idx into an absolute index
+Converts the acceptable index idx
+into an equivalent absolute index
(that is, one that does not depend on the stack top).
The type of the memory-allocation function used by Lua states.
The allocator function must provide a
functionality similar to realloc,
but not exactly the same.
Its arguments are
ud, an opaque pointer passed to lua_newstate;
ptr, a pointer to the block being allocated/reallocated/freed;
osize, the original size of the block or some code about what
is being allocated;
and nsize, the new size of the block.
When ptr is not NULL,
osize is the size of the block pointed by ptr,
that is, the size given when it was allocated or reallocated.
When ptr is NULL,
osize encodes the kind of object that Lua is allocating.
osize is any of
LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION,
LUA_TUSERDATA, or LUA_TTHREAD when (and only when)
Lua is creating a new object of that type.
When osize is some other value,
Lua is allocating memory for something else.
Lua assumes the following behavior from the allocator function:
When nsize is zero,
the allocator must behave like free
and return NULL.
When nsize is not zero,
the allocator must behave like realloc.
The allocator returns NULL
if and only if it cannot fulfill the request.
Lua assumes that the allocator never fails when
osize >= nsize.
Here is a simple implementation for the allocator function.
It is used in the auxiliary library by luaL_newstate.
Note that Standard C ensures
that free(NULL) has no effect and that
realloc(NULL,size) is equivalent to malloc(size).
This code assumes that realloc does not fail when shrinking a block.
(Although Standard C does not ensure this behavior,
it seems to be a safe assumption.)
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.
The function follows the semantics of the corresponding Lua operator
(that is, it may call metamethods).
The value of op must be one of the following constants:
void lua_call (lua_State *L, int nargs, int nresults);
Calls a function.
To call a function you must use the following protocol:
first, the function to be called is pushed onto the stack;
then, the arguments to the function are pushed
in direct order;
that is, the first argument is pushed first.
Finally you call lua_call;
nargs is the number of arguments that you pushed onto the stack.
All arguments and the function value are popped from the stack
when the function is called.
The function results are pushed onto the stack when the function returns.
The number of results is adjusted to nresults,
unless nresults is LUA_MULTRET.
-In this case, all results from the function are pushed.
-Lua takes care that the returned values fit into the stack space.
+In this case, all results from the function are pushed;
+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.
Any error inside the called function is propagated upwards
(with a longjmp).
The following example shows how the host program can do the
equivalent to this Lua code:
a = f("how", t.x, 14)
Here it is in C:
lua_getglobal(L, "f"); /* function to be called */
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 */
lua_pushinteger(L, 14); /* 3rd argument */
lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */
lua_setglobal(L, "a"); /* set global 'a' */
Note that the code above is balanced:
at its end, the stack is back to its original configuration.
This is considered good programming practice.
In order to communicate properly with Lua,
a C function must use the following protocol,
which defines the way parameters and results are passed:
a C function receives its arguments from Lua in its stack
in direct order (the first argument is pushed first).
So, when the function starts,
lua_gettop(L) returns the number of arguments received by the function.
The first argument (if any) is at index 1
and its last argument is at index lua_gettop(L).
To return values to Lua, a C function just pushes them onto the stack,
in direct order (the first result is pushed first),
and returns the number of results.
Any other value in the stack below the results will be properly
discarded by Lua.
Like a Lua function, a C function called by Lua can also return
many results.
As an example, the following function receives a variable number
-of numerical arguments and returns their average and their sum:
+of numeric arguments and returns their average and their sum:
static int foo (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number sum = 0.0;
int i;
for (i = 1; i <= n; i++) {
if (!lua_isnumber(L, i)) {
lua_pushliteral(L, "incorrect argument");
lua_error(L);
}
sum += lua_tonumber(L, i);
}
lua_pushnumber(L, sum/n); /* first result */
lua_pushnumber(L, sum); /* second result */
return 2; /* number of results */
}
-Ensures that the stack has space for at least n extra slots.
+Ensures that the stack has space for at least n extra slots
+(that is, that you can safely push up to n values into it).
It returns false if it cannot fulfill the request,
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.
Destroys all objects in the given Lua state
(calling the corresponding garbage-collection metamethods, if any)
and frees all dynamic memory used by this state.
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,
will probably need to close states as soon as they are not needed.
int lua_compare (lua_State *L, int index1, int index2, int op);
Compares two Lua values.
Returns 1 if the value at index index1 satisfies op
when compared with the value at index index2,
following the semantics of the corresponding Lua operator
(that is, it may call metamethods).
Otherwise returns 0.
Also returns 0 if any of the indices is not valid.
The value of op must be one of the following constants:
Concatenates the n values at the top of the stack,
pops them, and leaves the result at the top.
If n is 1, the result is the single value on the stack
(that is, the function does nothing);
if n is 0, the result is the empty string.
Concatenation is performed following the usual semantics of Lua
(see §3.4.6).
void lua_createtable (lua_State *L, int narr, int nrec);
Creates a new empty table and pushes it onto the stack.
Parameter narr is a hint for how many elements the table
will have as a sequence;
parameter nrec 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 lua_newtable.
int lua_dump (lua_State *L,
lua_Writer writer,
void *data,
int strip);
Dumps a function as a binary chunk.
Receives a Lua function on the top of the stack
and produces a binary chunk that,
if loaded again,
results in a function equivalent to the one dumped.
As it produces parts of the chunk,
lua_dump calls function writer (see lua_Writer)
with the given data
to write them.
If strip is true,
-the binary representation is created without debug information
-about the function.
+the binary representation may not include all debug information
+about the function,
+to save space.
The value returned is the error code returned by the last
call to the writer;
0 means no errors.
This function does not pop the Lua function from the stack.
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 luaL_error).
This function performs several tasks,
according to the value of the parameter what:
LUA_GCSTOP:
stops the garbage collector.
LUA_GCRESTART:
restarts the garbage collector.
LUA_GCCOLLECT:
performs a full garbage-collection cycle.
LUA_GCCOUNT:
returns the current amount of memory (in Kbytes) in use by Lua.
LUA_GCCOUNTB:
returns the remainder of dividing the current amount of bytes of
memory in use by Lua by 1024.
LUA_GCSTEP:
performs an incremental step of garbage collection.
LUA_GCSETPAUSE:
sets data as the new value
for the pause of the collector (see §2.5)
and returns the previous value of the pause.
LUA_GCSETSTEPMUL:
sets data as the new value for the step multiplier of
the collector (see §2.5)
and returns the previous value of the step multiplier.
LUA_GCISRUNNING:
returns a boolean that tells whether the collector is running
(i.e., not stopped).
For more details about these options,
see collectgarbage.
Returns the memory-allocation function of a given state.
If ud is not NULL, Lua stores in *ud the
opaque pointer given when the memory-allocator function was set.
int lua_getfield (lua_State *L, int index, const char *k);
Pushes onto the stack the value t[k],
where t is the value at the given index.
As in Lua, this function may trigger a metamethod
for the "index" event (see §2.4).
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.
Each new thread has this area initialized with a copy
of the area of the main thread.
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 LUA_EXTRASPACE in luaconf.h.)
int lua_geti (lua_State *L, int index, lua_Integer i);
Pushes onto the stack the value t[i],
where t is the value at the given index.
As in Lua, this function may trigger a metamethod
for the "index" event (see §2.4).
If the value at the given index has a metatable,
the function pushes that metatable onto the stack and returns 1.
Otherwise,
the function returns 0 and pushes nothing on the stack.
Pushes onto the stack the value t[k],
where t is the value at the given index
and k is the value at the top of the stack.
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 §2.4).
Returns the index of the top element in the stack.
Because indices start at 1,
this result is equal to the number of elements in the stack;
in particular, 0 means an empty stack.
-Pushes onto the stack the Lua value associated with the userdata
+Pushes onto the stack the Lua value associated with the full userdata
at the given index.
Moves the top element into the given valid index,
shifting up the elements above this index to open space.
This function cannot be called with a pseudo-index,
because a pseudo-index is not an actual stack position.
By default this type is long long,
(usually a 64-bit two-complement integer),
but that can be changed to long or int
(usually a 32-bit two-complement integer).
-(See LUA_INT in luaconf.h.)
+(See LUA_INT_TYPE in luaconf.h.)
Lua also defines the constants
LUA_MININTEGER and LUA_MAXINTEGER,
with the minimum and the maximum values that fit in this type.
The type for continuation-function contexts.
-It must be a numerical type.
+It must be a numeric type.
This type is defined as intptr_t
when intptr_t is available,
so that it can store pointers too.
Otherwise, it is defined as ptrdiff_t.
Returns the length of the value at the given index.
It is equivalent to the '#' operator in Lua (see §3.4.7) and
may trigger a metamethod for the "length" event (see §2.4).
The result is pushed on the stack.
Loads a Lua chunk without running it.
If there are no errors,
lua_load pushes the compiled chunk as a Lua
function on top of the stack.
Otherwise, it pushes an error message.
LUA_ERRGCMM:
error while running a __gc metamethod.
(This error has no relation with the chunk being loaded.
It is generated by the garbage collector.)
The lua_load function uses a user-supplied reader function
to read the chunk (see lua_Reader).
The data argument is an opaque value passed to the reader function.
The chunkname argument gives a name to the chunk,
which is used for error messages and in debug information (see §4.9).
lua_load automatically detects whether the chunk is text or binary
and loads it accordingly (see program luac).
The string mode works as in function load,
with the addition that
a NULL value is equivalent to the string "bt".
lua_load uses the stack internally,
so the reader function must always leave the stack
unmodified when returning.
If the resulting function has upvalues,
its first upvalue is set to the value of the global environment
stored at index LUA_RIDX_GLOBALS in the registry (see §4.5).
When loading main chunks,
this upvalue will be the _ENV variable (see §2.2).
Other upvalues are initialized with nil.
Creates a new thread running in a new, independent state.
Returns NULL if it cannot create the thread or the state
(due to lack of memory).
The argument f is the allocator function;
-Lua does all memory allocation for this state through this function.
+Lua does all memory allocation for this state
+through this function (see lua_Alloc).
The second argument, ud, is an opaque pointer that Lua
passes to the allocator in every call.
Creates a new thread, pushes it on the stack,
and returns a pointer to a lua_State that represents this new thread.
The new thread returned by this function shares with the original thread
its global environment,
but has an independent execution stack.
There is no explicit function to close or to destroy a thread.
Threads are subject to garbage collection,
like any Lua object.
This function allocates a new block of memory with the given size,
pushes onto the stack a new full userdata with the block address,
and returns this address.
The host program can freely use this memory.
Pops a key from the stack,
and pushes a key–value pair from the table at the given index
(the "next" pair after the given key).
If there are no more elements in the table,
then lua_next returns 0 (and pushes nothing).
A typical traversal looks like this:
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, t) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
printf("%s - %s\n",
lua_typename(L, lua_type(L, -2)),
lua_typename(L, lua_type(L, -1)));
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 1);
}
While traversing a table,
do not call lua_tolstring directly on a key,
unless you know that the key is actually a string.
Recall that lua_tolstring may change
the value at the given index;
this confuses the next call to lua_next.
See function next for the caveats of modifying
the table during its traversal.
By default this type is double,
-but that can be changed to a single float.
-(See LUA_REAL in luaconf.h.)
+but that can be changed to a single float or a long double.
+(See LUA_FLOAT_TYPE in luaconf.h.)
int lua_numbertointeger (lua_Number n, lua_Integer *p);
Converts a Lua float to a Lua integer.
This macro assumes that n has an integral value.
If that value is within the range of Lua integers,
it is converted to an integer and assigned to *p.
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.)
This macro may evaluate its arguments more than once.
int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
Calls a function in protected mode.
Both nargs and nresults have the same meaning as
in lua_call.
If there are no errors during the call,
lua_pcall behaves exactly like lua_call.
However, if there is any error,
lua_pcall 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 lua_call,
lua_pcall always removes the function
and its arguments from the stack.
If msgh 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, msgh is the stack index of a
message handler.
-(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 lua_pcall.
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 lua_pcall,
since by then the stack has unwound.
The lua_pcall function returns one of the following constants
(defined in lua.h):
LUA_ERRMEM:
memory allocation error.
For such errors, Lua does not call the message handler.
LUA_ERRERR:
error while running the message handler.
LUA_ERRGCMM:
error while running a __gc metamethod.
-(This error typically has no relation with the function being called.)
+For such errors, Lua does not call the message handler
+(as this kind of error typically has no relation
+with the function being called).
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
Pushes a new C closure onto the stack.
When a C function is created,
it is possible to associate some values with it,
thus creating a C closure (see §4.4);
these values are then accessible to the function whenever it is called.
To associate values with a C function,
first these values must be pushed onto the stack
(when there are multiple values, the first value is pushed first).
Then lua_pushcclosure
is called to create and push the C function onto the stack,
with the argument n telling how many values will be
associated with the function.
lua_pushcclosure also pops these values from the stack.
The maximum value for n is 255.
When n is zero,
-this function creates a light C function,
+this function creates a light C function,
which is just a pointer to the C function.
In that case, it never raises a memory error.
Pushes a C function onto the stack.
-This function receives a pointer to a C function
+This function receives a pointer to a C function
and pushes onto the stack a Lua value of type function that,
when called, invokes the corresponding C function.
-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 lua_CFunction).
-
Pushes onto the stack a formatted string
and returns a pointer to this string.
It is similar to the ISO C function sprintf,
but has some important differences:
You do not have to allocate space for the result:
the result is a Lua string and Lua takes care of memory allocation
(and deallocation, through garbage collection).
The conversion specifiers are quite restricted.
There are no flags, widths, or precisions.
The conversion specifiers can only be
'%%' (inserts the character '%'),
'%s' (inserts a zero-terminated string, with no size restrictions),
'%f' (inserts a lua_Number),
-'%L' (inserts a lua_Integer),
+'%I' (inserts a lua_Integer),
'%p' (inserts a pointer as a hexadecimal numeral),
'%d' (inserts an int),
'%c' (inserts an int as a one-byte character), and
'%U' (inserts a long int as a UTF-8 byte sequence).
+
+Unlike other push functions,
+this function checks for the stack space it needs,
+including the slot for its result.
+
+
Userdata represent C values in Lua.
A light userdata represents a pointer, a void*.
It is a value (like a number):
you do not create it, it has no individual metatable,
and it is not collected (as it was never created).
A light userdata is equal to "any"
light userdata with the same C address.
-This macro is equivalent to lua_pushlstring,
-but can be used only when s is a literal string.
-It automatically provides the string length.
+This macro is equivalent to lua_pushstring,
+but should be used only when s is a literal string.
Pushes the string pointed to by s with size len
onto the stack.
Lua makes (or reuses) an internal copy of the given string,
so the memory at s can be freed or reused immediately after
the function returns.
The string can contain any binary data,
including embedded zeros.
Returns a pointer to the internal copy of the string.
Pushes the zero-terminated string pointed to by s
onto the stack.
Lua makes (or reuses) an internal copy of the given string,
so the memory at s can be freed or reused immediately after
the function returns.
Returns a pointer to the internal copy of the string.
int lua_rawequal (lua_State *L, int index1, int index2);
Returns 1 if the two values in indices index1 and
index2 are primitively equal
-(that is, without calling metamethods).
+(that is, without calling the __eq metamethod).
Otherwise returns 0.
Also returns 0 if any of the indices are not valid.
int lua_rawgeti (lua_State *L, int index, lua_Integer n);
Pushes onto the stack the value t[n],
where t 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 __index metamethod.
int lua_rawgetp (lua_State *L, int index, const void *p);
Pushes onto the stack the value t[k],
where t is the table at the given index and
k is the pointer p represented as a light userdata.
The access is raw;
-that is, it does not invoke metamethods.
+that is, it does not invoke the __index metamethod.
Returns the raw "length" of the value at the given index:
for strings, this is the string length;
for tables, this is the result of the length operator ('#')
with no metamethods;
for userdata, this is the size of the block of memory allocated
for the userdata;
for other values, it is 0.
void lua_rawseti (lua_State *L, int index, lua_Integer i);
Does the equivalent of t[i] = v,
where t is the table at the given index
and v is the value at the top of the stack.
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 __newindex metamethod.
void lua_rawsetp (lua_State *L, int index, const void *p);
-Does the equivalent of t[k] = v,
+Does the equivalent of t[p] = v,
where t is the table at the given index,
-k is the pointer p represented as a light userdata,
+p is encoded as a light userdata,
and v is the value at the top of the stack.
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 __newindex metamethod.
The reader function used by lua_load.
Every time it needs another piece of the chunk,
lua_load calls the reader,
passing along its data parameter.
The reader must return a pointer to a block of memory
with a new piece of the chunk
and set size to the block size.
The block must exist until the reader function is called again.
To signal the end of the chunk,
the reader must return NULL or set size to zero.
The reader function may return pieces of any size greater than zero.
Removes the element at the given valid index,
shifting down the elements above this index to fill the gap.
This function cannot be called with a pseudo-index,
because a pseudo-index is not an actual stack position.
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.
int lua_resume (lua_State *L, lua_State *from, int nargs);
-Starts and resumes a coroutine in a given thread.
+Starts and resumes a coroutine in the given thread L.
To start a coroutine,
you push onto the thread stack the main function plus any arguments;
then you call lua_resume,
with nargs being the number of arguments.
This call returns when the coroutine suspends or finishes its execution.
When it returns, the stack contains all values passed to lua_yield,
or all values returned by the body function.
lua_resume returns
LUA_YIELD if the coroutine yields,
LUA_OK if the coroutine finishes its execution
without errors,
or an error code in case of errors (see lua_pcall).
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.
To resume a coroutine,
you remove any results from the last lua_yield,
put on its stack only the values to
be passed as results from yield,
and then call lua_resume.
The parameter from represents the coroutine that is resuming L.
If there is no such coroutine,
this parameter can be NULL.
-Rotates the stack elements from idx to the top n positions
-in the direction of the top, for a positive n,
+Rotates the stack elements between the valid index idx
+and the top of the stack.
+The elements are rotated n positions in the direction of the top,
+for a positive n,
or -n positions in the direction of the bottom,
for a negative n.
The absolute value of n 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.
Does the equivalent to t[k] = v,
where t is the value at the given index,
v is the value at the top of the stack,
and k is the value just below the top.
This function pops both the key and the value from the stack.
As in Lua, this function may trigger a metamethod
for the "newindex" event (see §2.4).
Accepts any index, or 0,
and sets the stack top to this index.
If the new top is larger than the old one,
then the new elements are filled with nil.
If index is 0, then all stack elements are removed.
Pops a value from the stack and sets it as
-the new value associated to the userdata at the given index.
+the new value associated to the full userdata at the given index.
An opaque structure that points to a thread and indirectly
(through the thread) to the whole state of a Lua interpreter.
The Lua library is fully reentrant:
it has no global variables.
All information about a state is accessible through this structure.
A pointer to this structure must be passed as the first argument to
every function in the library, except to lua_newstate,
which creates a Lua state from scratch.
The status can be 0 (LUA_OK) for a normal thread,
an error code if the thread finished the execution
of a lua_resume with an error,
or LUA_YIELD if the thread is suspended.
You can only call functions in threads with status LUA_OK.
You can resume threads with status LUA_OK
(to start a new coroutine) or LUA_YIELD
(to resume a coroutine).
Converts the zero-terminated string s 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 §3.1).
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.)
Converts the Lua value at the given index to a C boolean
value (0 or 1).
Like all tests in Lua,
lua_toboolean returns true for any Lua value
different from false and nil;
otherwise it returns false.
(If you want to accept only actual boolean values,
use lua_isboolean to test the value's type.)
lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);
Converts the Lua value at the given index
to the signed integral type lua_Integer.
The Lua value must be an integer,
or a number or string convertible to an integer (see §3.4.3);
otherwise, lua_tointegerx returns 0.
If isnum is not NULL,
its referent is assigned a boolean value that
indicates whether the operation succeeded.
const char *lua_tolstring (lua_State *L, int index, size_t *len);
Converts the Lua value at the given index to a C string.
If len is not NULL,
-it also sets *len with the string length.
+it sets *len with the string length.
The Lua value must be a string or a number;
otherwise, the function returns NULL.
If the value is a number,
then lua_tolstring also
changes the actual value in the stack to a string.
(This change confuses lua_next
when lua_tolstring is applied to keys during a table traversal.)
-lua_tolstring returns a fully aligned pointer
+lua_tolstring returns a pointer
to a string inside the Lua state.
This string always has a zero ('\0')
after its last character (as in C),
but can contain other zeros in its body.
Because Lua has garbage collection,
there is no guarantee that the pointer returned by lua_tolstring
will be valid after the corresponding Lua value is removed from the stack.
lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);
Converts the Lua value at the given index
to the C type lua_Number (see lua_Number).
The Lua value must be a number or a string convertible to a number
(see §3.4.3);
otherwise, lua_tonumberx returns 0.
If isnum is not NULL,
its referent is assigned a boolean value that
indicates whether the operation succeeded.
const void *lua_topointer (lua_State *L, int index);
Converts the value at the given index to a generic
C pointer (void*).
The value can be a userdata, a table, a thread, or a function;
otherwise, lua_topointer returns NULL.
Different objects will give different pointers.
There is no way to convert the pointer back to its original value.
-Typically this function is used only for debug information.
+Typically this function is used only for hashing and debug information.
If the value at the given index is a full userdata,
returns its block address.
If the value is a light userdata,
returns its pointer.
Otherwise, returns NULL.
-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 lua_State,
returns the address of the version used to create that state.
When called with NULL,
returns the address of the version running the call.
The type of the writer function used by lua_dump.
Every time it produces another piece of chunk,
lua_dump calls the writer,
passing along the buffer to be written (p),
its size (sz),
and the data parameter supplied to lua_dump.
The writer returns an error code:
0 means no errors;
any other value means an error and stops lua_dump from
calling the writer again.
This function is equivalent to lua_yieldk,
but it has no continuation (see §4.7).
Therefore, when the thread resumes,
it continues the function that called
the function calling lua_yield.
int lua_yieldk (lua_State *L,
int nresults,
lua_KContext ctx,
lua_KFunction k);
Yields a coroutine (thread).
When a C function calls lua_yieldk,
the running coroutine suspends its execution,
and the call to lua_resume that started this coroutine returns.
The parameter nresults is the number of values from the stack
that will be passed as results to lua_resume.
When the coroutine is resumed again,
Lua calls the given continuation function k to continue
-the execution of the C function that yielded (see §4.7).
+the execution of the C function that yielded (see §4.7).
This continuation function receives the same stack
from the previous function,
with the n results removed and
replaced by the arguments passed to lua_resume.
Moreover,
the continuation function receives the value ctx
that was passed to lua_yieldk.
Usually, this function does not return;
when the coroutine eventually resumes,
it continues executing the continuation function.
However, there is one special case,
which is when this function is called
-from inside a line hook (see §4.9).
+from inside a line or a count hook (see §4.9).
In that case, lua_yieldk should be called with no continuation
-(probably in the form of lua_yield),
+(probably in the form of lua_yield) 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.
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).
Lua has no built-in debugging facilities.
Instead, it offers a special interface
by means of functions and hooks.
This interface allows the construction of different
kinds of debuggers, profilers, and other tools
that need "inside information" from the interpreter.
typedef struct lua_Debug {
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) */
const char *what; /* (S) */
const char *source; /* (S) */
int currentline; /* (l) */
int linedefined; /* (S) */
int lastlinedefined; /* (S) */
unsigned char nups; /* (u) number of upvalues */
unsigned char nparams; /* (u) number of parameters */
char isvararg; /* (u) */
char istailcall; /* (t) */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
other fields
} lua_Debug;
A structure used to carry different pieces of
information about a function or an activation record.
lua_getstack fills only the private part
of this structure, for later use.
To fill the other fields of lua_Debug with useful information,
call lua_getinfo.
The fields of lua_Debug have the following meaning:
source:
the name of the chunk that created the function.
If source starts with a '@',
it means that the function was defined in a file where
the file name follows the '@'.
If source starts with a '=',
the remainder of its contents describe the source in a user-dependent manner.
Otherwise,
the function was defined in a string where
source is that string.
short_src:
a "printable" version of source, to be used in error messages.
linedefined:
the line number where the definition of the function starts.
lastlinedefined:
the line number where the definition of the function ends.
what:
the string "Lua" if the function is a Lua function,
"C" if it is a C function,
"main" if it is the main part of a chunk.
currentline:
the current line where the given function is executing.
When no line information is available,
currentline is set to -1.
name:
a reasonable name for the given function.
Because functions in Lua are first-class values,
they do not have a fixed name:
some functions can be the value of multiple global variables,
while others can be stored only in a table field.
The lua_getinfo function checks how the function was
called to find a suitable name.
If it cannot find a name,
then name is set to NULL.
namewhat:
explains the name field.
The value of namewhat can be
"global", "local", "method",
"field", "upvalue", or "" (the empty string),
according to how the function was called.
(Lua uses the empty string when no other option seems to apply.)
istailcall:
true if this function invocation was called by a tail call.
In this case, the caller of this level is not in the stack.
nups:
the number of upvalues of the function.
nparams:
the number of fixed parameters of the function
(always 0 for C functions).
isvararg:
true if the function is a vararg function
(always true for C functions).
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
Gets information about a specific function or function invocation.
To get information about a function invocation,
the parameter ar must be a valid activation record that was
filled by a previous call to lua_getstack or
given as argument to a hook (see lua_Hook).
To get information about a function you push it onto the stack
and start the what string with the character '>'.
(In that case,
lua_getinfo pops the function from the top of the stack.)
For instance, to know in which line a function f was defined,
you can write the following code:
lua_Debug ar;
lua_getglobal(L, "f"); /* get global 'f' */
lua_getinfo(L, ">S", &ar);
printf("%d\n", ar.linedefined);
Each character in the string what
selects some fields of the structure ar to be filled or
a value to be pushed on the stack:
'n': fills in the field name and namewhat;
'S':
fills in the fields source, short_src,
linedefined, lastlinedefined, and what;
'l': fills in the field currentline;
't': fills in the field istailcall;
'u': fills in the fields
nups, nparams, and isvararg;
'f':
pushes onto the stack the function that is
running at the given level;
'L':
pushes onto the stack a table whose indices are the
numbers of the lines that are valid on the function.
(A valid line 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.)
If this option is given together with option 'f',
its table is pushed after the function.
This function returns 0 on error
(for instance, an invalid option in what).
const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
Gets information about a local variable of
a given activation record or a given function.
In the first case,
the parameter ar must be a valid activation record that was
filled by a previous call to lua_getstack or
given as argument to a hook (see lua_Hook).
The index n selects which local variable to inspect;
see debug.getlocal for details about variable indices
and names.
lua_getlocal pushes the variable's value onto the stack
and returns its name.
In the second case, ar must be NULL 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)
and no values are pushed onto the stack.
Returns NULL (and pushes nothing)
when the index is greater than
the number of active local variables.
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
Gets information about the interpreter runtime stack.
This function fills parts of a lua_Debug structure with
an identification of the activation record
of the function executing at a given level.
Level 0 is the current running function,
whereas level n+1 is the function that has called level n
(except for tail calls, which do not count on the stack).
When there are no errors, lua_getstack returns 1;
when called with a level greater than the stack depth,
it returns 0.
const char *lua_getupvalue (lua_State *L, int funcindex, int n);
-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.)
-lua_getupvalue gets the index n of an upvalue,
-pushes the upvalue's value onto the stack,
+Gets information about the n-th upvalue
+of the closure at index funcindex.
+It pushes the upvalue's value onto the stack
and returns its name.
-funcindex 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 NULL (and pushes nothing)
+when the index n is greater than the number of upvalues.
-Returns NULL (and pushes nothing)
-when the index is greater than the number of upvalues.
For C functions, this function uses the empty string ""
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.)
+
+Upvalues have no particular order,
+as they are active through the whole function.
+They are numbered in an arbitrary order.
+
+
Whenever a hook is called, its ar argument has its field
event set to the specific event that triggered the hook.
Lua identifies these events with the following constants:
LUA_HOOKCALL, LUA_HOOKRET,
LUA_HOOKTAILCALL, LUA_HOOKLINE,
and LUA_HOOKCOUNT.
Moreover, for line events, the field currentline is also set.
To get the value of any other field in ar,
the hook must call lua_getinfo.
For call events, event can be LUA_HOOKCALL,
the normal value, or LUA_HOOKTAILCALL, for a tail call;
in this case, there will be no corresponding return event.
While Lua is running a hook, it disables other calls to hooks.
Therefore, if a hook calls back Lua to execute a function or a chunk,
this execution occurs without any calls to hooks.
Hook functions cannot have continuations,
that is, they cannot call lua_yieldk,
lua_pcallk, or lua_callk with a non-null k.
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 lua_yield with nresults equal to zero.
+Only count and line events can yield;
+to yield, a hook function must finish its execution
+calling lua_yield with nresults equal to zero
+(that is, with no values).
void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
Sets the debugging hook function.
Argument f is the hook function.
mask 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
LUA_MASKCALL,
LUA_MASKRET,
LUA_MASKLINE,
and LUA_MASKCOUNT.
The count argument is only meaningful when the mask
includes LUA_MASKCOUNT.
For each event, the hook is called as explained below:
The call hook: is called when the interpreter calls a function.
The hook is called just after Lua enters the new function,
before the function gets its arguments.
The return hook: is called when the interpreter returns from a function.
The hook is called just before Lua leaves the function.
There is no standard way to access the values
to be returned by the function.
The line hook: is called when the interpreter is about to
start the execution of a new line of code,
or when it jumps back in the code (even to the same line).
(This event only happens while Lua is executing a Lua function.)
The count hook: is called after the interpreter executes every
count instructions.
(This event only happens while Lua is executing a Lua function.)
const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
Sets the value of a local variable of a given activation record.
-Parameters ar and n are as in lua_getlocal
-(see lua_getlocal).
-lua_setlocal 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.
Returns NULL (and pops nothing)
when the index is greater than
the number of active local variables.
+
+Parameters ar and n are as in function lua_getlocal.
+
+
const char *lua_setupvalue (lua_State *L, int funcindex, int n);
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 funcindex and n are as in the lua_getupvalue
-(see lua_getupvalue).
Returns NULL (and pops nothing)
-when the index is greater than the number of upvalues.
+when the index n is greater than the number of upvalues.
+
+Parameters funcindex and n are as in function lua_getupvalue.
+
+
void *lua_upvalueid (lua_State *L, int funcindex, int n);
Returns a unique identifier for the upvalue numbered n
from the closure at index funcindex.
-Parameters funcindex and n are as in the lua_getupvalue
-(see lua_getupvalue)
-(but n cannot be greater than the number of upvalues).
These unique identifiers allow a program to check whether different
closures share upvalues.
Lua closures that share an upvalue
(that is, that access a same external local variable)
will return identical ids for those upvalue indices.
+
+Parameters funcindex and n are as in function lua_getupvalue,
+but n cannot be greater than the number of upvalues.
+
+
The auxiliary library provides several convenient functions
to interface C with Lua.
While the basic API provides the primitive functions for all
interactions between C and Lua,
the auxiliary library provides higher-level functions for some
common tasks.
All functions and types from the auxiliary library
are defined in header file lauxlib.h and
have a prefix luaL_.
All functions in the auxiliary library are built on
top of the basic API,
and so they provide nothing that cannot be done with that API.
Nevertheless, the use of the auxiliary library ensures
more consistency to your code.
Several functions in the auxiliary library use internally some
extra stack slots.
When a function in the auxiliary library uses less than five slots,
it does not check the stack size;
it simply assumes that there are enough slots.
Several functions in the auxiliary library are used to
check C function arguments.
Because the error message is formatted for arguments
(e.g., "bad argument #1"),
you should not use these functions for other stack values.
Functions called luaL_check*
always raise an error if the check is not satisfied.
Adds the value at the top of the stack
to the buffer B
(see luaL_Buffer).
Pops the value.
This is the only function on string buffers that can (and must)
be called with an extra element on the stack,
which is the value to be added to the buffer.
int luaL_argerror (lua_State *L, int arg, const char *extramsg);
Raises an error reporting a problem with argument arg
-of the C function that called it,
+of the C function that called it,
using a standard message
that includes extramsg as a comment:
Then initialize it and preallocate a space of
size sz with a call luaL_buffinitsize(L, &b, sz).
Then copy the string into that space.
Finish by calling luaL_pushresultsize(&b, sz),
where sz is the total size of the resulting string
copied into that space.
During its normal operation,
a string buffer uses a variable number of stack slots.
So, while using a buffer, you cannot assume that you know where
the top of the stack is.
You can use the stack between successive calls to buffer operations
as long as that use is balanced;
that is,
when you call a buffer operation,
the stack is at the same level
it was immediately after the previous buffer operation.
(The only exception to this rule is luaL_addvalue.)
After calling luaL_pushresult the stack is back to its
level when the buffer was initialized,
plus the final string on its top.
int luaL_callmeta (lua_State *L, int obj, const char *e);
Calls a metamethod.
If the object at index obj has a metatable and this
metatable has a field e,
this function calls this field passing the object as its only argument.
In this case this function returns true and pushes onto the
stack the value returned by the call.
If there is no metatable or no metamethod,
this function returns false (without pushing any value on the stack).
int luaL_checkoption (lua_State *L,
int arg,
const char *def,
const char *const lst[]);
Checks whether the function argument arg is a string and
searches for this string in the array lst
(which must be NULL-terminated).
Returns the index in the array where the string was found.
Raises an error if the argument is not a string or
if the string cannot be found.
If def is not NULL,
the function uses def as a default value when
there is no argument arg or when this argument is nil.
This is a useful function for mapping strings to C enums.
(The usual convention in Lua libraries is
to use strings instead of numbers to select options.)
void luaL_checkstack (lua_State *L, int sz, const char *msg);
Grows the stack size to top + sz elements,
raising an error if the stack cannot grow to that size.
msg is an additional text to go into the error message
(or NULL for no additional text).
void *luaL_checkudata (lua_State *L, int arg, const char *tname);
Checks whether the function argument arg is a userdata
of the type tname (see luaL_newmetatable) and
returns the userdata address (see lua_touserdata).
Checks whether the core running the call,
the core that created the Lua state,
and the code making the call are all using the same version of Lua.
Also checks whether the core running the call
and the core that created the Lua state
are using the same address space.
int luaL_error (lua_State *L, const char *fmt, ...);
Raises an error.
The error message format is given by fmt
plus any extra arguments,
following the same rules of lua_pushfstring.
It also adds at the beginning of the message the file name and
the line number where the error occurred,
if this information is available.
This function never returns,
but it is an idiom to use it in C functions
as return luaL_error(args).
int luaL_getmetafield (lua_State *L, int obj, const char *e);
Pushes onto the stack the field e from the metatable
of the object at index obj and returns the type of pushed value.
If the object does not have a metatable,
or if the metatable does not have this field,
pushes nothing and returns LUA_TNIL.
int luaL_getmetatable (lua_State *L, const char *tname);
Pushes onto the stack the metatable associated with name tname
-in the registry (see luaL_newmetatable).
-If there is no metatable associated with tname,
-returns false and pushes nil.
+in the registry (see luaL_newmetatable)
+(nil if there is no metatable associated with that name).
+Returns the type of the pushed value.
int luaL_getsubtable (lua_State *L, int idx, const char *fname);
Ensures that the value t[fname],
where t is the value at index idx,
is a table,
and pushes that table onto the stack.
Returns true if it finds a previous table there
and false if it creates a new table.
Returns the "length" of the value at the given index
as a number;
it is equivalent to the '#' operator in Lua (see §3.4.7).
Raises an error if the result of the operation is not an integer.
(This case only can happen through metamethods.)
Loads a buffer as a Lua chunk.
This function uses lua_load to load the chunk in the
buffer pointed to by buff with size sz.
This function returns the same results as lua_load.
name is the chunk name,
used for debug information and error messages.
The string mode works as in function lua_load.
int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode);
Loads a file as a Lua chunk.
This function uses lua_load to load the chunk in the file
named filename.
If filename is NULL,
then it loads from the standard input.
The first line in the file is ignored if it starts with a #.
This function returns the same results as lua_load,
but it has an extra error code LUA_ERRFILE
-if it cannot open/read the file or the file has a wrong mode.
+for file-related errors
+(e.g., it cannot open or read the file).
As lua_load, this function only loads the chunk;
it does not run it.
Creates a new table with a size optimized
to store all entries in the array l
(but does not actually store them).
It is intended to be used in conjunction with luaL_setfuncs
(see luaL_newlib).
It is implemented as a macro.
The array l must be the actual array,
not a pointer to it.
int luaL_newmetatable (lua_State *L, const char *tname);
If the registry already has the key tname,
returns 0.
Otherwise,
creates a new table to be used as a metatable for userdata,
adds to this new table the pair __name = tname,
adds to the registry the pair [tname] = new table,
and returns 1.
(The entry __name is used by some error-reporting functions.)
In both cases pushes onto the stack the final value associated
with tname in the registry.
Creates a new Lua state.
It calls lua_newstate with an
allocator based on the standard C realloc function
and then sets a panic function (see §4.6) that prints
an error message to the standard error output in case of fatal
errors.
Returns the new state,
or NULL if there is a memory allocation error.
+In words, if the argument arg is nil or absent,
+the macro results in the default dflt.
+Otherwise, it results in the result of calling func
+with the state L and the argument index arg as
+parameters.
+Note that it evaluates the expression dflt only if needed.
+
+
+
+
+
lua_Integer luaL_optinteger (lua_State *L,
int arg,
lua_Integer d);
If the function argument arg is an integer
(or convertible to an integer),
returns this integer.
If this argument is absent or is nil,
returns d.
Otherwise, raises an error.
If the function argument arg is a string,
returns this string.
If this argument is absent or is nil,
returns d.
Otherwise, raises an error.
If l is not NULL,
fills the position *l with the result's length.
+If the result is NULL
+(only possible when returning d and d == NULL),
+its length is considered zero.
+
+This function uses lua_tolstring to get its result,
+so all conversions and caveats of that function apply here.
+
+
Returns an address to a space of size sz
where you can copy a string to be added to buffer B
(see luaL_Buffer).
After copying the string into this space you must call
luaL_addsize with the size of the string to actually add
it to the buffer.
Creates and returns a reference,
in the table at index t,
for the object at the top of the stack (and pops the object).
A reference is a unique integer key.
As long as you do not manually add integer keys into table t,
luaL_ref ensures the uniqueness of the key it returns.
You can retrieve an object referred by reference r
by calling lua_rawgeti(L, t, r).
Function luaL_unref frees a reference and its associated object.
If the object at the top of the stack is nil,
luaL_ref returns the constant LUA_REFNIL.
The constant LUA_NOREF is guaranteed to be different
from any reference returned by luaL_ref.
Type for arrays of functions to be registered by
luaL_setfuncs.
name is the function name and func is a pointer to
the function.
Any array of luaL_Reg must end with a sentinel entry
in which both name and func are NULL.
If modname is not already present in package.loaded,
calls function openf with string modname as an argument
and sets the call result in package.loaded[modname],
as if that function has been called through require.
If glb is true,
also stores the module into global modname.
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
Registers all functions in the array l
(see luaL_Reg) into the table on the top of the stack
(below optional upvalues, see next).
When nup is not zero,
all functions are created sharing nup upvalues,
which must be previously pushed on the stack
on top of the library table.
These values are popped from the stack after the registration.
The standard representation for file handles,
which is used by the standard I/O library.
A file handle is implemented as a full userdata,
with a metatable called LUA_FILEHANDLE
(where LUA_FILEHANDLE is a macro with the actual metatable's name).
The metatable is created by the I/O library
(see luaL_newmetatable).
This userdata must start with the structure luaL_Stream;
it can contain other data after this initial structure.
Field f points to the corresponding C stream
(or it can be NULL to indicate an incompletely created handle).
Field closef 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 true (in case of success)
or nil plus an error message (in case of error).
Once Lua calls this field,
-the field value is changed to NULL
+it changes the field value to NULL
to signal that the handle is closed.
const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
Converts any Lua value at the given index to a C string
in a reasonable format.
The resulting string is pushed onto the stack and also
returned by the function.
If len is not NULL,
the function also sets *len with the string length.
-If the value has a metatable with a "__tostring" field,
+If the value has a metatable with a __tostring field,
then luaL_tolstring calls the corresponding metamethod
with the value as argument,
and uses the result of the call as its result.
Creates and pushes a traceback of the stack L1.
If msg is not NULL it is appended
at the beginning of the traceback.
The level parameter tells at which level
to start the traceback.
Releases reference ref from the table at index t
(see luaL_ref).
The entry is removed from the table,
so that the referred object can be collected.
The reference ref is also freed to be used again.
Pushes onto the stack a string identifying the current position
of the control at level lvl in the call stack.
Typically this string has the following format:
chunkname:currentline:
Level 0 is the running function,
level 1 is the function that called the running function,
etc.
This function is used to build a prefix for error messages.
The standard Lua libraries provide useful functions
that are implemented directly through the C API.
Some of these functions provide essential services to the language
(e.g., type and getmetatable);
others provide access to "outside" services (e.g., I/O);
and others could be implemented in Lua itself,
but are quite useful or have critical performance requirements that
deserve an implementation in C (e.g., table.sort).
All libraries are implemented through the official C API
and are provided as separate C modules.
Currently, Lua has the following standard libraries:
Except for the basic and the package libraries,
each library provides all its functions as fields of a global table
or as methods of its objects.
To have access to these libraries,
the C host program should call the luaL_openlibs function,
which opens all standard libraries.
Alternatively,
the host program can open them individually by using
luaL_requiref to call
luaopen_base (for the basic library),
luaopen_package (for the package library),
luaopen_coroutine (for the coroutine library),
luaopen_string (for the string library),
luaopen_utf8 (for the UTF8 library),
luaopen_table (for the table library),
luaopen_math (for the mathematical library),
luaopen_io (for the I/O library),
luaopen_os (for the operating system library),
and luaopen_debug (for the debug library).
These functions are declared in lualib.h.
The basic library provides core functions to Lua.
If you do not include this library in your application,
you should check carefully whether you need to provide
implementations for some of its facilities.
Calls error if
the value of its argument v is false (i.e., nil or false);
otherwise, returns all its arguments.
In case of error,
message is the error object;
when absent, it defaults to "assertion failed!"
This function is a generic interface to the garbage collector.
It performs different functions according to its first argument, opt:
"collect":
performs a full garbage-collection cycle.
This is the default option.
"stop":
stops automatic execution of the garbage collector.
The collector will run only when explicitly invoked,
until a call to restart it.
"restart":
restarts automatic execution of the garbage collector.
"count":
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).
"step":
performs a garbage-collection step.
The step "size" is controlled by arg.
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 true if the step finished a collection cycle.
"setpause":
sets arg as the new value for the pause of
the collector (see §2.5).
Returns the previous value for pause.
"setstepmul":
sets arg as the new value for the step multiplier of
the collector (see §2.5).
Returns the previous value for step.
"isrunning":
returns a boolean that tells whether the collector is running
(i.e., not stopped).
Opens the named file and executes its contents as a Lua chunk.
When called without arguments,
dofile executes the contents of the standard input (stdin).
Returns all values returned by the chunk.
In case of errors, dofile propagates the error
to its caller (that is, dofile does not run in protected mode).
Terminates the last protected function called
and returns message as the error object.
Function error never returns.
Usually, error adds some information about the error position
at the beginning of the message, if the message is a string.
The level argument specifies how to get the error position.
With level 1 (the default), the error position is where the
error function was called.
Level 2 points the error to where the function
that called error was called; and so on.
Passing a level 0 avoids the addition of error position information
to the message.
A global variable (not a function) that
holds the global environment (see §2.2).
Lua itself does not use this variable;
changing its value does not affect any environment,
nor vice versa.
If object does not have a metatable, returns nil.
Otherwise,
-if the object's metatable has a "__metatable" field,
+if the object's metatable has a __metatable field,
returns the associated value.
Otherwise, returns the metatable of the given object.
If chunk is a string, the chunk is this string.
If chunk is a function,
load calls it repeatedly to get the chunk pieces.
Each call to chunk must return a string that concatenates
with previous results.
A return of an empty string, nil, or no value signals the end of the chunk.
If there are no syntactic errors,
returns the compiled chunk as a function;
otherwise, returns nil plus the error message.
If the resulting function has upvalues,
the first upvalue is set to the value of env,
if that parameter is given,
or to the value of the global environment.
Other upvalues are initialized with nil.
(When you load a main chunk,
the resulting function will always have exactly one upvalue,
the _ENV variable (see §2.2).
However,
when you load a binary chunk created from a function (see string.dump),
the resulting function can have an arbitrary number of upvalues.)
All upvalues are fresh, that is,
they are not shared with any other function.
chunkname is used as the name of the chunk for error messages
and debug information (see §4.9).
When absent,
it defaults to chunk, if chunk is a string,
or to "=(load)" otherwise.
The string mode controls whether the chunk can be text or binary
(that is, a precompiled chunk).
It may be the string "b" (only binary chunks),
"t" (only text chunks),
or "bt" (both binary and text).
The default is "bt".
Lua does not check the consistency of binary chunks.
Maliciously crafted binary chunks can crash
the interpreter.
Allows a program to traverse all fields of a table.
Its first argument is a table and its second argument
is an index in this table.
next returns the next index of the table
and its associated value.
When called with nil as its second argument,
next returns an initial index
and its associated value.
When called with the last index,
or with nil in an empty table,
next returns nil.
If the second argument is absent, then it is interpreted as nil.
In particular,
you can use next(t) to check whether a table is empty.
The order in which the indices are enumerated is not specified,
even for numeric indices.
-(To traverse a table in numeric order,
+(To traverse a table in numerical order,
use a numerical for.)
The behavior of next is undefined if,
during the traversal,
you assign any value to a non-existent field in the table.
You may however modify existing fields.
In particular, you may clear existing fields.
Calls function f with
the given arguments in protected mode.
This means that any error inside f is not propagated;
instead, pcall catches the error
and returns a status code.
Its first result is the status code (a boolean),
which is true if the call succeeds without errors.
In such case, pcall also returns all results from the call,
after this first result.
In case of any error, pcall returns false plus the error message.
Receives any number of arguments
and prints their values to stdout,
using the tostring function to convert each argument to a string.
print is not intended for formatted output,
but only as a quick way to show a value,
for instance for debugging.
For complete control over the output,
use string.format and io.write.
Gets the real value of table[index],
-without invoking any metamethod.
+without invoking the __index metamethod.
table must be a table;
index may be any value.
Returns the length of the object v,
which must be a table or a string,
-without invoking any metamethod.
+without invoking the __len metamethod.
Returns an integer.
Sets the real value of table[index] to value,
-without invoking any metamethod.
+without invoking the __newindex metamethod.
table must be a table,
index any value different from nil and NaN,
and value any Lua value.
If index is a number,
returns all arguments after argument number index;
a negative number indexes from the end (-1 is the last argument).
Otherwise, index must be the string "#",
and select returns the total number of extra arguments it received.
Sets the metatable for the given table.
-(You cannot change the metatable of other types from Lua, only from C.)
+(To change the metatable of other types from Lua code,
+you must use the debug library (§6.10).)
If metatable is nil,
removes the metatable of the given table.
-If the original metatable has a "__metatable" field,
+If the original metatable has a __metatable field,
raises an error.
When called with no base,
tonumber tries to convert its argument to a number.
If the argument is already a number or
a string convertible to a number,
then tonumber returns this number;
otherwise, it returns nil.
The conversion of strings can result in integers or floats,
according to the lexical conventions of Lua (see §3.1).
(The string may have leading and trailing spaces and a sign.)
When called with base,
then e 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 10, the letter 'A' (in either upper or lower case)
represents 10, 'B' represents 11, and so forth,
with 'Z' representing 35.
If the string e is not a valid numeral in the given base,
the function returns nil.
Receives a value of any type and
converts it to a string in a human-readable format.
-Floats always produce strings with some
-floating-point indication (either a decimal dot or an exponent).
(For complete control of how numbers are converted,
use string.format.)
-If the metatable of v has a "__tostring" field,
+If the metatable of v has a __tostring field,
then tostring calls the corresponding value
with v as argument,
and uses the result of the call as its result.
Returns the type of its only argument, coded as a string.
The possible results of this function are
"nil" (a string, not the value nil),
"number",
"string",
"boolean",
"table",
"function",
"thread",
and "userdata".
A global variable (not a function) that
-holds a string containing the current interpreter version.
+holds a string containing the running Lua version.
The current value of this variable is "Lua 5.3".
-The operations related to coroutines comprise a sub-library of
-the basic library and come inside the table coroutine.
+This library comprises the operations to manipulate coroutines,
+which come inside the table coroutine.
See §2.6 for a general description of coroutines.
Returns true when the running coroutine can yield.
A running coroutine is yieldable if it is not the main thread and
-it is not inside a non-yieldable C function.
+it is not inside a non-yieldable C function.
Starts or continues the execution of coroutine co.
The first time you resume a coroutine,
it starts running its body.
The values val1, ... are passed
as the arguments to the body function.
If the coroutine has yielded,
resume restarts it;
the values val1, ... are passed
as the results from the yield.
If the coroutine runs without any errors,
resume returns true plus any values passed to yield
(when the coroutine yields) or any values returned by the body function
(when the coroutine terminates).
If there is any error,
resume returns false plus the error message.
Returns the status of coroutine co, as a string:
"running",
if the coroutine is running (that is, it called status);
"suspended", if the coroutine is suspended in a call to yield,
or if it has not started running yet;
"normal" if the coroutine is active but not running
(that is, it has resumed another coroutine);
and "dead" if the coroutine has finished its body function,
or if it has stopped with an error.
Creates a new coroutine, with body f.
-f must be a Lua function.
+f 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 resume.
Returns the same values returned by resume,
except the first boolean.
In case of error, propagates the error.
The package library provides basic
facilities for loading modules in Lua.
It exports one function directly in the global environment:
require.
Everything else is exported in a table package.
Loads the given module.
The function starts by looking into the package.loaded table
to determine whether modname is already loaded.
If it is, then require returns the value stored
at package.loaded[modname].
Otherwise, it tries to find a loader for the module.
To find a loader,
require is guided by the package.searchers sequence.
By changing this sequence,
we can change how require looks for a module.
The following explanation is based on the default configuration
for package.searchers.
First require queries package.preload[modname].
If it has a value,
this value (which must be a function) is the loader.
Otherwise require searches for a Lua loader using the
path stored in package.path.
If that also fails, it searches for a C loader using the
path stored in package.cpath.
If that also fails,
it tries an all-in-one loader (see package.searchers).
Once a loader is found,
require calls the loader with two arguments:
modname and an extra value dependent on how it got the loader.
(If the loader came from a file,
this extra value is the file name.)
If the loader returns any non-nil value,
require assigns the returned value to package.loaded[modname].
If the loader does not return a non-nil value and
has not assigned any value to package.loaded[modname],
then require assigns true to this entry.
In any case, require returns the
final value of package.loaded[modname].
If there is any error loading or running the module,
or if it cannot find any loader for the module,
then require raises an error.
The path used by require to search for a C loader.
Lua initializes the C path package.cpath in the same way
it initializes the Lua path package.path,
-using the environment variable LUA_CPATH_5_3
-or the environment variable LUA_CPATH
+using the environment variable LUA_CPATH_5_3,
+or the environment variable LUA_CPATH,
or a default path defined in luaconf.h.
A table used by require to control which
modules are already loaded.
When you require a module modname and
package.loaded[modname] is not false,
require simply returns the value stored there.
This variable is only a reference to the real table;
assignments to this variable do not change the
table used by require.
Dynamically links the host program with the C library libname.
If funcname is "*",
then it only links with the library,
making the symbols exported by the library
available to other dynamically linked libraries.
Otherwise,
it looks for a function funcname inside the library
and returns this function as a C function.
So, funcname must follow the lua_CFunction prototype
(see lua_CFunction).
This is a low-level function.
It completely bypasses the package and module system.
Unlike require,
it does not perform any path searching and
does not automatically adds extensions.
libname must be the complete file name of the C library,
including if necessary a path and an extension.
funcname must be the exact name exported by the C library
(which may depend on the C compiler and linker used).
This function is not supported by Standard C.
As such, it is only available on some platforms
(Windows, Linux, Mac OS X, Solaris, BSD,
plus other Unix systems that support the dlfcn standard).
The path used by require to search for a Lua loader.
At start-up, Lua initializes this variable with
the value of the environment variable LUA_PATH_5_3 or
the environment variable LUA_PATH or
with a default path defined in luaconf.h,
if those environment variables are not defined.
Any ";;" in the value of the environment variable
is replaced by the default path.
A table used by require to control how to load modules.
Each entry in this table is a searcher function.
When looking for a module,
require calls each of these searchers in ascending order,
with the module name (the argument given to require) as its
sole parameter.
The function can return another function (the module loader)
plus an extra value that will be passed to that loader,
or a string explaining why it did not find that module
(or nil if it has nothing to say).
Lua initializes this table with four searcher functions.
The first searcher simply looks for a loader in the
package.preload table.
The second searcher looks for a loader as a Lua library,
using the path stored at package.path.
The search is done as described in function package.searchpath.
The third searcher looks for a loader as a C library,
using the path given by the variable package.cpath.
Again,
the search is done as described in function package.searchpath.
For instance,
if the C path is the string
"./?.so;./?.dll;/usr/local/?/init.so"
the searcher for module foo
will try to open the files ./foo.so, ./foo.dll,
and /usr/local/foo/init.so, in that order.
Once it finds a C library,
this searcher first uses a dynamic link facility to link the
application with the library.
Then it tries to find a C function inside the library to
be used as the loader.
The name of this C function is the string "luaopen_"
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 suffix after (and including) the first hyphen is removed.
For instance, if the module name is a.b.c-v2.1,
the function name will be luaopen_a_b_c.
The fourth searcher tries an all-in-one loader.
It searches the C path for a library for
the root name of the given module.
For instance, when requiring a.b.c,
it will search for a C library for a.
If found, it looks into it for an open function for
the submodule;
in our example, that would be luaopen_a_b_c.
With this facility, a package can pack several C submodules
into one single library,
with each submodule keeping its original open function.
All searchers except the first one (preload) return as the extra value
the file name where the module was found,
as returned by package.searchpath.
The first searcher returns no extra value.
A path is a string containing a sequence of
templates separated by semicolons.
For each template,
the function replaces each interrogation mark (if any)
in the template with a copy of name
wherein all occurrences of sep
(a dot, by default)
were replaced by rep
(the system's directory separator, by default),
and then tries to open the resulting file name.
For instance, if the path is the string
"./?.lua;./?.lc;/usr/local/?/init.lua"
the search for the name foo.a
will try to open the files
./foo/a.lua, ./foo/a.lc, and
/usr/local/foo/a/init.lua, in that order.
Returns the resulting name of the first file that it can
open in read mode (after closing the file),
or nil plus an error message if none succeeds.
(This error message lists all file names it tried to open.)
This library provides generic functions for string manipulation,
such as finding and extracting substrings, and pattern matching.
When indexing a string in Lua, the first character is at position 1
(not at 0, as in C).
Indices are allowed to be negative and are interpreted as indexing backwards,
from the end of the string.
Thus, the last character is at position -1, and so on.
The string library provides all its functions inside the table
string.
It also sets a metatable for strings
where the __index field points to the string table.
Therefore, you can use the string functions in object-oriented style.
For instance, string.byte(s,i)
can be written as s:byte(i).
The string library assumes one-byte character encodings.
-Returns the internal numerical codes of the characters s[i],
+Returns the internal numeric codes of the characters s[i],
s[i+1], ..., s[j].
The default value for i is 1;
the default value for j is i.
These indices are corrected
following the same rules of function string.sub.
-Numerical codes are not necessarily portable across platforms.
+Numeric codes are not necessarily portable across platforms.
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.
-Numerical codes are not necessarily portable across platforms.
+Numeric codes are not necessarily portable across platforms.
Returns a string containing a binary representation
(a binary chunk)
of the given function,
so that a later load on this string returns
a copy of the function (but with new upvalues).
If strip is a true value,
-the binary representation is created without debug information
-about the function
-(local variable names, lines, etc.).
+the binary representation may not include all debug information
+about the function,
+to save space.
Functions with upvalues have only their number of upvalues saved.
When (re)loaded,
those upvalues receive fresh instances containing nil.
(You can use the debug library to serialize
and reload the upvalues of a function
in a way adequate to your needs.)
Looks for the first match of
pattern (see §6.4.1) in the string s.
If it finds a match, then find returns the indices of s
where this occurrence starts and ends;
otherwise, it returns nil.
-A third, optional numerical argument init specifies
+A third, optional numeric argument init specifies
where to start the search;
its default value is 1 and can be negative.
A value of true as a fourth, optional argument plain
turns off the pattern matching facilities,
so the function does a plain "find substring" operation,
with no characters in pattern being considered magic.
Note that if plain is given, then init must be given as well.
If the pattern has captures,
then in a successful match
the captured values are also returned,
after the two indices.
Returns a formatted version of its variable number of arguments
following the description given in its first argument (which must be a string).
The format string follows the same rules as the ISO C function sprintf.
The only differences are that the options/modifiers
*, h, L, l, n,
and p are not supported
and that there is an extra option, q.
+
+
+
The q 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.
For instance, the call
string.format('%q', 'a string with "quotes" and \n new line')
may produce the string:
"a string with \"quotes\" and \
new line"
Options
-A and a (when available),
-E, e, f,
+A, a, E, e, f,
G, and g all expect a number as argument.
Options c, d,
i, o, u, X, and x
expect an integer.
-Option q expects a string;
-option s expects a string without embedded zeros.
-If the argument to option s is not a string,
+When Lua is compiled with a C89 compiler,
+options A and a (hexadecimal floats)
+do not support any modifier (flags, width, length).
+
+
+
+Option s expects a string;
+if its argument is not a string,
it is converted to one following the same rules of tostring.
+If the option has any modifier (flags, width, length),
+the string argument should not contain embedded zeros.
Returns an iterator function that,
each time it is called,
returns the next captures from pattern (see §6.4.1)
over the string s.
If pattern specifies no captures,
then the whole match is produced in each call.
As an example, the following loop
will iterate over all the words from string s,
printing one per line:
s = "hello world from Lua"
for w in string.gmatch(s, "%a+") do
print(w)
end
The next example collects all pairs key=value from the
given string into a table:
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
For this function, a caret '^' at the start of a pattern does not
work as an anchor, as this would prevent the iteration.
Returns a copy of s
in which all (or the first n, if given)
occurrences of the pattern (see §6.4.1) have been
replaced by a replacement string specified by repl,
which can be a string, a table, or a function.
gsub also returns, as its second value,
the total number of matches that occurred.
The name gsub comes from Global SUBstitution.
If repl is a string, then its value is used for replacement.
The character % works as an escape character:
any sequence in repl of the form %d,
with d between 1 and 9,
stands for the value of the d-th captured substring.
The sequence %0 stands for the whole match.
The sequence %% stands for a single %.
If repl is a table, then the table is queried for every match,
using the first capture as the key.
If repl is a function, then this function is called every time a
match occurs, with all captured substrings passed as arguments,
in order.
In any case,
if the pattern specifies no captures,
then it behaves as if the whole pattern was inside a capture.
If the value returned by the table query or by the function call
is a string or a number,
then it is used as the replacement string;
otherwise, if it is false or nil,
then there is no replacement
(that is, the original match is kept in the string).
Here are some examples:
x = string.gsub("hello world", "(%w+)", "%1 %1")
--> x="hello hello world world"
x = string.gsub("hello world", "%w+", "%0 %0", 1)
--> x="hello hello world"
x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
--> x="world hello Lua from"
x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
--> x="home = /home/roberto, user = roberto"
x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
return load(s)()
end)
--> x="4+5 = 9"
local t = {name="lua", version="5.3"}
x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
--> x="lua-5.3.tar.gz"
Receives a string and returns a copy of this string with all
uppercase letters changed to lowercase.
All other characters are left unchanged.
The definition of what an uppercase letter is depends on the current locale.
Looks for the first match of
pattern (see §6.4.1) in the string s.
If it finds one, then match returns
the captures from the pattern;
otherwise it returns nil.
If pattern specifies no captures,
then the whole match is returned.
-A third, optional numerical argument init specifies
+A third, optional numeric argument init specifies
where to start the search;
its default value is 1 and can be negative.
Returns a binary string containing the values v1, v2, etc.
packed (that is, serialized in binary form)
-according to the format string fmt (see §6.4.2).
+according to the format string fmt (see §6.4.2).
Returns the size of a string resulting from string.pack
with the given format.
The format string cannot have the variable-length options
's' or 'z' (see §6.4.2).
Returns a string that is the concatenation of n copies of
the string s separated by the string sep.
The default value for sep is the empty string
(that is, no separator).
Returns the empty string if n is not positive.
+
+(Note that it is very easy to exhaust the memory of your machine
+with a single call to this function.)
+
+
Returns the substring of s that
starts at i and continues until j;
i and j can be negative.
If j is absent, then it is assumed to be equal to -1
(which is the same as the string length).
In particular,
the call string.sub(s,1,j) returns a prefix of s
with length j,
-and string.sub(s, -i) returns a suffix of s
+and string.sub(s, -i) (for a positive i)
+returns a suffix of s
with length i.
If, after the translation of negative indices,
i is less than 1,
it is corrected to 1.
If j is greater than the string length,
it is corrected to that length.
If, after these corrections,
i is greater than j,
the function returns the empty string.
Returns the values packed in string s (see string.pack)
according to the format string fmt (see §6.4.2).
An optional pos marks where
to start reading in s (default is 1).
After the read values,
this function also returns the index of the first unread byte in s.
Receives a string and returns a copy of this string with all
lowercase letters changed to uppercase.
All other characters are left unchanged.
The definition of what a lowercase letter is depends on the current locale.
Patterns in Lua are described by regular strings,
which are interpreted as patterns by the pattern-matching functions
string.find,
string.gmatch,
string.gsub,
and string.match.
This section describes the syntax and the meaning
(that is, what they match) of these strings.
Character Class:
A character class is used to represent a set of characters.
The following combinations are allowed in describing a character class:
x:
(where x is not one of the magic characters^$()%.[]*+-?)
represents the character x itself.
.: (a dot) represents all characters.
%a: represents all letters.
%c: represents all control characters.
%d: represents all digits.
%g: represents all printable characters except space.
%l: represents all lowercase letters.
%p: represents all punctuation characters.
%s: represents all space characters.
%u: represents all uppercase letters.
%w: represents all alphanumeric characters.
%x: represents all hexadecimal digits.
%x: (where x is any non-alphanumeric character)
represents the character x.
This is the standard way to escape the magic characters.
Any non-alphanumeric character
-(including all punctuations, even the non-magical)
+(including all punctuation characters, even the non-magical)
can be preceded by a '%'
when used to represent itself in a pattern.
[set]:
represents the class which is the union of all
characters in set.
A range of characters can be specified by
separating the end characters of the range,
in ascending order, with a '-'.
All classes %x described above can also be used as
components in set.
All other characters in set represent themselves.
For example, [%w_] (or [_%w])
represents all alphanumeric characters plus the underscore,
[0-7] represents the octal digits,
and [0-7%l%-] represents the octal digits plus
the lowercase letters plus the '-' character.
+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.)
+
+
+
The interaction between ranges and classes is not defined.
Therefore, patterns like [%a-z] or [a-%%]
have no meaning.
[^set]:
represents the complement of set,
where set is interpreted as above.
For all classes represented by single letters (%a, %c, etc.),
the corresponding uppercase letter represents the complement of the class.
For instance, %S represents all non-space characters.
The definitions of letter, space, and other character groups
depend on the current locale.
In particular, the class [a-z] may not be equivalent to %l.
Pattern Item:
A pattern item can be
a single character class,
which matches any single character in the class;
a single character class followed by '*',
which matches zero or more repetitions of characters in the class.
These repetition items will always match the longest possible sequence;
a single character class followed by '+',
which matches one or more repetitions of characters in the class.
These repetition items will always match the longest possible sequence;
a single character class followed by '-',
which also matches zero or more repetitions of characters in the class.
Unlike '*',
these repetition items will always match the shortest possible sequence;
a single character class followed by '?',
which matches zero or one occurrence of a character in the class.
It always matches one occurrence if possible;
%n, for n between 1 and 9;
such item matches a substring equal to the n-th captured string
(see below);
%bxy, where x and y are two distinct characters;
such item matches strings that start with x, end with y,
and where the x and y are balanced.
This means that, if one reads the string from left to right,
counting +1 for an x and -1 for a y,
the ending y is the first y where the count reaches 0.
For instance, the item %b() matches expressions with
balanced parentheses.
%f[set], a frontier pattern;
such item matches an empty string at any position such that
the next character belongs to set
and the previous character does not belong to set.
The set set is interpreted as previously described.
The beginning and the end of the subject are handled as if
they were the character '\0'.
Pattern:
A pattern is a sequence of pattern items.
A caret '^' at the beginning of a pattern anchors the match at the
beginning of the subject string.
A '$' at the end of a pattern anchors the match at the
end of the subject string.
At other positions,
'^' and '$' have no special meaning and represent themselves.
Captures:
A pattern can contain sub-patterns enclosed in parentheses;
they describe captures.
When a match succeeds, the substrings of the subject string
that match captures are stored (captured) for future use.
Captures are numbered according to their left parentheses.
For instance, in the pattern "(a*(.)%w(%s*))",
the part of the string matching "a*(.)%w(%s*)" is
stored as the first capture (and therefore has number 1);
the character matching "." is captured with number 2,
and the part matching "%s*" has number 3.
As a special case, the empty capture () captures
the current string position (a number).
For instance, if we apply the pattern "()aa()" on the
string "flaaap", there will be two captures: 3 and 5.
The first argument to string.pack,
string.packsize, and string.unpack
is a format string,
which describes the layout of the structure being created or read.
A format string is a sequence of conversion options.
The conversion options are as follows:
<: sets little endian
>: sets big endian
=: sets native endian
![n]: sets maximum alignment to n
(default is native alignment)
b: a signed byte (char)
B: an unsigned byte (char)
h: a signed short (native size)
H: an unsigned short (native size)
l: a signed long (native size)
L: an unsigned long (native size)
j: a lua_Integer
J: a lua_Unsigned
T: a size_t (native size)
i[n]: a signed int with n bytes
(default is native size)
I[n]: an unsigned int with n bytes
(default is native size)
f: a float (native size)
d: a double (native size)
n: a lua_Number
cn: a fixed-sized string with n bytes
z: a zero-terminated string
s[n]: a string preceded by its length
coded as an unsigned integer with n bytes
(default is a size_t)
x: one byte of padding
Xop: an empty item that aligns
according to option op
(which is otherwise ignored)
'': (empty space) ignored
(A "[n]" means an optional integral numeral.)
Except for padding, spaces, and configurations
(options "xX <=>!"),
each option corresponds to an argument (in string.pack)
or a result (in string.unpack).
For options "!n", "sn", "in", and "In",
n can be any integer between 1 and 16.
All integral options check overflows;
string.pack checks whether the given value fits in the given size;
string.unpack checks whether the read value fits in a Lua integer.
Any format string starts as if prefixed by "!1=",
that is,
with maximum alignment of 1 (no alignment)
and native endianness.
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 "c" and "z" are not aligned;
option "s" follows the alignment of its starting integer.
This library provides basic support for UTF-8 encoding.
It provides all its functions inside the table utf8.
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.
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.
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.
The pattern (a string, not a function) "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
(see §6.4.1),
which matches exactly one UTF-8 byte sequence,
assuming that the subject is a valid UTF-8 string.
will iterate over all characters in string s,
with p being the position (in bytes) and c the code point
of each character.
It raises an error if it meets any invalid byte sequence.
Returns the codepoints (as integers) from all characters in s
that start between byte position i and j (both included).
The default for i is 1 and for j is i.
It raises an error if it meets any invalid byte sequence.
Returns the number of UTF-8 characters in string s
that start between positions i and j (both inclusive).
The default for i is 1 and for j is -1.
If it finds any invalid byte sequence,
-returns a false value plus the position of the first invalid byte.
+returns a false value plus the position of the first invalid byte.
Returns the position (in bytes) where the encoding of the
n-th character of s
(counting from position i) starts.
A negative n gets characters before position i.
The default for i is 1 when n is non-negative
and #s + 1 otherwise,
so that utf8.offset(s, -n) gets the offset of the
n-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 nil.
As a special case,
when n is 0 the function returns the start of the encoding
of the character that contains the i-th byte of s.
This function assumes that s is a valid UTF-8 string.
This library provides generic functions for table manipulation.
It provides all its functions inside the table table.
Remember that, whenever an operation needs the length of a table,
-the table must be a proper sequence
-or have a __len metamethod (see §3.4.7).
+all caveats about the length operator apply (see §3.4.7).
All functions ignore non-numeric keys
in the tables given as arguments.
Given a list where all elements are strings or numbers,
returns the string list[i]..sep..list[i+1] ··· sep..list[j].
The default value for sep is the empty string,
the default for i is 1,
and the default for j is #list.
If i is greater than j, returns the empty string.
Inserts element value at position pos in list,
shifting up the elements
list[pos], list[pos+1], ···, list[#list].
The default value for pos is #list+1,
so that a call table.insert(t,x) inserts x at the end
of list t.
-Moves elements from table a1 to table a2.
-This function performs the equivalent to the following
+Moves elements from table a1 to table a2,
+performing the equivalent to the following
multiple assignment:
a2[t],··· = a1[f],···,a1[e].
The default for a2 is a1.
The destination range can overlap with the source range.
-Index f must be positive.
+The number of elements to be moved must fit in a Lua integer.
+
Returns a new table with all parameters stored into keys 1, 2, etc.
and with a field "n" with the total number of parameters.
Note that the resulting table may not be a sequence.
Removes from list the element at position pos,
returning the value of the removed element.
When pos is an integer between 1 and #list,
it shifts down the elements
list[pos+1], list[pos+2], ···, list[#list]
and erases element list[#list];
The index pos can also be 0 when #list is 0,
or #list + 1;
in those cases, the function erases the element list[pos].
The default value for pos is #list,
so that a call table.remove(l) removes the last element
of list l.
Sorts list elements in a given order, in-place,
from list[1] to list[#list].
If comp 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 not comp(list[i+1],list[i]) will be true after the sort).
+(so that, after the sort,
+i < j implies not comp(list[j],list[i])).
If comp is not given,
then the standard Lua operator < is used instead.
-The sort algorithm is not stable;
-that is, elements considered equal by the given order
+Note that the comp 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.
+
+
+
+The sort algorithm is not stable:
+elements considered equal by the given order
may have their relative positions changed by the sort.
This library provides basic mathematical functions.
It provides all its functions and constants inside the table math.
Functions with the annotation "integer/float" give
integer results for integer arguments
and float results for float (or mixed) arguments.
Rounding functions
(math.ceil, math.floor, and math.modf)
return an integer when the result fits in the range of an integer,
or a float otherwise.
Returns the arc tangent of y/x (in radians),
but uses the signs of both parameters to find the
quadrant of the result.
(It also handles correctly the case of x being zero.)
The default value for x is 1,
so that the call math.atan(y)
returns the arc tangent of y.
When called without arguments,
returns a pseudo-random float with uniform distribution
in the range [0,1).
When called with two integers m and n,
math.random returns a pseudo-random integer
with uniform distribution in the range [m, n].
-(The value m-n cannot be negative and must fit in a Lua integer.)
+(The value n-m cannot be negative and must fit in a Lua integer.)
The call math.random(n) is equivalent to math.random(1,n).
This function is an interface to the underling
pseudo-random generator function provided by C.
-No guarantees can be given for its statistical properties.
Returns a boolean,
-true if integer m is below integer n when
+true if and only if integer m is below integer n when
they are compared as unsigned integers.
The I/O library provides two different styles for file manipulation.
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 handles.
When using implicit file handles,
all operations are supplied by table io.
When using explicit file handles,
the operation io.open returns a file handle
and then all operations are supplied as methods of the file handle.
The table io also provides
three predefined file handles with their usual meanings from C:
io.stdin, io.stdout, and io.stderr.
The I/O library never closes these files.
Unless otherwise stated,
all I/O functions return nil 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 nil on success.
On non-POSIX systems,
the computation of the error message and error code
in case of errors
may be not thread safe,
because they rely on the global C variable errno.
When called with a file name, it opens the named file (in text mode),
and sets its handle as the default input file.
When called with a file handle,
it simply sets this file handle as the default input file.
When called without parameters,
it returns the current default input file.
In case of errors this function raises the error,
instead of returning an error code.
Opens the given file name in read mode
and returns an iterator function that
works like file:lines(···) over the opened file.
When the iterator function detects the end of file,
it returns no values (to finish the loop) and automatically closes the file.
The call io.lines() (with no file name) is equivalent
to io.input():lines("*l");
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.
In case of errors this function raises the error,
instead of returning an error code.
This function opens a file,
in the mode specified in the string mode.
-It returns a new file handle,
-or, in case of errors, nil plus an error message.
+In case of success,
+it returns a new file handle.
The mode string can be any of the following:
"r": read mode (the default);
"w": write mode;
"a": append mode;
"r+": update mode, all previous data is preserved;
"w+": update mode, all previous data is erased;
"a+": append update mode, previous data is preserved,
writing is only allowed at the end of file.
The mode string can also have a 'b' at the end,
which is needed in some systems to open the file in binary mode.
This function is system dependent and is not available
on all platforms.
Starts program prog in a separated process and returns
a file handle that you can use to read data from this program
(if mode is "r", the default)
or to write data to this program
(if mode is "w").
-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.
Checks whether obj is a valid file handle.
Returns the string "file" if obj is an open file handle,
"closed file" if obj is a closed file handle,
or nil if obj is not a file handle.
Closes file.
Note that files are automatically closed when
their handles are garbage collected,
but that takes an unpredictable amount of time to happen.
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.
As an example, the construction
for c in file:lines(1) do body end
will iterate over all characters of the file,
starting at the current position.
Unlike io.lines, this function does not close the file
when the loop ends.
In case of errors this function raises the error,
instead of returning an error code.
Reads the file file,
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,
or nil 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).
The available formats are
"n":
reads a numeral and returns it as a float or an integer,
following the lexical conventions of Lua.
(The numeral may have leading spaces and a sign.)
This format always reads the longest input sequence that
-is a valid prefix for a number;
-if that prefix does not form a valid number
+is a valid prefix for a numeral;
+if that prefix does not form a valid numeral
(e.g., an empty string, "0x", or "3.4e-"),
it is discarded and the function returns nil.
-
"i":
-reads an integral number and returns it as an integer.
-
-
"a":
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
"l":
reads the next line skipping the end of line,
returning nil on end of file.
This is the default format.
"L":
reads the next line keeping the end-of-line character (if present),
returning nil on end of file.
number:
reads a string with up to this number of bytes,
returning nil on end of file.
If number is zero,
it reads nothing and returns an empty string,
or nil on end of file.
The formats "l" and "L" should be used only for text files.
Sets and gets the file position,
measured from the beginning of the file,
to the position given by offset plus a base
specified by the string whence, as follows:
"set": base is position 0 (beginning of the file);
"cur": base is current position;
"end": base is end of file;
In case of success, seek returns the final file position,
measured in bytes from the beginning of the file.
If seek fails, it returns nil,
plus a string describing the error.
The default value for whence is "cur",
and for offset is 0.
Therefore, the call file:seek() returns the current
file position, without changing it;
the call file:seek("set") sets the position to the
beginning of the file (and returns 0);
and the call file:seek("end") sets the position to the
end of the file, and returns its size.
Returns a string or a table containing date and time,
formatted according to the given string format.
If the time argument is present,
this is the time to be formatted
(see the os.time function for a description of this value).
Otherwise, date formats the current time.
If format starts with '!',
then the date is formatted in Coordinated Universal Time.
After this optional character,
if format is the string "*t",
then date returns a table with the following fields:
-year (four digits), month (1–12), day (1–31),
+year, month (1–12), day (1–31),
hour (0–23), min (0–59), sec (0–61),
-wday (weekday, Sunday is 1),
-yday (day of the year),
+wday (weekday, 1–7, Sunday is 1),
+yday (day of the year, 1–366),
and isdst (daylight saving flag, a boolean).
This last field may be absent
if the information is not available.
If format is not "*t",
then date returns the date as a string,
formatted according to the same rules as the ISO C function strftime.
When called without arguments,
date returns a reasonable date and time representation that depends on
-the host system and on the current locale
-(that is, os.date() is equivalent to os.date("%c")).
+the host system and on the current locale.
+(More specifically, os.date() is equivalent to os.date("%c").)
On non-POSIX systems,
this function may be not thread safe
because of its reliance on C function gmtime and C function localtime.
Returns the difference, in seconds,
from time t1 to time t2
(where the times are values returned by os.time).
In POSIX, Windows, and some other systems,
this value is exactly t2-t1.
This function is equivalent to the ISO C function system.
It passes command to be executed by an operating system shell.
Its first result is true
if the command terminated successfully,
or nil otherwise.
After this first result
the function returns a string plus a number,
as follows:
"exit":
the command terminated normally;
the following number is the exit status of the command.
"signal":
the command was terminated by a signal;
the following number is the signal that terminated the command.
When called without a command,
os.execute returns a boolean that is true if a shell is available.
Calls the ISO C function exit to terminate the host program.
If code is true,
the returned status is EXIT_SUCCESS;
if code is false,
the returned status is EXIT_FAILURE;
if code is a number,
the returned status is this number.
The default value for code is true.
If the optional second argument close is true,
closes the Lua state before exiting.
Deletes the file (or empty directory, on POSIX systems)
with the given name.
If this function fails, it returns nil,
plus a string describing the error and the error code.
+Otherwise, it returns true.
-Renames file or directory named oldname to newname.
+Renames the file or directory named oldname to newname.
If this function fails, it returns nil,
plus a string describing the error and the error code.
+Otherwise, it returns true.
Sets the current locale of the program.
locale is a system-dependent string specifying a locale;
category is an optional string describing which category to change:
"all", "collate", "ctype",
"monetary", "numeric", or "time";
the default category is "all".
The function returns the name of the new locale,
or nil if the request cannot be honored.
If locale is the empty string,
the current locale is set to an implementation-defined native locale.
If locale is the string "C",
the current locale is set to the standard C locale.
When called with nil as the first argument,
this function only returns the name of the current locale
for the given category.
This function may be not thread safe
because of its reliance on C function setlocale.
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 year, month, and day,
and may have fields
hour (default is 12),
min (default is 0),
sec (default is 0),
and isdst (default is nil).
+Other fields are ignored.
For a description of these fields, see the os.date function.
+The values in these fields do not need to be inside their valid ranges.
+For instance, if sec is -10,
+it means -10 seconds from the time specified by the other fields;
+if hour is 1000,
+it means +1000 hours from the time specified by the other fields.
+
+
+
The returned value is a number, whose meaning depends on your system.
In POSIX, Windows, and some other systems,
this number counts the number
of seconds since some given start time (the "epoch").
In other systems, the meaning is not specified,
and the number returned by time can be used only as an argument to
os.date and os.difftime.
Returns a string with a file name that can
be used for a temporary file.
The file must be explicitly opened before its use
and explicitly removed when no longer needed.
On POSIX systems,
this function also creates a file with that name,
to avoid security risks.
(Someone else might create the file with wrong permissions
in the time between getting the name and creating the file.)
You still have to open the file to use it
and to remove it (even if you do not use it).
When possible,
you may prefer to use io.tmpfile,
which automatically removes the file when the program ends.
This library provides
the functionality of the debug interface (§4.9) to Lua programs.
You should exert care when using this library.
Several of its functions
violate basic assumptions about Lua code
(e.g., that variables local to a function
cannot be accessed from outside;
that userdata metatables cannot be changed by Lua code;
that Lua programs do not crash)
and therefore can compromise otherwise secure code.
Moreover, some functions in this library may be slow.
All functions in this library are provided
inside the debug table.
All functions that operate over a thread
have an optional first argument which is the
thread to operate over.
The default is always the current thread.
Enters an interactive mode with the user,
running each string that the user enters.
Using simple commands and other debug facilities,
the user can inspect global and local variables,
change their values, evaluate expressions, and so on.
A line containing only the word cont finishes this function,
so that the caller continues its execution.
Note that commands for debug.debug are not lexically nested
within any function and so have no direct access to local variables.
Returns the current hook settings of the thread, as three values:
the current hook function, the current hook mask,
and the current hook count
(as set by the debug.sethook function).
Returns a table with information about a function.
You can give the function directly
or you can give a number as the value of f,
which means the function running at level f of the call stack
of the given thread:
level 0 is the current function (getinfo itself);
level 1 is the function that called getinfo
(except for tail calls, which do not count on the stack);
and so on.
If f is a number larger than the number of active functions,
then getinfo returns nil.
The returned table can contain all the fields returned by lua_getinfo,
with the string what describing which fields to fill in.
The default for what is to get all information available,
except the table of valid lines.
If present,
the option 'f'
adds a field named func with the function itself.
If present,
the option 'L'
adds a field named activelines with the table of
valid lines.
For instance, the expression debug.getinfo(1,"n").name 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 debug.getinfo(print)
returns a table with all available information
about the print function.
This function returns the name and the value of the local variable
with index local of the function at level f of the stack.
This function accesses not only explicit local variables,
but also parameters, temporaries, etc.
The first parameter or local variable has index 1, and so on,
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 nil if there is no variable with the given index,
and raises an error when called with a level out of range.
(You can call debug.getinfo to check whether the level is valid.)
Variable names starting with '(' (open parenthesis)
represent variables with no known names
(internal variables such as loop control variables,
and variables from chunks saved without debug information).
The parameter f may also be a function.
In that case, getlocal returns only the name of function parameters.
This function returns the name and the value of the upvalue
with index up of the function f.
The function returns nil if there is no upvalue with the given index.
Variable names starting with '(' (open parenthesis)
represent variables with no known names
(variables from chunks saved without debug information).
Sets the given function as a hook.
The string mask and the number count describe
when the hook will be called.
The string mask may have any combination of the following characters,
with the given meaning:
'c': the hook is called every time Lua calls a function;
'r': the hook is called every time Lua returns from a function;
'l': the hook is called every time Lua enters a new line of code.
Moreover,
with a count different from zero,
the hook is called also after every count instructions.
When called without arguments,
debug.sethook turns off the hook.
When the hook is called, its first parameter is a string
describing the event that has triggered its call:
"call" (or "tail call"),
"return",
"line", and "count".
For line events,
the hook also gets the new line number as its second parameter.
Inside a hook,
you can call getinfo with level 2 to get more information about
the running function
(level 0 is the getinfo function,
and level 1 is the hook function).
This function assigns the value value to the local variable
with index local of the function at level level of the stack.
The function returns nil if there is no local
variable with the given index,
and raises an error when called with a level out of range.
(You can call getinfo to check whether the level is valid.)
Otherwise, it returns the name of the local variable.
See debug.getlocal for more information about
variable indices and names.
This function assigns the value value to the upvalue
with index up of the function f.
The function returns nil if there is no upvalue
with the given index.
Otherwise, it returns the name of the upvalue.
If message is present but is neither a string nor nil,
this function returns message without further processing.
Otherwise,
it returns a string with a traceback of the call stack.
The optional message string is appended
at the beginning of the traceback.
An optional level number tells at which level
to start the traceback
(default is 1, the function calling traceback).
Returns a unique identifier (as a light userdata)
for the upvalue numbered n
from the given function.
These unique identifiers allow a program to check whether different
closures share upvalues.
Lua closures that share an upvalue
(that is, that access a same external local variable)
will return identical ids for those upvalue indices.
Although Lua has been designed as an extension language,
to be embedded in a host C program,
it is also frequently used as a standalone language.
An interpreter for Lua as a standalone language,
called simply lua,
is provided with the standard distribution.
The standalone interpreter includes
all standard libraries, including the debug library.
Its usage is:
lua [options] [script [args]]
The options are:
-e stat: executes string stat;
-l mod: "requires" mod;
-i: enters interactive mode after running script;
-v: prints version information;
-E: ignores environment variables;
--: stops handling options;
-: executes stdin as a file and stops handling options.
After handling its options, lua runs the given script.
When called without arguments,
lua behaves as lua -v -i
when the standard input (stdin) is a terminal,
and as lua - otherwise.
-When called without option -E,
+When called without option -E,
the interpreter checks for an environment variable LUA_INIT_5_3
(or LUA_INIT if the versioned name is not defined)
before running any argument.
If the variable content has the format @filename,
then lua executes the file.
Otherwise, lua executes the string itself.
When called with option -E,
besides ignoring LUA_INIT,
Lua also ignores
the values of LUA_PATH and LUA_CPATH,
setting the values of
package.path and package.cpath
with the default paths defined in luaconf.h.
All options are handled in order, except -i and -E.
For instance, an invocation like
$ lua -e'a=1' -e 'print(a)' script.lua
will first set a to 1, then print the value of a,
and finally run the file script.lua with no arguments.
(Here $ is the shell prompt. Your prompt may be different.)
Before running any code,
lua collects all command-line arguments
in a global table called arg.
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 its options)
go to negative indices.
For instance, in the call
If there is no script in the call,
the interpreter name goes to index 0,
followed by the other arguments.
For instance, the call
$ lua -e "print(arg[1])"
will print "-e".
If there is a script,
the script is called with parameters
arg[1], ···, arg[#arg].
(Like all chunks in Lua,
the script is compiled as a vararg function.)
In interactive mode,
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.
+If the global variable _PROMPT contains a string,
+then its value is used as the prompt.
+Similarly, if the global variable _PROMPT2 contains a string,
+its value is used as the secondary prompt
+(issued during incomplete statements).
+
+
+
In case of unprotected errors in the script,
the interpreter reports the error to the standard error stream.
-If the error object is not a string but
+If the error object is not a string but
has a metamethod __tostring,
the interpreter calls this metamethod to produce the final message.
Otherwise, the interpreter converts the error object to a string
and adds a stack traceback to it.
When finishing normally,
the interpreter closes its main Lua state
(see lua_close).
The script can avoid this step by
calling os.exit to terminate.
To allow the use of Lua as a
script interpreter in Unix systems,
the standalone interpreter skips
the first line of a chunk if it starts with #.
Therefore, Lua scripts can be made into executable programs
by using chmod +x and the #! form,
as in
#!/usr/local/bin/lua
(Of course,
the location of the Lua interpreter may be different in your machine.
If lua is in your PATH,
then
Here we list the incompatibilities that you may find when moving a program
from Lua 5.2 to Lua 5.3.
You can avoid some incompatibilities by compiling Lua with
appropriate options (see file luaconf.h).
However,
all these compatibility options will be removed in the future.
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.
Similarly, Lua versions can always change the internal representation
of precompiled chunks;
precompiled chunks are not compatible between different Lua versions.
The standard paths in the official distribution may
change between versions.
The main difference between Lua 5.2 and Lua 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.
You can fix these differences by forcing a number to be a float
(in Lua 5.2 all numbers were float),
in particular writing constants with an ending .0
or using x = x + 0.0 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.)
The conversion of a float to a string now adds a .0 suffix
to the result if it looks like an integer.
(For instance, the float 2.0 will be printed as 2.0,
not as 2.)
You should always use an explicit format
when you need a specific format for numbers.
(Formally this is not an incompatibility,
because Lua does not specify how numbers are formatted as strings,
but some programs assumed a specific format.)
The generational mode for the garbage collector was removed.
(It was an experimental feature in Lua 5.2.)
The bit32 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 bit32 operates on 32-bit integers,
-while the bitwise operators in standard Lua operate on 64-bit integers.)
+while the bitwise operators in Lua 5.3 operate on Lua integers,
+which by default have 64 bits.)
The Table library now respects metamethods
for setting and getting elements.
The ipairs iterator now respects metamethods and
its __ipairs metamethod has been deprecated.
Option names in io.read do not have a starting '*' anymore.
-For compatibility, Lua will continue to ignore this character.
+For compatibility, Lua will continue to accept (and ignore) this character.
The following functions were deprecated in the mathematical library:
atan2, cosh, sinh, tanh, pow,
frexp, and ldexp.
You can replace math.pow(x,y) with x^y;
you can replace math.atan2 with math.atan,
which now accepts one or two parameters;
you can replace math.ldexp(x,exp) with x * 2.0^exp.
For the other operations,
you can either use an external library or
implement them in Lua.
The searcher for C loaders used by require
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 5.2 already worked that way,
but it did not document the change.)
+
+The call collectgarbage("count") now returns only one result.
+(You can compute that second result from the fractional part
+of the first result.)
+
Continuation functions now receive as parameters what they needed
to get through lua_getctx,
so lua_getctx has been removed.
Adapt your code accordingly.
Function lua_dump has an extra parameter, strip.
Use 0 as the value of this parameter to get the old behavior.
Functions to inject/project unsigned integers
(lua_pushunsigned, lua_tounsigned, lua_tounsignedx,
luaL_checkunsigned, luaL_optunsigned)
were deprecated.
Use their signed equivalents with a type cast.
Macros to project non-default integer types
(luaL_checkint, luaL_optint, luaL_checklong, luaL_optlong)
were deprecated.
Use their equivalent over lua_Integer with a type cast
(or, when possible, use lua_Integer in your code).
Here is the complete syntax of Lua in extended BNF.
As usual in extended BNF,
{A} means 0 or more As,
and [A] means an optional A.
(For operator precedences, see §3.4.8;
for a description of the terminals
Name, Numeral,
and LiteralString, see §3.1.)
chunk ::= block
block ::= {stat} [retstat]
stat ::= ‘;’ |
varlist ‘=’ explist |
functioncall |
label |
break |
goto Name |
do block end |
while exp do block end |
repeat block until exp |
if exp then block {elseif exp then block} [else block] end |
for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end |
for namelist in explist do block end |
function funcname funcbody |
localfunction Name funcbody |
local namelist [‘=’ explist]
retstat ::= return [explist] [‘;’]
label ::= ‘::’ Name ‘::’
funcname ::= Name {‘.’ Name} [‘:’ Name]
varlist ::= var {‘,’ var}
var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name
namelist ::= Name {‘,’ Name}
explist ::= exp {‘,’ exp}
exp ::= nil | false | true | Numeral | LiteralString | ‘...’ | functiondef |
prefixexp | tableconstructor | exp binop exp | unop exp
prefixexp ::= var | functioncall | ‘(’ exp ‘)’
functioncall ::= prefixexp args | prefixexp ‘:’ Name args
args ::= ‘(’ [explist] ‘)’ | tableconstructor | LiteralString
functiondef ::= function funcbody
funcbody ::= ‘(’ [parlist] ‘)’ block end
parlist ::= namelist [‘,’ ‘...’] | ‘...’
tableconstructor ::= ‘{’ [fieldlist] ‘}’
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
fieldsep ::= ‘,’ | ‘;’
binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ |
‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ |
‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ |
and | or
unop ::= ‘-’ | not | ‘#’ | ‘~’
-
-
-
+
Last update:
-Tue Jan 6 10:10:50 BRST 2015
-
+Mon Jan 9 13:30:53 BRST 2017
+
Lua is a powerful, fast, lightweight, embeddable scripting language
developed by a
team
at
PUC-Rio,
the Pontifical Catholic University of Rio de Janeiro in Brazil.
Lua is
free software
used in many products and projects around the world.
Lua is distributed in
source
form.
You need to build it before using it.
Building Lua should be straightforward
because
Lua is implemented in pure ANSI C and compiles unmodified in all known
platforms that have an ANSI C compiler.
Lua also compiles unmodified as C++.
The instructions given below for building Lua are for Unix-like platforms.
See also
instructions for other systems
and
customization options.
If you don't have the time or the inclination to compile Lua yourself,
get a binary from
LuaBinaries.
Try also
LuaDist,
a multi-platform distribution of Lua that includes batteries.
Building Lua
-
In most Unix-like platforms, simply do "make" with a suitable target.
Here are the details.
Open a terminal window and move to
-the top-level directory, which is named lua-5.3.0.
+the top-level directory, which is named lua-5.3.x.
The Makefile there controls both the build process and the installation process.
Do "make" and see if your platform is listed.
The platforms currently supported are:
aix bsd c89 freebsd generic linux macosx mingw posix solaris
If your platform is listed, just do "make xxx", where xxx
is your platform name.
If your platform is not listed, try the closest one or posix, generic,
c89, in this order.
The compilation takes only a few moments
and produces three files in the src directory:
lua (the interpreter),
luac (the compiler),
and liblua.a (the library).
To check that Lua has been built correctly, do "make test"
after building Lua. This will run the interpreter and print its version.
If you're running Linux and get compilation errors,
-make sure you have installed the readline development package.
+make sure you have installed the readline development package
+(which is probably named libreadline-dev or readline-devel).
If you get link errors after that,
then try "make linux MYLIBS=-ltermcap".
Installing Lua
Once you have built Lua, you may want to install it in an official
place in your system. In this case, do "make install". The official
place and the way to install files are defined in the Makefile. You'll
probably need the right permissions to install files.
To build and install Lua in one step, do "make xxx install",
where xxx is your platform name.
To install Lua locally, do "make local".
This will create a directory install with subdirectories
bin, include, lib, man, share,
and install Lua as listed below.
To install Lua locally, but in some other directory, do
"make install INSTALL_TOP=xxx", where xxx is your chosen directory.
The installation starts in the src and doc directories,
so take care if INSTALL_TOP is not an absolute path.
These are the only directories you need for development.
If you only want to run Lua programs,
you only need the files in bin and man.
The files in include and lib are needed for
embedding Lua in C or C++ programs.
Three kinds of things can be customized by editing a file:
Where and how to install Lua — edit Makefile.
How to build Lua — edit src/Makefile.
Lua features — edit src/luaconf.h.
You don't actually need to edit the Makefiles because you may set the
relevant variables in the command line when invoking make.
Nevertheless, it's probably best to edit and save the Makefiles to
record the changes you've made.
On the other hand, if you need to customize some Lua features, you'll need
to edit src/luaconf.h before building and installing Lua.
The edited file will be the one installed, and
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.
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
projects (or whatever your compiler uses) for building the library,
the interpreter, and the compiler, as follows:
To use Lua as a library in your own programs you'll need to know how to
create and use libraries with your compiler. Moreover, to dynamically load
C libraries for Lua you'll need to know how to create dynamic libraries
and you'll need to make sure that the Lua API functions are accessible to
those dynamic libraries — but don't link the Lua library
into each dynamic library. For Unix, we recommend that the Lua library
be linked statically into the host program and its symbols exported for
dynamic linking; src/Makefile does this for the Lua interpreter.
For Windows, we recommend that the Lua library be a DLL.
In all cases, the compiler luac should be linked statically.
As mentioned above, you may edit src/luaconf.h to customize
some features before building Lua.
Lua is free software distributed under the terms of the
MIT license
reproduced below;
it may be used for any purpose, including commercial purposes,
at absolutely no cost without having to ask us.
The only requirement is that if you do use Lua,
then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.
For details, see
this.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
-
+
Last update:
-Fri Dec 12 09:58:42 BRST 2014
-
+Thu Dec 22 18:22:57 BRST 2016
+
Index: vendor/lua/dist/src/Makefile
===================================================================
--- vendor/lua/dist/src/Makefile (revision 326343)
+++ vendor/lua/dist/src/Makefile (revision 326344)
@@ -1,197 +1,197 @@
# Makefile for building Lua
# See ../doc/readme.html for installation and customization instructions.
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
# Your platform. See PLATS for possible values.
PLAT= none
CC= gcc -std=gnu99
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 $(SYSCFLAGS) $(MYCFLAGS)
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
LIBS= -lm $(SYSLIBS) $(MYLIBS)
AR= ar rcu
RANLIB= ranlib
RM= rm -f
SYSCFLAGS=
SYSLDFLAGS=
SYSLIBS=
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
MYOBJS=
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
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 lutf8lib.o loadlib.o linit.o
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
LUA_T= lua
LUA_O= lua.o
LUAC_T= luac
LUAC_O= luac.o
ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O)
ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
ALL_A= $(LUA_A)
# Targets start here.
default: $(PLAT)
all: $(ALL_T)
o: $(ALL_O)
a: $(ALL_A)
$(LUA_A): $(BASE_O)
$(AR) $@ $(BASE_O)
$(RANLIB) $@
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
$(LUAC_T): $(LUAC_O) $(LUA_A)
$(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
clean:
$(RM) $(ALL_T) $(ALL_O)
depend:
@$(CC) $(CFLAGS) -MM l*.c
echo:
@echo "PLAT= $(PLAT)"
@echo "CC= $(CC)"
@echo "CFLAGS= $(CFLAGS)"
@echo "LDFLAGS= $(SYSLDFLAGS)"
@echo "LIBS= $(LIBS)"
@echo "AR= $(AR)"
@echo "RANLIB= $(RANLIB)"
@echo "RM= $(RM)"
# Convenience targets for popular platforms
ALL= all
none:
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
@echo " $(PLATS)"
aix:
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
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"
generic: $(ALL)
linux:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
macosx:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
mingw:
$(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
posix:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
solaris:
$(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 lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
- lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
- ltable.h lundump.h lvm.h
+ lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
+ ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lbitlib.o: lbitlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
- llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
- ldo.h lgc.h lstring.h ltable.h lvm.h
+ llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
+ ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
- lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
- ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
+ lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
+ ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
- lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
- lparser.h lstring.h ltable.h lundump.h lvm.h
+ lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
+ lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
- ltm.h lzio.h lmem.h lundump.h
+ ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
- lgc.h lstate.h ltm.h lzio.h lmem.h
+ lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
- llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
+ llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
-llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldo.h \
- lobject.h lstate.h ltm.h lzio.h lmem.h lgc.h llex.h lparser.h lstring.h \
- ltable.h
+llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
+ lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
+ lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
- llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
+ llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
- ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
- lvm.h
+ ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
+ lvm.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
- llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
- ldo.h lfunc.h lstring.h lgc.h ltable.h
+ llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
+ ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
- lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
- lstring.h ltable.h
+ lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
+ lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
- lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
+ lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
- llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
+ llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
- llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
+ llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
luac.o: luac.c lprefix.h lua.h luaconf.h lauxlib.h lobject.h llimits.h \
- lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
+ lstate.h ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
- lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
- lundump.h
+ lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
+ lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
- llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
- ltable.h lvm.h
+ llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
+ ltable.h lvm.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
- lobject.h ltm.h lzio.h
+ lobject.h ltm.h lzio.h
# (end of Makefile)
Index: vendor/lua/dist/src/lapi.c
===================================================================
--- vendor/lua/dist/src/lapi.c (revision 326343)
+++ vendor/lua/dist/src/lapi.c (revision 326344)
@@ -1,1270 +1,1298 @@
/*
-** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 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
#include
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
const char lua_ident[] =
"$LuaVersion: " LUA_COPYRIGHT " $"
"$LuaAuthors: " LUA_AUTHORS " $";
/* value at a non-valid index */
#define NONVALIDVALUE cast(TValue *, luaO_nilobject)
/* corresponding test */
#define isvalid(o) ((o) != luaO_nilobject)
/* 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(o) api_check(isvalid(o), "invalid index")
+#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index")
-#define api_checkstackindex(i, o) \
- api_check(isstackindex(i, o), "index not in the stack")
+#define api_checkstackindex(l, i, o) \
+ api_check(l, isstackindex(i, o), "index not in the stack")
static TValue *index2addr (lua_State *L, int idx) {
CallInfo *ci = L->ci;
if (idx > 0) {
TValue *o = ci->func + idx;
- api_check(idx <= ci->top - (ci->func + 1), "unacceptable index");
+ api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
if (o >= L->top) return NONVALIDVALUE;
else return o;
}
else if (!ispseudo(idx)) { /* negative index */
- api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
+ api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
return L->top + idx;
}
else if (idx == LUA_REGISTRYINDEX)
return &G(L)->l_registry;
else { /* upvalues */
idx = LUA_REGISTRYINDEX - idx;
- api_check(idx <= MAXUPVAL + 1, "upvalue index too large");
+ api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
if (ttislcf(ci->func)) /* light C function? */
return NONVALIDVALUE; /* it has no upvalues */
else {
CClosure *func = clCvalue(ci->func);
return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;
}
}
}
/*
** to be called by 'lua_checkstack' in protected mode, to grow stack
** capturing memory errors
*/
static void growstack (lua_State *L, void *ud) {
int size = *(int *)ud;
luaD_growstack(L, size);
}
LUA_API int lua_checkstack (lua_State *L, int n) {
int res;
CallInfo *ci = L->ci;
lua_lock(L);
- api_check(n >= 0, "negative 'n'");
+ api_check(L, n >= 0, "negative 'n'");
if (L->stack_last - L->top > n) /* stack large enough? */
res = 1; /* yes; check is OK */
else { /* no; need to grow stack */
int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;
if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
res = 0; /* no */
else /* try to grow stack */
res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);
}
if (res && ci->top < L->top + n)
ci->top = L->top + n; /* adjust frame top */
lua_unlock(L);
return res;
}
LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
int i;
if (from == to) return;
lua_lock(to);
api_checknelems(from, n);
- api_check(G(from) == G(to), "moving among independent states");
- api_check(to->ci->top - to->top >= n, "not enough elements to move");
+ api_check(from, G(from) == G(to), "moving among independent states");
+ api_check(from, to->ci->top - to->top >= n, "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);
}
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
lua_CFunction old;
lua_lock(L);
old = G(L)->panic;
G(L)->panic = panicf;
lua_unlock(L);
return old;
}
LUA_API const lua_Number *lua_version (lua_State *L) {
static const lua_Number version = LUA_VERSION_NUM;
if (L == NULL) return &version;
else return G(L)->version;
}
/*
** basic stack manipulation
*/
/*
** convert an acceptable stack index into an absolute index
*/
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;
}
LUA_API int lua_gettop (lua_State *L) {
return cast_int(L->top - (L->ci->func + 1));
}
LUA_API void lua_settop (lua_State *L, int idx) {
StkId func = L->ci->func;
lua_lock(L);
if (idx >= 0) {
- api_check(idx <= L->stack_last - (func + 1), "new top too large");
+ api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
while (L->top < (func + 1) + idx)
setnilvalue(L->top++);
L->top = (func + 1) + idx;
}
else {
- api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top");
+ api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
L->top += idx+1; /* 'subtract' index (index is negative) */
}
lua_unlock(L);
}
/*
** 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);
}
}
/*
** 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);
t = L->top - 1; /* end of stack segment being rotated */
p = index2addr(L, idx); /* start of segment */
- api_checkstackindex(idx, p);
- api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
+ api_checkstackindex(L, idx, p);
+ api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
reverse(L, p, m); /* reverse the prefix with length 'n' */
reverse(L, m + 1, t); /* reverse the suffix */
reverse(L, p, t); /* reverse the entire segment */
lua_unlock(L);
}
LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
TValue *fr, *to;
lua_lock(L);
fr = index2addr(L, fromidx);
to = index2addr(L, toidx);
- api_checkvalidindex(to);
+ api_checkvalidindex(L, to);
setobj(L, to, fr);
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_unlock(L);
}
LUA_API void lua_pushvalue (lua_State *L, int idx) {
lua_lock(L);
setobj2s(L, L->top, index2addr(L, idx));
api_incr_top(L);
lua_unlock(L);
}
/*
** access functions (stack -> C)
*/
LUA_API int lua_type (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (isvalid(o) ? ttnov(o) : LUA_TNONE);
}
LUA_API const char *lua_typename (lua_State *L, int t) {
UNUSED(L);
- api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
+ api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
return ttypename(t);
}
LUA_API int lua_iscfunction (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (ttislcf(o) || (ttisCclosure(o)));
}
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) {
lua_Number n;
const TValue *o = index2addr(L, idx);
return tonumber(o, &n);
}
LUA_API int lua_isstring (lua_State *L, int idx) {
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 (ttisfulluserdata(o) || ttislightuserdata(o));
}
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
StkId o1 = index2addr(L, index1);
StkId o2 = index2addr(L, index2);
return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;
}
LUA_API void lua_arith (lua_State *L, int op) {
lua_lock(L);
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++;
+ api_incr_top(L);
}
/* first operand at top - 2, second at top - 1; result go to top - 2 */
luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
L->top--; /* remove second operand */
lua_unlock(L);
}
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
StkId o1, o2;
int i = 0;
lua_lock(L); /* may call tag method */
o1 = index2addr(L, index1);
o2 = index2addr(L, index2);
if (isvalid(o1) && isvalid(o2)) {
switch (op) {
case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
- default: api_check(0, "invalid option");
+ default: api_check(L, 0, "invalid option");
}
}
lua_unlock(L);
return i;
}
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_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
lua_Number n;
const TValue *o = index2addr(L, idx);
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_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
lua_Integer res;
const TValue *o = index2addr(L, idx);
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;
}
LUA_API int lua_toboolean (lua_State *L, int idx) {
const TValue *o = index2addr(L, idx);
return !l_isfalse(o);
}
LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
StkId o = index2addr(L, idx);
if (!ttisstring(o)) {
if (!cvt2str(o)) { /* not convertible? */
if (len != NULL) *len = 0;
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 */
- luaO_tostring(L, o);
lua_unlock(L);
}
- if (len != NULL) *len = tsvalue(o)->len;
+ if (len != NULL)
+ *len = vslen(o);
return svalue(o);
}
LUA_API size_t lua_rawlen (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
- switch (ttnov(o)) {
- case LUA_TSTRING: return tsvalue(o)->len;
+ switch (ttype(o)) {
+ case LUA_TSHRSTR: return tsvalue(o)->shrlen;
+ case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
case LUA_TUSERDATA: return uvalue(o)->len;
case LUA_TTABLE: return luaH_getn(hvalue(o));
default: return 0;
}
}
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
if (ttislcf(o)) return fvalue(o);
else if (ttisCclosure(o))
return clCvalue(o)->f;
else return NULL; /* not a C function */
}
LUA_API void *lua_touserdata (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttnov(o)) {
case LUA_TUSERDATA: return getudatamem(uvalue(o));
case LUA_TLIGHTUSERDATA: return pvalue(o);
default: return NULL;
}
}
LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
return (!ttisthread(o)) ? NULL : thvalue(o);
}
LUA_API const void *lua_topointer (lua_State *L, int idx) {
StkId o = index2addr(L, idx);
switch (ttype(o)) {
case LUA_TTABLE: return hvalue(o);
case LUA_TLCL: return clLvalue(o);
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;
}
}
/*
** push functions (C -> stack)
*/
LUA_API void lua_pushnil (lua_State *L) {
lua_lock(L);
setnilvalue(L->top);
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
lua_lock(L);
setfltvalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
lua_lock(L);
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;
}
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;
}
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;
}
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
lua_lock(L);
if (n == 0) {
setfvalue(L->top, fn);
}
else {
CClosure *cl;
api_checknelems(L, n);
- api_check(n <= MAXUPVAL, "upvalue index too large");
- luaC_checkGC(L);
+ api_check(L, n <= MAXUPVAL, "upvalue index too large");
cl = luaF_newCclosure(L, n);
cl->f = fn;
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);
}
LUA_API void lua_pushboolean (lua_State *L, int b) {
lua_lock(L);
setbvalue(L->top, (b != 0)); /* ensure that true is 1 */
api_incr_top(L);
lua_unlock(L);
}
LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
lua_lock(L);
setpvalue(L->top, p);
api_incr_top(L);
lua_unlock(L);
}
LUA_API int lua_pushthread (lua_State *L) {
lua_lock(L);
setthvalue(L, L->top, L);
api_incr_top(L);
lua_unlock(L);
return (G(L)->mainthread == L);
}
/*
** get functions (Lua -> stack)
*/
+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, name));
- luaV_gettable(L, gt, L->top - 1, L->top - 1);
- lua_unlock(L);
- return ttnov(L->top - 1);
+ return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
}
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) {
- StkId t;
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);
- lua_unlock(L);
- return ttnov(L->top - 1);
+ return auxgetstr(L, index2addr(L, idx), 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);
- setivalue(L->top, n);
- 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 int lua_rawget (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
- api_check(ttistable(t), "table expected");
+ api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
- api_check(ttistable(t), "table expected");
+ api_check(L, ttistable(t), "table expected");
setobj2s(L, L->top, luaH_getint(hvalue(t), n));
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
StkId t;
TValue k;
lua_lock(L);
t = index2addr(L, idx);
- api_check(ttistable(t), "table expected");
+ api_check(L, ttistable(t), "table expected");
setpvalue(&k, cast(void *, p));
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
api_incr_top(L);
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;
int res = 0;
lua_lock(L);
obj = index2addr(L, objindex);
switch (ttnov(obj)) {
case LUA_TTABLE:
mt = hvalue(obj)->metatable;
break;
case LUA_TUSERDATA:
mt = uvalue(obj)->metatable;
break;
default:
mt = G(L)->mt[ttnov(obj)];
break;
}
if (mt != NULL) {
sethvalue(L, L->top, mt);
api_incr_top(L);
res = 1;
}
lua_unlock(L);
return res;
}
LUA_API int lua_getuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
o = index2addr(L, idx);
- api_check(ttisfulluserdata(o), "full userdata expected");
+ api_check(L, ttisfulluserdata(o), "full userdata expected");
getuservalue(L, uvalue(o), L->top);
api_incr_top(L);
lua_unlock(L);
return ttnov(L->top - 1);
}
/*
** 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 *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, name));
- 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);
}
LUA_API void lua_settable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
api_checknelems(L, 2);
t = index2addr(L, idx);
luaV_settable(L, t, L->top - 2, L->top - 1);
L->top -= 2; /* pop index and value */
lua_unlock(L);
}
LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
- StkId t;
- 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 */
- lua_unlock(L);
+ 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);
- setivalue(L->top++, n);
- 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 o;
- Table *t;
+ TValue *slot;
lua_lock(L);
api_checknelems(L, 2);
o = index2addr(L, idx);
- api_check(ttistable(o), "table expected");
- t = hvalue(o);
- setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
- invalidateTMcache(t);
- luaC_barrierback(L, t, L->top-1);
+ 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, lua_Integer n) {
StkId o;
- Table *t;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
- api_check(ttistable(o), "table expected");
- t = hvalue(o);
- luaH_setint(L, t, n, L->top - 1);
- luaC_barrierback(L, t, L->top-1);
+ 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 o;
- Table *t;
- TValue k;
+ TValue k, *slot;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
- api_check(ttistable(o), "table expected");
- t = hvalue(o);
+ api_check(L, ttistable(o), "table expected");
setpvalue(&k, cast(void *, p));
- setobj2t(L, luaH_set(L, t, &k), L->top - 1);
- luaC_barrierback(L, 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);
}
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
TValue *obj;
Table *mt;
lua_lock(L);
api_checknelems(L, 1);
obj = index2addr(L, objindex);
if (ttisnil(L->top - 1))
mt = NULL;
else {
- api_check(ttistable(L->top - 1), "table expected");
+ api_check(L, ttistable(L->top - 1), "table expected");
mt = hvalue(L->top - 1);
}
switch (ttnov(obj)) {
case LUA_TTABLE: {
hvalue(obj)->metatable = mt;
if (mt) {
luaC_objbarrier(L, gcvalue(obj), mt);
luaC_checkfinalizer(L, gcvalue(obj), mt);
}
break;
}
case LUA_TUSERDATA: {
uvalue(obj)->metatable = mt;
if (mt) {
luaC_objbarrier(L, uvalue(obj), mt);
luaC_checkfinalizer(L, gcvalue(obj), mt);
}
break;
}
default: {
G(L)->mt[ttnov(obj)] = mt;
break;
}
}
L->top--;
lua_unlock(L);
return 1;
}
LUA_API void lua_setuservalue (lua_State *L, int idx) {
StkId o;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
- api_check(ttisfulluserdata(o), "full userdata expected");
+ api_check(L, ttisfulluserdata(o), "full userdata expected");
setuservalue(L, uvalue(o), L->top - 1);
luaC_barrier(L, gcvalue(o), L->top - 1);
L->top--;
lua_unlock(L);
}
/*
** 'load' and 'call' functions (run Lua code)
*/
#define checkresults(L,na,nr) \
- api_check((nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
"results from function overflow current stack size")
LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k) {
StkId func;
lua_lock(L);
- api_check(k == NULL || !isLua(L->ci),
+ api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
- api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
+ api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
func = L->top - (nargs+1);
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
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);
}
/*
** Execute a protected call.
*/
struct CallS { /* data to 'f_call' */
StkId func;
int nresults;
};
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,
lua_KContext ctx, lua_KFunction k) {
struct CallS c;
int status;
ptrdiff_t func;
lua_lock(L);
- api_check(k == NULL || !isLua(L->ci),
+ api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
- api_check(L->status == LUA_OK, "cannot do calls on non-normal thread");
+ api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
if (errfunc == 0)
func = 0;
else {
StkId o = index2addr(L, errfunc);
- api_checkstackindex(errfunc, o);
+ api_checkstackindex(L, errfunc, o);
func = savestack(L, o);
}
c.func = L->top - (nargs+1); /* function to be called */
if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */
c.nresults = nresults; /* do a 'conventional' protected call */
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
}
else { /* prepare continuation (call is already protected by 'resume') */
CallInfo *ci = L->ci;
ci->u.c.k = k; /* save continuation */
ci->u.c.ctx = ctx; /* save context */
/* save information for error recovery */
ci->extra = savestack(L, c.func);
ci->u.c.old_errfunc = L->errfunc;
L->errfunc = func;
setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
ci->callstatus |= CIST_YPCALL; /* function can do error recovery */
- luaD_call(L, c.func, nresults, 1); /* do the call */
+ 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 */
}
adjustresults(L, nresults);
lua_unlock(L);
return status;
}
LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const char *chunkname, const char *mode) {
ZIO z;
int status;
lua_lock(L);
if (!chunkname) chunkname = "?";
luaZ_init(L, &z, reader, 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 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_upvalbarrier(L, f->upvals[0]);
}
}
lua_unlock(L);
return status;
}
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, strip);
else
status = 1;
lua_unlock(L);
return status;
}
LUA_API int lua_status (lua_State *L) {
return L->status;
}
/*
** Garbage-collection function
*/
LUA_API int lua_gc (lua_State *L, int what, int data) {
int res = 0;
global_State *g;
lua_lock(L);
g = G(L);
switch (what) {
case LUA_GCSTOP: {
g->gcrunning = 0;
break;
}
case LUA_GCRESTART: {
luaE_setdebt(g, 0);
g->gcrunning = 1;
break;
}
case LUA_GCCOLLECT: {
luaC_fullgc(L, 0);
break;
}
case LUA_GCCOUNT: {
/* GC values are expressed in Kbytes: #bytes/2^10 */
res = cast_int(gettotalbytes(g) >> 10);
break;
}
case LUA_GCCOUNTB: {
res = cast_int(gettotalbytes(g) & 0x3ff);
break;
}
case LUA_GCSTEP: {
l_mem debt = 1; /* =1 to signal that it did an actual step */
- int oldrunning = g->gcrunning;
+ 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 { /* 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: {
res = g->gcpause;
g->gcpause = data;
break;
}
case LUA_GCSETSTEPMUL: {
res = g->gcstepmul;
if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */
g->gcstepmul = data;
break;
}
case LUA_GCISRUNNING: {
res = g->gcrunning;
break;
}
default: res = -1; /* invalid option */
}
lua_unlock(L);
return res;
}
/*
** miscellaneous functions
*/
LUA_API int lua_error (lua_State *L) {
lua_lock(L);
api_checknelems(L, 1);
luaG_errormsg(L);
/* code unreachable; will unlock when control actually leaves the kernel */
return 0; /* to avoid warnings */
}
LUA_API int lua_next (lua_State *L, int idx) {
StkId t;
int more;
lua_lock(L);
t = index2addr(L, idx);
- api_check(ttistable(t), "table expected");
+ api_check(L, ttistable(t), "table expected");
more = luaH_next(L, hvalue(t), L->top - 1);
if (more) {
api_incr_top(L);
}
else /* no more elements */
L->top -= 1; /* remove key */
lua_unlock(L);
return more;
}
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 */
setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
api_incr_top(L);
}
/* else n == 1; nothing to do */
+ luaC_checkGC(L);
lua_unlock(L);
}
LUA_API void lua_len (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
luaV_objlen(L, L->top, t);
api_incr_top(L);
lua_unlock(L);
}
LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
lua_Alloc f;
lua_lock(L);
if (ud) *ud = G(L)->ud;
f = G(L)->frealloc;
lua_unlock(L);
return f;
}
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
lua_lock(L);
G(L)->ud = ud;
G(L)->frealloc = f;
lua_unlock(L);
}
LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
Udata *u;
lua_lock(L);
- luaC_checkGC(L);
u = luaS_newudata(L, size);
setuvalue(L, L->top, u);
api_incr_top(L);
+ luaC_checkGC(L);
lua_unlock(L);
return getudatamem(u);
}
static const char *aux_upvalue (StkId fi, int n, TValue **val,
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 = f;
return "";
}
case LUA_TLCL: { /* Lua closure */
LClosure *f = clLvalue(fi);
TString *name;
Proto *p = f->p;
if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
*val = f->upvals[n-1]->v;
if (uv) *uv = f->upvals[n - 1];
name = p->upvalues[n-1].name;
return (name == NULL) ? "(*no name)" : getstr(name);
}
default: return NULL; /* not a closure */
}
}
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, NULL);
if (name) {
setobj2s(L, L->top, val);
api_incr_top(L);
}
lua_unlock(L);
return name;
}
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name;
TValue *val = 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, &uv);
if (name) {
L->top--;
setobj(L, val, L->top);
if (owner) { luaC_barrier(L, owner, L->top); }
else if (uv) { luaC_upvalbarrier(L, uv); }
}
lua_unlock(L);
return name;
}
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
LClosure *f;
StkId fi = index2addr(L, fidx);
- api_check(ttisLclosure(fi), "Lua function expected");
+ api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi);
- api_check((1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
+ api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
if (pf) *pf = f;
return &f->upvals[n - 1]; /* get its upvalue pointer */
}
LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
StkId fi = index2addr(L, fidx);
switch (ttype(fi)) {
case LUA_TLCL: { /* lua closure */
return *getupvalref(L, fidx, n, NULL);
}
case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi);
- api_check(1 <= n && n <= f->nupvalues, "invalid upvalue index");
+ api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
return &f->upvalue[n - 1];
}
default: {
- api_check(0, "closure expected");
+ api_check(L, 0, "closure expected");
return NULL;
}
}
}
LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
int fidx2, int n2) {
LClosure *f1;
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
luaC_upvdeccount(L, *up1);
*up1 = *up2;
(*up1)->refcount++;
if (upisopen(*up1)) (*up1)->u.open.touched = 1;
luaC_upvalbarrier(L, *up1);
}
Index: vendor/lua/dist/src/lapi.h
===================================================================
--- vendor/lua/dist/src/lapi.h (revision 326343)
+++ vendor/lua/dist/src/lapi.h (revision 326344)
@@ -1,24 +1,24 @@
/*
-** $Id: lapi.h,v 2.8 2014/07/15 21:26:50 roberto Exp $
+** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
#ifndef lapi_h
#define lapi_h
#include "llimits.h"
#include "lstate.h"
-#define api_incr_top(L) {L->top++; api_check(L->top <= L->ci->top, \
+#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
#define adjustresults(L,nres) \
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
-#define api_checknelems(L,n) api_check((n) < (L->top - L->ci->func), \
+#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
#endif
Index: vendor/lua/dist/src/lauxlib.c
===================================================================
--- vendor/lua/dist/src/lauxlib.c (revision 326343)
+++ vendor/lua/dist/src/lauxlib.c (revision 326344)
@@ -1,972 +1,1043 @@
/*
-** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp $
+** $Id: lauxlib.c,v 1.289 2016/12/20 18:37:00 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#define lauxlib_c
#define LUA_LIB
#include "lprefix.h"
#include
#include
#include
#include
#include
-/* 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.
*/
#include "lua.h"
#include "lauxlib.h"
/*
** {======================================================
** Traceback
** =======================================================
*/
-#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 */
/*
** search for 'objidx' in table at index -1.
** return 1 + string at top if find a good name.
*/
static int findfield (lua_State *L, int objidx, int level) {
if (level == 0 || !lua_istable(L, -1))
return 0; /* not found */
lua_pushnil(L); /* start 'next' loop */
while (lua_next(L, -2)) { /* for each pair in table */
if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
if (lua_rawequal(L, objidx, -1)) { /* found object? */
lua_pop(L, 1); /* remove value (but keep name) */
return 1;
}
else if (findfield(L, objidx, level - 1)) { /* try recursively */
lua_remove(L, -2); /* remove table (but keep name) */
lua_pushliteral(L, ".");
lua_insert(L, -2); /* place '.' between the two names */
lua_concat(L, 3);
return 1;
}
}
lua_pop(L, 1); /* remove value */
}
return 0; /* not found */
}
/*
** 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_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
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;
}
else {
lua_settop(L, top); /* remove function and global table */
return 0;
}
}
static void pushfuncname (lua_State *L, lua_Debug *ar) {
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') /* for Lua functions, use */
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 */
while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
/* do a binary search */
while (li < le) {
int m = (li + le)/2;
if (lua_getstack(L, m, &ar)) li = m + 1;
else le = m;
}
return le - 1;
}
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);
lua_pushfstring(L, "\n\t%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
lua_pushliteral(L, " in ");
pushfuncname(L, &ar);
if (ar.istailcall)
lua_pushliteral(L, "\n\t(...tail calls...)");
lua_concat(L, lua_gettop(L) - top);
}
}
lua_concat(L, lua_gettop(L) - top);
}
/* }====================================================== */
/*
** {======================================================
** Error-report functions
** =======================================================
*/
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)", arg, extramsg);
lua_getinfo(L, "n", &ar);
if (strcmp(ar.namewhat, "method") == 0) {
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 '%s' (%s)",
arg, ar.name, extramsg);
}
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 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 */
lua_getinfo(L, "Sl", &ar); /* get info about it */
if (ar.currentline > 0) { /* is there info? */
lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
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);
luaL_where(L, 1);
lua_pushvfstring(L, fmt, argp);
va_end(argp);
lua_concat(L, 2);
return lua_error(L);
}
LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
int en = errno; /* calls to Lua API may change this value */
if (stat) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushnil(L);
if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en));
else
lua_pushstring(L, strerror(en));
lua_pushinteger(L, en);
return 3;
}
}
#if !defined(l_inspectstat) /* { */
#if defined(LUA_USE_POSIX)
#include
/*
** use appropriate macros to interpret 'pclose' return status
*/
#define l_inspectstat(stat,what) \
if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
#else
#define l_inspectstat(stat,what) /* no op */
#endif
#endif /* } */
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
const char *what = "exit"; /* type of termination */
if (stat == -1) /* error? */
return luaL_fileresult(L, 0, NULL);
else {
l_inspectstat(stat, what); /* interpret result */
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
else
lua_pushnil(L);
lua_pushstring(L, what);
lua_pushinteger(L, stat);
return 3; /* return true/nil,what,code */
}
}
/* }====================================================== */
/*
** {======================================================
** Userdata's metatable manipulation
** =======================================================
*/
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
- if (luaL_getmetatable(L, tname)) /* name already in use? */
+ if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
- lua_newtable(L); /* create metatable */
+ 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;
}
LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
luaL_getmetatable(L, tname);
lua_setmetatable(L, -2);
}
LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
void *p = lua_touserdata(L, ud);
if (p != NULL) { /* value is a userdata? */
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
luaL_getmetatable(L, tname); /* get correct metatable */
if (!lua_rawequal(L, -1, -2)) /* not the same? */
p = NULL; /* value is a userdata with wrong metatable */
lua_pop(L, 2); /* remove both metatables */
return p;
}
}
return NULL; /* value is not a userdata with a metatable */
}
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
void *p = luaL_testudata(L, ud, tname);
if (p == NULL) typeerror(L, ud, tname);
return p;
}
/* }====================================================== */
/*
** {======================================================
** Argument check functions
** =======================================================
*/
LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
const char *const lst[]) {
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, 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
luaL_error(L, "stack overflow");
}
}
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 arg) {
if (lua_type(L, arg) == LUA_TNONE)
luaL_argerror(L, arg, "value expected");
}
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 arg,
const char *def, size_t *len) {
if (lua_isnoneornil(L, arg)) {
if (len)
*len = (def ? strlen(def) : 0);
return def;
}
else return luaL_checklstring(L, arg, len);
}
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
int isnum;
lua_Number d = lua_tonumberx(L, arg, &isnum);
if (!isnum)
tag_error(L, arg, LUA_TNUMBER);
return d;
}
LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
return luaL_opt(L, luaL_checknumber, arg, def);
}
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_Integer luaL_checkinteger (lua_State *L, int arg) {
int isnum;
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 arg,
lua_Integer def) {
return luaL_opt(L, luaL_checkinteger, arg, def);
}
/* }====================================================== */
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
+/* 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
*/
#define buffonstack(B) ((B)->b != (B)->initb)
/*
** returns a pointer to a free area with at least 'sz' bytes
*/
LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
lua_State *L = B->L;
if (B->size - B->n < sz) { /* not enough space? */
char *newbuff;
size_t newsize = B->size * 2; /* double buffer size */
if (newsize - B->n < sz) /* not big enough? */
newsize = B->n + 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;
}
return &B->b[B->n];
}
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);
+ }
}
LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
luaL_addlstring(B, s, strlen(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 */
+ }
}
LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
luaL_addsize(B, sz);
luaL_pushresult(B);
}
LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
lua_State *L = B->L;
size_t l;
const char *s = lua_tolstring(L, -1, &l);
if (buffonstack(B))
lua_insert(L, -2); /* put value below buffer */
luaL_addlstring(B, s, l);
lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */
}
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
B->L = L;
B->b = B->initb;
B->n = 0;
B->size = LUAL_BUFFERSIZE;
}
LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
luaL_buffinit(L, B);
return luaL_prepbuffsize(B, sz);
}
/* }====================================================== */
/*
** {======================================================
** Reference system
** =======================================================
*/
/* index of free-list header */
#define freelist 0
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 */
}
t = lua_absindex(L, t);
lua_rawgeti(L, t, freelist); /* get first free element */
ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */
lua_pop(L, 1); /* remove it from stack */
if (ref != 0) { /* any free element? */
lua_rawgeti(L, t, ref); /* remove it from list */
lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */
}
else /* no free elements */
ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */
lua_rawseti(L, t, ref);
return ref;
}
LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
if (ref >= 0) {
t = lua_absindex(L, t);
lua_rawgeti(L, t, freelist);
lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */
lua_pushinteger(L, ref);
lua_rawseti(L, t, freelist); /* t[freelist] = ref */
}
}
/* }====================================================== */
/*
** {======================================================
** Load functions
** =======================================================
*/
typedef struct LoadF {
int n; /* number of pre-read characters */
FILE *f; /* file being read */
char buff[BUFSIZ]; /* area for reading file */
} LoadF;
static const char *getF (lua_State *L, void *ud, size_t *size) {
LoadF *lf = (LoadF *)ud;
(void)L; /* not used */
if (lf->n > 0) { /* are there pre-read characters to be read? */
*size = lf->n; /* return them (chars already in buffer) */
lf->n = 0; /* no more pre-read characters */
}
else { /* read a block from file */
/* 'fread' can return > 0 *and* set the EOF flag. If next call to
'getF' called 'fread', it might still wait for user input.
The next check avoids this problem. */
if (feof(lf->f)) return NULL;
*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */
}
return lf->buff;
}
static int errfile (lua_State *L, const char *what, int fnameindex) {
const char *serr = strerror(errno);
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
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 {
c = getc(lf->f);
if (c == EOF || c != *(const unsigned char *)p++) return c;
lf->buff[lf->n++] = c; /* to be read by the parser */
} while (*p != '\0');
lf->n = 0; /* prefix matched; discard it */
return getc(lf->f); /* return next character */
}
/*
** reads the first character of file 'f' and skips an optional BOM mark
** in its beginning plus its first line if it starts with '#'. Returns
** true if it skipped the first line. In any case, '*cp' has the
** first "valid" character of the file (after the optional BOM and
** a first-line comment).
*/
static int skipcomment (LoadF *lf, int *cp) {
int c = *cp = skipBOM(lf);
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 */
}
else return 0; /* no comment */
}
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode) {
LoadF lf;
int status, readstatus;
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
if (filename == NULL) {
lua_pushliteral(L, "=stdin");
lf.f = stdin;
}
else {
lua_pushfstring(L, "@%s", filename);
lf.f = fopen(filename, "r");
if (lf.f == NULL) return errfile(L, "open", fnameindex);
}
if (skipcomment(&lf, &c)) /* read initial portion */
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
skipcomment(&lf, &c); /* re-read initial portion */
}
if (c != EOF)
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
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' */
return errfile(L, "read", fnameindex);
}
lua_remove(L, fnameindex);
return status;
}
typedef struct LoadS {
const char *s;
size_t size;
} LoadS;
static const char *getS (lua_State *L, void *ud, size_t *size) {
LoadS *ls = (LoadS *)ud;
(void)L; /* not used */
if (ls->size == 0) return NULL;
*size = ls->size;
ls->size = 0;
return ls->s;
}
LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
const char *name, const char *mode) {
LoadS ls;
ls.s = buff;
ls.size = size;
return lua_load(L, getS, &ls, name, mode);
}
LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
return luaL_loadbuffer(L, s, strlen(s), s);
}
/* }====================================================== */
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
if (!lua_getmetatable(L, obj)) /* no metatable? */
return LUA_TNIL;
else {
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) == LUA_TNIL) /* no metafield? */
return 0;
lua_pushvalue(L, obj);
lua_call(L, 1, 1);
return 1;
}
LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
lua_Integer l;
int isnum;
lua_len(L, idx);
l = lua_tointegerx(L, -1, &isnum);
if (!isnum)
luaL_error(L, "object length is not an integer");
lua_pop(L, 1); /* remove object */
return l;
}
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
- if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
+ if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */
+ if (!lua_isstring(L, -1))
+ luaL_error(L, "'__tostring' must return a string");
+ }
+ else {
switch (lua_type(L, idx)) {
case LUA_TNUMBER: {
if (lua_isinteger(L, idx))
- lua_pushfstring(L, "%I", lua_tointeger(L, idx));
+ lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
else
- lua_pushfstring(L, "%f", lua_tonumber(L, idx));
+ lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
break;
}
case LUA_TSTRING:
lua_pushvalue(L, idx);
break;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
break;
- default:
- lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
- lua_topointer(L, idx));
+ default: {
+ int tt = luaL_getmetafield(L, idx, "__name"); /* try name */
+ const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) :
+ luaL_typename(L, idx);
+ lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx));
+ if (tt != LUA_TNIL)
+ lua_remove(L, -2); /* remove '__name' */
break;
+ }
}
}
return lua_tolstring(L, -1, len);
}
/*
** {======================================================
** Compatibility with 5.1 module functions
** =======================================================
*/
#if defined(LUA_COMPAT_MODULE)
static const char *luaL_findtable (lua_State *L, int idx,
const char *fname, int szhint) {
const char *e;
if (idx) lua_pushvalue(L, idx);
do {
e = strchr(fname, '.');
if (e == NULL) e = fname + strlen(fname);
lua_pushlstring(L, fname, e - fname);
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);
lua_pushvalue(L, -2);
lua_settable(L, -4); /* set new table into field */
}
else if (!lua_istable(L, -1)) { /* field has a non-table value? */
lua_pop(L, 2); /* remove table and value */
return fname; /* return problematic part of the name */
}
lua_remove(L, -2); /* remove previous table */
fname = e + 1;
} while (*e == '.');
return NULL;
}
/*
** Count number of elements in a luaL_Reg list.
*/
static int libsize (const luaL_Reg *l) {
int size = 0;
for (; l && l->name; l++) size++;
return size;
}
/*
** Find or create a module table with a given name. The function
-** first looks at the _LOADED table and, if that fails, try a
+** first looks at the LOADED table and, if that fails, try a
** global variable with that name. In any case, leaves on the stack
** the module table.
*/
LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
int sizehint) {
- luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */
- if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */
+ luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1);
+ 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 '%s'", modname);
lua_pushvalue(L, -1);
- lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */
+ lua_setfield(L, -3, modname); /* LOADED[modname] = new table */
}
- lua_remove(L, -2); /* remove _LOADED table */
+ lua_remove(L, -2); /* remove LOADED table */
}
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
const luaL_Reg *l, int nup) {
luaL_checkversion(L);
if (libname) {
luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */
lua_insert(L, -(nup + 1)); /* move library table to below upvalues */
}
if (l)
luaL_setfuncs(L, l, nup);
else
lua_pop(L, nup); /* remove upvalues */
}
#endif
/* }====================================================== */
/*
** set functions from list 'l' into table at top - 'nup'; each
** function gets the 'nup' elements at the top as upvalues.
** Returns with only the table at the stack.
*/
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
luaL_checkstack(L, nup, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */
int i;
for (i = 0; i < nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
lua_setfield(L, -(nup + 2), l->name);
}
lua_pop(L, nup); /* remove upvalues */
}
/*
** ensure that stack[idx][fname] has a table and push that table
** into the stack
*/
LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
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);
lua_newtable(L);
lua_pushvalue(L, -1); /* copy to be left at top */
lua_setfield(L, idx, fname); /* assign new table to field */
return 0; /* false, because did not find table there */
}
}
/*
** 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) {
- luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
- lua_getfield(L, -1, modname); /* _LOADED[modname] */
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_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_setfield(L, -3, modname); /* LOADED[modname] = module */
}
- lua_remove(L, -2); /* remove _LOADED table */
+ lua_remove(L, -2); /* remove LOADED table */
if (glb) {
lua_pushvalue(L, -1); /* copy of module */
lua_setglobal(L, modname); /* _G[modname] = module */
}
}
LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
const char *r) {
const char *wild;
size_t l = strlen(p);
luaL_Buffer b;
luaL_buffinit(L, &b);
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' */
}
luaL_addstring(&b, s); /* push last suffix */
luaL_pushresult(&b);
return lua_tostring(L, -1);
}
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
free(ptr);
return NULL;
}
else
return realloc(ptr, nsize);
}
static int panic (lua_State *L) {
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
lua_tostring(L, -1));
return 0; /* return to Lua to abort */
}
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (L) lua_atpanic(L, &panic);
return L;
}
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);
+ (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v);
}
Index: vendor/lua/dist/src/lauxlib.h
===================================================================
--- vendor/lua/dist/src/lauxlib.h (revision 326343)
+++ vendor/lua/dist/src/lauxlib.h (revision 326344)
@@ -1,256 +1,264 @@
/*
-** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp $
+** $Id: lauxlib.h,v 1.131 2016/12/06 14:54:31 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
#ifndef lauxlib_h
#define lauxlib_h
#include
#include
#include "lua.h"
-/* extra error code for 'luaL_load' */
+/* extra error code for 'luaL_loadfilex' */
#define LUA_ERRFILE (LUA_ERRERR+1)
+/* key, in the registry, for table of loaded modules */
+#define LUA_LOADED_TABLE "_LOADED"
+
+
+/* key, in the registry, for table of preloaded loaders */
+#define LUA_PRELOAD_TABLE "_PRELOAD"
+
+
typedef struct luaL_Reg {
const char *name;
lua_CFunction func;
} luaL_Reg;
#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 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 arg,
const char *def, size_t *l);
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 arg);
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
lua_Integer def);
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
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);
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
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 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)
LUALIB_API int (luaL_ref) (lua_State *L, int t);
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
const char *name, const char *mode);
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
LUALIB_API lua_State *(luaL_newstate) (void);
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);
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
const char *msg, int level);
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
lua_CFunction openf, int glb);
/*
** ===============================================================
** some useful macros
** ===============================================================
*/
#define luaL_newlibtable(L,l) \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) \
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
#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_typename(L,i) lua_typename(L, lua_type(L,(i)))
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
/*
** {======================================================
** Generic Buffer manipulation
** =======================================================
*/
typedef struct luaL_Buffer {
char *b; /* buffer address */
size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L;
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
} luaL_Buffer;
#define luaL_addchar(B,c) \
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
((B)->b[(B)->n++] = (c)))
#define luaL_addsize(B,s) ((B)->n += (s))
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
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);
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
/* }====================================================== */
/*
** {======================================================
** File handles for IO library
** =======================================================
*/
/*
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
** initial structure 'luaL_Stream' (it may contain other fields
** after that initial structure).
*/
#define LUA_FILEHANDLE "FILE*"
typedef struct luaL_Stream {
FILE *f; /* stream (NULL for incompletely created streams) */
lua_CFunction closef; /* to close stream (NULL for closed streams) */
} luaL_Stream;
/* }====================================================== */
/* compatibility with old module system */
#if defined(LUA_COMPAT_MODULE)
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
int sizehint);
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
const luaL_Reg *l, int nup);
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
#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: vendor/lua/dist/src/lbaselib.c
===================================================================
--- vendor/lua/dist/src/lbaselib.c (revision 326343)
+++ vendor/lua/dist/src/lbaselib.c (revision 326344)
@@ -1,520 +1,498 @@
/*
-** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp $
+** $Id: lbaselib.c,v 1.314 2016/09/05 19:06:34 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
#define lbaselib_c
#define LUA_LIB
#include "lprefix.h"
#include
#include
#include
#include
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int luaB_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
size_t l;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tolstring(L, -1, &l); /* get result */
if (s == NULL)
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 */
}
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;
+ : (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? */
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;
lua_Integer n = 0; /* to avoid warnings */
lua_Integer base = luaL_checkinteger(L, 2);
- luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */
- s = luaL_checklstring(L, 1, &l);
+ 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");
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 = (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);
}
return lua_error(L);
}
static int luaB_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L);
return 1; /* no metatable */
}
luaL_getmetafield(L, 1, "__metatable");
return 1; /* returns either __metatable field (if present) or metatable */
}
static int luaB_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
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") != LUA_TNIL)
return luaL_error(L, "cannot change a protected metatable");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1;
}
static int luaB_rawequal (lua_State *L) {
luaL_checkany(L, 1);
luaL_checkany(L, 2);
lua_pushboolean(L, lua_rawequal(L, 1, 2));
return 1;
}
static int luaB_rawlen (lua_State *L) {
int t = lua_type(L, 1);
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
"table or string expected");
lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
}
static int luaB_rawget (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_rawget(L, 1);
return 1;
}
static int luaB_rawset (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checkany(L, 2);
luaL_checkany(L, 3);
lua_settop(L, 3);
lua_rawset(L, 1);
return 1;
}
static int luaB_collectgarbage (lua_State *L) {
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
"isrunning", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCISRUNNING};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
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, (lua_Number)res + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: case LUA_GCISRUNNING: {
lua_pushboolean(L, res);
return 1;
}
default: {
lua_pushinteger(L, res);
return 1;
}
}
}
-/*
-** This function has all type names as upvalues, to maximize performance.
-*/
static int luaB_type (lua_State *L) {
- luaL_checkany(L, 1);
- lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 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) {
+ luaL_checkany(L, 1);
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, */
if (iszero) lua_pushinteger(L, 0); /* and initial value */
else lua_pushnil(L);
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
lua_call(L, 1, 3); /* get 3 values from metamethod */
}
return 3;
}
static int luaB_next (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
if (lua_next(L, 1))
return 2;
else {
lua_pushnil(L);
return 1;
}
}
static int luaB_pairs (lua_State *L) {
return pairsmeta(L, "__pairs", 0, luaB_next);
}
/*
-** Traversal function for 'ipairs' for raw tables
+** Traversal function for 'ipairs'
*/
-static int ipairsaux_raw (lua_State *L) {
- lua_Integer i = luaL_checkinteger(L, 2) + 1;
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_pushinteger(L, i);
- return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2;
-}
-
-
-/*
-** Traversal function for 'ipairs' for tables with metamethods
-*/
static int ipairsaux (lua_State *L) {
lua_Integer i = luaL_checkinteger(L, 2) + 1;
lua_pushinteger(L, i);
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
}
/*
-** This function will use either 'ipairsaux' or 'ipairsaux_raw' to
-** traverse a table, depending on whether the table has metamethods
-** that can affect the traversal.
+** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
+** (The given "table" may not be a table.)
*/
static int luaB_ipairs (lua_State *L) {
- lua_CFunction iter = (luaL_getmetafield(L, 1, "__index") != LUA_TNIL)
- ? ipairsaux : ipairsaux_raw;
#if defined(LUA_COMPAT_IPAIRS)
- return pairsmeta(L, "__ipairs", 1, iter);
+ return pairsmeta(L, "__ipairs", 1, ipairsaux);
#else
luaL_checkany(L, 1);
- lua_pushcfunction(L, iter); /* iteration function */
+ lua_pushcfunction(L, ipairsaux); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
#endif
}
static int load_aux (lua_State *L, int status, int envidx) {
if (status == LUA_OK) {
if (envidx != 0) { /* 'env' parameter? */
lua_pushvalue(L, envidx); /* environment for loaded function */
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
lua_pop(L, 1); /* remove 'env' if not used by previous call */
}
return 1;
}
else { /* error (message is on top of the stack) */
lua_pushnil(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return nil plus error message */
}
}
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
const char *mode = luaL_optstring(L, 2, NULL);
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
int status = luaL_loadfilex(L, fname, mode);
return load_aux(L, status, env);
}
/*
** {======================================================
** Generic Read function
** =======================================================
*/
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** 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.
*/
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
else if (!lua_isstring(L, -1))
luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
return lua_tolstring(L, RESERVEDSLOT, size);
}
static int luaB_load (lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = luaL_loadbufferx(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = lua_load(L, generic_reader, NULL, chunkname, mode);
}
return load_aux(L, status, env);
}
/* }====================================================== */
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;
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
lua_settop(L, 1);
if (luaL_loadfile(L, fname) != LUA_OK)
return lua_error(L);
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
return dofilecont(L, 0, 0);
}
static int luaB_assert (lua_State *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' */
}
}
static int luaB_select (lua_State *L) {
int n = lua_gettop(L);
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
lua_pushinteger(L, n-1);
return 1;
}
else {
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 - (int)i;
}
}
/*
** 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 */
}
else
return lua_gettop(L) - (int)extra; /* return all results */
}
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
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 ; 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_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);
}
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
#if defined(LUA_COMPAT_LOADSTRING)
{"loadstring", luaB_load},
#endif
{"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"rawequal", luaB_rawequal},
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"select", luaB_select},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
+ {"type", luaB_type},
{"xpcall", luaB_xpcall},
/* placeholders */
- {"type", NULL},
{"_G", NULL},
{"_VERSION", NULL},
{NULL, NULL}
};
LUAMOD_API int luaopen_base (lua_State *L) {
- int i;
/* open lib into global table */
lua_pushglobaltable(L);
luaL_setfuncs(L, base_funcs, 0);
/* set global _G */
lua_pushvalue(L, -1);
lua_setfield(L, -2, "_G");
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
- /* set function 'type' with proper upvalues */
- for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */
- lua_pushstring(L, lua_typename(L, i));
- lua_pushcclosure(L, luaB_type, LUA_NUMTAGS);
- lua_setfield(L, -2, "type");
return 1;
}
Index: vendor/lua/dist/src/lbitlib.c
===================================================================
--- vendor/lua/dist/src/lbitlib.c (revision 326343)
+++ vendor/lua/dist/src/lbitlib.c (revision 326344)
@@ -1,230 +1,233 @@
/*
-** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 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
*/
#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)
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
static lua_Unsigned andaux (lua_State *L) {
int i, n = lua_gettop(L);
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) {
lua_Unsigned r = andaux(L);
- lua_pushunsigned(L, r);
+ pushunsigned(L, r);
return 1;
}
static int b_test (lua_State *L) {
lua_Unsigned r = andaux(L);
lua_pushboolean(L, r != 0);
return 1;
}
static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
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);
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) {
- lua_Unsigned 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, lua_Unsigned r, lua_Integer i) {
if (i < 0) { /* shift right? */
i = -i;
r = trim(r);
if (i >= LUA_NBITS) r = 0;
else r >>= i;
}
else { /* shift left */
if (i >= LUA_NBITS) r = 0;
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_checkinteger(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_checkinteger(L, 2));
+ return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
}
static int b_arshift (lua_State *L) {
- lua_Unsigned r = luaL_checkunsigned(L, 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) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
- lua_pushunsigned(L, r);
+ pushunsigned(L, r);
return 1;
}
}
static int b_rot (lua_State *L, lua_Integer d) {
- lua_Unsigned r = luaL_checkunsigned(L, 1);
+ 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_checkinteger(L, 2));
}
static int b_rrot (lua_State *L) {
return b_rot(L, -luaL_checkinteger(L, 2));
}
/*
** get field and width arguments for field-manipulation functions,
** checking whether they are valid.
** ('luaL_error' called without 'return' to avoid later warnings about
** 'width' being used uninitialized.)
*/
static int fieldargs (lua_State *L, int farg, int *width) {
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 = (int)w;
return (int)f;
}
static int b_extract (lua_State *L) {
int w;
- lua_Unsigned r = trim(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;
- lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
- lua_Unsigned 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;
}
static const luaL_Reg bitlib[] = {
{"arshift", b_arshift},
{"band", b_and},
{"bnot", b_not},
{"bor", b_or},
{"bxor", b_xor},
{"btest", b_test},
{"extract", b_extract},
{"lrotate", b_lrot},
{"lshift", b_lshift},
{"replace", b_replace},
{"rrotate", b_rrot},
{"rshift", b_rshift},
{NULL, NULL}
};
LUAMOD_API int luaopen_bit32 (lua_State *L) {
luaL_newlib(L, bitlib);
return 1;
}
#else /* }{ */
LUAMOD_API int luaopen_bit32 (lua_State *L) {
return luaL_error(L, "library 'bit32' has been deprecated");
}
#endif /* } */
Index: vendor/lua/dist/src/lcode.c
===================================================================
--- vendor/lua/dist/src/lcode.c (revision 326343)
+++ vendor/lua/dist/src/lcode.c (revision 326344)
@@ -1,954 +1,1203 @@
/*
-** $Id: lcode.c,v 2.99 2014/12/29 16:49:25 roberto Exp $
+** $Id: lcode.c,v 2.112 2016/12/22 13:08:50 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
#define lcode_c
#define LUA_CORE
#include "lprefix.h"
#include
#include
#include "lua.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "llex.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
#include "lstring.h"
#include "ltable.h"
#include "lvm.h"
-/* Maximum number of registers in a Lua function */
-#define MAXREGS 250
+/* Maximum number of registers in a Lua function (must fit in 8 bits) */
+#define MAXREGS 255
#define hasjumps(e) ((e)->t != (e)->f)
-static int tonumeral(expdesc *e, TValue *v) {
- if (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(const 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? */
if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */
if (pl > l) l = pl; /* l = max(l, pl) */
SETARG_A(*previous, from);
SETARG_B(*previous, l - from);
return;
}
} /* else go through */
}
luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */
}
+/*
+** 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
** optimizations with consecutive instructions not in the same basic block).
*/
int luaK_getlabel (FuncState *fs) {
fs->lasttarget = fs->pc;
return fs->pc;
}
-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))))
return pi-1;
else
return pi;
}
/*
-** 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) {
int next = getjump(fs, list);
if (patchtestreg(fs, list, reg))
fixjump(fs, list, vtarget);
else
fixjump(fs, list, dtarget); /* jump to default target */
list = next;
}
}
+/*
+** 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);
}
}
+/*
+** 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 */
/* put new instruction in code array */
luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
MAX_INT, "opcodes");
f->code[fs->pc] = i;
/* save corresponding line information */
luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
MAX_INT, "opcodes");
f->lineinfo[fs->pc] = fs->ls->lastline;
return fs->pc++;
}
+/*
+** 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);
lua_assert(getCMode(o) != OpArgN || c == 0);
lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C);
return luaK_code(fs, CREATE_ABC(o, a, b, 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);
lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx);
return luaK_code(fs, CREATE_ABx(o, a, 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);
else {
int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
codeextraarg(fs, k);
return p;
}
}
+/*
+** 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 >= MAXREGS)
- luaX_syntaxerror(fs->ls, "function or expression too complex");
+ luaX_syntaxerror(fs->ls,
+ "function or expression needs too many registers");
fs->f->maxstacksize = cast_byte(newstack);
}
}
+/*
+** 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--;
lua_assert(reg == fs->freereg);
}
}
+/*
+** 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
+** 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;
Proto *f = fs->f;
TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */
int k, oldsize;
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 */
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);
fs->nk++;
luaC_barrier(L, f, v);
return k;
}
+/*
+** 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 */
}
/*
-** Integers use userdata as keys to avoid collision with floats with same
-** value; conversion to 'void*' used only for hashing, no "precision"
-** problems
+** 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;
setfltvalue(&o, r);
- return addk(fs, &o, &o);
+ 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->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;
}
default: break; /* there is one value available (somewhere) */
}
}
-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) {
case VNIL: {
luaK_nil(fs, reg, 1);
break;
}
case VFALSE: case VTRUE: {
luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
break;
}
case VK: {
luaK_codek(fs, reg, e->u.info);
break;
}
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: {
if (reg != e->u.info)
luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
break;
}
default: {
- lua_assert(e->k == VVOID || e->k == VJMP);
+ lua_assert(e->k == VJMP);
return; /* nothing to do... */
}
}
e->u.info = reg;
e->k = VNONRELOC;
}
+/*
+** 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)
+ 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);
patchlistaux(fs, e->f, final, reg, p_f);
patchlistaux(fs, e->t, final, reg, p_t);
}
e->f = e->t = NO_JUMP;
e->u.info = reg;
e->k = VNONRELOC;
}
+/*
+** 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);
luaK_reserveregs(fs, 1);
exp2reg(fs, e, fs->freereg - 1);
}
+/*
+** 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);
else
luaK_dischargevars(fs, 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 VKINT: {
- e->u.info = luaK_intK(fs, e->u.ival);
- e->k = VK;
- goto vk;
- }
- case VKFLT: {
- e->u.info = luaK_numberK(fs, e->u.nval);
- e->k = VK;
- /* go through */
- }
- case VK: {
+ 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;
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 */
return luaK_exp2anyreg(fs, 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: {
int e = luaK_exp2anyreg(fs, ex);
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
break;
}
case VINDEXED: {
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
int e = luaK_exp2RK(fs, 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);
SETARG_A(*pc, !(GETARG_A(*pc)));
}
+/*
+** 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);
}
/* else go through */
}
discharge2anyreg(fs, e);
freeexp(fs, e);
return condjump(fs, OP_TESTSET, NO_REG, e->u.info, 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 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: {
pc = NO_JUMP; /* always false; do nothing */
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 VKFLT: case VKINT: case VTRUE: {
- e->k = VFALSE;
+ 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:
case VNONRELOC: {
discharge2anyreg(fs, e);
freeexp(fs, e);
e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
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;
}
/*
-** return false if folding can raise an error
+** 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 */
}
}
/*
-** Try to "constant-fold" an operation; return 1 iff successful
+** 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) {
+static int constfolding (FuncState *fs, int op, expdesc *e1,
+ const 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 collapsing with -0.0) */
+ 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;
}
/*
-** Code for binary and unary expressions that "produce values"
-** (arithmetic operations, bitwise operations, concat, length). First
-** try to do constant folding (only for numeric [arithmetic and
-** bitwise] operations, which is what 'lua_arith' accepts).
+** 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'.
+** Because 'luaK_exp2RK' can free registers, its calls must be
+** in "stack order" (that is, first on 'e2', which may have more
+** recent registers to be released).
*/
-static void codeexpval (FuncState *fs, OpCode op,
- expdesc *e1, expdesc *e2, int line) {
- lua_assert(op >= OP_ADD);
- if (op <= OP_BNOT && constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2))
- return; /* result has been folded */
- else {
- int o1, o2;
- /* move operands to registers (if needed) */
- if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { /* unary op? */
- o2 = 0; /* no second expression */
- o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */
+static void codebinexpval (FuncState *fs, OpCode op,
+ expdesc *e1, expdesc *e2, int line) {
+ int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
+ int rk1 = luaK_exp2RK(fs, e1);
+ 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;
}
- else { /* regular case (binary operators) */
- o2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
- o1 = luaK_exp2RK(fs, e1);
+ 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;
}
- if (o1 > o2) { /* free registers in proper order */
- freeexp(fs, e1);
- freeexp(fs, e2);
+ default: { /* '==', '<', '<=' use their own opcodes */
+ OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ);
+ e1->u.info = condjump(fs, op, 1, rk1, rk2);
+ break;
}
- else {
- freeexp(fs, e2);
- freeexp(fs, e1);
- }
- e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */
- e1->k = VRELOCABLE; /* all those operations are relocable */
- luaK_fixline(fs, line);
}
-}
-
-
-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;
- }
- 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 = VKINT; e2.u.ival = 0;
+ static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};
switch (op) {
- case OPR_MINUS: case OPR_BNOT: case OPR_LEN: {
- codeexpval(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line);
+ case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */
+ 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;
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' */
break;
}
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);
+ if (!tonumeral(v, NULL))
+ luaK_exp2RK(fs, v);
+ /* else keep numeral, which may be folded with 2nd operand */
break;
}
default: {
luaK_exp2RK(fs, v);
break;
}
}
}
+/*
+** 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;
break;
}
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' */
- codeexpval(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_IDIV: case OPR_MOD: case OPR_POW:
case OPR_BAND: case OPR_BOR: case OPR_BXOR:
case OPR_SHL: case OPR_SHR: {
- codeexpval(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line);
+ 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: {
- codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2);
- 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);
}
}
+/*
+** 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) {
luaK_codeABC(fs, OP_SETLIST, base, b, 0);
codeextraarg(fs, c);
}
else
luaX_syntaxerror(fs->ls, "constructor too long");
fs->freereg = base + 1; /* free registers with list values */
}
Index: vendor/lua/dist/src/lcode.h
===================================================================
--- vendor/lua/dist/src/lcode.h (revision 326343)
+++ vendor/lua/dist/src/lcode.h (revision 326344)
@@ -1,87 +1,88 @@
/*
-** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 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
*/
#ifndef lcode_h
#define lcode_h
#include "llex.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
/*
** Marks the end of a patch list. It is an invalid value both as an absolute
** address, and as a list link (would link an element to itself).
*/
#define NO_JUMP (-1)
/*
** grep "ORDER OPR" if you change these enums (ORDER OP)
*/
typedef enum BinOpr {
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,
OPR_AND, OPR_OR,
OPR_NOBINOPR
} BinOpr;
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)
#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET)
#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
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_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);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_jump (FuncState *fs);
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
expdesc *v2, int line);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
#endif
Index: vendor/lua/dist/src/lcorolib.c
===================================================================
--- vendor/lua/dist/src/lcorolib.c (revision 326343)
+++ vendor/lua/dist/src/lcorolib.c (revision 326344)
@@ -1,168 +1,168 @@
/*
-** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 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 "lprefix.h"
#include
#include "lua.h"
#include "lauxlib.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)) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
lua_pushliteral(L, "cannot resume dead coroutine");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resume(co, L, narg);
if (status == LUA_OK || status == LUA_YIELD) {
int nres = lua_gettop(co);
if (!lua_checkstack(L, nres + 1)) {
lua_pop(co, nres); /* remove results anyway */
lua_pushliteral(L, "too many results to resume");
return -1; /* error flag */
}
lua_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
lua_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int luaB_coresume (lua_State *L) {
lua_State *co = getco(L);
int r;
r = auxresume(L, co, lua_gettop(L) - 1);
if (r < 0) {
lua_pushboolean(L, 0);
lua_insert(L, -2);
return 2; /* return false + error message */
}
else {
lua_pushboolean(L, 1);
lua_insert(L, -(r + 1));
return r + 1; /* return true + 'resume' returns */
}
}
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);
}
return lua_error(L); /* propagate error */
}
return r;
}
static int luaB_cocreate (lua_State *L) {
lua_State *NL;
luaL_checktype(L, 1, LUA_TFUNCTION);
NL = lua_newthread(L);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int luaB_cowrap (lua_State *L) {
luaB_cocreate(L);
lua_pushcclosure(L, luaB_auxwrap, 1);
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static int luaB_costatus (lua_State *L) {
lua_State *co = getco(L);
if (L == co) lua_pushliteral(L, "running");
else {
switch (lua_status(co)) {
case LUA_YIELD:
lua_pushliteral(L, "suspended");
break;
case LUA_OK: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
lua_pushliteral(L, "normal"); /* it is running */
else if (lua_gettop(co) == 0)
lua_pushliteral(L, "dead");
else
lua_pushliteral(L, "suspended"); /* initial state */
break;
}
default: /* some error occurred */
lua_pushliteral(L, "dead");
break;
}
}
return 1;
}
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);
return 2;
}
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{"isyieldable", luaB_yieldable},
{NULL, NULL}
};
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}
Index: vendor/lua/dist/src/ldblib.c
===================================================================
--- vendor/lua/dist/src/ldblib.c (revision 326343)
+++ vendor/lua/dist/src/ldblib.c (revision 326344)
@@ -1,437 +1,456 @@
/*
-** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 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
#include
#include
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** 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");
+}
+
+
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
return 1;
}
static int db_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1; /* return 1st argument */
}
static int db_getuservalue (lua_State *L) {
if (lua_type(L, 1) != LUA_TUSERDATA)
lua_pushnil(L);
else
lua_getuservalue(L, 1);
return 1;
}
static int db_setuservalue (lua_State *L) {
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checkany(L, 2);
lua_settop(L, 2);
lua_setuservalue(L, 1);
return 1;
}
/*
** 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;
return lua_tothread(L, 1);
}
else {
*arg = 0;
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_rotate(L, -2, 1); /* exchange object and table */
else
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_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;
}
}
if (!lua_getinfo(L1, options, &ar))
return luaL_argerror(L, arg+2, "invalid option");
lua_newtable(L); /* table to collect results */
if (strchr(options, 'S')) {
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabsi(L, "lastlinedefined", ar.lastlinedefined);
settabss(L, "what", ar.what);
}
if (strchr(options, 'l'))
settabsi(L, "currentline", ar.currentline);
if (strchr(options, 'u')) {
settabsi(L, "nups", ar.nups);
settabsi(L, "nparams", ar.nparams);
settabsb(L, "isvararg", ar.isvararg);
}
if (strchr(options, 'n')) {
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
}
if (strchr(options, 't'))
settabsb(L, "istailcall", ar.istailcall);
if (strchr(options, 'L'))
treatstackoption(L, L1, "activelines");
if (strchr(options, 'f'))
treatstackoption(L, L1, "func");
return 1; /* return table */
}
static int db_getlocal (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
const char *name;
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 only name (there is no value) */
}
else { /* stack-level argument */
int level = (int)luaL_checkinteger(L, arg + 1);
if (!lua_getstack(L1, level, &ar)) /* out of range? */
return luaL_argerror(L, arg+1, "level out of range");
+ checkstack(L, L1, 1);
name = lua_getlocal(L1, &ar, nvar);
if (name) {
lua_xmove(L1, L, 1); /* move local value */
lua_pushstring(L, name); /* push name */
lua_rotate(L, -2, 1); /* re-order */
return 2;
}
else {
lua_pushnil(L); /* no name (nor value) */
return 1;
}
}
}
static int db_setlocal (lua_State *L) {
int arg;
const char *name;
lua_State *L1 = getthread(L, &arg);
lua_Debug ar;
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);
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 = (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)); /* no-op if get is false */
return get + 1;
}
static int db_getupvalue (lua_State *L) {
return auxupvalue(L, 1);
}
static int db_setupvalue (lua_State *L) {
luaL_checkany(L, 3);
return auxupvalue(L, 0);
}
/*
** Check whether a given upvalue from a given closure exists and
** returns its index
*/
static int checkupval (lua_State *L, int argf, int argnup) {
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;
}
static int db_upvalueid (lua_State *L) {
int n = checkupval(L, 1, 2);
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1 = checkupval(L, 1, 2);
int n2 = checkupval(L, 3, 4);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
return 0;
}
/*
** 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"};
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
lua_pushthread(L);
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); /* push current line */
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
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;
if (strchr(smask, 'r')) mask |= LUA_MASKRET;
if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
/*
** 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';
if (mask & LUA_MASKRET) smask[i++] = 'r';
if (mask & LUA_MASKLINE) smask[i++] = 'l';
smask[i] = '\0';
return smask;
}
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)) { /* 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 = (int)luaL_optinteger(L, arg + 3, 0);
func = hookf; mask = makemask(smask, count);
}
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); /* 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;
}
static int db_gethook (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook == NULL) /* no hook? */
lua_pushnil(L);
else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else { /* hook table must exist */
lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
+ checkstack(L, L1, 1);
lua_pushthread(L1); lua_xmove(L1, L, 1);
lua_rawget(L, -2); /* 1st result = hooktable[L1] */
lua_remove(L, -2); /* remove hook table */
}
lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */
lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */
return 3;
}
static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
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))
lua_writestringerror("%s\n", lua_tostring(L, -1));
lua_settop(L, 0); /* remove eventual returns */
}
}
static int db_traceback (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
const char *msg = lua_tostring(L, arg + 1);
if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */
lua_pushvalue(L, arg + 1); /* return it untouched */
else {
int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0);
luaL_traceback(L, L1, msg, level);
}
return 1;
}
static const luaL_Reg dblib[] = {
{"debug", db_debug},
{"getuservalue", db_getuservalue},
{"gethook", db_gethook},
{"getinfo", db_getinfo},
{"getlocal", db_getlocal},
{"getregistry", db_getregistry},
{"getmetatable", db_getmetatable},
{"getupvalue", db_getupvalue},
{"upvaluejoin", db_upvaluejoin},
{"upvalueid", db_upvalueid},
{"setuservalue", db_setuservalue},
{"sethook", db_sethook},
{"setlocal", db_setlocal},
{"setmetatable", db_setmetatable},
{"setupvalue", db_setupvalue},
{"traceback", db_traceback},
{NULL, NULL}
};
LUAMOD_API int luaopen_debug (lua_State *L) {
luaL_newlib(L, dblib);
return 1;
}
Index: vendor/lua/dist/src/ldebug.c
===================================================================
--- vendor/lua/dist/src/ldebug.c (revision 326343)
+++ vendor/lua/dist/src/ldebug.c (revision 326344)
@@ -1,643 +1,698 @@
/*
-** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp $
+** $Id: ldebug.c,v 2.121 2016/10/19 12:32:10 roberto Exp $
** Debug Interface
** See Copyright Notice in lua.h
*/
#define ldebug_c
#define LUA_CORE
#include "lprefix.h"
#include
#include
#include
#include "lua.h"
#include "lapi.h"
#include "lcode.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL)
-static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
+/* Active Lua function (given call info) */
+#define ci_func(ci) (clLvalue((ci)->func))
+static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
+ const char **name);
+
+
static int currentpc (CallInfo *ci) {
lua_assert(isLua(ci));
return pcRel(ci->u.l.savedpc, ci_func(ci)->p);
}
static int currentline (CallInfo *ci) {
return getfuncline(ci_func(ci)->p, currentpc(ci));
}
/*
-** this function can be called asynchronous (e.g. during a signal)
+** If function yielded, its 'func' can be in the 'extra' field. The
+** next function restores 'func' to its correct value for debugging
+** purposes. (It exchanges 'func' and 'extra'; so, when called again,
+** after debugging, it also "re-restores" ** 'func' to its altered value.
*/
+static void swapextra (lua_State *L) {
+ if (L->status == LUA_YIELD) {
+ CallInfo *ci = L->ci; /* get function that yielded */
+ StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
+ ci->func = restorestack(L, ci->extra);
+ ci->extra = savestack(L, temp);
+ }
+}
+
+
+/*
+** This function can be called 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 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;
}
if (isLua(L->ci))
L->oldpc = L->ci->u.l.savedpc;
L->hook = func;
L->basehookcount = count;
resethookcount(L);
L->hookmask = cast_byte(mask);
}
LUA_API lua_Hook lua_gethook (lua_State *L) {
return L->hook;
}
LUA_API int lua_gethookmask (lua_State *L) {
return L->hookmask;
}
LUA_API int lua_gethookcount (lua_State *L) {
return L->basehookcount;
}
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
int status;
CallInfo *ci;
if (level < 0) return 0; /* invalid (negative) level */
lua_lock(L);
for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous)
level--;
if (level == 0 && ci != &L->base_ci) { /* level found? */
status = 1;
ar->i_ci = ci;
}
else status = 0; /* no such level */
lua_unlock(L);
return status;
}
static const char *upvalname (Proto *p, int uv) {
TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
if (s == NULL) return "?";
else return getstr(s);
}
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;
return "(*vararg)"; /* generic name for any vararg */
}
}
static const char *findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos) {
const char *name = NULL;
StkId base;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
return findvararg(ci, -n, pos);
else {
base = ci->u.l.base;
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
}
}
else
base = ci->func + 1;
if (name == NULL) { /* no 'standard' name? */
StkId limit = (ci == L->ci) ? L->top : ci->next->func;
if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
name = "(*temporary)"; /* generic name for any valid slot */
else
return NULL; /* no name */
}
*pos = base + (n - 1);
return name;
}
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
const char *name;
lua_lock(L);
+ swapextra(L);
if (ar == NULL) { /* information about non-active function? */
if (!isLfunction(L->top - 1)) /* not a Lua function? */
name = NULL;
else /* consider live variables at function start (parameters) */
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0);
}
else { /* active function; get information through 'ar' */
- StkId pos = 0; /* to avoid warnings */
+ StkId pos = NULL; /* to avoid warnings */
name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobj2s(L, L->top, pos);
api_incr_top(L);
}
}
+ swapextra(L);
lua_unlock(L);
return name;
}
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
- StkId pos = 0; /* to avoid warnings */
- const char *name = findlocal(L, ar->i_ci, n, &pos);
+ StkId pos = NULL; /* to avoid warnings */
+ const char *name;
lua_lock(L);
+ swapextra(L);
+ name = findlocal(L, ar->i_ci, n, &pos);
if (name) {
setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */
}
+ swapextra(L);
lua_unlock(L);
return name;
}
static void funcinfo (lua_Debug *ar, Closure *cl) {
if (noLuaClosure(cl)) {
ar->source = "=[C]";
ar->linedefined = -1;
ar->lastlinedefined = -1;
ar->what = "C";
}
else {
Proto *p = cl->l.p;
ar->source = p->source ? getstr(p->source) : "=?";
ar->linedefined = p->linedefined;
ar->lastlinedefined = p->lastlinedefined;
ar->what = (ar->linedefined == 0) ? "main" : "Lua";
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
}
static void collectvalidlines (lua_State *L, Closure *f) {
if (noLuaClosure(f)) {
setnilvalue(L->top);
api_incr_top(L);
}
else {
int i;
TValue v;
int *lineinfo = f->l.p->lineinfo;
Table *t = luaH_new(L); /* new table to store active lines */
sethvalue(L, L->top, t); /* push it on stack */
api_incr_top(L);
setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */
luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */
}
}
+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
+ if (ci == NULL) /* no 'ci'? */
+ return NULL; /* no info */
+ else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */
+ *name = "__gc";
+ return "metamethod"; /* report it as such */
+ }
+ /* calling function is a known Lua function? */
+ else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
+ return funcnamefromcode(L, ci->previous, name);
+ else return NULL; /* no way to find a name */
+}
+
+
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
Closure *f, CallInfo *ci) {
int status = 1;
for (; *what; what++) {
switch (*what) {
case 'S': {
funcinfo(ar, f);
break;
}
case 'l': {
ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1;
break;
}
case 'u': {
ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
if (noLuaClosure(f)) {
ar->isvararg = 1;
ar->nparams = 0;
}
else {
ar->isvararg = f->l.p->is_vararg;
ar->nparams = f->l.p->numparams;
}
break;
}
case 't': {
ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
break;
}
case 'n': {
- /* calling function is a known Lua function? */
- if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous))
- ar->namewhat = getfuncname(L, ci->previous, &ar->name);
- else
- ar->namewhat = NULL;
+ ar->namewhat = getfuncname(L, ci, &ar->name);
if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */
ar->name = NULL;
}
break;
}
case 'L':
case 'f': /* handled by lua_getinfo */
break;
default: status = 0; /* invalid option */
}
}
return status;
}
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
int status;
Closure *cl;
CallInfo *ci;
StkId func;
lua_lock(L);
+ swapextra(L);
if (*what == '>') {
ci = NULL;
func = L->top - 1;
- api_check(ttisfunction(func), "function expected");
+ api_check(L, ttisfunction(func), "function expected");
what++; /* skip the '>' */
L->top--; /* pop function */
}
else {
ci = ar->i_ci;
func = ci->func;
lua_assert(ttisfunction(ci->func));
}
cl = ttisclosure(func) ? clvalue(func) : NULL;
status = auxgetinfo(L, what, ar, cl, ci);
if (strchr(what, 'f')) {
setobjs2s(L, L->top, func);
api_incr_top(L);
}
+ swapextra(L); /* correct before option 'L', which can raise a mem. error */
if (strchr(what, 'L'))
collectvalidlines(L, cl);
lua_unlock(L);
return status;
}
/*
** {======================================================
** Symbolic Execution
** =======================================================
*/
static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name);
/*
** find a "name" for the RK value 'c'
*/
static void kname (Proto *p, int pc, int c, const char **name) {
if (ISK(c)) { /* is 'c' a constant? */
TValue *kvalue = &p->k[INDEXK(c)];
if (ttisstring(kvalue)) { /* literal constant? */
*name = svalue(kvalue); /* it is its own name */
return;
}
/* else no reasonable name found */
}
else { /* 'c' is a register */
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
if (what && *what == 'c') { /* found a constant name? */
return; /* 'name' already filled */
}
/* else no reasonable name found */
}
*name = "?"; /* no reasonable name found */
}
static int filterpc (int pc, int jmptarget) {
if (pc < jmptarget) /* is code conditional (inside a jump)? */
return -1; /* cannot know who sets that register */
else return pc; /* current position sets that register */
}
/*
** try to find last instruction before 'lastpc' that modified register 'reg'
*/
static int findsetreg (Proto *p, int lastpc, int reg) {
int pc;
int setreg = -1; /* keep last instruction that changed 'reg' */
int jmptarget = 0; /* any code before this address is conditional */
for (pc = 0; pc < lastpc; pc++) {
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
int a = GETARG_A(i);
switch (op) {
case OP_LOADNIL: {
int b = GETARG_B(i);
if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_TFORCALL: {
if (reg >= a + 2) /* affect all regs above its base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_CALL:
case OP_TAILCALL: {
if (reg >= a) /* affect all registers above base */
setreg = filterpc(pc, jmptarget);
break;
}
case OP_JMP: {
int b = GETARG_sBx(i);
int dest = pc + 1 + b;
/* jump is forward and do not skip 'lastpc'? */
if (pc < dest && dest <= lastpc) {
if (dest > jmptarget)
jmptarget = dest; /* update 'jmptarget' */
}
break;
}
default:
if (testAMode(op) && reg == a) /* any instruction that set A */
setreg = filterpc(pc, jmptarget);
break;
}
}
return setreg;
}
static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) {
int pc;
*name = luaF_getlocalname(p, reg + 1, lastpc);
if (*name) /* is a local? */
return "local";
/* else try symbolic execution */
pc = findsetreg(p, lastpc, reg);
if (pc != -1) { /* could find instruction? */
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
switch (op) {
case OP_MOVE: {
int b = GETARG_B(i); /* move from 'b' to 'a' */
if (b < GETARG_A(i))
return getobjname(p, pc, b, name); /* get name for 'b' */
break;
}
case OP_GETTABUP:
case OP_GETTABLE: {
int k = GETARG_C(i); /* key index */
int t = GETARG_B(i); /* table index */
const char *vn = (op == OP_GETTABLE) /* name of indexed variable */
? luaF_getlocalname(p, t + 1, pc)
: upvalname(p, t);
kname(p, pc, k, name);
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
}
case OP_GETUPVAL: {
*name = upvalname(p, GETARG_B(i));
return "upvalue";
}
case OP_LOADK:
case OP_LOADKX: {
int b = (op == OP_LOADK) ? GETARG_Bx(i)
: GETARG_Ax(p->code[pc + 1]);
if (ttisstring(&p->k[b])) {
*name = svalue(&p->k[b]);
return "constant";
}
break;
}
case OP_SELF: {
int k = GETARG_C(i); /* key index */
kname(p, pc, k, name);
return "method";
}
default: break; /* go through to return NULL */
}
}
return NULL; /* could not find reasonable name */
}
-static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
- TMS tm = (TMS)0; /* to avoid warnings */
+/*
+** Try to find a name for a function based on the code that called it.
+** (Only works when function was called by a Lua function.)
+** Returns what the name is (e.g., "for iterator", "method",
+** "metamethod") and sets '*name' to point to the name.
+*/
+static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
+ const char **name) {
+ TMS tm = (TMS)0; /* (initial value avoids 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 */
- return getobjname(p, pc, GETARG_A(i), name);
+ case OP_TAILCALL:
+ return getobjname(p, pc, GETARG_A(i), name); /* get function name */
case OP_TFORCALL: { /* for iterator */
*name = "for iterator";
return "for iterator";
}
- /* all other instructions can call only through metamethods */
+ /* other instructions can do calls 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_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;
- default: lua_assert(0); /* other instructions cannot call a function */
+ default:
+ return NULL; /* cannot find a reasonable name */
}
*name = getstr(G(L)->tmname[tm]);
return "metamethod";
}
/* }====================================================== */
/*
** 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) {
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);
int i;
for (i = 0; i < c->nupvalues; i++) {
if (c->upvals[i]->v == o) {
*name = upvalname(c->p, i);
return "upvalue";
}
}
return NULL;
}
static const char *varinfo (lua_State *L, const TValue *o) {
const char *name = NULL; /* to avoid warnings */
CallInfo *ci = L->ci;
const char *kind = NULL;
if (isLua(ci)) {
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
if (!kind && isinstack(ci, o)) /* no? try a register */
kind = getobjname(ci_func(ci)->p, currentpc(ci),
cast_int(o - ci->u.l.base), &name);
}
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 = objtypename(o);
+ 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, const TValue *p1, const TValue *p2) {
if (ttisstring(p1) || cvt2str(p1)) p1 = p2;
luaG_typeerror(L, p1, "concatenate");
}
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);
setobjs2s(L, L->top, L->top - 1); /* move argument */
setobjs2s(L, L->top - 1, errfunc); /* push function */
L->top++; /* assume EXTRA_STACK */
- luaD_call(L, L->top - 2, 1, 0); /* call it */
+ 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 = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
+ 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: vendor/lua/dist/src/ldebug.h
===================================================================
--- vendor/lua/dist/src/ldebug.h (revision 326343)
+++ vendor/lua/dist/src/ldebug.h (revision 326344)
@@ -1,40 +1,39 @@
/*
-** $Id: ldebug.h,v 2.12 2014/11/10 14:46:05 roberto Exp $
+** $Id: ldebug.h,v 2.14 2015/05/22 17:45:56 roberto Exp $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
#ifndef ldebug_h
#define ldebug_h
#include "lstate.h"
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
#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, 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: vendor/lua/dist/src/ldo.c
===================================================================
--- vendor/lua/dist/src/ldo.c (revision 326343)
+++ vendor/lua/dist/src/ldo.c (revision 326344)
@@ -1,717 +1,802 @@
/*
-** $Id: ldo.c,v 2.135 2014/11/11 17:13:39 roberto Exp $
+** $Id: ldo.c,v 2.157 2016/12/13 15:52:21 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
#define ldo_c
#define LUA_CORE
#include "lprefix.h"
#include
#include
#include
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lundump.h"
#include "lvm.h"
#include "lzio.h"
#define errorstatus(s) ((s) > LUA_YIELD)
/*
** {======================================================
** Error-recovery functions
** =======================================================
*/
/*
** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By
** default, Lua handles errors with exceptions when compiling as
** C++ code, with _longjmp/_setjmp when asked to use them, and with
** longjmp/setjmp otherwise.
*/
#if !defined(LUAI_THROW) /* { */
#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_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 /* }{ */
/* 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 /* } */
/* chain list of long jump buffers */
struct lua_longjmp {
struct lua_longjmp *previous;
luai_jmpbuf b;
volatile int status; /* error code */
};
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
switch (errcode) {
case LUA_ERRMEM: { /* memory error? */
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
break;
}
case LUA_ERRERR: {
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
break;
}
default: {
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
break;
}
}
L->top = oldtop + 1;
}
l_noret luaD_throw (lua_State *L, int errcode) {
if (L->errorJmp) { /* thread has an error handler? */
L->errorJmp->status = errcode; /* set status */
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->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->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->panic(L); /* call panic function (last chance to jump out) */
}
abort();
}
}
}
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
unsigned short oldnCcalls = L->nCcalls;
struct lua_longjmp lj;
lj.status = LUA_OK;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
LUAI_TRY(L, &lj,
(*f)(L, ud);
);
L->errorJmp = lj.previous; /* restore old error handler */
L->nCcalls = oldnCcalls;
return lj.status;
}
/* }====================================================== */
+/*
+** {==================================================================
+** Stack reallocation
+** ===================================================================
+*/
static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
UpVal *up;
L->top = (L->top - 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;
if (isLua(ci))
ci->u.l.base = (ci->u.l.base - oldstack) + L->stack;
}
}
/* some space for error handling */
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
void luaD_reallocstack (lua_State *L, int newsize) {
TValue *oldstack = L->stack;
int lim = L->stacksize;
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
for (; lim < newsize; lim++)
setnilvalue(L->stack + lim); /* erase new segment */
L->stacksize = newsize;
L->stack_last = L->stack + newsize - EXTRA_STACK;
correctstack(L, oldstack);
}
void luaD_growstack (lua_State *L, int n) {
int size = L->stacksize;
if (size > LUAI_MAXSTACK) /* error after extra size? */
luaD_throw(L, LUA_ERRERR);
else {
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
int newsize = 2 * size;
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
if (newsize < needed) newsize = needed;
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
luaD_reallocstack(L, ERRORSTACKSIZE);
luaG_runerror(L, "stack overflow");
}
else
luaD_reallocstack(L, newsize);
}
}
static int stackinuse (lua_State *L) {
CallInfo *ci;
StkId lim = L->top;
for (ci = L->ci; ci != NULL; ci = ci->previous) {
- lua_assert(ci->top <= L->stack_last);
if (lim < ci->top) lim = ci->top;
}
+ lua_assert(lim <= L->stack_last);
return cast_int(lim - L->stack) + 1; /* part of stack in use */
}
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 (L->stacksize > LUAI_MAXSTACK) /* was handling stack overflow? */
+ if (goodsize > LUAI_MAXSTACK)
+ goodsize = LUAI_MAXSTACK; /* respect stack limit */
+ if (L->stacksize > LUAI_MAXSTACK) /* had been 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 || /* still handling stack overflow? */
- goodsize >= L->stacksize) /* would grow instead of shrink? */
- condmovestack(L); /* don't change stack (change only for debugging) */
- else
- luaD_reallocstack(L, goodsize); /* shrink it */
+ /* if thread is currently not handling a stack overflow and its
+ good size is smaller than current size, shrink its stack */
+ if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) &&
+ goodsize < L->stacksize)
+ luaD_reallocstack(L, goodsize);
+ else /* don't change stack */
+ condmovestack(L,{},{}); /* (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);
lua_Debug ar;
ar.event = event;
ar.currentline = line;
ar.i_ci = ci;
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
L->allowhook = 0; /* cannot call hooks inside a hook */
ci->callstatus |= CIST_HOOKED;
lua_unlock(L);
(*hook)(L, &ar);
lua_lock(L);
lua_assert(!L->allowhook);
L->allowhook = 1;
ci->top = restorestack(L, ci_top);
L->top = restorestack(L, top);
ci->callstatus &= ~CIST_HOOKED;
}
}
static void callhook (lua_State *L, CallInfo *ci) {
int hook = LUA_HOOKCALL;
ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
if (isLua(ci->previous) &&
GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) {
ci->callstatus |= CIST_TAIL;
hook = LUA_HOOKTAILCALL;
}
luaD_hook(L, hook, -1);
ci->u.l.savedpc--; /* correct 'pc' */
}
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; itop++, 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;
}
/*
** 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;
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);
L->top++; /* slot ensured by caller */
setobj2s(L, func, tm); /* tag method is the new function to be called */
}
+/*
+** 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 = ci->nresults;
+ if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
+ if (L->hookmask & LUA_MASKRET) {
+ ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
+ luaD_hook(L, LUA_HOOKRET, -1);
+ firstResult = restorestack(L, fr);
+ }
+ L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
+ }
+ res = ci->func; /* res == final position of 1st result */
+ L->ci = ci->previous; /* back to caller */
+ /* move results to proper place */
+ return moveresults(L, firstResult, res, nres, wanted);
+}
+
+
+
#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)
+ base = adjust_varargs(L, p, n);
+ else { /* non vararg function */
+ for (; n < p->numparams; n++)
+ setnilvalue(L->top++); /* complete missing arguments */
base = func + 1;
}
- 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 */
- luaD_checkstack(L, 1); /* ensure space for metamethod */
- func = restorestack(L, funcr); /* previous call may change stack */
+ 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) {
- StkId res;
- int wanted, i;
- CallInfo *ci = L->ci;
- if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
- if (L->hookmask & LUA_MASKRET) {
- ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
- luaD_hook(L, LUA_HOOKRET, -1);
- firstResult = restorestack(L, fr);
- }
- 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 */
+/*
+** 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 */
}
/*
** Call a function (C or Lua). The function to be called is at *func.
** The arguments are on the stack, right after the function.
** 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--;
}
/*
+** 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;
/* 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;
+ ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */
+ L->errfunc = ci->u.c.old_errfunc; /* with the same error function */
}
/* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
handled */
adjustresults(L, ci->nresults);
- /* call continuation function */
lua_unlock(L);
- n = (*ci->u.c.k)(L, status, ci->u.c.ctx);
+ n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */
lua_lock(L);
api_checknelems(L, n);
- /* finish 'luaD_precall' */
- luaD_poscall(L, L->top - n);
+ luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */
}
/*
** 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) {
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, LUA_YIELD); /* complete its execution */
else { /* Lua function */
luaV_finishOp(L); /* finish interrupted instruction */
luaV_execute(L); /* execute down to higher C 'boundary' */
}
}
}
/*
** Try to find a suspended protected call (a "recover point") for the
** given thread.
*/
static CallInfo *findpcall (lua_State *L) {
CallInfo *ci;
for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */
if (ci->callstatus & CIST_YPCALL)
return ci;
}
return NULL; /* no pending pcall */
}
/*
** 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);
if (ci == NULL) return 0; /* no recovery point */
/* "finish" luaD_pcall */
oldtop = restorestack(L, ci->extra);
luaF_close(L, oldtop);
seterrorobj(L, status, oldtop);
L->ci = ci;
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;
return 1; /* continue running the coroutine */
}
/*
-** signal an error in the call to 'resume', not in the execution of the
-** coroutine itself. (Such errors should not be handled by any coroutine
-** error handler and should not kill the coroutine.)
+** Signal an error in the call to 'lua_resume', not in the execution
+** of the coroutine itself. (Such errors should not be handled by any
+** coroutine error handler and should not kill the coroutine.)
*/
-static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
- L->top = firstArg; /* remove args from the stack */
+static int resume_error (lua_State *L, const char *msg, int narg) {
+ L->top -= narg; /* remove args from the stack */
setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */
api_incr_top(L);
- luaD_throw(L, -1); /* jump back to 'lua_resume' */
+ lua_unlock(L);
+ return LUA_ERRRUN;
}
/*
** 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);
- if (L->status == LUA_OK) { /* may be starting a coroutine */
- if (ci != &L->base_ci) /* not in base level? */
- resume_error(L, "cannot resume non-suspended coroutine", firstArg);
- /* coroutine is in base level; start running it */
+ if (L->status == LUA_OK) { /* starting a coroutine? */
if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */
luaV_execute(L); /* call it */
}
- else if (L->status != LUA_YIELD)
- resume_error(L, "cannot resume dead coroutine", firstArg);
else { /* resuming from previous yield */
+ lua_assert(L->status == LUA_YIELD);
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 function? */
- int n;
lua_unlock(L);
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
lua_lock(L);
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
- luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
+ luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */
}
unroll(L, NULL); /* run continuation */
}
- lua_assert(nCcalls == L->nCcalls);
}
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status;
- int oldnny = L->nny; /* save "number of non-yieldable" calls */
+ unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
lua_lock(L);
- luai_userstateresume(L, nargs);
+ if (L->status == LUA_OK) { /* may be starting a coroutine */
+ if (L->ci != &L->base_ci) /* not in base level? */
+ return resume_error(L, "cannot resume non-suspended coroutine", nargs);
+ }
+ else if (L->status != LUA_YIELD)
+ return resume_error(L, "cannot resume dead coroutine", nargs);
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
+ if (L->nCcalls >= LUAI_MAXCCALLS)
+ return resume_error(L, "C stack overflow", nargs);
+ luai_userstateresume(L, nargs);
L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
- status = luaD_rawrunprotected(L, resume, L->top - nargs);
+ status = luaD_rawrunprotected(L, resume, &nargs);
if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN;
else { /* continue running after recoverable errors */
while (errorstatus(status) && recover(L, status)) {
/* unroll continuation */
status = luaD_rawrunprotected(L, unroll, &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--;
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
lua_unlock(L);
return status;
}
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);
api_checknelems(L, nresults);
if (L->nny > 0) {
if (L != G(L)->mainthread)
luaG_runerror(L, "attempt to yield across a C-call boundary");
else
luaG_runerror(L, "attempt to yield from outside a coroutine");
}
L->status = LUA_YIELD;
ci->extra = savestack(L, ci->func); /* save current 'func' */
if (isLua(ci)) { /* inside a hook? */
- api_check(k == NULL, "hooks cannot continue after yielding");
+ api_check(L, k == NULL, "hooks cannot continue after yielding");
}
else {
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
ci->u.c.ctx = ctx; /* save context */
ci->func = L->top - nresults - 1; /* protect stack below results */
luaD_throw(L, LUA_YIELD);
}
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
lua_unlock(L);
return 0; /* return to 'luaD_hook' */
}
int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t old_top, ptrdiff_t ef) {
int status;
CallInfo *old_ci = L->ci;
lu_byte old_allowhooks = L->allowhook;
unsigned short old_nny = L->nny;
ptrdiff_t old_errfunc = L->errfunc;
L->errfunc = ef;
status = luaD_rawrunprotected(L, func, u);
if (status != LUA_OK) { /* an error occurred? */
StkId oldtop = restorestack(L, old_top);
luaF_close(L, oldtop); /* close possible pending closures */
seterrorobj(L, status, oldtop);
L->ci = old_ci;
L->allowhook = old_allowhooks;
L->nny = old_nny;
luaD_shrinkstack(L);
}
L->errfunc = old_errfunc;
return status;
}
/*
** Execute a protected 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 */
const char *mode;
const char *name;
};
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 '%s')", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);
}
}
static void f_parser (lua_State *L, void *ud) {
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->nupvalues == cl->p->sizeupvalues);
luaF_initupvals(L, cl);
}
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p;
int status;
L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--;
return status;
}
Index: vendor/lua/dist/src/ldo.h
===================================================================
--- vendor/lua/dist/src/ldo.h (revision 326343)
+++ vendor/lua/dist/src/ldo.h (revision 326344)
@@ -1,46 +1,58 @@
/*
-** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 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
*/
#ifndef ldo_h
#define ldo_h
#include "lobject.h"
#include "lstate.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' */
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);
#endif
Index: vendor/lua/dist/src/ldump.c
===================================================================
--- vendor/lua/dist/src/ldump.c (revision 326343)
+++ vendor/lua/dist/src/ldump.c (revision 326344)
@@ -1,214 +1,215 @@
/*
-** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 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
*/
#define ldump_c
#define LUA_CORE
#include "lprefix.h"
#include
#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;
} DumpState;
/*
** 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) {
+ if (D->status == 0 && size > 0) {
lua_unlock(D->L);
D->status = (*D->writer)(D->L, b, size, D->data);
lua_lock(D->L);
}
}
#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 DumpNumber (lua_Number x, DumpState *D) {
DumpVar(x, D);
}
static void DumpInteger (lua_Integer x, DumpState *D) {
DumpVar(x, D);
}
static void DumpString (const TString *s, DumpState *D) {
if (s == NULL)
DumpByte(0, D);
else {
- size_t size = s->len + 1; /* include trailing '\0' */
+ size_t size = tsslen(s) + 1; /* include trailing '\0' */
+ const char *str = getstr(s);
if (size < 0xFF)
DumpByte(cast_int(size), D);
else {
DumpByte(0xFF, D);
DumpVar(size, D);
}
- DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */
+ DumpVector(str, size - 1, D); /* no need to save '\0' */
}
}
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);
}
}
}
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;
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, 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) {
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);
DumpByte(f->sizeupvalues, &D);
DumpFunction(f, NULL, &D);
return D.status;
}
Index: vendor/lua/dist/src/lfunc.h
===================================================================
--- vendor/lua/dist/src/lfunc.h (revision 326343)
+++ vendor/lua/dist/src/lfunc.h (revision 326344)
@@ -1,54 +1,61 @@
/*
-** $Id: lfunc.h,v 2.14 2014/06/19 18:27:20 roberto Exp $
+** $Id: lfunc.h,v 2.15 2015/01/13 15:49:11 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#ifndef lfunc_h
#define lfunc_h
#include "lobject.h"
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
cast(int, sizeof(TValue)*((n)-1)))
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
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 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 const char *luaF_getlocalname (const Proto *func, int local_number,
int pc);
#endif
Index: vendor/lua/dist/src/lgc.c
===================================================================
--- vendor/lua/dist/src/lgc.c (revision 326343)
+++ vendor/lua/dist/src/lgc.c (revision 326344)
@@ -1,1159 +1,1178 @@
/*
-** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp $
+** $Id: lgc.c,v 2.215 2016/12/22 13:08:50 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#define lgc_c
#define LUA_CORE
#include "lprefix.h"
#include
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.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
** by some adjust for the sweep speed)
*/
#define GCSWEEPCOST ((sizeof(TString) + 4) / 4)
/* maximum number of elements to sweep in each single step */
#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
/* cost of calling one finalizer */
#define GCFINALIZECOST GCSWEEPCOST
/*
** macro to adjust 'stepmul': 'stepmul' is actually used like
** 'stepmul / STEPMULADJ' (value chosen by tests)
*/
#define STEPMULADJ 200
/*
** macro to adjust 'pause': 'pause' is actually used like
** 'pause / PAUSEADJ' (value chosen by tests)
*/
#define PAUSEADJ 100
/*
** 'makewhite' erases all color bits then sets only the current white
** bit
*/
#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS))
#define makewhite(g,x) \
(x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g)))
#define white2gray(x) resetbits(x->marked, WHITEBITS)
#define black2gray(x) resetbit(x->marked, BLACKBIT)
#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n)))
#define checkconsistency(obj) \
lua_longassert(!iscollectable(obj) || righttt(obj))
#define markvalue(g,o) { checkconsistency(o); \
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
-#define markobject(g,t) \
- { if ((t) && iswhite(t)) reallymarkobject(g, obj2gco(t)); }
+#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
+/*
+** mark an object that can be NULL (either because it is really optional,
+** or it was stripped as debug info, or inside an uncompleted structure)
+*/
+#define markobjectN(g,t) { if (t) markobject(g,t); }
+
static void reallymarkobject (global_State *g, GCObject *o);
/*
** {======================================================
** Generic functions
** =======================================================
*/
/*
** one after last element in a hash array
*/
#define gnodelast(h) gnode(h, cast(size_t, sizenode(h)))
/*
** link collectable object 'o' into list pointed by 'p'
*/
#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(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
** 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, tsvalue(o)); /* strings are 'values', so are never weak */
return 0;
}
else return iswhite(gcvalue(o));
}
/*
** barrier that moves collector forward, that is, mark the white 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));
if (keepinvariant(g)) /* must keep invariant? */
reallymarkobject(g, v); /* restore invariant */
else { /* sweep phase */
lua_assert(issweepphase(g));
makewhite(g, o); /* mark main obj. as white to avoid other barriers */
}
}
/*
** barrier that moves collector backward, that is, mark the black object
** pointing to a white object as gray again.
*/
void luaC_barrierback_ (lua_State *L, Table *t) {
global_State *g = G(L);
lua_assert(isblack(t) && !isdead(g, t));
black2gray(t); /* make table gray (again) */
linkgclist(t, g->grayagain);
}
/*
** 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.
*/
void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
global_State *g = G(L);
GCObject *o = gcvalue(uv->v);
lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
if (keepinvariant(g))
markobject(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 'allgc' list.
*/
GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
global_State *g = G(L);
GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz));
o->marked = luaC_white(g);
o->tt = tt;
o->next = g->allgc;
g->allgc = o;
return o;
}
/* }====================================================== */
/*
** {======================================================
** Mark functions
** =======================================================
*/
/*
** mark an object. Userdata, strings, and closed upvalues are visited
** and turned black here. Other objects are marked gray and added
** to appropriate list to be visited (and turned black) later. (Open
** upvalues are already linked in 'headuv' list.)
*/
static void reallymarkobject (global_State *g, GCObject *o) {
reentry:
white2gray(o);
switch (o->tt) {
- case LUA_TSHRSTR:
+ case LUA_TSHRSTR: {
+ gray2black(o);
+ g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
+ break;
+ }
case LUA_TLNGSTR: {
gray2black(o);
- g->GCmemtrav += sizestring(gco2ts(o));
+ g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
break;
}
case LUA_TUSERDATA: {
TValue uvalue;
- markobject(g, gco2u(o)->metatable); /* mark its metatable */
+ markobjectN(g, gco2u(o)->metatable); /* mark its metatable */
gray2black(o);
g->GCmemtrav += sizeudata(gco2u(o));
getuservalue(g->mainthread, gco2u(o), &uvalue);
if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */
o = gcvalue(&uvalue);
goto reentry;
}
break;
}
case LUA_TLCL: {
linkgclist(gco2lcl(o), g->gray);
break;
}
case LUA_TCCL: {
linkgclist(gco2ccl(o), g->gray);
break;
}
case LUA_TTABLE: {
linkgclist(gco2t(o), g->gray);
break;
}
case LUA_TTHREAD: {
linkgclist(gco2th(o), g->gray);
break;
}
case LUA_TPROTO: {
linkgclist(gco2p(o), g->gray);
break;
}
default: lua_assert(0); break;
}
}
/*
** mark metamethods for basic types
*/
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]);
}
/*
** mark all objects in list of being-finalized
*/
static void markbeingfnz (global_State *g) {
GCObject *o;
for (o = g->tobefnz; o != NULL; o = o->next)
markobject(g, o);
}
/*
** 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) {
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 collection
*/
static void restartcollection (global_State *g) {
g->gray = g->grayagain = NULL;
g->weak = g->allweak = g->ephemeron = NULL;
markobject(g, g->mainthread);
markvalue(g, &g->l_registry);
markmt(g);
markbeingfnz(g); /* mark any finalizing object left from previous cycle */
}
/* }====================================================== */
/*
** {======================================================
** Traverse functions
** =======================================================
*/
/*
** 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 (it is not
worth traversing it now just to check) */
int hasclears = (h->sizearray > 0);
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {
lua_assert(!ttisnil(gkey(n)));
markvalue(g, gkey(n)); /* mark key */
if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */
hasclears = 1; /* table will have to be cleared */
}
}
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 hasww = 0; /* true if table has entry "white-key -> white-value" */
Node *n, *limit = gnodelast(h);
unsigned int i;
/* traverse array part */
for (i = 0; i < h->sizearray; i++) {
if (valiswhite(&h->array[i])) {
marked = 1;
reallymarkobject(g, gcvalue(&h->array[i]));
}
}
/* traverse hash part */
for (n = gnode(h, 0); n < limit; n++) {
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
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? */
hasww = 1; /* white-white entry */
}
else if (valiswhite(gval(n))) { /* value not marked yet? */
marked = 1;
reallymarkobject(g, gcvalue(gval(n))); /* mark it now */
}
}
/* 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);
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 */
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
else {
lua_assert(!ttisnil(gkey(n)));
markvalue(g, gkey(n)); /* mark key */
markvalue(g, gval(n)); /* mark value */
}
}
}
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(h); /* keep table gray */
if (!weakkey) /* strong keys? */
traverseweakvalue(g, h);
else if (!weakvalue) /* strong values? */
traverseephemeron(g, h);
else /* all weak */
linkgclist(h, g->allweak); /* nothing to traverse now */
}
else /* not weak */
traversestrongtable(g, h);
return sizeof(Table) + sizeof(TValue) * h->sizearray +
- sizeof(Node) * cast(size_t, sizenode(h));
+ sizeof(Node) * cast(size_t, allocsizenode(h));
}
+/*
+** Traverse a prototype. (While a prototype is being build, its
+** arrays can be larger than needed; the extra slots are filled with
+** NULL, so the use of 'markobjectN')
+*/
static int traverseproto (global_State *g, Proto *f) {
int i;
if (f->cache && iswhite(f->cache))
f->cache = NULL; /* allow cache to be collected */
- markobject(g, f->source);
+ markobjectN(g, f->source);
for (i = 0; i < f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */
- markobject(g, f->upvalues[i].name);
+ markobjectN(g, f->upvalues[i].name);
for (i = 0; i < f->sizep; i++) /* mark nested protos */
- markobject(g, f->p[i]);
+ markobjectN(g, f->p[i]);
for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
- markobject(g, f->locvars[i].varname);
+ markobjectN(g, f->locvars[i].varname);
return sizeof(Proto) + sizeof(Instruction) * f->sizecode +
sizeof(Proto *) * f->sizep +
sizeof(TValue) * f->sizek +
sizeof(int) * f->sizelineinfo +
sizeof(LocVar) * f->sizelocvars +
sizeof(Upvaldesc) * f->sizeupvalues;
}
static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
markvalue(g, &cl->upvalue[i]);
return sizeCclosure(cl->nupvalues);
}
/*
** 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 */
+ 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 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 == 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 */
+ /* '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 if (g->gckind != KGC_EMERGENCY)
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
- return (sizeof(lua_State) + sizeof(TValue) * th->stacksize);
+ return (sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * th->nci);
}
/*
** traverse one gray object, turning it to black (except for threads,
** which are always gray).
*/
static void propagatemark (global_State *g) {
lu_mem size;
GCObject *o = g->gray;
lua_assert(isgray(o));
gray2black(o);
switch (o->tt) {
case LUA_TTABLE: {
Table *h = gco2t(o);
g->gray = h->gclist; /* remove from 'gray' list */
size = traversetable(g, h);
break;
}
case LUA_TLCL: {
LClosure *cl = gco2lcl(o);
g->gray = cl->gclist; /* remove from 'gray' list */
size = traverseLclosure(g, cl);
break;
}
case LUA_TCCL: {
CClosure *cl = gco2ccl(o);
g->gray = cl->gclist; /* remove from 'gray' list */
size = traverseCclosure(g, cl);
break;
}
case LUA_TTHREAD: {
lua_State *th = gco2th(o);
g->gray = th->gclist; /* remove from 'gray' list */
linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
black2gray(o);
size = traversethread(g, th);
break;
}
case LUA_TPROTO: {
Proto *p = gco2p(o);
g->gray = p->gclist; /* remove from 'gray' list */
size = traverseproto(g, p);
break;
}
default: lua_assert(0); return;
}
g->GCmemtrav += size;
}
static void propagateall (global_State *g) {
while (g->gray) propagatemark(g);
}
static void convergeephemerons (global_State *g) {
int changed;
do {
GCObject *w;
GCObject *next = g->ephemeron; /* get ephemeron list */
g->ephemeron = NULL; /* tables may return to this list when traversed */
changed = 0;
while ((w = next) != NULL) {
next = gco2t(w)->gclist;
if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */
propagateall(g); /* propagate changes */
changed = 1; /* will have to revisit all ephemeron tables */
}
}
} while (changed);
}
/* }====================================================== */
/*
** {======================================================
** Sweep Functions
** =======================================================
*/
/*
** clear entries with unmarked keys from all weaktables in list 'l' up
** to element 'f'
*/
static void clearkeys (global_State *g, GCObject *l, GCObject *f) {
for (; l != f; l = gco2t(l)->gclist) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
for (n = gnode(h, 0); n < limit; n++) {
if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
}
}
}
/*
** clear entries with unmarked values from all weaktables in list 'l' up
** to element 'f'
*/
static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
for (; l != f; l = gco2t(l)->gclist) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
unsigned int i;
for (i = 0; i < h->sizearray; i++) {
TValue *o = &h->array[i];
if (iscleared(g, o)) /* value was collected? */
setnilvalue(o); /* remove value */
}
for (n = gnode(h, 0); n < limit; n++) {
if (!ttisnil(gval(n)) && iscleared(g, gval(n))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
}
}
}
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 (o->tt) {
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
case LUA_TLCL: {
freeLclosure(L, gco2lcl(o));
break;
}
case LUA_TCCL: {
luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
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:
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
- /* go through */
+ luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
+ break;
case LUA_TLNGSTR: {
- luaM_freemem(L, o, sizestring(gco2ts(o)));
+ luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
break;
}
default: lua_assert(0);
}
}
#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
/*
** sweep at most 'count' elements from a list of GCObjects erasing dead
** 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 white = luaC_white(g); /* current white */
while (*p != NULL && count-- > 0) {
GCObject *curr = *p;
int marked = curr->marked;
if (isdeadm(ow, marked)) { /* is 'curr' dead? */
*p = curr->next; /* remove 'curr' from list */
freeobj(L, curr); /* erase 'curr' */
}
else { /* change mark to 'white' */
curr->marked = cast_byte((marked & maskcolors) | white);
p = &curr->next; /* go to next element */
}
}
return (*p == NULL) ? NULL : p;
}
/*
** sweep a list until a live object (or end of list)
*/
-static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
+static GCObject **sweeptolive (lua_State *L, GCObject **p) {
GCObject **old = p;
- int i = 0;
do {
- i++;
p = sweeplist(L, p, 1);
} while (p == old);
- if (n) *n += i;
return p;
}
/* }====================================================== */
/*
** {======================================================
** Finalization
** =======================================================
*/
/*
-** If possible, free concatenation buffer and shrink string table
+** If possible, shrink string table
*/
static void checkSizes (lua_State *L, global_State *g) {
if (g->gckind != KGC_EMERGENCY) {
l_mem olddebt = g->GCdebt;
- luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
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(tofinalize(o));
g->tobefnz = o->next; /* remove it from 'tobefnz' list */
o->next = g->allgc; /* return it to 'allgc' list */
g->allgc = o;
resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */
if (issweepphase(g))
makewhite(g, o); /* "sweep" object */
return o;
}
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);
}
static void GCTM (lua_State *L, int propagateerrors) {
global_State *g = G(L);
const TValue *tm;
TValue v;
setgcovalue(L, &v, udata2finalize(g));
tm = luaT_gettmbyobj(L, &v, TM_GC);
if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */
int status;
lu_byte oldah = L->allowhook;
int running = g->gcrunning;
L->allowhook = 0; /* stop debug hooks during GC metamethod */
g->gcrunning = 0; /* avoid GC steps */
setobj2s(L, L->top, tm); /* push finalizer... */
setobj2s(L, L->top + 1, &v); /* ... and its argument */
L->top += 2; /* and (next line) call the finalizer */
+ L->ci->callstatus |= CIST_FIN; /* will run a finalizer */
status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
+ L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
L->allowhook = oldah; /* restore hooks */
g->gcrunning = running; /* restore state */
if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
if (status == LUA_ERRRUN) { /* is there an error object? */
const char *msg = (ttisstring(L->top - 1))
? svalue(L->top - 1)
: "no message";
luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
status = LUA_ERRGCMM; /* error in __gc metamethod */
}
luaD_throw(L, status); /* re-throw error */
}
}
}
/*
** 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, int propagateerrors) {
+static void callallpendingfinalizers (lua_State *L) {
global_State *g = G(L);
while (g->tobefnz)
- GCTM(L, propagateerrors);
+ 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 (global_State *g, int all) {
GCObject *curr;
GCObject **p = &g->finobj;
GCObject **lastnext = findlast(&g->tobefnz);
while ((curr = *p) != NULL) { /* traverse all finalizable objects */
lua_assert(tofinalize(curr));
if (!(iswhite(curr) || all)) /* not being collected? */
p = &curr->next; /* don't bother with it */
else {
*p = curr->next; /* remove 'curr' from 'finobj' list */
curr->next = *lastnext; /* link at the end of 'tobefnz' list */
*lastnext = curr;
lastnext = &curr->next;
}
}
}
/*
** if object 'o' has a finalizer, remove it from 'allgc' list (must
** search the list to find it) and link it in 'finobj' list.
*/
void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
global_State *g = G(L);
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;
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, NULL); /* change 'sweepgc' */
+ g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
}
/* search for pointer pointing to 'o' */
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(o->marked, FINALIZEDBIT); /* mark it as such */
}
}
/* }====================================================== */
/*
** {======================================================
** GC control
** =======================================================
*/
/*
** 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 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 = gettotalbytes(g) - threshold;
luaE_setdebt(g, debt);
}
/*
** Enter first sweep phase.
-** The call to 'sweeptolive' makes 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.
-** Returns how many objects it swept.
+** 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 int entersweep (lua_State *L) {
+static void entersweep (lua_State *L) {
global_State *g = G(L);
- int n = 0;
g->gcstate = GCSswpallgc;
lua_assert(g->sweepgc == NULL);
- g->sweepgc = sweeptolive(L, &g->allgc, &n);
- return n;
+ g->sweepgc = sweeplist(L, &g->allgc, 1);
}
void luaC_freeallobjects (lua_State *L) {
global_State *g = G(L);
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);
sweepwholelist(L, &g->allgc);
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;
GCObject *origweak, *origall;
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 global metatables */
/* remark occasional upvalues of (maybe) dead threads */
remarkupvals(g);
propagateall(g); /* propagate changes */
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 */
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(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 '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 */
/* 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: {
g->GCmemtrav = g->strt.size * sizeof(GCObject*);
restartcollection(g);
g->gcstate = GCSpropagate;
return g->GCmemtrav;
}
case GCSpropagate: {
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 GCSatomic: {
lu_mem work;
- int sw;
propagateall(g); /* make sure gray list is empty */
work = atomic(L); /* work is what was traversed by 'atomic' */
- sw = entersweep(L);
+ entersweep(L);
g->GCestimate = gettotalbytes(g); /* first estimate */;
- return work + sw * GCSWEEPCOST;
+ return work;
}
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 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 { /* emergency mode or no more finalizers */
g->gcstate = GCSpause; /* finish collection */
return 0;
}
}
default: lua_assert(0); return 0;
}
}
/*
** advances the garbage collector until it reaches a state allowed
** by 'statemask'
*/
void luaC_runtilstate (lua_State *L, int statesmask) {
global_State *g = G(L);
while (!testbit(statesmask, g->gcstate))
singlestep(L);
}
/*
** 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;
- debt = (debt / STEPMULADJ) + 1;
- debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
- return debt;
+ if (debt <= 0) return 0; /* minimal debt */
+ else {
+ debt = (debt / STEPMULADJ) + 1;
+ debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
+ return debt;
+ }
}
/*
** performs a basic GC step when collector is running
*/
void luaC_step (lua_State *L) {
global_State *g = G(L);
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); /* pause until next cycle */
else {
debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */
luaE_setdebt(g, debt);
runafewfinalizers(L);
}
}
/*
** 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);
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(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: vendor/lua/dist/src/lgc.h
===================================================================
--- vendor/lua/dist/src/lgc.h (revision 326343)
+++ vendor/lua/dist/src/lgc.h (revision 326344)
@@ -1,138 +1,147 @@
/*
-** $Id: lgc.h,v 2.86 2014/10/25 11:50:46 roberto Exp $
+** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
#ifndef lgc_h
#define lgc_h
#include "lobject.h"
#include "lstate.h"
/*
** Collectable objects may have one of three colors: white, which
** means the object is not marked; gray, which means the
** object is marked, but its references may be not marked; and
** black, which means that the object and all its references are marked.
** The main invariant of the garbage collector, while marking objects,
** is that a black object can never point to a white one. Moreover,
** any gray object must be in a "gray list" (gray, grayagain, weak,
** allweak, ephemeron) so that it can be visited again before finishing
** the collection cycle. These lists have no meaning when the invariant
** is not being enforced (e.g., sweep phase).
*/
/* how much to allocate before next GC step */
#if !defined(GCSTEPSIZE)
/* ~100 small strings */
#define GCSTEPSIZE (cast_int(100 * sizeof(TString)))
#endif
/*
** Possible states of the Garbage Collector
*/
#define GCSpropagate 0
#define GCSatomic 1
#define GCSswpallgc 2
#define GCSswpfinobj 3
#define GCSswptobefnz 4
#define GCSswpend 5
#define GCScallfin 6
#define GCSpause 7
#define issweepphase(g) \
(GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
/*
** 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.
*/
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
/*
** some useful bit tricks
*/
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
#define setbits(x,m) ((x) |= (m))
#define testbits(x,m) ((x) & (m))
#define bitmask(b) (1<<(b))
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
#define l_setbit(x,b) setbits(x, bitmask(b))
#define resetbit(x,b) resetbits(x, bitmask(b))
#define testbit(x,b) testbits(x, bitmask(b))
/* 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 marked for finalization */
/* bit 7 is currently used by tests (luaL_checkmemory) */
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
#define iswhite(x) testbits((x)->marked, WHITEBITS)
#define isblack(x) testbit((x)->marked, BLACKBIT)
#define isgray(x) /* neither white nor black */ \
(!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT)))
#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT)
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked)
#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 (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \
- luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
-#define luaC_barrierback(L,p,v) { \
- if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \
- 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 (isblack(p) && iswhite(o)) \
- 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_upvalbarrier(L,uv) \
- { if (iscollectable((uv)->v) && !upisopen(uv)) \
- luaC_upvalbarrier_(L,uv); }
+#define luaC_objbarrier(L,p,o) ( \
+ (isblack(p) && iswhite(o)) ? \
+ luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
+
+#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_runtilstate (lua_State *L, int statesmask);
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o);
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
#endif
Index: vendor/lua/dist/src/linit.c
===================================================================
--- vendor/lua/dist/src/linit.c (revision 326343)
+++ vendor/lua/dist/src/linit.c (revision 326344)
@@ -1,68 +1,68 @@
/*
-** $Id: linit.c,v 1.38 2015/01/05 13:48:33 roberto Exp $
+** $Id: linit.c,v 1.39 2016/12/04 20:17:24 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");
+** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
** lua_pushcfunction(L, luaopen_modname);
** lua_setfield(L, -2, modname);
-** lua_pop(L, 1); // remove _PRELOAD table
+** lua_pop(L, 1); // remove PRELOAD table
*/
#include "lprefix.h"
#include
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
/*
** these libs are loaded by lua.c and are readily available to any Lua
** program
*/
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_UTF8LIBNAME, luaopen_utf8},
{LUA_DBLIBNAME, luaopen_debug},
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},
#endif
{NULL, NULL}
};
LUALIB_API void luaL_openlibs (lua_State *L) {
const luaL_Reg *lib;
/* "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 */
}
}
Index: vendor/lua/dist/src/liolib.c
===================================================================
--- vendor/lua/dist/src/liolib.c (revision 326343)
+++ vendor/lua/dist/src/liolib.c (revision 326344)
@@ -1,757 +1,771 @@
/*
-** $Id: liolib.c,v 2.142 2015/01/02 12:50:28 roberto Exp $
+** $Id: liolib.c,v 2.151 2016/12/20 18:37:00 roberto Exp $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
#define liolib_c
#define LUA_LIB
#include "lprefix.h"
#include
#include
#include
#include
#include
#include
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
-#if !defined(l_checkmode)
+
/*
-** Check whether 'mode' matches '[rwa]%+?b?'.
** Change this macro to accept other modes for 'fopen' besides
** the standard ones.
*/
-#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'))
+#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]*' */
+static int l_checkmode (const char *mode) {
+ return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
+ (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
+ (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
+}
+
+#endif
+
/*
** {======================================================
** l_popen spawns a new process connected to the current
** one through the file streams.
** =======================================================
*/
#if !defined(l_popen) /* { */
#if defined(LUA_USE_POSIX) /* { */
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
#define l_pclose(L,file) (pclose(file))
#elif defined(LUA_USE_WINDOWS) /* }{ */
#define l_popen(L,c,m) (_popen(c,m))
#define l_pclose(L,file) (_pclose(file))
#else /* }{ */
/* 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 /* } */
/* }====================================================== */
#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 /* } */
/*
** {======================================================
** l_fseek: configuration for longer offsets
** =======================================================
*/
#if !defined(l_fseek) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include
#define l_fseek(f,o,w) fseeko(f,o,w)
#define l_ftell(f) ftello(f)
#define l_seeknum off_t
#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
&& defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
/* 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
#else /* }{ */
/* 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 /* } */
/* }====================================================== */
#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")
typedef luaL_Stream LStream;
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
#define isclosed(p) ((p)->closef == NULL)
static int io_type (lua_State *L) {
LStream *p;
luaL_checkany(L, 1);
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
if (p == NULL)
lua_pushnil(L); /* not a file */
else if (isclosed(p))
lua_pushliteral(L, "closed file");
else
lua_pushliteral(L, "file");
return 1;
}
static int f_tostring (lua_State *L) {
LStream *p = tolstream(L);
if (isclosed(p))
lua_pushliteral(L, "file (closed)");
else
lua_pushfstring(L, "file (%p)", p->f);
return 1;
}
static FILE *tofile (lua_State *L) {
LStream *p = tolstream(L);
if (isclosed(p))
luaL_error(L, "attempt to use a closed file");
lua_assert(p->f);
return p->f;
}
/*
** 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));
p->closef = NULL; /* mark file handle as 'closed' */
luaL_setmetatable(L, LUA_FILEHANDLE);
return p;
}
/*
** 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);
volatile lua_CFunction cf = p->closef;
p->closef = NULL; /* mark stream as closed */
return (*cf)(L); /* close it */
}
static int io_close (lua_State *L) {
if (lua_isnone(L, 1)) /* no argument? */
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
tofile(L); /* make sure argument is an open stream */
return aux_close(L);
}
static int f_gc (lua_State *L) {
LStream *p = tolstream(L);
if (!isclosed(p) && p->f != NULL)
aux_close(L); /* ignore closed and incompletely open files */
return 0;
}
/*
** function to close regular files
*/
static int io_fclose (lua_State *L) {
LStream *p = tolstream(L);
int res = fclose(p->f);
return luaL_fileresult(L, (res == 0), NULL);
}
static LStream *newfile (lua_State *L) {
LStream *p = newprefile(L);
p->f = NULL;
p->closef = &io_fclose;
return p;
}
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 '%s' (%s)", fname, strerror(errno));
}
static int io_open (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
LStream *p = newfile(L);
const char *md = mode; /* to traverse/check 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;
}
/*
** function to close 'popen' files
*/
static int io_pclose (lua_State *L) {
LStream *p = tolstream(L);
return luaL_execresult(L, l_pclose(L, p->f));
}
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 = l_popen(L, filename, mode);
p->closef = &io_pclose;
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}
static int io_tmpfile (lua_State *L) {
LStream *p = newfile(L);
p->f = tmpfile();
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
}
static FILE *getiofile (lua_State *L, const char *findex) {
LStream *p;
lua_getfield(L, LUA_REGISTRYINDEX, findex);
p = (LStream *)lua_touserdata(L, -1);
if (isclosed(p))
luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
return p->f;
}
static int g_iofile (lua_State *L, const char *f, const char *mode) {
if (!lua_isnoneornil(L, 1)) {
const char *filename = lua_tostring(L, 1);
if (filename)
opencheck(L, filename, mode);
else {
tofile(L); /* check that it's a valid file handle */
lua_pushvalue(L, 1);
}
lua_setfield(L, LUA_REGISTRYINDEX, f);
}
/* return current value */
lua_getfield(L, LUA_REGISTRYINDEX, f);
return 1;
}
static int io_input (lua_State *L) {
return g_iofile(L, IO_INPUT, "r");
}
static int io_output (lua_State *L) {
return g_iofile(L, IO_OUTPUT, "w");
}
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 n = lua_gettop(L) - 1; /* number of arguments to read */
+ 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 */
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
lua_pushcclosure(L, io_readline, 3 + n);
}
static int f_lines (lua_State *L) {
tofile(L); /* check that it's a valid file handle */
aux_lines(L, 0);
return 1;
}
static int io_lines (lua_State *L) {
int toclose;
if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
if (lua_isnil(L, 1)) { /* no file name? */
lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
lua_replace(L, 1); /* put it at index 1 */
tofile(L); /* check that it's a valid file handle */
toclose = 0; /* do not close it after iteration */
}
else { /* open a new file */
const char *filename = luaL_checkstring(L, 1);
opencheck(L, filename, "r");
lua_replace(L, 1); /* put file at index 1 */
toclose = 1; /* close it after iteration */
}
aux_lines(L, toclose);
return 1;
}
/*
** {======================================================
** READ
** =======================================================
*/
/* maximum length of a numeral */
-#define MAXRN 200
+#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[MAXRN + 1]; /* +1 for ending '\0' */
+ 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 >= MAXRN) { /* buffer overflow? */
+ 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 1 or 2)
+** 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] && rn->c != '\0'))
+ 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;
}
-/* access to locale "radix character" (decimal point) */
-#if !defined(l_getlocaledecpoint)
-#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
-#endif
-
-
/*
** Read a number: first reads a valid prefix of a numeral into a buffer.
** Then it calls 'lua_stringtonumber' to check whether the format is
** 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] = ".";
+ char decp[2];
rn.f = f; rn.n = 0;
- decp[0] = l_getlocaledecpoint(); /* get decimal point from locale */
+ decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
+ decp[1] = '.'; /* 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, "0")) {
+ 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 */
}
}
static int test_eof (lua_State *L, FILE *f) {
int c = getc(f);
ungetc(c, f); /* no-op when c == EOF */
- lua_pushlstring(L, NULL, 0);
+ lua_pushliteral(L, "");
return (c != EOF);
}
static int read_line (lua_State *L, FILE *f, int chop) {
luaL_Buffer b;
int c = '\0';
luaL_buffinit(L, &b);
while (c != EOF && c != '\n') { /* repeat until end of line */
- char *buff = luaL_prepbuffer(&b); /* pre-allocate buffer */
+ 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);
}
static void read_all (lua_State *L, FILE *f) {
size_t nr;
luaL_Buffer b;
luaL_buffinit(L, &b);
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
- char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE);
+ char *p = luaL_prepbuffer(&b);
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
luaL_addsize(&b, nr);
} while (nr == LUAL_BUFFERSIZE);
luaL_pushresult(&b); /* close buffer */
}
static int read_chars (lua_State *L, FILE *f, size_t n) {
size_t nr; /* number of chars actually read */
char *p;
luaL_Buffer b;
luaL_buffinit(L, &b);
p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
luaL_addsize(&b, nr);
luaL_pushresult(&b); /* close buffer */
return (nr > 0); /* true iff read something */
}
static int g_read (lua_State *L, FILE *f, int first) {
int nargs = lua_gettop(L) - 1;
int success;
int n;
clearerr(f);
if (nargs == 0) { /* no arguments? */
success = read_line(L, f, 1);
n = first+1; /* to return 1 result */
}
else { /* ensure stack space for all results and for auxlib's buffer */
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
success = 1;
for (n = first; nargs-- && success; n++) {
if (lua_type(L, n) == LUA_TNUMBER) {
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 = luaL_checkstring(L, n);
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
switch (*p) {
case 'n': /* number */
success = read_number(L, f);
break;
case 'l': /* line */
success = read_line(L, f, 1);
break;
case 'L': /* line with end-of-line */
success = read_line(L, f, 0);
break;
case 'a': /* file */
read_all(L, f); /* read entire file */
success = 1; /* always success */
break;
default:
return luaL_argerror(L, n, "invalid format");
}
}
}
}
if (ferror(f))
return luaL_fileresult(L, 0, NULL);
if (!success) {
lua_pop(L, 1); /* remove last result */
lua_pushnil(L); /* push nil instead */
}
return n - first;
}
static int io_read (lua_State *L) {
return g_read(L, getiofile(L, IO_INPUT), 1);
}
static int f_read (lua_State *L) {
return g_read(L, tofile(L), 2);
}
static int io_readline (lua_State *L) {
LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
int i;
int n = (int)lua_tointeger(L, lua_upvalueindex(2));
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_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? */
/* 2nd result is error message */
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
}
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
lua_settop(L, 0);
lua_pushvalue(L, lua_upvalueindex(1));
aux_close(L); /* close it */
}
return 0;
}
}
/* }====================================================== */
static int g_write (lua_State *L, FILE *f, int arg) {
int nargs = lua_gettop(L) - arg;
int status = 1;
for (; nargs--; arg++) {
if (lua_type(L, arg) == LUA_TNUMBER) {
/* optimization: could be done exactly as for strings */
int len = lua_isinteger(L, arg)
- ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg))
- : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg));
+ ? fprintf(f, LUA_INTEGER_FMT,
+ (LUAI_UACINT)lua_tointeger(L, arg))
+ : fprintf(f, LUA_NUMBER_FMT,
+ (LUAI_UACNUMBER)lua_tonumber(L, arg));
status = status && (len > 0);
}
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
if (status) return 1; /* file handle already on stack top */
else return luaL_fileresult(L, status, NULL);
}
static int io_write (lua_State *L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
}
static int f_write (lua_State *L) {
FILE *f = tofile(L);
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
}
static int f_seek (lua_State *L) {
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL};
FILE *f = tofile(L);
int op = luaL_checkoption(L, 2, "cur", modenames);
lua_Integer p3 = luaL_optinteger(L, 3, 0);
l_seeknum offset = (l_seeknum)p3;
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_pushinteger(L, (lua_Integer)l_ftell(f));
return 1;
}
}
static int f_setvbuf (lua_State *L) {
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
static const char *const modenames[] = {"no", "full", "line", NULL};
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], (size_t)sz);
return luaL_fileresult(L, res == 0, NULL);
}
static int io_flush (lua_State *L) {
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
}
static int f_flush (lua_State *L) {
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
}
/*
** functions for 'io' library
*/
static const luaL_Reg iolib[] = {
{"close", io_close},
{"flush", io_flush},
{"input", io_input},
{"lines", io_lines},
{"open", io_open},
{"output", io_output},
{"popen", io_popen},
{"read", io_read},
{"tmpfile", io_tmpfile},
{"type", io_type},
{"write", io_write},
{NULL, NULL}
};
/*
** methods for file handles
*/
static const luaL_Reg flib[] = {
{"close", io_close},
{"flush", f_flush},
{"lines", f_lines},
{"read", f_read},
{"seek", f_seek},
{"setvbuf", f_setvbuf},
{"write", f_write},
{"__gc", f_gc},
{"__tostring", f_tostring},
{NULL, NULL}
};
static void createmeta (lua_State *L) {
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
lua_pushvalue(L, -1); /* push metatable */
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
lua_pop(L, 1); /* pop new metatable */
}
/*
** function to (not) close the standard files stdin, stdout, and stderr
*/
static int io_noclose (lua_State *L) {
LStream *p = tolstream(L);
p->closef = &io_noclose; /* keep file opened */
lua_pushnil(L);
lua_pushliteral(L, "cannot close standard file");
return 2;
}
static void createstdfile (lua_State *L, FILE *f, const char *k,
const char *fname) {
LStream *p = newprefile(L);
p->f = f;
p->closef = &io_noclose;
if (k != NULL) {
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
}
lua_setfield(L, -2, fname); /* add file to module */
}
LUAMOD_API int luaopen_io (lua_State *L) {
luaL_newlib(L, iolib); /* new module */
createmeta(L);
/* create (and set) default files */
createstdfile(L, stdin, IO_INPUT, "stdin");
createstdfile(L, stdout, IO_OUTPUT, "stdout");
createstdfile(L, stderr, NULL, "stderr");
return 1;
}
Index: vendor/lua/dist/src/llex.c
===================================================================
--- vendor/lua/dist/src/llex.c (revision 326343)
+++ vendor/lua/dist/src/llex.c (revision 326344)
@@ -1,602 +1,565 @@
/*
-** $Id: llex.c,v 2.89 2014/11/14 16:06:09 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
#include
#include "lua.h"
#include "lctype.h"
+#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "llex.h"
#include "lobject.h"
#include "lparser.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "lzio.h"
#define next(ls) (ls->current = zgetc(ls->z))
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
/* ORDER RESERVED */
static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while",
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "",
"", "", "", ""
};
#define save_and_next(ls) (save(ls, ls->current), next(ls))
static l_noret lexerror (LexState *ls, const char *msg, int token);
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_SIZE/2)
lexerror(ls, "lexical element too long", 0);
newsize = luaZ_sizebuffer(b) * 2;
luaZ_resizebuffer(ls->L, b, newsize);
}
b->buffer[luaZ_bufflen(b)++] = cast(char, c);
}
void luaX_init (lua_State *L) {
int i;
- TString *e = luaS_new(L, LUA_ENV); /* create env name */
+ TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */
luaC_fix(L, obj2gco(e)); /* never collect this name */
for (i=0; iextra = 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_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, "'%s'", s);
else /* names, strings, and numerals */
return s;
}
}
static const char *txtToken (LexState *ls, int token) {
switch (token) {
case TK_NAME: case TK_STRING:
case TK_FLT: case TK_INT:
save(ls, '\0');
return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff));
default:
return luaX_token2str(ls, 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);
}
l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
lexerror(ls, msg, ls->t.token);
}
/*
** 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' */
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->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 = tsvalue(keyfromval(o)); /* re-use value previously stored */
}
L->top--; /* remove string from stack */
return ts;
}
/*
** increment line number and skips newline sequence (any of
** \n, \r, \n\r, or \r\n)
*/
static void inclinenumber (LexState *ls) {
int old = ls->current;
lua_assert(currIsNewline(ls));
next(ls); /* skip '\n' or '\r' */
if (currIsNewline(ls) && ls->current != old)
next(ls); /* skip '\n\r' or '\r\n' */
if (++ls->linenumber >= MAX_INT)
lexerror(ls, "chunk has too many lines", 0);
}
void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
int firstchar) {
ls->t.token = 0;
- ls->decpoint = '.';
ls->L = L;
ls->current = firstchar;
ls->lookahead.token = TK_EOS; /* no look-ahead token */
ls->z = z;
ls->fs = NULL;
ls->linenumber = 1;
ls->lastline = 1;
ls->source = source;
- ls->envn = luaS_new(L, LUA_ENV); /* get env name */
+ ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
}
/*
** =======================================================
** LEXICAL ANALYZER
** =======================================================
*/
static int check_next1 (LexState *ls, int c) {
if (ls->current == c) {
next(ls);
return 1;
}
else return 0;
}
/*
** Check whether current char is in set 'set' (with two chars) and
** saves it
*/
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;
}
-/*
-** change all characters 'from' in buffer to 'to'
-*/
-static void buffreplace (LexState *ls, char from, char to) {
- if (from != to) {
- size_t n = luaZ_bufflen(ls->buff);
- char *p = luaZ_buffer(ls->buff);
- while (n--)
- if (p[n] == from) p[n] = to;
- }
-}
-
-
-#if !defined(l_getlocaledecpoint)
-#define l_getlocaledecpoint() (localeconv()->decimal_point[0])
-#endif
-
-
-#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
-
-/*
-** in case of format error, try to change decimal point separator to
-** the one defined in the current locale and check again
-*/
-static void trydecpoint (LexState *ls, TValue *o) {
- char old = ls->decpoint;
- ls->decpoint = l_getlocaledecpoint();
- buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
- if (!buff2num(ls->buff, o)) {
- /* format error with correct decimal point: no more options */
- buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
- lexerror(ls, "malformed number", TK_FLT);
- }
-}
-
-
/* LUA_NUMBER */
/*
** this function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals.
*/
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_next2(ls, "xX")) /* hexadecimal? */
expo = "Pp";
for (;;) {
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;
}
save(ls, '\0');
- buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
- if (!buff2num(ls->buff, &obj)) /* format error? */
- trydecpoint(ls, &obj); /* 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;
int s = ls->current;
lua_assert(s == '[' || s == ']');
save_and_next(ls);
while (ls->current == '=') {
save_and_next(ls);
count++;
}
return (ls->current == s) ? count : (-count) - 1;
}
static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {
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: { /* 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 ']' */
goto endloop;
}
break;
}
case '\n': case '\r': {
save(ls, '\n');
inclinenumber(ls);
if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */
break;
}
default: {
if (seminfo) save_and_next(ls);
else next(ls);
}
}
} endloop:
if (seminfo)
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),
luaZ_bufflen(ls->buff) - 2*(2 + sep));
}
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 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 i;
int r = 0; /* result accumulator */
for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */
r = 10*r + ls->current - '0';
save_and_next(ls);
}
esccheck(ls, r <= UCHAR_MAX, "decimal escape too large");
luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */
return r;
}
static void read_string (LexState *ls, int del, SemInfo *seminfo) {
save_and_next(ls); /* keep delimiter (for error messages) */
while (ls->current != del) {
switch (ls->current) {
case EOZ:
lexerror(ls, "unfinished string", TK_EOS);
break; /* to avoid warnings */
case '\n':
case '\r':
lexerror(ls, "unfinished string", TK_STRING);
break; /* to avoid warnings */
case '\\': { /* escape sequences */
int c; /* final character to be saved */
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;
case 'f': c = '\f'; goto read_save;
case 'n': c = '\n'; goto read_save;
case 'r': c = '\r'; goto read_save;
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);
else next(ls);
}
goto no_save;
}
default: {
esccheck(ls, lisdigit(ls->current), "invalid escape sequence");
c = readdecesc(ls); /* digital escape '\ddd' */
goto only_save;
}
}
read_save:
next(ls);
/* go through */
only_save:
luaZ_buffremove(ls->buff, 1); /* remove '\\' */
save(ls, c);
/* go through */
no_save: break;
}
default:
save_and_next(ls);
}
}
save_and_next(ls); /* skip delimiter */
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,
luaZ_bufflen(ls->buff) - 2);
}
static int llex (LexState *ls, SemInfo *seminfo) {
luaZ_resetbuffer(ls->buff);
for (;;) {
switch (ls->current) {
case '\n': case '\r': { /* line breaks */
inclinenumber(ls);
break;
}
case ' ': case '\f': case '\t': case '\v': { /* spaces */
next(ls);
break;
}
case '-': { /* '-' or '--' (comment) */
next(ls);
if (ls->current != '-') return '-';
/* else is a comment */
next(ls);
if (ls->current == '[') { /* long comment? */
int sep = skip_sep(ls);
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. */
break;
}
}
/* else short comment */
while (!currIsNewline(ls) && ls->current != EOZ)
next(ls); /* skip until end of line (or end of file) */
break;
}
case '[': { /* long string or simply '[' */
int sep = skip_sep(ls);
if (sep >= 0) {
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 (check_next1(ls, '=')) return TK_EQ;
else return '=';
}
case '<': {
next(ls);
if (check_next1(ls, '=')) return TK_LE;
else if (check_next1(ls, '<')) return TK_SHL;
else return '<';
}
case '>': {
next(ls);
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 (check_next1(ls, '=')) return TK_NE;
else return '~';
}
case ':': {
next(ls);
if (check_next1(ls, ':')) return TK_DBCOLON;
else return ':';
}
case '"': case '\'': { /* short literal strings */
read_string(ls, ls->current, seminfo);
return TK_STRING;
}
case '.': { /* '.', '..', '...', or number */
save_and_next(ls);
if (check_next1(ls, '.')) {
if (check_next1(ls, '.'))
return TK_DOTS; /* '...' */
else return TK_CONCAT; /* '..' */
}
else if (!lisdigit(ls->current)) return '.';
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': {
return read_numeral(ls, seminfo);
}
case EOZ: {
return TK_EOS;
}
default: {
if (lislalpha(ls->current)) { /* identifier or reserved word? */
TString *ts;
do {
save_and_next(ls);
} while (lislalnum(ls->current));
ts = luaX_newstring(ls, luaZ_buffer(ls->buff),
luaZ_bufflen(ls->buff));
seminfo->ts = ts;
if (isreserved(ts)) /* reserved word? */
return ts->extra - 1 + FIRST_RESERVED;
else {
return TK_NAME;
}
}
else { /* single-char tokens (+ - / ...) */
int c = ls->current;
next(ls);
return c;
}
}
}
}
}
void luaX_next (LexState *ls) {
ls->lastline = ls->linenumber;
if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */
ls->t = ls->lookahead; /* use this one */
ls->lookahead.token = TK_EOS; /* and discharge it */
}
else
ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */
}
int luaX_lookahead (LexState *ls) {
lua_assert(ls->lookahead.token == TK_EOS);
ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);
return ls->lookahead.token;
}
Index: vendor/lua/dist/src/llex.h
===================================================================
--- vendor/lua/dist/src/llex.h (revision 326343)
+++ vendor/lua/dist/src/llex.h (revision 326344)
@@ -1,86 +1,85 @@
/*
-** $Id: llex.h,v 1.78 2014/10/29 15:38:24 roberto Exp $
+** $Id: llex.h,v 1.79 2016/05/02 14:02:12 roberto Exp $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#ifndef llex_h
#define llex_h
#include "lobject.h"
#include "lzio.h"
#define FIRST_RESERVED 257
#if !defined(LUA_ENV)
#define LUA_ENV "_ENV"
#endif
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER RESERVED"
*/
enum RESERVED {
/* terminal symbols denoted by reserved words */
TK_AND = FIRST_RESERVED, TK_BREAK,
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
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_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 */
#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
typedef union {
lua_Number r;
lua_Integer i;
TString *ts;
} SemInfo; /* semantics information */
typedef struct Token {
int token;
SemInfo seminfo;
} Token;
/* state of the lexer plus state of the parser when shared by all
functions */
typedef struct LexState {
int current; /* current character (charint) */
int linenumber; /* input line counter */
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;
LUAI_FUNC void luaX_init (lua_State *L);
LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,
TString *source, int firstchar);
LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);
LUAI_FUNC void luaX_next (LexState *ls);
LUAI_FUNC int luaX_lookahead (LexState *ls);
LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s);
LUAI_FUNC const char *luaX_token2str (LexState *ls, int token);
#endif
Index: vendor/lua/dist/src/llimits.h
===================================================================
--- vendor/lua/dist/src/llimits.h (revision 326343)
+++ vendor/lua/dist/src/llimits.h (revision 326344)
@@ -1,242 +1,323 @@
/*
-** $Id: llimits.h,v 1.125 2014/12/19 13:30:23 roberto Exp $
+** $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
*/
#ifndef llimits_h
#define llimits_h
#include
#include
#include "lua.h"
/*
** '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) */
typedef unsigned char lu_byte;
/* 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))
#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1))
#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 point2int(p) ((unsigned int)((size_t)(p) & UINT_MAX))
+#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
/* type to ensure maximum alignment */
#if defined(LUAI_USER_ALIGNMENT_T)
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
#else
-typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign;
+typedef union {
+ lua_Number n;
+ double u;
+ void *s;
+ lua_Integer i;
+ long l;
+} L_Umaxalign;
#endif
/* 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)
#define lua_longassert(c) ((void)0)
#endif
/*
** assertion for checking API calls
*/
-#if defined(LUA_USE_APICHECK)
-#include
-#define luai_apicheck(e) assert(e)
-#else
-#define luai_apicheck(e) lua_assert(e)
+#if !defined(luai_apicheck)
+#define luai_apicheck(l,e) lua_assert(e)
#endif
+#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
-#define api_check(e,msg) luai_apicheck((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) && _MSC_VER >= 1200
#define l_noret void __declspec(noreturn)
#else
#define l_noret void
#endif
/*
** maximum depth for nested C calls and syntactical nested non-terminals
** in a program. (Value must fit in an unsigned short int.)
*/
#if !defined(LUAI_MAXCCALLS)
#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;
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
#if LUAI_BITSINT >= 32
typedef unsigned int Instruction;
#else
typedef unsigned long Instruction;
#endif
+/*
+** Maximum length for short strings, that is, strings that are
+** internalized. (Cannot be smaller than reserved words or tags for
+** metamethods, as these strings must be internalized;
+** #("function") = 8, #("__newindex") = 10.)
+*/
+#if !defined(LUAI_MAXSHORTLEN)
+#define LUAI_MAXSHORTLEN 40
+#endif
-/* minimum size for the string table (must be power of 2) */
+
+/*
+** Initial size for the string table (must be power of 2).
+** The Lua core alone registers ~50 strings (reserved words +
+** metaevent keys + a few others). Libraries would typically add
+** a few dozens more.
+*/
#if !defined(MINSTRTABSIZE)
-#define MINSTRTABSIZE 64 /* minimum size for "predefined" strings */
+#define MINSTRTABSIZE 128
#endif
+/*
+** Size of cache for strings in the API. '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
+
+
/* minimum size for string buffer */
#if !defined(LUA_MINBUFFER)
#define LUA_MINBUFFER 32
#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)
#endif
+/*
+** macro executed during Lua functions at points where the
+** function can yield.
+*/
#if !defined(luai_threadyield)
#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);}
#endif
/*
** these macros allow user-specific actions on threads when you defined
** LUAI_EXTRASPACE and need to do something extra when a thread is
** created/deleted/resumed/yielded.
*/
#if !defined(luai_userstateopen)
#define luai_userstateopen(L) ((void)L)
#endif
#if !defined(luai_userstateclose)
#define luai_userstateclose(L) ((void)L)
#endif
#if !defined(luai_userstatethread)
#define luai_userstatethread(L,L1) ((void)L)
#endif
#if !defined(luai_userstatefree)
#define luai_userstatefree(L,L1) ((void)L)
#endif
#if !defined(luai_userstateresume)
#define luai_userstateresume(L,n) ((void)L)
#endif
#if !defined(luai_userstateyield)
#define luai_userstateyield(L,n) ((void)L)
#endif
/*
+** The luai_num* macros define the primitive operations over numbers.
+*/
+
+/* floor division (defined as 'floor(a/b)') */
+#if !defined(luai_numidiv)
+#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
+#endif
+
+/* float division */
+#if !defined(luai_numdiv)
+#define luai_numdiv(L,a,b) ((a)/(b))
+#endif
+
+/*
+** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when
+** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of
+** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b)
+** ~= floor(a/b)'. That happens when the division has a non-integer
+** negative result, which is equivalent to the test below.
+*/
+#if !defined(luai_nummod)
+#define luai_nummod(L,a,b,m) \
+ { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
+#endif
+
+/* exponentiation */
+#if !defined(luai_numpow)
+#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
+#endif
+
+/* the others are quite standard operations */
+#if !defined(luai_numadd)
+#define luai_numadd(L,a,b) ((a)+(b))
+#define luai_numsub(L,a,b) ((a)-(b))
+#define luai_nummul(L,a,b) ((a)*(b))
+#define luai_numunm(L,a) (-(a))
+#define luai_numeq(a,b) ((a)==(b))
+#define luai_numlt(a,b) ((a)<(b))
+#define luai_numle(a,b) ((a)<=(b))
+#define luai_numisnan(a) (!luai_numeq((a), (a)))
+#endif
+
+
+
+
+
+/*
** macro to control inclusion of some hard tests on stack reallocation
*/
#if !defined(HARDSTACKTESTS)
-#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: vendor/lua/dist/src/lmathlib.c
===================================================================
--- vendor/lua/dist/src/lmathlib.c (revision 326343)
+++ vendor/lua/dist/src/lmathlib.c (revision 326344)
@@ -1,404 +1,410 @@
/*
-** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp $
+** $Id: lmathlib.c,v 1.119 2016/12/22 13:08:50 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
#define lmathlib_c
#define LUA_LIB
#include "lprefix.h"
#include
#include
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#undef PI
#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) {
if (lua_isinteger(L, 1)) {
lua_Integer n = lua_tointeger(L, 1);
- if (n < 0) n = (lua_Integer)(0u - n);
+ 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;
}
static int math_sin (lua_State *L) {
lua_pushnumber(L, l_mathop(sin)(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_tan (lua_State *L) {
lua_pushnumber(L, l_mathop(tan)(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;
}
static int math_acos (lua_State *L) {
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
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_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 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) {
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) {
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) {
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_ult (lua_State *L) {
lua_Integer a = luaL_checkinteger(L, 1);
lua_Integer b = luaL_checkinteger(L, 2);
lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b);
return 1;
}
static int math_log (lua_State *L) {
lua_Number x = luaL_checknumber(L, 1);
lua_Number res;
if (lua_isnoneornil(L, 2))
res = l_mathop(log)(x);
else {
lua_Number base = luaL_checknumber(L, 2);
- if (base == 10.0) res = l_mathop(log10)(x);
- else res = l_mathop(log)(x)/l_mathop(log)(base);
+#if !defined(LUA_USE_C89)
+ if (base == l_mathop(2.0))
+ res = l_mathop(log2)(x); else
+#endif
+ if (base == l_mathop(10.0))
+ res = l_mathop(log10)(x);
+ else
+ res = l_mathop(log)(x)/l_mathop(log)(base);
}
lua_pushnumber(L, res);
return 1;
}
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) * (l_mathop(180.0) / PI));
return 1;
}
static int math_rad (lua_State *L) {
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 */
int imin = 1; /* index of current minimum value */
int i;
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_pushvalue(L, imin);
return 1;
}
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int imax = 1; /* index of current maximum value */
int i;
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_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) {
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, (lua_Number)r); /* Number between 0 and 1 */
return 1;
}
case 1: { /* only upper limit */
low = 1;
up = luaL_checkinteger(L, 1);
break;
}
case 2: { /* lower and upper limits */
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 <= 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) {
l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
- (void)rand(); /* discard first value to avoid undesirable correlations */
+ (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");
+ lua_pushliteral(L, "integer");
else
- lua_pushliteral(L, "float");
+ 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},
{"atan", math_atan},
{"ceil", math_ceil},
{"cos", math_cos},
{"deg", math_deg},
{"exp", math_exp},
{"tointeger", math_toint},
{"floor", math_floor},
{"fmod", math_fmod},
{"ult", math_ult},
{"log", math_log},
{"max", math_max},
{"min", math_min},
{"modf", math_modf},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed},
{"sin", math_sin},
{"sqrt", math_sqrt},
{"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}
};
/*
** Open math library
*/
LUAMOD_API int luaopen_math (lua_State *L) {
luaL_newlib(L, mathlib);
lua_pushnumber(L, PI);
lua_setfield(L, -2, "pi");
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: vendor/lua/dist/src/lmem.c
===================================================================
--- vendor/lua/dist/src/lmem.c (revision 326343)
+++ vendor/lua/dist/src/lmem.c (revision 326344)
@@ -1,99 +1,100 @@
/*
-** $Id: lmem.c,v 1.89 2014/11/02 19:33:33 roberto Exp $
+** $Id: lmem.c,v 1.91 2015/03/06 19:45:54 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#define lmem_c
#define LUA_CORE
#include "lprefix.h"
#include
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.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)
**
** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no
** matter 'x').
**
** * 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 ISO C)
**
** frealloc returns NULL if it cannot create or reallocate the area
** (any reallocation to an equal or smaller size cannot fail!)
*/
#define MINSIZEARRAY 4
void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
int limit, const char *what) {
void *newblock;
int newsize;
if (*size >= limit/2) { /* cannot double it? */
if (*size >= limit) /* cannot grow even a little? */
luaG_runerror(L, "too many %s (limit is %d)", what, limit);
newsize = limit; /* still have at least one free place */
}
else {
newsize = (*size)*2;
if (newsize < MINSIZEARRAY)
newsize = MINSIZEARRAY; /* minimum size */
}
newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
*size = newsize; /* update only when everything else is OK */
return newblock;
}
l_noret luaM_toobig (lua_State *L) {
luaG_runerror(L, "memory allocation error: block too big");
}
/*
** generic allocation routine.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
void *newblock;
global_State *g = G(L);
size_t realosize = (block) ? osize : 0;
lua_assert((realosize == 0) == (block == NULL));
#if defined(HARDMEMTESTS)
if (nsize > realosize && g->gcrunning)
luaC_fullgc(L, 1); /* force a GC whenever possible */
#endif
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
if (newblock == NULL && nsize > 0) {
- api_check( nsize > realosize,
- "realloc cannot fail when shrinking a block");
- luaC_fullgc(L, 1); /* try to free some memory... */
- newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
+ lua_assert(nsize > realosize); /* cannot fail when shrinking a block */
+ if (g->version) { /* is state fully built? */
+ luaC_fullgc(L, 1); /* try to free some memory... */
+ newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
+ }
if (newblock == NULL)
luaD_throw(L, LUA_ERRMEM);
}
lua_assert((nsize == 0) == (newblock == NULL));
g->GCdebt = (g->GCdebt + nsize) - realosize;
return newblock;
}
Index: vendor/lua/dist/src/loadlib.c
===================================================================
--- vendor/lua/dist/src/loadlib.c (revision 326343)
+++ vendor/lua/dist/src/loadlib.c (revision 326344)
@@ -1,786 +1,790 @@
/*
-** $Id: loadlib.c,v 1.124 2015/01/05 13:51:39 roberto Exp $
+** $Id: loadlib.c,v 1.130 2017/01/12 17:14:26 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**
** This module contains an implementation of loadlib for Unix systems
** that have dlfcn, an implementation for Windows, and a stub for other
** systems.
*/
#define loadlib_c
#define LUA_LIB
#include "lprefix.h"
+#include
#include
#include
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
-** 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_VAR)
-#define LUA_PATH_VAR "LUA_PATH"
-#endif
-
-#if !defined(LUA_CPATH_VAR)
-#define LUA_CPATH_VAR "LUA_CPATH"
-#endif
-
-#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
-
-#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.
-** LUA_PATH_MARK is the string that marks the substitution points in a
-** template.
-** LUA_EXEC_DIR in a Windows path is replaced by the executable's
-** directory.
** LUA_IGMARK is a mark to ignore all before it when building the
** luaopen_ function name.
*/
-#if !defined (LUA_PATH_SEP)
-#define LUA_PATH_SEP ";"
-#endif
-#if !defined (LUA_PATH_MARK)
-#define LUA_PATH_MARK "?"
-#endif
-#if !defined (LUA_EXEC_DIR)
-#define LUA_EXEC_DIR "!"
-#endif
#if !defined (LUA_IGMARK)
#define LUA_IGMARK "-"
#endif
/*
** LUA_CSUBSEP is the character that replaces dots in submodule names
** when searching for a C loader.
** LUA_LSUBSEP is the character that replaces dots in submodule names
** when searching for a Lua loader.
*/
#if !defined(LUA_CSUBSEP)
#define LUA_CSUBSEP LUA_DIRSEP
#endif
#if !defined(LUA_LSUBSEP)
#define LUA_LSUBSEP LUA_DIRSEP
#endif
/* prefix for open functions in C libraries */
#define LUA_POF "luaopen_"
/* separator for open functions in C libraries */
#define LUA_OFSEP "_"
/*
** unique key for table in the registry that keeps handles
** for all loaded C libraries
*/
static const int CLIBS = 0;
#define LIB_FAIL "open"
-#define setprogdir(L) ((void)0)
+#define setprogdir(L) ((void)0)
+
/*
** system-dependent functions
*/
/*
** 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) /* { */
/*
** {========================================================================
** This is an implementation of loadlib based on the dlfcn interface.
** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
** as an emulation layer on top of native functions.
** =========================================================================
*/
#include
/*
-** Macro to covert pointer to void* to pointer to function. This cast
-** is undefined according to ISO C, but POSIX assumes that it must work.
+** Macro to convert pointer-to-void* to pointer-to-function. This cast
+** is undefined according to ISO C, but POSIX assumes that it works.
** (The '__extension__' in gnu compilers is only to avoid warnings.)
*/
#if defined(__GNUC__)
#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 *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 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;
}
/* }====================================================== */
#elif defined(LUA_DL_DLL) /* }{ */
/*
** {======================================================================
** This is an implementation of loadlib for Windows using native functions.
** =======================================================================
*/
#include
-#undef setprogdir
/*
** optional flags for LoadLibraryEx
*/
#if !defined(LUA_LLE_FLAGS)
#define LUA_LLE_FLAGS 0
#endif
+#undef setprogdir
+
+
+/*
+** Replace in the path (on the top of the stack) any occurrence
+** of LUA_EXEC_DIR with the executable's path.
+*/
static void setprogdir (lua_State *L) {
char buff[MAX_PATH + 1];
char *lb;
DWORD nsize = sizeof(buff)/sizeof(char);
- DWORD n = GetModuleFileNameA(NULL, buff, nsize);
+ DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
luaL_error(L, "unable to get ModuleFileName");
else {
- *lb = '\0';
+ *lb = '\0'; /* cut name on the last '\\' to get the path */
luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff);
lua_remove(L, -2); /* remove original string */
}
}
+
+
static void pusherror (lua_State *L) {
int error = GetLastError();
char buffer[128];
if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL))
lua_pushstring(L, buffer);
else
lua_pushfstring(L, "system error %d\n", error);
}
static void lsys_unloadlib (void *lib) {
FreeLibrary((HMODULE)lib);
}
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);
return lib;
}
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;
}
/* }====================================================== */
#else /* }{ */
/*
** {======================================================
** Fallback for other systems
** =======================================================
*/
#undef LIB_FAIL
#define LIB_FAIL "absent"
#define DLMSG "dynamic libraries not enabled; check your Lua installation"
static void lsys_unloadlib (void *lib) {
(void)(lib); /* not used */
}
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 lsys_sym (lua_State *L, void *lib, const char *sym) {
(void)(lib); (void)(sym); /* not used */
lua_pushliteral(L, DLMSG);
return NULL;
}
/* }====================================================== */
#endif /* } */
/*
+** {==================================================================
+** Set Paths
+** ===================================================================
+*/
+
+/*
+** 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_VAR)
+#define LUA_PATH_VAR "LUA_PATH"
+#endif
+
+#if !defined(LUA_CPATH_VAR)
+#define LUA_CPATH_VAR "LUA_CPATH"
+#endif
+
+
+#define AUXMARK "\1" /* auxiliary mark */
+
+
+/*
+** return registry.LUA_NOENV as a boolean
+*/
+static int noenv (lua_State *L) {
+ int b;
+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
+ b = lua_toboolean(L, -1);
+ lua_pop(L, 1); /* remove value */
+ return b;
+}
+
+
+/*
+** Set a path
+*/
+static void setpath (lua_State *L, const char *fieldname,
+ const char *envname,
+ const char *dft) {
+ const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
+ const char *path = getenv(nver); /* use versioned name */
+ if (path == NULL) /* no environment variable? */
+ path = getenv(envname); /* try unversioned name */
+ if (path == NULL || noenv(L)) /* no environment variable? */
+ lua_pushstring(L, dft); /* use default */
+ else {
+ /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
+ path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
+ LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
+ luaL_gsub(L, path, AUXMARK, dft);
+ lua_remove(L, -2); /* remove result from 1st 'gsub' */
+ }
+ setprogdir(L);
+ lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
+ lua_pop(L, 1); /* pop versioned variable name */
+}
+
+/* }================================================================== */
+
+
+/*
** return registry.CLIBS[path]
*/
static void *checkclib (lua_State *L, const char *path) {
void *plib;
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' */
return plib;
}
/*
** registry.CLIBS[path] = plib -- for queries
** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
*/
static void addtoclib (lua_State *L, const char *path, void *plib) {
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_pushlightuserdata(L, plib);
lua_pushvalue(L, -1);
lua_setfield(L, -3, path); /* CLIBS[path] = plib */
lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
lua_pop(L, 1); /* pop CLIBS table */
}
/*
** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib
** handles in list CLIBS
*/
static int gctm (lua_State *L) {
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] */
lsys_unloadlib(lua_touserdata(L, -1));
lua_pop(L, 1); /* pop handle */
}
return 0;
}
/* 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 = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */
if (reg == NULL) return ERRLIB; /* unable to load library */
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 = lsys_sym(L, reg, sym);
if (f == NULL)
return ERRFUNC; /* unable to find function */
lua_pushcfunction(L, f); /* else create new function */
return 0; /* no errors */
}
}
static int ll_loadlib (lua_State *L) {
const char *path = luaL_checkstring(L, 1);
const char *init = luaL_checkstring(L, 2);
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 */
lua_pushnil(L);
lua_insert(L, -2);
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
return 3; /* return nil, error message, and where */
}
}
/*
** {======================================================
** 'require' function
** =======================================================
*/
static int readable (const char *filename) {
FILE *f = fopen(filename, "r"); /* try to open file */
if (f == NULL) return 0; /* open failed */
fclose(f);
return 1;
}
static const char *pushnexttemplate (lua_State *L, const char *path) {
const char *l;
while (*path == *LUA_PATH_SEP) path++; /* skip separators */
if (*path == '\0') return NULL; /* no more templates */
l = strchr(path, *LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path + strlen(path);
lua_pushlstring(L, path, l - path); /* template */
return l;
}
static const char *searchpath (lua_State *L, const char *name,
const char *path,
const char *sep,
const char *dirsep) {
luaL_Buffer msg; /* to build error message */
luaL_buffinit(L, &msg);
if (*sep != '\0') /* non-empty separator? */
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
while ((path = pushnexttemplate(L, path)) != NULL) {
const char *filename = luaL_gsub(L, lua_tostring(L, -1),
LUA_PATH_MARK, 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 '%s'", filename);
lua_remove(L, -2); /* remove file name */
luaL_addvalue(&msg); /* concatenate error msg. entry */
}
luaL_pushresult(&msg); /* create error message */
return NULL; /* not found */
}
static int ll_searchpath (lua_State *L) {
const char *f = searchpath(L, luaL_checkstring(L, 1),
luaL_checkstring(L, 2),
luaL_optstring(L, 3, "."),
luaL_optstring(L, 4, LUA_DIRSEP));
if (f != NULL) return 1;
else { /* error message is on top of the stack */
lua_pushnil(L);
lua_insert(L, -2);
return 2; /* return nil + error message */
}
}
static const char *findfile (lua_State *L, const char *name,
const char *pname,
const char *dirsep) {
const char *path;
lua_getfield(L, lua_upvalueindex(1), pname);
path = lua_tostring(L, -1);
if (path == NULL)
luaL_error(L, "'package.%s' must be a string", pname);
return searchpath(L, name, path, ".", dirsep);
}
static int checkload (lua_State *L, int stat, const char *filename) {
if (stat) { /* module loaded successfully? */
lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2; /* return open function and file name */
}
else
return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s",
lua_tostring(L, 1), filename, lua_tostring(L, -1));
}
static int searcher_Lua (lua_State *L) {
const char *filename;
const char *name = luaL_checkstring(L, 1);
filename = findfile(L, name, "path", LUA_LSUBSEP);
if (filename == NULL) return 1; /* module not found in this path */
return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
}
/*
** 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 *openfunc;
const char *mark;
modname = luaL_gsub(L, modname, ".", LUA_OFSEP);
mark = strchr(modname, *LUA_IGMARK);
if (mark) {
int stat;
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 */
}
openfunc = lua_pushfstring(L, LUA_POF"%s", modname);
return lookforfunc(L, filename, openfunc);
}
static int searcher_C (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* module not found in this path */
return checkload(L, (loadfunc(L, filename, name) == 0), filename);
}
static int searcher_Croot (lua_State *L) {
const char *filename;
const char *name = luaL_checkstring(L, 1);
const char *p = strchr(name, '.');
int stat;
if (p == NULL) return 0; /* is root */
lua_pushlstring(L, name, p - name);
filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP);
if (filename == NULL) return 1; /* root not found */
if ((stat = loadfunc(L, filename, name)) != 0) {
if (stat != ERRFUNC)
return checkload(L, 0, filename); /* real error */
else { /* open function not found */
lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename);
return 1;
}
}
lua_pushstring(L, filename); /* will be 2nd argument to module */
return 2;
}
static int searcher_preload (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
- lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
return 1;
}
static void findloader (lua_State *L, const char *name) {
int i;
luaL_Buffer msg; /* to build error message */
luaL_buffinit(L, &msg);
/* 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++) {
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 '%s' not found:%s", name, lua_tostring(L, -1));
}
lua_pushstring(L, name);
lua_call(L, 1, 2); /* call it */
if (lua_isfunction(L, -2)) /* did it find a loader? */
return; /* module loader found */
else if (lua_isstring(L, -2)) { /* searcher returned error message? */
lua_pop(L, 1); /* remove extra return */
luaL_addvalue(&msg); /* concatenate error message */
}
else
lua_pop(L, 2); /* remove both returns */
}
}
static int ll_require (lua_State *L) {
const char *name = luaL_checkstring(L, 1);
- lua_settop(L, 1); /* _LOADED table will be at index 2 */
- lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
- lua_getfield(L, 2, name); /* _LOADED[name] */
+ lua_settop(L, 1); /* LOADED table will be at index 2 */
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
+ lua_getfield(L, 2, name); /* LOADED[name] */
if (lua_toboolean(L, -1)) /* is it there? */
return 1; /* package is already loaded */
/* else must load package */
lua_pop(L, 1); /* remove 'getfield' result */
findloader(L, name);
lua_pushstring(L, name); /* pass name as argument to module loader */
lua_insert(L, -2); /* name is 1st argument (before search data) */
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_setfield(L, 2, name); /* LOADED[name] = returned 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 */
+ lua_setfield(L, 2, name); /* LOADED[name] = true */
}
return 1;
}
/* }====================================================== */
/*
** {======================================================
** 'module' function
** =======================================================
*/
#if defined(LUA_COMPAT_MODULE)
/*
** changes the environment variable of calling function
*/
static void set_env (lua_State *L) {
lua_Debug ar;
if (lua_getstack(L, 1, &ar) == 0 ||
lua_getinfo(L, "f", &ar) == 0 || /* get calling function */
lua_iscfunction(L, -1))
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 */
}
static void dooptions (lua_State *L, int n) {
int i;
for (i = 2; i <= n; i++) {
if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */
lua_pushvalue(L, i); /* get option (a function) */
lua_pushvalue(L, -2); /* module */
lua_call(L, 1, 0);
}
}
}
static void modinit (lua_State *L, const char *modname) {
const char *dot;
lua_pushvalue(L, -1);
lua_setfield(L, -2, "_M"); /* module._M = module */
lua_pushstring(L, modname);
lua_setfield(L, -2, "_NAME");
dot = strrchr(modname, '.'); /* look for last dot in module name */
if (dot == NULL) dot = modname;
else dot++;
/* set _PACKAGE as package name (full module name minus last part) */
lua_pushlstring(L, modname, dot - modname);
lua_setfield(L, -2, "_PACKAGE");
}
static int ll_module (lua_State *L) {
const char *modname = luaL_checkstring(L, 1);
int lastarg = lua_gettop(L); /* last parameter */
luaL_pushmodule(L, modname, 1); /* get/create module table */
/* check whether table already has a _NAME field */
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);
}
lua_pushvalue(L, -1);
set_env(L);
dooptions(L, lastarg);
return 1;
}
static int ll_seeall (lua_State *L) {
luaL_checktype(L, 1, LUA_TTABLE);
if (!lua_getmetatable(L, 1)) {
lua_createtable(L, 0, 1); /* create new metatable */
lua_pushvalue(L, -1);
lua_setmetatable(L, 1);
}
lua_pushglobaltable(L);
lua_setfield(L, -2, "__index"); /* mt.__index = _G */
return 0;
}
#endif
/* }====================================================== */
-/* auxiliary mark (for internal use) */
-#define AUXMARK "\1"
-
-
-/*
-** return registry.LUA_NOENV as a boolean
-*/
-static int noenv (lua_State *L) {
- int b;
- lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
- b = lua_toboolean(L, -1);
- lua_pop(L, 1); /* remove value */
- return b;
-}
-
-
-static void setpath (lua_State *L, const char *fieldname, const char *envname1,
- const char *envname2, const char *def) {
- const char *path = getenv(envname1);
- if (path == NULL) /* no environment variable? */
- path = getenv(envname2); /* try alternative name */
- if (path == NULL || noenv(L)) /* no environment variable? */
- lua_pushstring(L, def); /* use default */
- else {
- /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */
- path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP,
- LUA_PATH_SEP AUXMARK LUA_PATH_SEP);
- luaL_gsub(L, path, AUXMARK, def);
- lua_remove(L, -2);
- }
- setprogdir(L);
- lua_setfield(L, -2, fieldname);
-}
-
-
static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib},
{"searchpath", ll_searchpath},
#if defined(LUA_COMPAT_MODULE)
{"seeall", ll_seeall},
#endif
/* placeholders */
{"preload", NULL},
{"cpath", NULL},
{"path", NULL},
{"searchers", NULL},
{"loaded", NULL},
{NULL, NULL}
};
static const luaL_Reg ll_funcs[] = {
#if defined(LUA_COMPAT_MODULE)
{"module", ll_module},
#endif
{"require", ll_require},
{NULL, NULL}
};
static void createsearcherstable (lua_State *L) {
static const lua_CFunction searchers[] =
{searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
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' */
}
/*
** 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);
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);
- /* set field 'path' */
- setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT);
- /* set field 'cpath' */
- setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT);
+ /* set paths */
+ setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT);
+ setpath(L, "cpath", 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' */
- luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
lua_setfield(L, -2, "loaded");
/* set field 'preload' */
- luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD");
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
lua_setfield(L, -2, "preload");
lua_pushglobaltable(L);
lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */
luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */
lua_pop(L, 1); /* pop global table */
return 1; /* return 'package' table */
}
Index: vendor/lua/dist/src/lobject.c
===================================================================
--- vendor/lua/dist/src/lobject.c (revision 326343)
+++ vendor/lua/dist/src/lobject.c (revision 326344)
@@ -1,470 +1,521 @@
/*
-** $Id: lobject.c,v 2.101 2014/12/26 14:43:45 roberto Exp $
+** $Id: lobject.c,v 2.113 2016/12/22 13:08:50 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
#define lobject_c
#define LUA_CORE
#include "lprefix.h"
+#include
+#include
#include
#include
#include
#include
#include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "lvm.h"
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
/*
** converts an integer to a "floating point byte", represented as
** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
** eeeee != 0 and (xxx) otherwise.
*/
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);
}
/* 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,
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,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
};
int l = 0;
x--;
while (x >= 256) { l += 8; x >>= 8; }
return l + log_2[x];
}
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
lua_Integer v2) {
switch (op) {
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;
}
}
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;
}
}
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));
+ luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
}
int luaO_hexavalue (int c) {
if (lisdigit(c)) return c - '0';
- else return ltolower(c) - 'a' + 10;
+ else return (ltolower(c) - 'a') + 10;
}
static int isneg (const char **s) {
if (**s == '-') { (*s)++; return 1; }
else if (**s == '+') (*s)++;
return 0;
}
/*
** {==================================================================
** Lua's implementation for 'lua_strx2number'
** ===================================================================
*/
+
#if !defined(lua_strx2number)
-#include
-
/* 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) {
+ int dot = lua_getlocaledecpoint();
lua_Number r = 0.0; /* result (accumulator) */
int sigdig = 0; /* number of significant digits */
int nosigdig = 0; /* number of non-significant digits */
int e = 0; /* exponent correction */
int neg; /* 1 if number is negative */
- int dot = 0; /* true after seen a dot */
+ int hasdot = 0; /* true after seen a dot */
*endptr = cast(char *, s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check signal */
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
return 0.0; /* invalid format (no '0x') */
for (s += 2; ; s++) { /* skip '0x' and read numeral */
- if (*s == '.') {
- if (dot) break; /* second dot? stop loop */
- else dot = 1;
+ if (*s == dot) {
+ if (hasdot) break; /* second dot? stop loop */
+ else hasdot = 1;
}
else if (lisxdigit(cast_uchar(*s))) {
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
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 (dot) e--; /* decimal digit? correct exponent */
+ if (hasdot) e--; /* decimal digit? correct exponent */
}
else break; /* neither a dot nor a digit */
}
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; /* exponent value */
int neg1; /* exponent signal */
s++; /* skip 'p' */
neg1 = isneg(&s); /* signal */
if (!lisdigit(cast_uchar(*s)))
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 */
}
if (neg) r = -r;
return l_mathop(ldexp)(r, e);
}
#endif
/* }====================================================== */
-static const char *l_str2d (const char *s, lua_Number *result) {
+/* maximum length of a numeral */
+#if !defined (L_MAXLENNUM)
+#define L_MAXLENNUM 200
+#endif
+
+static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
char *endptr;
- if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
+ *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;
- else if (strpbrk(s, "xX")) /* hex? */
- *result = lua_strx2number(s, &endptr);
- else
- *result = lua_str2number(s, &endptr);
- if (endptr == s) return 0; /* nothing recognized */
- while (lisspace(cast_uchar(*endptr))) endptr++;
- return (*endptr == '\0' ? endptr : NULL); /* OK if no trailing characters */
+ endptr = l_str2dloc(s, result, mode); /* try to convert */
+ if (endptr == NULL) { /* failed? may be a different locale */
+ char buff[L_MAXLENNUM + 1];
+ const 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++) {
- a = a * 10 + *s - '0';
+ 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
return 0; /* conversion failed */
- return (e - s + 1); /* success; return string size */
+ 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, ivalue(obj));
+ len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
else {
- len = lua_number2str(buff, fltvalue(obj));
+ 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++] = '.';
+ 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'
- conventional formats, plus Lua-specific '%I' and '%U' */
+/*
+** 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': {
+ 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': {
- setivalue(L->top++, va_arg(argp, int));
- luaO_tostring(L, L->top - 1);
- break;
+ case 'd': { /* an 'int' */
+ setivalue(L->top, va_arg(argp, int));
+ goto top2str;
}
- case 'I': {
- setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
- luaO_tostring(L, L->top - 1);
- break;
+ case 'I': { /* a 'lua_Integer' */
+ setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
+ goto top2str;
}
- case 'f': {
- setfltvalue(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': {
+ case 'p': { /* a pointer */
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
- int l = sprintf(buff, "%p", va_arg(argp, void *));
+ int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff, l);
break;
}
- case 'U': {
+ 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 '%%%c' to 'lua_pushfstring'",
*(e + 1));
}
}
n += 2;
fmt = e+2;
}
luaD_checkstack(L, 1);
pushstr(L, fmt, strlen(fmt));
if (n > 0) luaV_concat(L, n + 1);
return svalue(L->top - 1);
}
const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
const char *msg;
va_list argp;
va_start(argp, fmt);
msg = luaO_pushvfstring(L, fmt, argp);
va_end(argp);
return msg;
}
/* number of chars of a literal string without the ending \0 */
#define LL(x) (sizeof(x)/sizeof(char) - 1)
#define RETS "..."
#define PRE "[string \""
#define POS "\"]"
#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
void luaO_chunkid (char *out, const char *source, size_t bufflen) {
size_t l = strlen(source);
if (*source == '=') { /* 'literal' source */
if (l <= bufflen) /* small enough? */
memcpy(out, source + 1, l * sizeof(char));
else { /* truncate it */
addstr(out, source + 1, bufflen - 1);
*out = '\0';
}
}
else if (*source == '@') { /* file name */
if (l <= bufflen) /* small enough? */
memcpy(out, source + 1, l * sizeof(char));
else { /* add '...' before rest of name */
addstr(out, RETS, LL(RETS));
bufflen -= LL(RETS);
memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
}
}
else { /* string; format as [string "source"] */
const char *nl = strchr(source, '\n'); /* find first new line (if any) */
addstr(out, PRE, LL(PRE)); /* add prefix */
bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
if (l < bufflen && nl == NULL) { /* small one-line source? */
addstr(out, source, l); /* keep it */
}
else {
if (nl != NULL) l = nl - source; /* stop at first newline */
if (l > bufflen) l = bufflen;
addstr(out, source, l);
addstr(out, RETS, LL(RETS));
}
memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
}
}
Index: vendor/lua/dist/src/lobject.h
===================================================================
--- vendor/lua/dist/src/lobject.h (revision 326343)
+++ vendor/lua/dist/src/lobject.h (revision 326344)
@@ -1,540 +1,549 @@
/*
-** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp $
+** $Id: lobject.h,v 2.117 2016/08/01 19:51:24 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
#ifndef lobject_h
#define lobject_h
#include
#include "llimits.h"
#include "lua.h"
/*
** Extra tags for non-values
*/
-#define LUA_TPROTO LUA_NUMTAGS
-#define LUA_TDEADKEY (LUA_NUMTAGS+1)
+#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_TPROTO + 2)
/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* value)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/
-#define VARBITS (3 << 4)
-
/*
** LUA_TFUNCTION variants:
** 0 - Lua function
** 1 - light C function
** 2 - regular C function (closure)
*/
/* Variant tags for functions */
#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */
#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */
#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */
/* Variant tags for strings */
#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
#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)
/* mark a tag as collectable */
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
/*
** Common type for all collectable objects
*/
typedef struct GCObject GCObject;
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
/*
** Common type has only the common header
*/
struct GCObject {
CommonHeader;
};
-/*
-** Union of all Lua values
-*/
-typedef union Value Value;
-
-
-
/*
** Tagged Values. This is the basic representation of values in Lua,
** 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 */
#define NILCONSTANT {NULL}, LUA_TNIL
#define val_(o) ((o)->value_)
/* raw type tag of a TValue */
#define rttype(o) ((o)->tt_)
/* tag with no variants (bits 0-3) */
#define novariant(x) ((x) & 0x0F)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define ttype(o) (rttype(o) & 0x3F)
/* type tag of a TValue with no variants (bits 0-3) */
#define ttnov(o) (novariant(rttype(o)))
/* Macros to test type */
#define checktag(o,t) (rttype(o) == (t))
#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)
#define ttisstring(o) checktype((o), LUA_TSTRING)
#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR))
#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR))
#define ttistable(o) checktag((o), ctb(LUA_TTABLE))
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION)
#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL))
#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL))
#define ttislcf(o) checktag((o), LUA_TLCF)
#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA))
#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD))
#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY)
/* Macros to access values */
#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 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), gco2t(val_(o).gc))
#define bvalue(o) check_exp(ttisboolean(o), val_(o).b)
#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))
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE)
/* Macros for internal tests */
#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 setfltvalue(obj,x) \
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); }
+#define chgfltvalue(obj,x) \
+ { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); }
+
#define setivalue(obj,x) \
{ TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); }
+#define chgivalue(obj,x) \
+ { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
+
#define setnilvalue(obj) settt_(obj, LUA_TNIL)
#define setfvalue(obj,x) \
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); }
#define setpvalue(obj,x) \
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); }
#define setbvalue(obj,x) \
{ 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(i_g->tt)); }
#define setsvalue(L,obj,x) \
{ TValue *io = (obj); TString *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define setuvalue(L,obj,x) \
{ TValue *io = (obj); Udata *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define setthvalue(L,obj,x) \
{ TValue *io = (obj); lua_State *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define setclLvalue(L,obj,x) \
{ TValue *io = (obj); LClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define setclCvalue(L,obj,x) \
{ TValue *io = (obj); CClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define sethvalue(L,obj,x) \
{ TValue *io = (obj); Table *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
- checkliveness(G(L),io); }
+ checkliveness(L,io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
#define setobj(L,obj1,obj2) \
{ TValue *io1=(obj1); *io1 = *(obj2); \
- (void)L; checkliveness(G(L),io1); }
+ (void)L; checkliveness(L,io1); }
/*
** different types of assignments, according to destination
*/
/* from stack to (same) stack */
#define setobjs2s setobj
/* to stack (not from same stack) */
#define setobj2s setobj
#define setsvalue2s setsvalue
#define sethvalue2s sethvalue
#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)))
+
/*
** {======================================================
** types and prototypes
** =======================================================
*/
-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 */
-};
-
-
-struct lua_TValue {
- TValuefields;
-};
-
-
typedef TValue *StkId; /* index to stack elements */
/*
** Header for string value; string bytes follow the end of this structure
** (aligned according to 'UTString'; see next).
*/
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
+ lu_byte shrlen; /* length for short strings */
unsigned int hash;
- size_t len; /* number of characters in string */
- struct TString *hnext; /* linked list for hash table */
+ union {
+ size_t lnglen; /* length for long strings */
+ struct TString *hnext; /* linked list for hash table */
+ } u;
} TString;
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UTString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
TString tsv;
} UTString;
/*
** Get the actual string (array of bytes) from a 'TString'.
** (Access to 'extra' ensures that value is really a 'TString'.)
*/
-#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString))
#define getstr(ts) \
- check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts)))
+ check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))
+
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(tsvalue(o))
+/* get string length from 'TString *s' */
+#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen)
+/* get string length from 'TValue *o' */
+#define vslen(o) tsslen(tsvalue(o))
+
+
/*
** Header for userdata; memory area follows the end of this structure
** (aligned according to 'UUdata'; see next).
*/
typedef struct Udata {
CommonHeader;
lu_byte ttuv_; /* user value's tag */
struct Table *metatable;
size_t len; /* number of bytes */
union Value user_; /* user value */
} Udata;
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UUdata {
L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */
Udata uv;
} UUdata;
/*
** Get the address of memory block inside 'Udata'.
** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
*/
#define getudatamem(u) \
check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))
#define setuservalue(L,u,o) \
{ const TValue *io=(o); Udata *iu = (u); \
- iu->user_ = io->value_; iu->ttuv_ = io->tt_; \
- checkliveness(G(L),io); }
+ 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_; io->tt_ = iu->ttuv_; \
- checkliveness(G(L),io); }
+ io->value_ = iu->user_; settt_(io, iu->ttuv_); \
+ checkliveness(L,io); }
/*
** Description of an upvalue for function prototypes
*/
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;
/*
** Description of a local variable for function prototypes
** (used for debug information)
*/
typedef struct LocVar {
TString *varname;
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
} LocVar;
/*
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg;
- lu_byte maxstacksize; /* maximum stack used by this function */
+ lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of 'p' */
int sizelocvars;
- int linedefined;
- int lastlinedefined;
+ 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 */
- struct LClosure *cache; /* last created closure with this prototype */
+ struct LClosure *cache; /* last-created closure with this prototype */
TString *source; /* used for debug information */
GCObject *gclist;
} Proto;
/*
** Lua Upvalues
*/
typedef struct UpVal UpVal;
/*
** Closures
*/
#define ClosureHeader \
CommonHeader; lu_byte nupvalues; GCObject *gclist
typedef struct CClosure {
ClosureHeader;
lua_CFunction f;
TValue upvalue[1]; /* list of upvalues */
} CClosure;
typedef struct LClosure {
ClosureHeader;
struct Proto *p;
UpVal *upvals[1]; /* list of upvalues */
} LClosure;
typedef union Closure {
CClosure c;
LClosure l;
} Closure;
#define isLfunction(o) ttisLclosure(o)
#define getproto(o) (clLvalue(o)->p)
/*
** Tables
*/
typedef union TKey {
struct {
TValuefields;
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(G(L),io_); }
+ (void)L; checkliveness(L,io_); }
typedef struct Node {
TValue i_val;
TKey i_key;
} Node;
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<