1
0
mirror of https://github.com/lua/lua synced 2026-06-08 15:34:49 +00:00

Compare commits

...

3299 Commits

Author SHA1 Message Date
Roberto Ierusalimschy c33b1728ae Details
Added as incompatibility, in the manual, the extra return of 'io.lines'.
2020-06-18 11:07:27 -03:00
Roberto Ierusalimschy a304199836 Detail in 'lua_resetthread'
'lua_resetthread' should reset the CallInfo list before calling
'luaF_close'. luaF_close can call functions, and those functions
should not run with dead functions still in the CallInfo list.
2020-06-17 10:36:42 -03:00
Roberto Ierusalimschy 6d7cd31fee Fixed missing GC barriers in compiler and undump
While building a new prototype, the GC needs barriers for every object
(strings and nested prototypes) that is attached to the new prototype.
2020-06-16 09:54:20 -03:00
Roberto Ierusalimschy 993c58fde3 In 'lua_checkmemory', userdata can be gray, too
Since commit ca6fe7449a, userdata with uservalues can be gray
and can belong to gray lists ('gclist').
2020-06-15 12:01:36 -03:00
Roberto Ierusalimschy d49b288728 'luaE_shrinkCI' shouldn't remove first free CallInfo
Due to emergency collections, 'luaE_shrinkCI' can be called while Lua
is building a new CallInfo, which for a while is still a free CallInfo.
2020-06-15 11:58:59 -03:00
Roberto Ierusalimschy 69e84805e4 Details 2020-06-10 16:39:37 -03:00
Roberto Ierusalimschy 364e569945 Avoid calling 'fprintf' with NULL
Avoid undefined behavior in calls like «fprintf("%s", NULL)».
('lua_writestringerror' is implemented as 'fprintf', and 'lua_tostring'
can return NULL if object is not a string.)
2020-06-09 16:12:01 -03:00
Roberto Ierusalimschy 63295f1f7f Fixed two bugs in to-be-closed variables x constants
The parser were mixing compiler indices of variables with stack indices,
so that when a to-be-closed variable was used inside the scope of
compile-time constants (which may be optimized away), it might be closed
in the wrong place. (See new tests for examples.)

Besides fixing the bugs, this commit also changed comments and variable
names to avoid that kind of confusion and added tests.
2020-06-01 15:07:58 -03:00
Roberto Ierusalimschy 50523b107d Improvements in the manual
- more consistent nomenclature for error handling
- more precise definition for dead objects
- added algorithm used by 'math.random'
- added luaL_pushfail
- some other minor changes
2020-05-29 10:41:32 -03:00
Roberto Ierusalimschy aa8d4a782d Details (more uniformity in error messages) 2020-05-27 11:46:47 -03:00
Roberto Ierusalimschy efcf24be0c 'luaL_execresult' does not assume -1 status as error
ISO C is silent about the return of 'system'. Windows sets 'errno' in
case of errors. Linux has several different error cases, with different
return values. ISO C allows 'system' to set 'errno' even if there are no
errors. Here we assume that a status==0 is success (which is the case
on several platforms), otherwise it is an error. If there is an error
number, gives the error based on it. (The worst a spurious 'errno'
can do is to generate a bad error message.) Otherwise uses the normal
results.
2020-05-22 15:39:29 -03:00
Roberto Ierusalimschy 17dbaa8639 Improvements in the handling of signals
Added 'volatile' to 'l_signalT' variables plus some minor changes.
2020-05-22 11:40:34 -03:00
Roberto Ierusalimschy 9514abc2da Cleaner definition for 'TString'
Use a variable-sized array to store string contents at the end of a
structure 'TString', instead of raw memory.
2020-05-19 12:42:20 -03:00
Roberto Ierusalimschy 0be57b9b6d Details in comments 2020-05-07 14:52:19 -03:00
Roberto Ierusalimschy 61a4e64a66 Back to old encoding of versions in binary files
(Undoing part of commit f53eabeed8.)  It is better to keep this encoding
stable, so that all Lua versions can read at least the version of a
binary file.
2020-05-06 14:19:08 -03:00
Roberto Ierusalimschy 9a6f47f0ed C-Stack test does not assume minimum of 400 slots 2020-05-04 14:17:15 -03:00
Roberto Ierusalimschy 948fb628d9 Details
When in test mode (#include "tests.h"), force Lua to use its own
implementation of 'lua_strx2number' and 'lua_number2strx' to test them.
2020-04-30 17:29:27 -03:00
Roberto Ierusalimschy a901c505ab Fixed warning about casts between function pointers
gcc now warns (with -Wextra) about casts between pointers to different
function types. The type 'void(*)(void)' works as a 'void*' for function
pointers, cleaning the warning.
2020-04-29 16:37:25 -03:00
Roberto Ierusalimschy 0ddc0f47bd Several details about 5.4.0 rc1
Corrected several small details: added 'const', adjusts in tabs x
spaces, removed unused #includes and #defines, misspellings, etc.
2020-04-23 14:48:15 -03:00
Roberto Ierusalimschy cac075a122 Small issue in 'exprstat'
The code should not compute an instruction address before checking that
it exists. (Virtually no machine complains of computing an invalid
address, as long as the address is not used, but for ISO C that is
undefined behavior.)
2020-04-23 14:39:34 -03:00
Roberto Ierusalimschy 9e0a8475cd Added 'simplesect' sections to the manual
'simplesect' encloses the introductory text of sections with
subsections, so that each section either is all text or is all
subsections. (This commit also corrects a small brace error in the
manual and extra spaces/tabs in some other files.)
2020-04-13 13:42:40 -03:00
Roberto Ierusalimschy 7ccc6d8290 Improvements in the manual
Several small improvements, in particular a new subsection consolidating
all status codes in the API.
2020-04-10 15:44:48 -03:00
Roberto Ierusalimschy 7288528a1e Short strings always use all bytes in the hash
Collisions in short strings occurr just by their existence, when
internalizing them. (Collisions in long strings is caused/controlled
by the program, when adding them as keys to the same table.)
2020-04-01 10:52:41 -03:00
Roberto Ierusalimschy 513559cc47 Fixed bug in 'string.format("%p")'
The string "(null)" used for non-collectable values must be printed as a
string, not as a pointer. (Bug introduced in commit e0cbaa50fa).
2020-03-16 14:13:13 -03:00
Roberto Ierusalimschy e460752323 Fixed "conceptual" bug in 'luaK_setreturns'
This function was computing invalid instruction addresses when the
expression was not a multi-return instruction. (Virtually all machines
don't raise errors when computing an invalid address, as long as the
address is not accessed, but this computation is undefined behavior in
ISO C.)
2020-03-02 13:24:06 -03:00
Roberto Ierusalimschy 92594f0939 Corrected direct use of 'snprintf' in 'lstrlib.c' 2020-02-28 10:37:14 -03:00
Roberto Ierusalimschy e8a52281d9 Code style in 'ldump'/'lundump'.
- function names start with lower case;
- state is always the first parameter.
2020-02-27 15:17:44 -03:00
Roberto Ierusalimschy 6eb53b7526 Details
Several details in code (e.g., moving a variable to the most inner
scope that encloses its uses), comments, parameter names, extra tests.
2020-02-27 12:59:22 -03:00
Roberto Ierusalimschy 9b7987a9d1 OP_LOADFALSE broken in two instructions 2020-02-11 11:12:33 -03:00
Roberto Ierusalimschy 28ef7061bb Tag values don't need to be different from type values
Variants can use zero for first variant.
2020-01-31 13:13:28 -03:00
Roberto Ierusalimschy 46c3587a6f Clearer distinction between types and tags
LUA_T* represents only types; tags (types + Variants) are represented
by LUA_V* constants.
2020-01-31 11:09:53 -03:00
Roberto Ierusalimschy 69c7139ff8 New macro 'makevariant' to codify variant tags 2020-01-06 14:50:36 -03:00
Roberto Ierusalimschy 5ff408d218 Changed internal representation of booleans
Instead of an explicit value (field 'b'), true and false use different
tag variants. This avoids reading an extra field and results in more
direct code. (Most code that uses booleans needs to distinguish between
true and false anyway.)
2020-01-06 11:38:31 -03:00
Roberto Ierusalimschy e3c83835e7 Fixed bug in 'aux_rawset'
In 'aux_rawset', top must be decremented after the barrier, which
refers to top-1. (Bug introduced in commit c646e57fd.)
2019-12-30 14:53:38 -03:00
Roberto Ierusalimschy bd1b87c579 Comments (mosty typos) 2019-12-30 11:45:08 -03:00
Roberto Ierusalimschy d7bb8df841 Copyright year changed to 2020 2019-12-27 10:38:53 -03:00
Roberto Ierusalimschy c646e57fd6 Joined common code in 'lua_rawset' and 'lua_rawsetp' 2019-12-17 15:45:13 -03:00
Roberto Ierusalimschy e0ab13c62f Easy way to allow Unicode characters in identifiers
For those that want to try it...
2019-12-17 14:24:30 -03:00
Roberto Ierusalimschy e0cbaa50fa Added test for NULL in string.format("%p")
ISO C states that standard library functions should not be called
with NULL arguments, unless stated otherwise. 'sprintf' does not
state otherwise, and it doesn't hurt to be on the safe side.
2019-12-17 10:49:55 -03:00
Roberto Ierusalimschy 3747487320 Small correction in assertion 2019-12-13 14:02:42 -03:00
Roberto Ierusalimschy 1e0ad018ce Comment about LUA_COMPAT_LT_LE moved to proper place 2019-12-10 13:50:20 -03:00
Roberto Ierusalimschy 95735bda46 Simplifications in 'op_arith*' family of macros 2019-12-05 14:51:58 -03:00
Roberto Ierusalimschy d30569c064 Using an enumeration for float->integer coercion modes 2019-12-05 14:14:29 -03:00
Roberto Ierusalimschy 2d92102dee 'l_mathlim' renamed to 'l_floatatt'
That macro is applied to float attributes, not to limits.
2019-12-05 13:31:07 -03:00
Roberto Ierusalimschy 490ecfcaa1 Better comments about the use of 'k' in opcodes 2019-12-05 12:59:42 -03:00
Roberto Ierusalimschy e174f43807 Manual a little more clear about string->number coersions 2019-12-05 12:57:40 -03:00
Roberto Ierusalimschy 81f2401c6d Code reorganization for opcodes OP_FORPREP and OP_FORLOOP
Parts of the code for opcodes OP_FORPREP and OP_FORLOOP were moved
to functions outside the interpreter loop.
2019-12-04 16:51:53 -03:00
Roberto Ierusalimschy 508a705c1c Removed some wrong comments
Both 'tonumber' and 'tointeger' cannot change the out parameter when
the conversion fails.
2019-11-28 18:10:26 -03:00
Roberto Ierusalimschy 6f1c033d72 More generic pattern when testing 'string.format'
The result of 'string.format("%a", 0.0)' can have multiple zeros
after the dot.
2019-11-22 11:07:47 -03:00
Roberto Ierusalimschy 5f83fb6582 Details 2019-11-18 14:54:06 -03:00
Roberto Ierusalimschy 679dc72c08 Using 'metavalues' for "metamethods" that are not methods
Several "metamethods" are not required to be methods (functions),
so it seems clearer not to call them metamethods. The manual now
uses the word 'metavalue' for those values.
2019-11-08 15:45:55 -03:00
Roberto Ierusalimschy 1499680f9e Comments in 'lopcodes.h'
Both 'R' and 'K' are arrays, so the comments should use square
brackets to index them.
2019-11-07 10:57:57 -03:00
Roberto Ierusalimschy bdcfae2e1c File 'bugs' no longer tracked by git
The file 'bugs' reports bugs in several different versions
(corresponding to different branches in the repository), without
a clear division of "this bugs belongs to this version". So, it
doesn't make sense to track it along with one (or many) versions.
2019-10-30 16:46:11 -03:00
Roberto Ierusalimschy 7d526e75a7 Fixed bug in tail calls of __call chains
A tail call of a __call chain (a __call metamethod that itself is
also not a function) was being perfomed as a regular call.
2019-10-28 15:58:07 -03:00
Roberto Ierusalimschy c12983cf8a Fixed warnings from Keil compiler 2019-10-25 17:41:40 -03:00
Roberto Ierusalimschy ba9cd0d25a Change in the prefix of messages from searchers
The initial "\n\t" to properly indent a searcher message is being added
by 'findloader' when building the error message, instead of being
included in the original message by each searcher itself.
2019-10-24 10:49:44 -03:00
Roberto Ierusalimschy b93f3b00bb Added function 'luaL_buffsub' 2019-10-23 11:10:19 -03:00
Roberto Ierusalimschy 4c32d9300c Several enhancements in the manual 2019-10-23 10:41:47 -03:00
Roberto Ierusalimschy 6e285e5392 More pious implementation of 'string.dump'
In 'str__dump', the call to 'lua_dump' assumes the function is on the
top of the stack, but the manual allows 'luaL_buffinit' to push stuff
on the stack (although the current implementation does not).  So, the
call to 'luaL_buffinit' must come after the call to 'lua_dump'.
2019-10-23 10:31:02 -03:00
Roberto Ierusalimschy b8cdea0190 Changed definition of macro 'l_isfalse'
The old definition did one test for nil, but three tests for the all
too common booleans (and two tests for other values); this definition
does two tests for all values.
2019-10-22 14:10:54 -03:00
Roberto Ierusalimschy e592f94a64 Details (mostly comments) 2019-10-22 14:08:22 -03:00
Roberto Ierusalimschy 6e1aec7a67 Larger C-stack limits for new threads
New threads were being created with very small C-stack limits.
This is not a problem for coroutines, because 'lua_resume' sets
a new limit, but not all threads are coroutines.
2019-10-17 13:09:17 -03:00
Roberto Ierusalimschy 6055a039b5 Easy redefinition of valid flags for 'string.format' 2019-10-17 13:02:07 -03:00
Roberto Ierusalimschy 6c0e44464b Improvements in the manual around metamethods 2019-10-08 10:34:43 -03:00
Roberto Ierusalimschy 6a84c32900 No coercion string->number in arithmetic with LUA_NOCVTS2N 2019-10-08 10:29:38 -03:00
Roberto Ierusalimschy 6a10f03ff8 Makefile compiles the Lua compiler with '-Os'
The performance of the Lua compiler is not critical for Lua
performance, but it is a big component in the source. So, it makes
sense to trade speed for size in this component.
2019-10-08 10:26:02 -03:00
Roberto Ierusalimschy 7bd1e53753 Fixed a warning and other minor issues
Fixed some minor issues from the feedback for 5.4-beta rc1.
2019-10-04 16:17:04 -03:00
Roberto Ierusalimschy b98d41db99 Script 'packtests' gets Lua version as a parameter 2019-10-02 17:04:06 -03:00
Roberto Ierusalimschy b2a580bdb1 Janitorial work
- Several details in 'lcode.c'
- A few more tests for code generation
- Bug in assert in 'lcode.c' ("=" x "==")
- Comments in 'lopcodes.h' and 'ltable.c'
2019-10-01 17:24:37 -03:00
Roberto Ierusalimschy 89f6a85f03 Details in the makefile (warning options) 2019-09-24 14:43:32 -03:00
Roberto Ierusalimschy 6ef366644f Subtraction of small constant integers optimized with OP_ADDI 2019-09-24 14:34:52 -03:00
Roberto Ierusalimschy 03cde80b58 'setCstacklimit' renamed to 'setcstacklimit'
Function names in the API use only lowercase letters.
2019-09-24 14:31:06 -03:00
Roberto Ierusalimschy 6b2e202df5 Janitorial work in 'lcode.c' 2019-09-19 14:29:21 -03:00
Roberto Ierusalimschy 40d8832ee0 Simplification in the call to 'constfolding' 2019-09-11 10:20:10 -03:00
Roberto Ierusalimschy 91dad09f65 Removed arithmetic opcodes with immediate operand
The difference in performance between immediate operands and K operands
does not seem to justify all those extra opcodes. We only keep OP_ADDI,
due to its ubiquity and because the difference is a little more relevant.
(Later, OP_SUBI will be implemented by OP_ADDI, negating the constant.)
2019-09-10 13:20:03 -03:00
Roberto Ierusalimschy 4518e5df24 Added macro 'testMMMode'
Macro 'testMMMode' checks whether opcode is an MM opcode.
2019-09-06 14:14:11 -03:00
Roberto Ierusalimschy 72a094bda7 Undo change in the handling of 'L->top' (commit b80077b8f3)
With MMBIN instructions, there are fewer opcodes that need to update
'L->top', so that change does not seem to pay for the increased
complexity.
2019-08-29 12:52:37 -03:00
Roberto Ierusalimschy 46b84580d6 Use of 'MMBIN' opcodes extended to shift operators
Plus, this commit removes useless 'tm' parameters in 'op_*' macros.
2019-08-28 09:58:03 -03:00
Roberto Ierusalimschy df13f25948 First version of OP_MMBIN opcodes
In arithmetic/bitwise operators, the call to metamethods is made
in a separate opcode following the main one. (The main
opcode skips this next one when the operation succeeds.) This
change reduces slightly the size of the binary and the complexity
of the arithmetic/bitwise opcodes. It also simplfies the treatment
of errors and yeld/resume in these operations, as there are much
fewer cases to consider. (Only OP_MMBIN/OP_MMBINI/OP_MMBINK,
instead of all variants of all arithmetic/bitwise operators.)
2019-08-27 13:59:39 -03:00
Roberto Ierusalimschy 643188d6e5 Fixed missing case in 'luaV_finishOp'
A metamethod call like '1 << a' was not being properly resumed
if it got yielded.
2019-08-27 10:28:09 -03:00
Roberto Ierusalimschy 3df5624ff4 Fixed bug when yiedling inside OP_ADDK opcode
The family of opcodes OP_ADDK (arithmetic operators with K constant)
were not being handled in 'luaV_finishOp', which completes their
task after an yield.
2019-08-21 12:19:47 -03:00
Roberto Ierusalimschy be78aeae4c Default for warnings changed to "off"
Warnings are mostly a tool to help developers (e.g., by showing hidden
error messages); regular users usually don't need to see them.
2019-08-20 13:42:26 -03:00
Roberto Ierusalimschy 5bc47fe830 Detail (extra test for warnings when closing state) 2019-08-19 14:41:48 -03:00
Roberto Ierusalimschy 9405472565 Improvement in warn-mode '@store' (for testing)
When using warn-mode '@store', from the test library, the tests ensure
not only that the expected warnings were issued, but also that there was
no extra warnings.
2019-08-18 17:29:46 -03:00
Roberto Ierusalimschy 45948e7e55 Manual corrected with the new syntax for attributes
Commit 0d52913804, with the change in the syntax of attributes,
did not update the manual accordingly.
2019-08-16 16:11:21 -03:00
Roberto Ierusalimschy b96b0b5abb Added macro 'luaL_pushfail'
The macro 'luaL_pushfail' documents all places in the standard libraries
that return nil to signal some kind of failure. It is defined as
'lua_pushnil'. The manual also got a notation (@fail) to document those
returns. The tests were changed to be agnostic regarding whether 'fail'
is 'nil' or 'false'.
2019-08-16 14:58:02 -03:00
Roberto Ierusalimschy ca13be9af7 Supressed errors in '__close' generate warnings 2019-08-16 09:51:54 -03:00
Roberto Ierusalimschy a1d8eb2743 Added control messages to warnings
Added the concept of control messages to the warning system, plus the
implementation of the controls "@on"/"@off" to turn warnings on/off.
Moreover, the warning system in the test library adds some other
controls to ease the test of warnings.
2019-08-15 13:44:36 -03:00
Roberto Ierusalimschy f64a1b175a Small optimization in 'convergeephemerons'
When converging marks on ephemeron tables, change the direction the
tables are traversed at each iteration, to try to avoid bad-case
scenarios with linked lists of entries in a table.
2019-08-12 15:32:44 -03:00
Roberto Ierusalimschy 09b4e527a0 Detail in the manual (method 'file:setvbuf')
ANSI C is vague about 'setvbuf'; most details are implementation
defined. So, the manual cannot give any guaranties, either.
2019-08-12 11:26:08 -03:00
Roberto Ierusalimschy 35a28a58b3 Details
- removed rule about RCS from makefile
- comments and nitpicking in 'llex.c'
2019-08-01 14:11:33 -03:00
Roberto Ierusalimschy 223bb04090 Correction in the documentation of 'io.lines'
The loop does not end on end of file, but when the iterator function
fails to read a value. (In particular, the format "a" never fails,
so a loop with 'io.lines(fname, "a")' never ends.)
2019-07-31 11:41:59 -03:00
Roberto Ierusalimschy fe040633a1 Tracebacks recognize metamethods '__close' 2019-07-31 11:22:39 -03:00
Roberto Ierusalimschy f645d31573 To-be-closed variables must be closed on initialization
When initializing a to-be-closed variable, check whether it has a
'__close' metamethod (or is a false value) and raise an error if
if it hasn't. This produces more accurate error messages. (The
check before closing still need to be done: in the C API, the value
is not constant; and the object may lose its '__close' metamethod
during the block.)
2019-07-31 10:43:51 -03:00
Roberto Ierusalimschy 35b4efc270 Fixed test in 'main.lua'
The test "to-be-closed variables in main chunk" was broken,
as it used the removed feature of functions as to-be-closed values.
The error was not detected because its expected result had no lines
to be checked (due to missing new lines).
2019-07-30 13:48:40 -03:00
Roberto Ierusalimschy 0d52913804 Change in the syntax of attributes
Attributes changed to posfixed ('x <const>', instead of '<const> x'),
and "toclose" renamed to "close". Posfixed attributes seem to make it
clearer that it applies to only one variable when there are multiple
variables.
2019-07-30 12:18:19 -03:00
Roberto Ierusalimschy b80077b8f3 Change in the handling of 'L->top' when calling metamethods
Instead of updating 'L->top' in every place that may call a
metamethod, the metamethod functions themselves (luaT_trybinTM and
luaT_callorderTM) correct the top. (When calling metamethods from
the C API, however, the callers must preserve 'L->top'.)
2019-07-26 14:59:39 -03:00
Roberto Ierusalimschy e70f275f32 Bug: 'Vardesc' array can be reallocated in 'localstat'
A reference to a 'Vardesc*' (as done by 'localstat') can be
invalidated by the creation of any new variable.
2019-07-26 13:27:43 -03:00
Roberto Ierusalimschy 9a37dc0ce6 Small corrections when setting 'L->top'
- OP_NEWTABLE can use 'ra + 1' to set top (instead of ci->top);
- OP_CLOSE doesn't need to set top ('Protect' already does that);
- OP_TFORCALL must use 'ProtectNT', to preserve the top already set.
  (That was a small bug, because iterators could be called with
   extra parameters besides the state and the control variable.)
- Comments and an extra test for the bug in previous item.
2019-07-25 13:55:29 -03:00
Roberto Ierusalimschy 0eb6aa4013 Some improvements in date/time functions
- Range in date table extended to full 32 bits.
- Easier support for times represented as floats.
- Added more tests.
2019-07-24 15:01:59 -03:00
Roberto Ierusalimschy 7f5c31cdca Fixed bug in 'string.format' with option '%f'
As an example, 'print(string.format("%.99f", 1e70))' may have a
lot of garbage after the number.

The old test to ensure that 'string.format("%.99f", n)' was not too
large, 'fabs(n) < 1e100', assumes that the number will fit in the 99
bytes; but the 99 is not the space for the number, it is the added
extra zeros.  The option worked for smaller numbers because of the
extra space added to MAX_ITEM.
2019-07-23 12:46:33 -03:00
Roberto Ierusalimschy 9e6807c3c9 Do not collect open upvalues
Open upvalues are kept alive together with their corresponding
stack. This change makes a simpler and safer fix to the issue in
commit 440a5ee78c, about upvalues in the list of open upvalues
being collected while others are being created. (That previous fix
may not be correct.)
2019-07-22 09:41:10 -03:00
Roberto Ierusalimschy 2f22c6bb79 'math.randomseed' always returns the two seed components 2019-07-19 13:31:53 -03:00
Roberto Ierusalimschy 3c0d3c6fbe Avoid using addresses of static variables as unique keys
The addresses of static variables may be different for different
instances of Lua, making these instances incompatible if they use
these addresses as unique keys in the registry (or other tables).
2019-07-19 13:14:06 -03:00
Roberto Ierusalimschy 440a5ee78c Fixed bug for emergency collection in upvalue creation
When creating an upvalue, an emergency collection can collect the
previous upvalue where the new one would be linked. The following
code can trigger the bug, using valgrind on Lua compiled with the
-DHARDMEMTESTS option:

  local x; local y
  (function () return y end)();
  (function () return x end)()
2019-07-19 12:13:00 -03:00
Roberto Ierusalimschy dc07719b0d Tag LUA_TUPVALTBC replaced by a flag
It is simpler to signal a to-be-closed upvalue with a boolean flag,
instead of using a different tag.
2019-07-19 11:12:31 -03:00
Roberto Ierusalimschy 9cdf6b7082 Some details in 'lmem.c' and 'lgc.c'
- Several new comments in 'lmem.c'.
- Both 'luaM_growaux_' and 'luaM_shrinkvector_' use 'luaM_saferealloc_'
  to check for errors. Moreover, the use of 'luaM_saferealloc_' makes
  'luaM_shrinkvector_' try again if shrink fails (which can happen now).
- In 'checkSizes', save old debt only when needed.
2019-07-19 09:43:35 -03:00
Roberto Ierusalimschy 3c1d415bd3 Details
- Macro 'checkliveness' (for debug) always uses 'L', to avoid warnings.
- Some old 'while' changed to 'for' in 'testes/gc.lua'.
- In 'testes/libs/makefile', do not make files depend on 'ltests.h',
which may not even exist.
2019-07-18 15:31:22 -03:00
Roberto Ierusalimschy d36a31e673 Reviving HARDMEMTESTS
This commit brings a new implementation for HARDMEMTESTS, which forces
an emergency GC whenever possible. It also fixes some issues detected
with this option:
  - A small bug in lvm.c: a closure could be collected by an emergency
  GC while being initialized.
  - Some tests: a memory address can be immediatly reused after a GC;
  for instance, two consecutive '{}' expressions can return exactly the
  same address, if the first one is not anchored.
2019-07-18 14:58:15 -03:00
Roberto Ierusalimschy 024a6071ca Small bug with stack reallocation
OP_RETURN must update trap before updating stack. (Bug detected with
-DHARDSTACKTESTS). Also, in 'luaF_close', do not create a variable
with 'uplevel(uv)', as the stack may change and invalidate this
value. (This is not a bug, but could become one if 'upl' was used
again.)
2019-07-18 11:26:03 -03:00
Roberto Ierusalimschy 4eefef07ab 'math.randomseed()' returns the seeds it used
A call to 'math.randomseed()' returns the two components of the seed
it set, so that they can be used to set that same seed again.
2019-07-17 16:00:24 -03:00
Roberto Ierusalimschy 9c28ed05c9 Calls 'luaF_close' in 'lua_settop' only when needed
In 'lua_settop', avoid calling 'luaF_close' when increasing the stack
or when the function has no to-be-closed variables.
2019-07-17 15:22:11 -03:00
Roberto Ierusalimschy 8082906c05 Fixed small issue with constant propagation
Constants directly assigned to other constants were not propagating:
For instance, in
  local <const> k1 = 10
  local <const> k2 = k1
'k2' were not treated as a compile-time constant.
2019-07-17 14:50:42 -03:00
Roberto Ierusalimschy d6af81084d New kind of expression VKSTR
String literal expressions have their own kind VKSTR, instead of the
generic VK. This allows strings to "cross" functions without entering
their constant tables (e.g., if they are used only by some nested
function).
2019-07-17 14:26:56 -03:00
Roberto Ierusalimschy 4846f7e3bb Micro optimization in OP_RETURN and OP_TAILCALL
Many functions are vararg but create no upvalues, so it is better
to separate the tests for these two kinds of "extra work".
2019-07-16 15:44:37 -03:00
Roberto Ierusalimschy c220b0a5d0 '__close' method may be called again in case of error
An error in a closing method may be caused by a lack of resources,
such as memory or stack space, and the error may free enough resources
(by unwinding the stack) to allow the method to work if called again.

If the closing method is already running after some error (including
its own), it is not called again.
2019-07-16 15:17:47 -03:00
Roberto Ierusalimschy 298f383ffc Avoid setting the stack top below upvalues to be closed
When leaving a scope, the new stack top should be set only after
closing any upvalue, to avoid manipulating values in an "invalid"
part of the stack.
2019-07-16 14:13:22 -03:00
Roberto Ierusalimschy 758c1ef445 Unification of size representation in OP_NEWTABLE and OP_SETLIST
Opcodes OP_NEWTABLE and OP_SETLIST use the same representation to
store the size of the array part of a table. This new representation
can go up to 2^33 (8 + 25 bits).
2019-07-15 14:59:35 -03:00
Roberto Ierusalimschy dd6d8db49a Reordering of instructions in the main loop
The instructions in the main interpreter loop were reordered to
the same order of their enumeration in 'lopcodes.h'.
2019-07-12 16:47:02 -03:00
Roberto Ierusalimschy 1fb4d53925 OP_NEWTABLE keeps exact size of arrays
OP_NEWTABLE is followed by an OP_EXTRAARG, so that it can keep
the exact size of the array part of the table to be created.
(Functions 'luaO_int2fb'/'luaO_fb2int' were removed.)
2019-07-12 16:13:50 -03:00
Roberto Ierusalimschy f6aab3ec1f First implementation of constant propagation
Local constant variables initialized with compile-time constants
are optimized away from the code.
2019-07-12 11:38:42 -03:00
Roberto Ierusalimschy be8445d7e4 Details
In the generic for loop, it is simpler for OP_TFORLOOP to use the
same 'ra' as OP_TFORCALL. Moreover, the internal names of the loop
temporaries "(for ...)" don't need to leak internal details (even
because the numerical for loop doesn't have a fixed role for each of
its temporaries).
2019-07-10 14:58:31 -03:00
Roberto Ierusalimschy 3d296304ef Towards constant propagation
This commit detaches the number of active variables from the
number of variables in the stack, during compilation. Soon,
compile-time constants will be propagated and therefore will
not exist during run time (in the stack).
2019-07-10 14:00:22 -03:00
Roberto Ierusalimschy 54f7b46c1e New implementation for constants
VLOCAL expressions keep a reference to their corresponding 'Vardesc',
and 'Upvaldesc' (for upvalues) has a field 'ro' (read-only). So, it is
easier to check whether a variable is read-only. The decoupling in
VLOCAL between 'vidx' ('Vardesc' index) and 'sidx' (stack index)
should also help the forthcoming implementation of compile-time
constant propagation.
2019-07-09 10:43:17 -03:00
Roberto Ierusalimschy e888976bc6 Details (typos in comments) 2019-07-05 15:03:15 -03:00
Roberto Ierusalimschy 4d46289331 Local attributes can be used in list of local variables
The syntax for local attributes ('const'/'toclose') was unified with
the regular syntax for local variables, so that we can have variables
with attributes in local definitions with multiple names; for instance:

  local <toclose> f, <const> err = io.open(fname)

This new syntax does not implement constant propagation, yet.

This commit also has some small improvements to the manual.
2019-07-03 14:18:07 -03:00
Roberto Ierusalimschy 8eca21c2e8 First take on constant propagation 2019-07-01 12:42:31 -03:00
Roberto Ierusalimschy 924bed7297 Methods separated from metamethods in 'io'
In the 'io' library, changed the use of the metatable also as its
own "method table", so that metamethods cannot be accessed as if they
were methods. (For instance, 'io.stdin.__gc' does not result in
the finalizer metamethod anymore.)
2019-07-01 12:25:00 -03:00
Roberto Ierusalimschy 8b7cfee26b Small changes around C-stack limit
- Better documentation in 'testes/cstack.lua' about using
'debug.setCstacklimit' to find a good limit.

- Constant LUAI_MAXCSTACK gets added CSTACKERR (extra stack for
error handling), so that it is compatible with the argument to
'debug.setCstacklimit'.
2019-06-26 13:26:36 -03:00
Roberto Ierusalimschy c1a63c45f8 '__call' metamethod can be any callable object
Removed the restriction that a '__call' metamethod must be an actual
function.
2019-06-25 17:45:50 -03:00
Roberto Ierusalimschy 4487c28ced A few more tests for table access in the API
Added tests where the table being accessed is also the index or
value in the operation.
2019-06-25 17:38:58 -03:00
Roberto Ierusalimschy 05ba288049 Added script 'packtests' to the project
The script 'packtests' creates the 'tar.gz' to deploy the test suite
for Lua.
2019-06-21 10:46:41 -03:00
Roberto Ierusalimschy 6b9490bd72 Details in tests
- Added a test for calling 'debug.traceback' after yields inside
hooks. (Lua 5.3 seems to have a bug there.)

- Removed test "repeat test with '__open' metamethod instead of a
function", as the previous test already uses the '__open' metamethod.
(It changed when functions were removed as possible to-be-closed
variables).
2019-06-21 10:21:07 -03:00
Roberto Ierusalimschy e4b02ca8e4 Structure 'Vardesc' does not need a 'name' field
Removed the field 'name' from the structure 'Vardesc', as the name
of the local variable is already available in the prototype of the
function, through the index 'idx'.
2019-06-21 10:16:57 -03:00
Roberto Ierusalimschy 20a9853e02 Cleaning macros in 'luaV_execute'
Ensure that operation macros, such as 'luai_numdiv' and 'luai_numidiv',
operate only on variables, or at most at 's2v(ra)'. ('s2v' is a nop, a
cast from pointer to pointer.)
2019-06-21 10:00:50 -03:00
Roberto Ierusalimschy 1d70708a78 Fixed bug [5.4 alpha] for errors in finalizers
Fixes the bug related in [1] (Lua can crash after raising an error
in a finalizer), following the lead in [2].

[1] http://lua-users.org/lists/lua-l/2019-06/msg00448.html
[2] http://lua-users.org/lists/lua-l/2019-06/msg00450.html
2019-06-21 09:34:49 -03:00
Roberto Ierusalimschy be73f72fcc New function 'setCstacklimit'
Added new functions to dynamically set the C-stack limit
('lua_setCstacklimit' in the C-API, 'debug.setCstacklimit' in Lua).
2019-06-18 16:52:22 -03:00
Roberto Ierusalimschy 3cd9b56ae6 Revamp around 'L->nCcalls' count
The field 'L->nCcalls' now counts downwards, so that the C-stack
limits do not depend on the stack size.
2019-06-12 10:31:38 -03:00
Roberto Ierusalimschy d2a9b4ffb8 Detail in the manual
More precision describing the variables that won't be closed if a
coroutine yields forever.
2019-06-10 13:59:19 -03:00
Roberto Ierusalimschy f39e8c06d6 Updated the documentation for the API function 'lua_gc' 2019-06-06 12:51:41 -03:00
Roberto Ierusalimschy 6aeaeb5656 Detail in makefile 2019-06-05 13:21:16 -03:00
Roberto Ierusalimschy b4d5dff8ec Multiple errors in '__toclose' report the first one
When there are multiple errors when closing objects, the error
reported by the protected call is the first one, for two reasons:
First, other errors may be caused by this one;
second, the first error is handled in the original execution context,
and therefore has the full traceback.
2019-06-05 13:16:25 -03:00
Roberto Ierusalimschy 14edd364c3 Function 'warn' is vararg
Instead of a 'tocont' flag, the function 'warn' in Lua now receives all
message pieces as multiple arguments in a single call. Besides being
simpler to use, this implementation ensures that Lua code cannot create
unfinished warnings.
2019-06-04 11:22:21 -03:00
Roberto Ierusalimschy 514d942748 'coroutine.kill' renamed 'coroutine.close' 2019-06-03 13:11:20 -03:00
Roberto Ierusalimschy 4a3fd8488d bug in 5.4 alpha rc1: to-be-closed x vararg functions
Closing methods must be run before correcting 'ci->func' when exiting
a vararg function, to get correct debug information (e.g., in case of
errors).
2019-06-03 12:13:13 -03:00
Roberto Ierusalimschy 2c68e66570 Details
Several small changes from feedback on 5.4 alhpa rc1 (warnings,
typos in the manual, and the like)
2019-06-03 11:36:42 -03:00
Roberto Ierusalimschy 7d0f41df41 Improvements in 'testes/cstack.lua'
- tests show progress in real time, so that we can see maximum
stack levels even if test crashes.
- new test for recursion continuing into message handler.
2019-06-03 11:34:32 -03:00
Roberto Ierusalimschy 2b8b53864c Improvements in 'luaL_traceback'
'luaL_traceback' changed to use an aux buffer instead of concats.
This should reduce the quantity of garbage it generates (in the
form of intermediate strings) while producing a trackback.
It also added information about the number of levels skipped when
skipping levels in a trace.
2019-05-28 15:50:40 -03:00
Roberto Ierusalimschy b293ae0577 Details
- new error message for "attempt to assign to const variable"
- note in the manual about compatibility options
- comments
- small changes in 'read_line' and 'pushstr'
2019-05-28 15:46:49 -03:00
Roberto Ierusalimschy d9f40e3f6f First implementation for 'const' variables
A variable can be declared const, which means it cannot be assigned to,
with the syntax 'local <const> name = exp'.
2019-05-17 11:11:44 -03:00
Roberto Ierusalimschy 347d6961ac Define LUA_MAXUNSIGNED as a preprocessor constant
The previous definition of LUA_MAXUNSIGNED used a typecast,
making it unsuitable for constant expressions in the preprocessor.
2019-05-14 11:10:24 -03:00
Roberto Ierusalimschy 0b63d79b36 Details
- 'luaL_setfuncs' avoids creating closures for placeholders.
- Fixed some warnings about unused values in comma expressions.
- Comments.
2019-05-13 16:20:40 -03:00
Roberto Ierusalimschy 279c3a6961 A few changes in tests about number of bits in integers
- The preprocessor must work with at least 'long', and therefore must
do shifts of up to 31 bits correctly.
- Whenever possible, use unsigned types in shifts.
2019-05-13 16:17:21 -03:00
Roberto Ierusalimschy 49c42f3615 Some improvements in 'luaconf.h'
Added '#if !defined' in some definitions to allow external definitions;
more comments; other small changes.
2019-05-13 14:24:10 -03:00
Roberto Ierusalimschy d881325c2f Flag for to-be-closed variables changed to '<toclose>'
The flag for to-be-closed variables was changed from '*toclose'
to '<toclose>'. Several people found confusing the old syntax and
the new one has a clear terminator, making it more flexible for
future changes.
2019-05-09 12:10:31 -03:00
Roberto Ierusalimschy 3f253f116e Test for dead coroutine moved to 'lua_resume'
The test for dead coroutines done in the 'coro' library was moved
to 'lua_resume', in the kernel, which already does other similar
tests.
2019-05-09 11:32:20 -03:00
Roberto Ierusalimschy 389116d8ab Coroutines do not unwind the stack in case of errors
Back to how it was, a coroutine does not unwind its stack in case of
errors (and therefore do not close its to-be-closed variables). This
allows the stack to be examined after the error. The program can
use 'coroutine.kill' to close the variables.

The function created by 'coroutine.wrap', however, closes the
coroutine's variables in case of errors, as it is impossible to examine
the stack any way.
2019-05-09 11:13:45 -03:00
Roberto Ierusalimschy 01bded3d8c File 'lib2-v2.so' generated from its own source
Instead of being a copy of 'lib2.so', 'lib2-v2.so' has its own source
file ('lib22.c'), so that the test can distinguish both libraries.
2019-05-03 10:36:19 -03:00
Roberto Ierusalimschy 7c5786479c A few more improvements in 'luaO_pushvfstring'
- 'L' added to the 'BuffFS' structure
- '%c' does not handle control characters (it is not its business.
This now is done by the lexer, who is the one in charge of that
kind of errors.)
- avoid the direct use of 'l_sprintf' in the Lua kernel
2019-05-03 10:18:44 -03:00
Roberto Ierusalimschy b14609032c Avoid the creation of too many strings in 'package'
Both when setting a path and searching for a file ('searchpath'),
this commit reduces the number of intermediate strings created
in Lua.
(For setting a path the change is not relevant, because this is
done only twice when loading the module. Anyway, it is a nice example
of how to use auxlib buffers to manipulate strings in the C API.)
2019-05-03 10:14:25 -03:00
Roberto Ierusalimschy b36e26f51b Some more small improvements to 'luaO_pushvfstring'
Details:
- counter 'pushed' moved to the struct 'BuffFS'
- new auxiliar function 'getbuff' to build strings directly on
the buffer.
2019-04-26 11:24:39 -03:00
Roberto Ierusalimschy 969b8c1f14 Fixed bug with to-be-closed variables in base C level
To-be-closed variables in C use 'ci.nresults' to code that there is
a variable to be closed in that function. The intialization of the
base C level (the one "running" when calling API functions outside
any Lua call) did not initialize 'ci.nresults', creating (correct)
warnings in valgrind.
2019-04-26 11:13:01 -03:00
Roberto Ierusalimschy c65605151c New function 'luaL_addgsub'
Added a new function 'luaL_addgsub', similar to 'luaL_gsub' but that
adds its result directly to a preexisting buffer, avoiding the creation
of one extra intermediate string. Also added two simple macros,
'luaL_bufflen' and 'luaL_buffaddr', to query the current length
and the contents address of a buffer.
2019-04-24 14:41:41 -03:00
Roberto Ierusalimschy 3da34a5fa7 Revamp of 'lua_pushfstring' / 'luaO_pushvfstring'
The function 'luaO_pushvfstring' now uses an internal buffer to
concatenate small strings, instead of pushing all pieces on the
stack. This avoids the creation of several small Lua strings for each
piece of the result. (For instance, a format like "n: '%d'" used to
create three intermediate strings: "n: '", the numeral, and "'".
Now it creates none.)
2019-04-24 14:01:20 -03:00
Roberto Ierusalimschy 20b161e285 Small correction in test about 'isdst'
The field 'isdst' can be false, so we cannot test its absence with
'if not D.isdst'; we must compare with nil for a correct test.
2019-04-22 12:31:29 -03:00
Roberto Ierusalimschy ed2872cd3b 'require' returns where module was found
The function 'require' returns the *loader data* as a second result.
For file searchers, this data is the path where they found the module.
2019-04-17 14:57:29 -03:00
Roberto Ierusalimschy 2d3f095448 Avoid using large buffers in 'string.format'
The result of "string.format("%.99f", -1e308) is 410 characters long,
but all other formats have much smaller limits (at most 99 plus a fex
extras). This commit avoids 'string.format' asking for a buffer
~400 chars large when ~100 will do.
2019-04-12 11:48:24 -03:00
Roberto Ierusalimschy b0810c51c3 Small optimizations in 'string.gsub'
Avoid creating extra strings when possible:

- avoid creating new resulting string when subject was not modified
(instead, return the subject itself);

- avoid creating strings representing the captured substrings when
handling replacements like '%1' (instead, add the substring directly
to the buffer).
2019-04-11 11:29:16 -03:00
Roberto Ierusalimschy a93e014447 Added an optional parameter to 'coroutine.isyieldable' 2019-04-10 13:23:14 -03:00
Roberto Ierusalimschy 8ba4523ccc 'print' does not call 'tostring' to format its arguments 2019-04-10 12:58:14 -03:00
Roberto Ierusalimschy 979ad95eb1 Thorough revision of the reference manual 2019-04-10 12:41:56 -03:00
Roberto Ierusalimschy 0f028b9008 Corrected tests around non-portable 'isdst' in dates
The field 'isdst' in date tables may not be present; portable tests
should not assume it is.
2019-04-09 18:44:13 -03:00
Roberto Ierusalimschy 65d1aa7a77 Syntax should not allow numbers touching identifiers
Code like 'a = 1print()' should not be accepted.
2019-04-09 18:40:39 -03:00
Roberto Ierusalimschy 8004798b03 Fixed wrong error message in 'return math.seed(0)'
Bug introduced in commit 28d829c8: OP_TAILCALL might raise an
error without saving 'pc'. (This commit also fixes a detail in
'testes/uf8.lua'.)
2019-04-04 16:31:24 -03:00
Roberto Ierusalimschy 5ca1075b71 Added field 'srclen' to structure 'lua_Debug'
This new field gets the length of 'source' in the same structure.
Unlike the other strings in that structure, 'source' can be
relatively large, and Lua already has its length readily available.
2019-04-04 11:45:26 -03:00
Roberto Ierusalimschy 38425e0692 Avoid moving the collector while in 'GCSenteratomic' state
The 'GCSenteratomic' is just an auxiliary state for transitioning
to 'GCSatomic'. All GC traversals should be done either on the
'GCSpropagate' state or the 'GCSatomic' state.
2019-04-01 14:22:07 -03:00
Roberto Ierusalimschy d12262068d Small optimizations in range checks
Checks of the form '1 <= x && x <= M' were rewritten in the form
'(unsigned)x - 1 < (unsigned)M', which is usually more efficient.
(Other similar checks have similar translations.) Although
some compilers do these optimizations, that does not happen
for all compilers or all cases.
2019-03-27 14:56:10 -03:00
Roberto Ierusalimschy 0443ad9e28 LUAI_MAXCCALLS renamed LUAI_MAXCSTACK
The limit LUAI_MAXCCALLS was renamed LUAI_MAXCSTACK, which better
represents its meaning. Moreover, its definition was moved to
'luaconf.h', given its importance now that Lua does not use
a "stackless" implementation.
2019-03-25 14:12:06 -03:00
Roberto Ierusalimschy f9b0cf0e2e Year in copyright notice updated to 2019 2019-03-25 14:00:09 -03:00
Roberto Ierusalimschy 7ceb2154ed Fixed small bugs/issues
- In 'readutf8esc' (llex.c), the overflow check must be done before
shifting the accumulator. It was working because tests were using
64-bit longs. Failed with 32-bit longs.

- In OP_FORPREP (lvm.c), avoid negating an unsigned value. Visual
Studio gives a warning for that operation, despite being well
defined in ISO C.

- In 'luaV_execute' (lvm.c), 'cond' can be defined only when needed,
like all other variables.
2019-03-25 10:38:56 -03:00
Roberto Ierusalimschy 23e6bac8a0 Keep correct type for immediate operands in comparisons
When calling metamethods for things like 'a < 3.0', which generates
the opcode OP_LTI, the C register tells that the operand was
converted to an integer, so that it can be corrected to float when
calling a metamethod.

This commit also includes some other stuff:
- file 'onelua.c' added to the project
- opcode OP_PREPVARARG renamed to OP_VARARGPREP
- comparison opcodes rewritten through macros
2019-03-22 13:37:17 -03:00
Roberto Ierusalimschy 682054920d Details in the implementation of the integer 'for' loop
Changed some implementation details; in particular, it is back using
an internal variable to keep the index, with the control variable
being only a copy of that internal variable. (The direct use of
the control variable demands a check of its type for each access,
which offsets the gains from the use of a single variable.)
2019-03-21 16:01:55 -03:00
Roberto Ierusalimschy f53eabeed8 Small changes in the header of binary files
- LUAC_VERSION is equal to LUA_VERSION_NUM, and it is stored
as an int.

- 'sizeof(int)' and 'sizeof(size_t)' removed from the header, as
the binary format does not depend on these sizes. (It uses its
own serialization for unsigned integer values.)
2019-03-19 15:31:08 -03:00
Roberto Ierusalimschy 39bb3cf242 Name 'nonstrict' in the UTF-8 library changed to 'lax'
It is not a good idea to use negative words to describe boolean
values. (When we negate that boolean we create a double negative...)
2019-03-19 11:15:49 -03:00
Roberto Ierusalimschy 9b37a4695e New semantics for the integer 'for' loop
The numerical 'for' loop over integers now uses a precomputed counter
to control its number of iteractions. This change eliminates several
weird cases caused by overflows (wrap-around) in the control variable.
(It also ensures that every integer loop halts.)

Also, the special opcodes for the usual case of step==1 were removed.
(The new code is already somewhat complex for the usual case,
but efficient.)
2019-03-19 10:53:18 -03:00
Roberto Ierusalimschy 1e0c73d5b6 Changes in the validation of UTF-8
All UTF-8 encoding functionality (including the escape
sequence '\u') accepts all values from the original UTF-8
specification (with sequences of up to six bytes).

By default, the decoding functions in the UTF-8 library do not
accept invalid Unicode code points, such as surrogates. A new
parameter 'nonstrict' makes them accept all code points up to
(2^31)-1, as in the original UTF-8 specification.
2019-03-15 13:14:17 -03:00
Roberto Ierusalimschy 8fa4f1380b Finalizers must be callable
Non-function __gc metamethods are not ignored; if present, the
metamethod will be called even if it is not a function.
2019-03-14 15:53:42 -03:00
Roberto Ierusalimschy b56d4e570a Changes in the warning system
- The warning functions get an extra parameter that tells whether
message is to be continued (instead of using end-of-lines as a signal).

- The user data for the warning function is a regular value, instead
of a writable slot inside the Lua state.
2019-03-14 15:30:54 -03:00
Roberto Ierusalimschy 9eca305e75 'math.randomseed()' sets a somewhat random seed
When called with no arguments, 'math.randomseed' uses time and ASLR
to generate a somewhat random seed. the initial seed when Lua starts
is generated this way.
2019-03-13 14:47:48 -03:00
Roberto Ierusalimschy c5feac2b5e Strings inside Lua are not fully aligned
Removed code to ensure that strings inside Lua (as returned by
'lua_tolstring') always start in fully aligned addresses.
Since version 5.3 the documentation does not ensure that.
2019-03-13 14:14:40 -03:00
Roberto Ierusalimschy dfebe439db New conversion specifier '%p' for 'string.format'
The call 'string.format("%p", val)' gives a Lua equivalent to the
C API function 'lua_topointer'.
2019-03-13 14:04:01 -03:00
Roberto Ierusalimschy cf71a5ddc7 Details
Several small improvements (code style, warnings, comments, more tests),
in particular:

- 'lua_topointer' extended to handle strings
- raises an error in 'string.format("%10q")' ('%q' with modifiers)
- in the manual for 'string.format', the term "option" replaced by
  "conversion specifier" (the term used by the C standard)
2019-03-13 13:16:53 -03:00
Roberto Ierusalimschy 2c32bff609 After a "bad collections", avoid switching back back to generational
After a major bad collection (one that collects too few objects),
next collection will be major again. In that case, avoid switching
back to generational mode (as it will have to switch again to
incremental to do next major collection).
2019-01-30 11:44:42 -02:00
Roberto Ierusalimschy 264659bd53 Optional 'init' argument to 'string.gmatch'
The function 'string.gmatch' now has an optional 'init' argument,
similar to 'string.find' and 'string.match'. Moreover, there was
some reorganization in the manipulation of indices in the string
library.
This commit also includes small janitorial work in the manual
and in comments in the interpreter loop.
2019-01-08 14:22:32 -02:00
Roberto Ierusalimschy 4ace93ca65 No more to-be-closed functions
To-be-closed variables must contain objects with '__toclose'
metamethods (or nil). Functions were removed for several reasons:

* Functions interact badly with sandboxes. If a sandbox raises
an error to interrupt a script, a to-be-closed function still
can hijack control and continue running arbitrary sandboxed code.

* Functions interact badly with coroutines. If a coroutine yields
and is never resumed again, its to-be-closed functions will never
run. To-be-closed objects, on the other hand, will still be closed,
provided they have appropriate finalizers.

* If you really need a function, it is easy to create a dummy
object to run that function in its '__toclose' metamethod.

This comit also adds closing of variables in case of panic.
2019-01-04 13:09:47 -02:00
Roberto Ierusalimschy c6f7181e91 No more LUA_ERRGCMM errors
Errors in finalizers (__gc metamethods) are never propagated.
Instead, they generate a warning.
2019-01-01 12:14:56 -02:00
Roberto Ierusalimschy 437a5b07d4 Added a warning system to Lua
The warning system is just a way for Lua to emit warnings, messages
to the programmer that do not interfere with the running program.
2018-12-28 15:42:34 -02:00
Roberto Ierusalimschy ba7da13ec5 Changes in the control of C-stack overflow
* unification of the 'nny' and 'nCcalls' counters;
  * external C functions ('lua_CFunction') count more "slots" in
    the C stack (to allow for their possible use of buffers)
  * added a new test script specific for C-stack overflows. (Most
    of those tests were already present, but concentrating them
    in a single script easies the task of checking whether
    'LUAI_MAXCCALLS' is adequate in a system.)
2018-12-27 14:32:29 -02:00
Roberto Ierusalimschy da37ac9c78 Detail
Slightly better error message for invalid conversions in 'string.format'.
2018-12-27 14:19:53 -02:00
Roberto Ierusalimschy 662506476b 'all' script automatically 'make's everything
The script 'all', to run all tests, automatically ensures that the
Lua interpreter and the test C libraries (in 'testes/libs/') are
updated with any changes in 'luaconf.h'.
2018-12-19 13:15:14 -02:00
Roberto Ierusalimschy 5d7dec5520 Added directory 'testes/libs/P1' to the repository
This directory is used for some tests. As standard Lua has no command
to create directories, it must be present before running tests.
2018-12-17 15:19:56 -02:00
Roberto Ierusalimschy af6d9f3116 Details
A few details in the makefile and in the manual. (In particular,
it updates the dependency lists in the makefile.)
2018-12-17 13:56:22 -02:00
Roberto Ierusalimschy 2258f3133b Added file 'testes/heavy.lua'
This file is not part of the regular tests. It tests error conditions
that demand too much memory or too much time to create:

* string with too many characters
* control structure with body too large
* chunk with too many lines
* identifier with too many characters
* chunks with too many instructions
* function with too many constants
* too many strings internalized
* table with too many entries

In machines with limited memory (less than 150 GB), many tests run up
to a "not enough memory" error. We need some memory (~256 GB) to
run all tests up to their intrinsic limits.
2018-12-14 13:49:02 -02:00
Roberto Ierusalimschy 57f5b81da9 Bug: Long brackets with a huge number of '=' causes overflow
A long bracket with too many equal signs can overflow the 'int' used for
the counting and some arithmetic done on the value. Changing the counter
to 'size_t' avoids that. (Because what is counted goes to a buffer, an
overflow in the counter will first raise a buffer-overflow error.)
2018-12-14 13:12:01 -02:00
Roberto Ierusalimschy fdc25a1ebf New functions 'lua_resetthread' and 'coroutine.kill'
New functions to reset/kill a thread/coroutine, mainly (only?) to
close any pending to-be-closed variable. ('lua_resetthread' also
allows a thread to be reused...)
2018-12-13 13:07:53 -02:00
Roberto Ierusalimschy 3b06f983ae Details
- in 'luaB_tonumber', do not need to "checkany" when argument
is a number.

- in 'lua_resume', the call to 'luaD_rawrunprotected' cannot return
a status equal to -1.
2018-12-11 11:54:14 -02:00
Roberto Ierusalimschy 51316f9df7 'math.rand()' uses higher bits to produce float value
The call 'math.rand()' converts the higher bits of the internal unsigned
integer random to a float, instead of its lower bits. That ensures that
Lua compiled with different float precisions always generates equal (up
to the available precision) random numbers when given the same seed.
2018-12-11 11:34:47 -02:00
Roberto Ierusalimschy 46beca5bed Better error messages for some polymorphic functions
New auxiliary functions/macros 'luaL_argexpected'/'luaL_typeerror'
ease the creation of error messages such as

  bad argument #2 to 'setmetatable' (nil or table expected, got boolean)

(The novelty being the "got boolean" part...)
2018-12-10 13:46:03 -02:00
Roberto Ierusalimschy 28d829c867 Calls cannot be tail in the scope of a to-be-closed variable
A to-be-closed variable must be closed when a block ends, so even
a 'return foo()' cannot directly returns the results of 'foo'; the
function must close the scope before returning.
2018-12-04 15:01:42 -02:00
Roberto Ierusalimschy 6d04537ea6 A to-be-closed variable must have a closable value (or be nil)
It is an error for a to-be-closed variable to have a non-closable
non-nil value when it is being closed. This situation does not seem to
be useful and often hints to an error. (Particularly in the C API, it is
easy to change a to-be-closed index by mistake.)
2018-11-29 16:02:44 -02:00
Roberto Ierusalimschy 7696c6474f Auxiliary buffer cannot close box with 'lua_remove'
To remove a to-be-closed variable from the stack in the C API a
function must use 'lua_settop' or 'lua_pop'. Previous implementation of
'luaL_pushresult' was not closing the box. (This commit also added
tests to check that box is being closed "as soon as possible".)
2018-11-26 14:16:17 -02:00
Roberto Ierusalimschy 7e63d3da02 Some bugs with stack reallocation by 'luaF_close'
(Long time without testing with '-DHARDSTACKTESTS'...)
With the introduction of to-be-closed variables, calls to 'luaF_close'
can move the stack, but some call sites where keeping pointers to the
stack without correcting them.
2018-11-24 11:59:15 -02:00
Roberto Ierusalimschy 84e32ad2eb Added opcodes for arithmetic with K operands
Added opcodes for all seven arithmetic operators with K operands
(that is, operands that are numbers in the array of constants of
the function). They cover the cases of constant float operands
(e.g., 'x + .0.0', 'x^0.5') and large integer operands (e.g.,
'x % 10000').
2018-11-23 12:23:45 -02:00
Roberto Ierusalimschy 35296e1fde Details
comments and other janitorial work.
2018-11-22 13:56:04 -02:00
Roberto Ierusalimschy bb0185b196 Documentation for to-be-closed variables 2018-11-13 14:33:14 -02:00
Roberto Ierusalimschy d40cd315f5 Visibility of non-API functions changed to "internal"
The visibility for functions marked as LUAI_FUNC was changed from
"hidden" to "internal". These functions cannot be called from
outside the Lua kernel, and "internal" visibility offers more
chances for optimizations.
2018-11-13 13:58:46 -02:00
Roberto Ierusalimschy 8cb84210ab String buffer using to-be-closed variable
The string buffers in the C API now mark their boxes as to-be-closed
variables, to release their buffers in case of errors.
2018-11-13 13:50:33 -02:00
Roberto Ierusalimschy 5fda30b4f9 'lua_toclose' gets the index to be closed as an argument
Sometimes it is useful to mark to-be-closed an index that is not
at the top of the stack (e.g., if the value to be closed came from
a function call returning multiple values).
2018-11-12 14:15:50 -02:00
Roberto Ierusalimschy 9eafe9c053 New implementation for 'luaL_addvalue'
The function 'luaL_addvalue' (from the buffer system) was rewritten
so that it does not change the position of the box (if present)
in the stack.
2018-11-09 17:03:52 -02:00
Roberto Ierusalimschy 7f6f70853c To-be-closed variable in 'for' loop separated from the state
The variable to be closed in a generic 'for' loop now is the
4th value produced in the loop initialization, instead of being
the loop state (the 2nd value produced). That allows a loop to
use a state with a '__toclose' metamethod but do not close it.
(As an example, 'f:lines()' might use the file 'f' as a state
for the loop, but it should not close the file when the loop ends.)
2018-11-07 14:42:05 -02:00
Roberto Ierusalimschy b8fed93215 New syntax for to-be-closed variables
The new syntax is <local *toclose x = f()>. The mark '*' allows other
attributes to be added later without the need of new keywords; it
also allows better error messages.  The API function was also renamed
('lua_tobeclosed' -> 'lua_toclose').
2018-11-07 10:03:05 -02:00
Roberto Ierusalimschy 5e76a4fd31 New macros for arithmetic/bitwise operations in 'luaV_execute'
The repetitive code of the arithmetic and bitwise operators in
the main iterpreter loop was moved to appropriate macros.
(As a detail, the function 'luaV_div' was renamed 'luaV_idiv',
as it does an "integer division" (floor division).
2018-11-05 16:10:42 -02:00
Roberto Ierusalimschy e8c779736f Removed internal cache for closures
The mechanism of "caching the last closure created for a prototype to
try to reuse it the next time a closure for that prototype is created"
was removed. There are several reasons:

- It is hard to find a natural example where this cache has a measurable
impact on performance.

- Programmers already perceive closure creation as something slow,
so they tend to avoid it inside hot paths. (Any case where the cache
could reuse a closure can be rewritten predefining the closure in some
variable and using that variable.)

- The implementation was somewhat complex, due to a bad interaction
with the generational collector. (Typically, new closures are new,
while prototypes are old. So, the cache breaks the invariant that
old objects should not point to new ones.)
2018-11-01 13:21:00 -03:00
Roberto Ierusalimschy 2fc6b55dae Removed resource-related "emergency collections"
New to-be-closed variables is a better way to ensure the proper release
of resources.
2018-10-31 16:25:29 -03:00
Roberto Ierusalimschy 947a372f58 State in generic 'for' acts as a to-be-closed variable
The implicit variable 'state' in a generic 'for' is marked as a
to-be-closed variable, so that the state will be closed as soon
as the loop ends, no matter how.

Taking advantage of this new facility, the call 'io.lines(filename)'
now returns the open file as a second result. Therefore,
an iteraction like 'for l in io.lines(name)...' will close the
file even when the loop ends with a break or an error.
2018-10-31 14:54:45 -03:00
Roberto Ierusalimschy e073cbc2e5 Better error messages for invalid operands in numeric 'for'
"Better" and similar to error messages for invalid function arguments.
  *old message: 'for' limit must be a number
  *new message: bad 'for' limit (number expected, got table)
2018-10-30 15:46:56 -03:00
Roberto Ierusalimschy 2316ec4c24 Back with optimization for 'if cond then goto'
Statements like 'if cond then goto label' generate code so that the
jump in the 'if' goes directly to the given label. This optimization
cannot be done when the jump is backwards leaving the scope of some
variable, as it cannot add the needed 'close' instruction. (The jumps
were already generated by the 'if'.)

This commit also added 'likely'/'unlikely' for tests for errors in
the parser, and it changed the way breaks outside loops are detected.
(Now they are detected like other goto's with undefined labels.)
2018-10-30 15:04:19 -03:00
Roberto Ierusalimschy a006514ea1 Big revamp in the implmentation of labels/gotos
Added restriction that, when a label is created, there cannot be
another label with the same name visible. That allows backward goto's
to be resolved when they are read. Backward goto's get a close if
they jump out of the scope of some variable; labels get a close only
if previous goto to it jumps out of the scope of some upvalue.
2018-10-29 14:26:48 -03:00
Roberto Ierusalimschy 6e9b719694 More uniformity in code generation for 'for' loops
Added new instruction 'OP_TFORPREP' to prepare a generic for loop.
Currently it is equivalent to a jump (but with a format 'iABx',
similar to other for-loop preparing instructions), but soon it will
be the place to create upvalues for closing loop states.
2018-10-26 10:38:50 -03:00
Roberto Ierusalimschy 34840301b5 To-be-closed variables in the C API 2018-10-25 15:30:15 -03:00
Roberto Ierusalimschy 41c800b352 Closing methods should not interfere with returning values
A closing method cannot be called in its own stack slot, as there may
be returning values in the stack after that slot, and the call would
corrupt those values. Instead, the closing method must be copied to the
top of the stack to be called.

Moreover, even when a function returns no value, its return istruction
still has to have its position (which will set the stack top) after
the local variables, otherwise a closing method might corrupt another
not-yet-called closing method.
2018-10-25 12:50:20 -03:00
Roberto Ierusalimschy 0a9aca56ca Added a '__close' metamethod to file handles 2018-10-23 13:57:25 -03:00
Roberto Ierusalimschy ea1322ef54 Detail: bad assertion in 'luaM_free_' 2018-10-23 12:58:38 -03:00
Roberto Ierusalimschy 6a4b9bb2b4 Removed extra information from RCS keyword strings in tests
Version numbers and dates (mostly wrong) from RCS keyword strings
removed from all test files; only the file name are kept.
2018-10-22 15:20:07 -03:00
Roberto Ierusalimschy 7c8146d556 Small improvements in the manual 2018-10-22 15:02:09 -03:00
Roberto Ierusalimschy c90176f969 Complete implementation of to-be-closed variables 2018-10-22 14:55:51 -03:00
Roberto Ierusalimschy 3c7dc52909 Handling of memory errors when creating to-be-closed upvalues 2018-10-18 16:15:09 -03:00
Roberto Ierusalimschy bd96330d03 First "complete" implementation of to-be-closed variables
Still missing:
- handling of memory errors when creating upvalue (must run closing
method all the same)
- interaction with coroutines
2018-10-17 10:44:42 -03:00
Roberto Ierusalimschy 4cd1f4aac0 Towards "to closed" local variables
Start of the implementation of "scoped variables" or "to be closed"
variables, local variables whose '__close' (or themselves) are called
when they go out of scope. This commit implements the syntax, the
opcode, and the creation of the corresponding upvalue, but it still
does not call the finalizations when the variable goes out of scope
(the most important part).

Currently, the syntax is 'local scoped name = exp', but that will
probably change.
2018-10-08 10:42:07 -03:00
Roberto Ierusalimschy b114c7d487 Added "cost" for the use of C stack by a coroutine invocation.
Resuming a coroutine uses more C stack than other operations (such as
function calls or recursive syntax). So, to avoid stack overflow
in recursive coroutine invocations, either LUAI_MAXCCALLS must be
too small or a coroutine invocation must "pay" a higher price.
New constant LUAL_COROCSTK ("COROutine C STaK") defines how much
is this price.
2018-09-11 14:24:14 -03:00
Roberto Ierusalimschy 9cbf17b0f1 Details (comments) 2018-09-11 08:39:12 -03:00
Roberto Ierusalimschy 5382a22e0e Corrections in the implementation of '%' for floats.
The multiplication (m*b) used to test whether 'm' is non-zero and
'm' and 'b' have different signs can underflow for very small numbers,
giving a wrong result. The use of explicit comparisons solves this
problem. This commit also adds several new tests for '%' (both for
floats and for integers) to exercise more corner cases, such as
very large and very small values.
2018-08-28 12:36:58 -03:00
Roberto Ierusalimschy 8c8a91f2ef Deprecated the emulation of '__le' using '__lt'
As hinted in the manual for Lua 5.3, the emulation of the metamethod
for '__le' using '__le' has been deprecated. It is slow, complicates
the logic, and it is easy to avoid this emulation by defining a proper
'__le' function.

Moreover, often this emulation was used wrongly, with a programmer
assuming that an order is total when it is not (e.g., NaN in
floating-point numbers).
2018-08-24 10:17:54 -03:00
Roberto Ierusalimschy f99509581e Removed extra information from RCS keyword strings
Version numbers and dates (mostly wrong) from RCS keyword strings
removed from all source files; only the file name are kept.
2018-08-23 14:26:12 -03:00
Roberto Ierusalimschy 3dcd04ad61 details
Minor optimizations in 'lvm.c'. (Not exactly optimizations, but more
chances for optimizations.)
2018-08-17 15:53:39 -03:00
Roberto Ierusalimschy faaf7e481f Removed use of 'rl_inhibit_completion' in 'lua.c'
Some old systems (e.g., Mac OS X 10.4) do not define
'rl_inhibit_completion', even when line history is available.
Anyway, the user can configure this option externally, using '~/.inputrc'.
2018-08-16 14:38:05 -03:00
Roberto Ierusalimschy 3d838f635c Added "emergency collection" to 'io.tmpfile' and 'os.tmpname'
These operations also can give errors for lack of resources, so they
also will try "emergency collections" in case of resource errors.
Because there are now two libraries with that kind of handling,
'resourcetryagain' was moved to the auxiliary library to be shared
by the libraries.
2018-07-27 15:50:53 -03:00
Roberto Ierusalimschy aa4c5cf190 Added directory to test file names in '$Id:'
From the point of view of 'git', all names are relative to the root
directory of the project. So, file names in '$Id:' also should be
relative to that directory: the proper name for test file 'all.lua'
is 'testes/all.lua'.
2018-07-25 15:31:04 -03:00
Roberto Ierusalimschy b47f2cd068 Small improvements in the manual 2018-07-25 14:56:42 -03:00
Roberto Ierusalimschy e885dee5ab File operations try an "emergency collection" when failing
If a file operation fails do to lack of resources (too many open
files or not enough memory), it does a full garbage collection and
tries the operation again. Lack of resources are "too many open
files" (process wise and system wise) and "not enough memory".
The code is full of '#if's because error codes are not part
of the standard ISO C.
2018-07-25 11:44:46 -03:00
Roberto Ierusalimschy ccae0f5aad Comments about OLD0/OLD1 ages
Improved the comments in file 'lgc.c' explaining the roles of "ages"
OLD0 and OLD1 in the generacional collector.
2018-07-18 11:43:45 -03:00
Roberto Ierusalimschy 2e297d6ab3 Fixed bug in generational collection of userdata
During generational collection, a userdatum must become gray and
go to a gray list after being traversed (like tables), so that
'correctgraylist' can handle it to its next stage.

This commit also added minimum tests for the generational collector,
including one that would detect this bug.
2018-07-13 15:43:02 -03:00
Roberto Ierusalimschy fb18346ddd Avoid using 'int' for UTF-8 values
An 'int' may have only 16 bits, so it may not be big enough for UTF-8
values. The new type 'utfint' (in the utf8 library) ensures at least
21 bits for those values.
2018-07-12 15:56:44 -03:00
Roberto Ierusalimschy 96f9643f33 Bug: wrong 'nCcalls' when resuming a coroutine
The counter 'nCcalls' now includes the number of CallInfo structures
pre-allocated (so that these "potential" C calls can be made without
checking 'nCcalls'). So, when copying this value from a thread to
another, in 'lua_resume', it must be corrected to the number of
CallInfo structures in the thread being resumed.
2018-07-11 16:11:50 -03:00
Roberto Ierusalimschy 84058b1506 Added definition for LUA_VERSION_RELEASE_NUM
LUA_VERSION_RELEASE_NUM is set to the release number of the Lua
interpreter (e.g., 5.4.0 becomes the integer 50400).
2018-07-11 13:17:46 -03:00
Roberto Ierusalimschy 4d5de1c1fb Fixed bug in line info. when using 'not' operator
When creating code for a jump on a 'not' condition, the code generator
was removing an instruction (the OP_NOT) without adjusting its
corresponding line information.

This fix also added tests for this case and extra functionality in
the test library to debug line info. structures.
2018-07-11 12:53:23 -03:00
Roberto Ierusalimschy 9a825f6bb9 In tests of opcodes, avoid coercion in bitwise operation 2018-07-10 14:55:16 -03:00
Roberto Ierusalimschy 941b189d98 Improvements in the manual
- More precise use of 'argument' x 'parameter'.
- Clarification about what the lexer considers 'letter', 'space',
and 'digit'.
2018-07-10 13:48:19 -03:00
Roberto Ierusalimschy 21f663d29f Added missing $Id$ to file 'ljumptab.h' 2018-07-10 13:40:30 -03:00
Roberto Ierusalimschy 626cf0581b Generational mode may wait longer after a major collection
When Lua is building large long-duration structures, frequent small
minor collections just waste time. Trying to avoid this, the
collector will do a larger pause after a major collection when it
does not collect enough garbage (which is a hint that memory is
being used for long-lasting objects).
2018-07-09 14:22:09 -03:00
Roberto Ierusalimschy ccf6d098f6 'searchpath' creates less temporary strings
When creating error messages, package loaders may create dozens of
temporary strings (one or more for each tried template). This change
reduces the number of these strings, and avoid creating some of
them if the search is successful.
2018-07-09 13:29:08 -03:00
Roberto Ierusalimschy de2caf7ee4 Bit-library file removed from the project (as it was deprecated)
This commit only removed the file 'lbitlib.c' from the project; the
makefile already was not using it.
2018-07-09 12:54:51 -03:00
Roberto Ierusalimschy b08c9079c5 Opcode names moved to a new header file
The array with the names of the opcodes was moved to a header file
('lopnames.h'), as it is not used by the Lua kernel. Files that need
that array ('luac.c' and 'ltests.c') include the header file to get
a private (static) copy.
2018-07-09 12:50:51 -03:00
Roberto Ierusalimschy 06e08c6d05 Fixed bug in OP_IDIVI
Opocode was using 'luai_numdiv' (float division) instead of
'luai_numidiv' (integer division).
2018-07-09 12:41:24 -03:00
Roberto Ierusalimschy 7c519dfbd0 Added manual and tests for version 5.4-w2 2018-07-09 12:33:01 -03:00
Roberto Ierusalimschy f59e6a93c0 opening functions must be exported! 2018-06-19 16:23:57 -03:00
Roberto Ierusalimschy 6683f83b51 several details 2018-06-18 15:25:19 -03:00
Roberto Ierusalimschy a314409dba in generational mode, an emergency collection can turn any object black
during any memory allocation +
'luaT_getvarargs' may reallocate the stack, and therefore the top must
be correct.
2018-06-18 14:58:21 -03:00
Roberto Ierusalimschy 15ce8d0904 in generational mode, an emergency collection can turn any object black
during any memory allocation.
2018-06-18 14:57:20 -03:00
Roberto Ierusalimschy b43300c14f change in 'LUAI_DDEC' to allow variables to be static in 'onelua'
+ change in 'LUAMOD_API' as opening functions do not need to be global
2018-06-18 09:51:05 -03:00
Roberto Ierusalimschy af70905246 no need to check whether libraries and host use the same kernel;
Lua should work correctly with several copies of the kernel
2018-06-18 09:08:10 -03:00
Roberto Ierusalimschy b95e466218 new field 'nilvalue' in struct 'global_State' to avoid the use of
addresses of static variables
2018-06-15 16:31:22 -03:00
Roberto Ierusalimschy d406d3d05f removed unused macros 'isstackindex'/'api_checkstackindex' +
macro 'api_checkvalidindex' (used only once) expanded and removed
2018-06-15 14:30:52 -03:00
Roberto Ierusalimschy b6780ee41b detail (removed unused definition for 'LUA_QS') 2018-06-15 12:49:28 -03:00
Roberto Ierusalimschy 2c107e13a8 warning (comparison between signed and unsigned integers) 2018-06-15 11:18:40 -03:00
Roberto Ierusalimschy 6e600695f8 field 'sizearray' in struct 'Table' changed to 'alimit', which can
be used as a hint for '#t'
2018-06-15 11:14:20 -03:00
Roberto Ierusalimschy 06127927ff new macro 'ispow2' 2018-06-15 11:13:45 -03:00
Roberto Ierusalimschy aedcfb9414 type 'Rand64' may not be long long, so it should not use 'LL' in its
constants
2018-06-14 15:47:22 -03:00
Roberto Ierusalimschy 992b6d2712 no more 'TESTGRAYBIT' (to free this bit for real uses) 2018-06-11 11:19:50 -03:00
Roberto Ierusalimschy 588dfa4ce5 detail in comment 2018-06-08 16:07:27 -03:00
Roberto Ierusalimschy 6f2b8e21c4 added 'const' to 'Proto*' when possible 2018-06-08 16:06:59 -03:00
Roberto Ierusalimschy c5dc521d65 added patch for bug 5.3.4-7 2018-06-08 13:23:18 -03:00
Roberto Ierusalimschy 505fc91222 no more 'luaO_nilobject' to avoid comparison of global variable addresses
(now uses static variables)
2018-06-01 14:40:38 -03:00
Roberto Ierusalimschy fb8fa66136 no more 'luaH_emptyobject' and comparisons of addresses of global variables
(instead, use a different kind of nil to signal the fake entry returned
when a key is not found in a table)
2018-06-01 13:51:34 -03:00
Roberto Ierusalimschy b397064955 avoid craches when loading tampered code with NULL as a string constant 2018-06-01 13:45:58 -03:00
Roberto Ierusalimschy 34aa0c5bd7 new macros 'likely'/'unlikely' with hints for jump predictions
(used only in errors for now)
2018-05-30 11:25:52 -03:00
Roberto Ierusalimschy 97e394ba18 macro 'luai_makeseed' now controls the whole process of making the seed 2018-05-29 15:02:51 -03:00
Roberto Ierusalimschy 950fbcb971 detail ('l_castU2S' should only be used over lua_Unsigned values) 2018-05-29 15:01:50 -03:00
Roberto Ierusalimschy b2d4d06428 avoid possible overflows when checking sizes in 'string.unpack' 2018-05-25 10:39:32 -03:00
Roberto Ierusalimschy 3b8dba5279 added patches for two bugs (5.3.4-2 and 5.3.4-3) 2018-05-24 17:25:14 -03:00
Roberto Ierusalimschy 892aff2a07 avoid circular inclusion between ltm.h <-> lstate.h 2018-05-23 11:41:20 -03:00
Roberto Ierusalimschy 02ed0b2c30 in 'luaD_poscall', there is no need to compute 'firstResult' when 'nres==0' 2018-05-22 09:02:36 -03:00
Roberto Ierusalimschy de53c2ec7e using some weak "randomness" (time and memory address) to initialize
seeds for the PRNG
2018-05-16 08:27:59 -03:00
Roberto Ierusalimschy 80bd4a8940 correction on xoshiro256** algorithm
(should use state[1] instead of state[0] for output)
2018-05-09 11:54:37 -03:00
Roberto Ierusalimschy 3e7415e846 reorganization of '#if's for sellecting a type for 'Rand64' +
comments
2018-05-04 17:01:45 -03:00
Roberto Ierusalimschy e64e20ac81 minimizing the code ran by 'vmfetch' + no more 'vra'
(the code is simpler without 'vra' and conversion is a no-op)
2018-05-02 15:17:59 -03:00
Roberto Ierusalimschy deb807837c 'luaO_pushvfstring' does not need to reallocate stack
(less error cases in the API)
2018-04-25 13:26:20 -03:00
Roberto Ierusalimschy 26eb144541 no need to define 'luaP_opnames' in regular builds 2018-04-19 12:42:41 -03:00
Roberto Ierusalimschy f9c3d6fdbe use test mode to test the interpreter without jump tables 2018-04-11 13:49:36 -03:00
Roberto Ierusalimschy 762baf0548 detail (trim constants are unsigned) 2018-04-06 14:52:42 -03:00
Roberto Ierusalimschy b8a04658b2 PRNG changed from 'xoroshiro128+' to 'xoshiro256**' + "I' renamed 'Rand64'
+ implementation can use integer types larger than 64 (or 32) bits
2018-04-06 12:41:29 -03:00
Roberto Ierusalimschy b44787652b using 'xoroshiro128+' for PRNG
(plus a rotate at the final result to have better lower bits)
2018-04-04 13:12:53 -03:00
Roberto Ierusalimschy 03c6a05ec8 no more nil-in-table 2018-04-04 11:23:41 -03:00
Roberto Ierusalimschy 3d0b5edfe4 using unsigned comparison in 'l_intfitsf' (avoids one comparison) 2018-04-02 14:52:07 -03:00
Roberto Ierusalimschy 8d50a998e3 definition for LUA_UNSIGNEDBITS (number of bits in a LUA_UNSIGNED) 2018-04-02 10:58:33 -03:00
Roberto Ierusalimschy bdd10a08b1 in 'random', uses high-order bits instead of low-order
(better statistical properties)
2018-03-26 16:48:46 -03:00
Roberto Ierusalimschy c5e3b2f814 in random/'project', remove the special case for "small" intervals;
it is slower than the general case.
2018-03-22 16:54:49 -03:00
Roberto Ierusalimschy 6486762463 missing LUAI_FUNC in prototype for 'luaK_patchgoto' 2018-03-19 17:03:44 -03:00
Roberto Ierusalimschy 4907444db9 'fTransfer' -> 'ftransfer' / 'nTransfer' -> 'ntransfer'
(keep the standard of names in lower case)
2018-03-16 12:33:34 -03:00
Roberto Ierusalimschy c3cb31fa9a some extra goodies for 'readline'
('rl_readline_name' and 'rl_inhibit_completion')
2018-03-16 11:23:08 -03:00
Roberto Ierusalimschy 0c7738240e FALLTHROUGH comment must be last "statement"
(so it does not work when inside a block)
2018-03-16 11:22:09 -03:00
Roberto Ierusalimschy 7b0b6b3b39 cannot use 'defined' inside a macro +
call to 'luaT_keydef' must be protected
2018-03-16 11:21:20 -03:00
Roberto Ierusalimschy 89da4168df avoid functions named 'pack'
(name too common, may collide when doing 'onelua.c')
2018-03-16 11:18:18 -03:00
Roberto Ierusalimschy 6b01b6cf6a 'lu_int32' may not be 'int' 2018-03-12 09:39:03 -03:00
Roberto Ierusalimschy e3388ebfad more explicit casts when converting an integer to a random float
(to ensure computations are done with all bits)
2018-03-11 11:48:09 -03:00
Roberto Ierusalimschy 9e3db70482 details (casts between 'lua_Number' and 'double') 2018-03-09 16:24:45 -03:00
Roberto Ierusalimschy dbec41f34c random floats of different sizes get exactly needed number of random bits
(up to 64)
2018-03-09 16:23:39 -03:00
Roberto Ierusalimschy 0b3db69e41 slight simplification in 'xorshift128plus' 2018-03-09 12:05:13 -03:00
Roberto Ierusalimschy 80ae1c1c16 fairer projection of random integers into an integer interval 2018-03-09 11:56:25 -03:00
Roberto Ierusalimschy 40683b4934 added definition for LUA_MAXUNSIGNED 2018-03-09 11:56:02 -03:00
Roberto Ierusalimschy 6480e73599 details (avoid using non-C89 '//' comment) 2018-03-07 13:26:01 -03:00
Roberto Ierusalimschy 4a1612ff9b new experimental syntax using reserved word 'undef' 2018-03-07 12:55:38 -03:00
Roberto Ierusalimschy 464658b16a better modularization of the code for the REPL 2018-03-06 17:30:17 -03:00
Roberto Ierusalimschy bdcde45d05 updated to use jump tables 2018-03-05 11:26:18 -03:00
Roberto Ierusalimschy 8b0434e5e6 both 'fTransfer' and 'nTransfer' may not fit in a 'char' 2018-03-05 11:15:32 -03:00
Roberto Ierusalimschy 8b0b675149 added casts (warnings in VS) 2018-03-05 11:15:04 -03:00
Roberto Ierusalimschy 8c429311a3 typo in comment 2018-03-05 11:13:55 -03:00
Roberto Ierusalimschy 66b7b075a6 'math.random' using the xorshift128+ algorithm 2018-03-05 11:07:48 -03:00
Roberto Ierusalimschy 62a392ff46 using jump tables when available 2018-03-02 15:59:19 -03:00
Roberto Ierusalimschy 893f382e94 Jump Table for the interpreter 2018-03-02 15:56:14 -03:00
Roberto Ierusalimschy 0eb10c6303 'LUA_USE_READLINE' moved to the make file 2018-03-02 15:31:51 -03:00
Roberto Ierusalimschy 00008b8ed0 back to one format per argument 2018-03-02 15:25:00 -03:00
Roberto Ierusalimschy df49384516 year in copyright changed to 2018 2018-03-02 13:30:47 -03:00
Roberto Ierusalimschy fbea553ca2 'lua_setiuservalue' removes value from the stack even in case of error 2018-02-27 17:01:55 -03:00
Roberto Ierusalimschy 34b00c16e2 removed compatibility code with older versions 2018-02-27 15:47:32 -03:00
Roberto Ierusalimschy 12110dec0e module has been deprecated. 2018-02-27 15:46:26 -03:00
Roberto Ierusalimschy 4105cafb84 no more 'bitlib' 2018-02-27 15:27:30 -03:00
Roberto Ierusalimschy 76ff55750e no optimizations in test mode + no more compat with 5.2 + a few more
options in comments
2018-02-27 15:24:23 -03:00
Roberto Ierusalimschy b7edf5d2d8 metamethods for 'removekey'/'keyin' 2018-02-27 14:48:28 -03:00
Roberto Ierusalimschy ef8263f81f better names for macros for tags and types.
rttype -> rawtt; ttyperaw -> withvariant; ttype -> ttypetag;
tnov -> ttype
2018-02-26 11:16:05 -03:00
Roberto Ierusalimschy 2952bc5fc9 special compact representation for userdata with no user values
(a common case)
2018-02-26 10:35:03 -03:00
Roberto Ierusalimschy 38d3bc8909 using 'offsetof' to compute the size of parts of a structure 2018-02-25 10:40:00 -03:00
Roberto Ierusalimschy 75efc6722b avoid variant tags with the same value of the original type
(to expose bugs more easily)
2018-02-25 09:52:32 -03:00
Roberto Ierusalimschy d766e2ae17 first (parcial) implementation of 'keyin'/'removekey'
(still no metamethods, no raw verssions)
2018-02-25 09:48:16 -03:00
Roberto Ierusalimschy f055a9dffd added check in 'obj2gco' to prevent its use in non Lua-object pointers
(otherwise its cast is blind, casting any value given to it)
2018-02-25 09:43:52 -03:00
Roberto Ierusalimschy 4a7fe61806 in 'clearbykeys', clear keys of just-removed entries too 2018-02-23 10:21:27 -03:00
Roberto Ierusalimschy 9243c414d9 first version of empty entries in tables
(so that, in the future, tables can contain regular nil entries)
2018-02-23 10:16:18 -03:00
Roberto Ierusalimschy 477ca2fe8c some reorganization in 'lobject.h'
(just moving stuff around)
2018-02-22 14:28:10 -03:00
Roberto Ierusalimschy c72ac048b9 conditional jumps "deunified"
(if a jump table is used, the unification may harm jump prediction.)
2018-02-21 16:43:44 -03:00
Roberto Ierusalimschy b03dddf9e4 removed coercion string->number in bitwise operations
(can be done with a Lua module)
2018-02-21 14:48:31 -03:00
Roberto Ierusalimschy c80c7a49fd details (comments) 2018-02-21 13:28:12 -03:00
Roberto Ierusalimschy 212095a601 new opcodes OP_GTI/OP_GEI 2018-02-21 12:49:32 -03:00
Roberto Ierusalimschy c67603fafb using new 'lua_newuserdatauv' instead of 'lua_newuserdata' 2018-02-21 10:48:44 -03:00
Roberto Ierusalimschy 06865aa01d simpler implementation for 'LTintfloat'/'LEintfloat'
+ 'LTfloatint'/'LEfloatint'
2018-02-21 10:47:03 -03:00
Roberto Ierusalimschy 465b474899 small reorganization of 'luaV_flttointeger'/'luaV_tointeger' 2018-02-21 09:54:26 -03:00
Roberto Ierusalimschy 6353d619a5 detail (comment) 2018-02-20 17:52:50 -03:00
Roberto Ierusalimschy ca6fe7449a userdata can have multiple user values 2018-02-20 13:52:50 -03:00
Roberto Ierusalimschy 1afd5a152d more generic way to handle 'gclist' 2018-02-19 17:06:56 -03:00
Roberto Ierusalimschy 422318f677 two new fields 'fTransfer'/'nTransfer' in 'lua_Debug' structure
(for information about values being given and returned in function calls)
2018-02-17 17:29:29 -02:00
Roberto Ierusalimschy 49dae52d08 correct way to check stack space for vararg functions 2018-02-17 17:20:00 -02:00
Roberto Ierusalimschy 104d249ffb in return hook, 'top' must be corrected only if smaller than 'ci->top'.
(It may be larger when returning multiple values, and then it must
be larger to preserve that stack slice.)
2018-02-17 16:22:00 -02:00
Roberto Ierusalimschy c7a8cba745 no more 'nfield' string 2018-02-15 16:06:24 -02:00
Roberto Ierusalimschy 0682fe8169 some simplifications/optimizations in returns from Lua functions 2018-02-15 13:34:29 -02:00
Roberto Ierusalimschy b1379936cf vararg back to '...' (but with another implementation)
new implementation should have zero overhead for non-vararg functions
2018-02-09 13:16:06 -02:00
Roberto Ierusalimschy 4e0de3a43c details 2018-02-07 13:55:18 -02:00
Roberto Ierusalimschy 318a9a5859 new opcode 'PREPVARARG'
(avoids test for vararg function in all function calls)
2018-02-07 13:18:04 -02:00
Roberto Ierusalimschy 73d797ce7e detail
(order of 'OT' and 'IT' bits corresponds with macro 'opmode')
2018-02-07 13:04:41 -02:00
Roberto Ierusalimschy 51280ef2ad call hooks for Lua functions called by 'luaV_execute' 2018-02-06 17:16:56 -02:00
Roberto Ierusalimschy fc3eaa2559 GC default mode for the stand-alone interpreter is generational mode 2018-02-06 13:32:36 -02:00
Roberto Ierusalimschy daff7c3b4d small corrections in generational mode
(cannot call finalizers in emergency collections +
 should set everything before calling finalizers)
2018-02-05 15:14:54 -02:00
Roberto Ierusalimschy a131eae925 default for minor collection intervals a little larger 2018-02-05 15:14:29 -02:00
Roberto Ierusalimschy 022abc301b 'gcemergency' should be zero before any memory allocation 2018-02-05 15:11:37 -02:00
Roberto Ierusalimschy 56e50e8bc5 'collectgarbage' returns old mode when changing mode 2018-02-05 15:10:52 -02:00
Roberto Ierusalimschy 90569630d6 detail
(uses a reserved-format name for an internal type in the registry)
2018-01-29 17:13:27 -02:00
Roberto Ierusalimschy dc0ab1e8ca warnings in VS (implicit casts from ptrdiff_t to int) 2018-01-29 14:21:35 -02:00
Roberto Ierusalimschy e2b15aa21d janitor work on casts 2018-01-28 13:13:26 -02:00
Roberto Ierusalimschy 89110986d7 bug in tailcall of vararg functions
(when adjusting missing parameters)
2018-01-28 11:39:52 -02:00
Roberto Ierusalimschy 53979dfe0d calling a vararg function needs to check GC
(because it creates a new table)
2018-01-28 10:08:04 -02:00
Roberto Ierusalimschy 6710a2b0ef detail (comment) 2018-01-28 10:07:53 -02:00
Roberto Ierusalimschy 5bd8d388de OP_CONCAT does not move its result (to simplify its execution) 2018-01-27 14:56:33 -02:00
Roberto Ierusalimschy 28f215ecf8 comments 2018-01-18 14:24:31 -02:00
Roberto Ierusalimschy d2fb34ac88 'OP_TAILCALL' calling C functions finishes the call and returns
(instead of waiting for following 'OP_RETURN')
2018-01-14 15:27:50 -02:00
Roberto Ierusalimschy ab0a851db4 'luaD_tryfuncTM' can ensure it does not change the stack 2018-01-10 17:19:27 -02:00
Roberto Ierusalimschy 728ff94595 error handler in protected calls must be a function 2018-01-10 10:02:35 -02:00
Roberto Ierusalimschy ad960095bf avoid jumping into a variable scope (C++ does not allow that) 2018-01-09 12:23:40 -02:00
Roberto Ierusalimschy 33e3774f44 keep more opcode arguments byte-aligned 2018-01-09 09:24:12 -02:00
Roberto Ierusalimschy a9295a2b8e typos in comments 2017-12-30 18:46:18 -02:00
Roberto Ierusalimschy c6fedc92f8 new command 'print' (to print literal strings) in mini-language 2017-12-29 13:59:37 -02:00
Roberto Ierusalimschy 68af7cc81a another try with table resize.
(Old version was leaving some elements unanchored while allocating
new memory)
2017-12-29 13:58:23 -02:00
Roberto Ierusalimschy 28323aeaa6 by-one error when filling missing arguments in a tail call 2017-12-29 13:44:51 -02:00
Roberto Ierusalimschy cf7eff45f3 keep control of stack top in Lua functions concentrated in 'luaV_execute' 2017-12-28 13:42:57 -02:00
Roberto Ierusalimschy 8691612f01 when calling a hook, cannot decrease 'ci->top' (to preserve stack
size if the stack is reallocated)
2017-12-28 12:17:09 -02:00
Roberto Ierusalimschy f99f3c42ff comment 2017-12-28 09:51:00 -02:00
Roberto Ierusalimschy f360e7778b assert cannot use instruction after the last 2017-12-22 14:43:59 -02:00
Roberto Ierusalimschy 4676f6599e new macros 'isOT'/'isIT'
(plus exchanged parameters of OP_VARARG to make it similar to other
'isOT' instructions)
2017-12-22 12:16:46 -02:00
Roberto Ierusalimschy 1d5b885437 when running Lua code, there is no need to keep 'L->top' "correct";
set it only when needed.
2017-12-20 12:58:05 -02:00
Roberto Ierusalimschy 4dc0be950a new macro 'isLuacode' (to distinguish regular Lua code from
hooks, where C code can run inside a Lua function).
2017-12-19 14:40:17 -02:00
Roberto Ierusalimschy 3153a41e33 no need to save 'pc' in case of allocation errors
(allocation errors do not call message handlers)
2017-12-19 14:18:04 -02:00
Roberto Ierusalimschy d388c165ef new opcodes 'FORLOOP1'/'FORPREP1' for "basic for" (integer variable
with increment of 1)
2017-12-18 15:53:50 -02:00
Roberto Ierusalimschy ab07005568 new auxiliary function 'luaK_isKint' + removal of 'luaK_needclose',
which was not being used anywhere.
2017-12-18 13:44:44 -02:00
Roberto Ierusalimschy 7024f49c42 default now is compiling without compatibility options + smaller
stack size in debug mode (clang uses still more stack space when
debugging).
2017-12-18 11:01:49 -02:00
Roberto Ierusalimschy 2f6f6abeba 'rehash' -> 'tablerehash'
(to avoid name colisions when compiling Lua as a single file)
2017-12-18 11:00:57 -02:00
Roberto Ierusalimschy 3064edead2 details (cleaning uses of 'exp1') 2017-12-18 10:33:54 -02:00
Roberto Ierusalimschy f8c1c1469a some cleaning on signed opcode parameters 2017-12-15 16:53:48 -02:00
Roberto Ierusalimschy 4b6928e7f5 (1 << 31) with signed integer has undefined behavior in C 2017-12-15 16:35:22 -02:00
Roberto Ierusalimschy b3f924bc69 'Proto->numparams' does not include vararg parameter
(one less subtraction when calling functions...)
2017-12-15 11:07:10 -02:00
Roberto Ierusalimschy e001d5aea6 'VRELOCABLE' -> 'VRELOC' 2017-12-14 12:24:02 -02:00
Roberto Ierusalimschy e752d84ed8 bug: memory-allocation error when resizing a table can leave it
in an inconsistent state.
2017-12-13 16:35:03 -02:00
Roberto Ierusalimschy 86431a2f1c new opcodes BANDK/BORK/BXORK. (They do not use immediate operands
because, too often, masks in bitwise operations are integers larger
than one byte.)
2017-12-13 16:32:09 -02:00
Roberto Ierusalimschy 36cf8f3a3c Code should not change the stack level after the initialization of a
string buffer.
2017-12-13 10:51:42 -02:00
Roberto Ierusalimschy 725c15a4ca when shrinking stack, always shrinks the CI list.
(Stack overflow is not corelated to CI overflow anymore.)
2017-12-12 09:57:30 -02:00
Roberto Ierusalimschy b077b20206 back to reallocation when resizing the string table.
(Not a good idea to explicitly allocate new memory when shrinking
something.)
2017-12-12 09:52:35 -02:00
Roberto Ierusalimschy 3cf340f676 allows memory-allocation errors when shrinking blocks 2017-12-11 16:55:31 -02:00
Roberto Ierusalimschy 7ad20af2cf more freedom in handling memory-allocation errors (not all allocations
automatically raise an error), which allows fixing a bug when resizing
a table.
2017-12-11 16:53:53 -02:00
Roberto Ierusalimschy bfb88e99e9 'luaD_growstack' cannot raise any errors when 'raiseerror' is
false (+ some comments)
2017-12-11 10:43:40 -02:00
Roberto Ierusalimschy c5ebed7399 'luaM_shrinkvector' raises an error if it cannot shrink the block
(several parts of Lua use array size in protos as proxies for
number of valid elements)
2017-12-11 10:27:48 -02:00
Roberto Ierusalimschy e663a24ab0 more freedom in handling memory-allocation errors (not all allocations
automatically raise an error), which allows fixing a bug when resizing
a table.
2017-12-08 15:28:25 -02:00
Roberto Ierusalimschy 40f823ec90 new C instruction "rawcheckstack" (to test failing in 'lua_checkstack') 2017-12-08 13:19:13 -02:00
Roberto Ierusalimschy 7622373033 using explicit tests for allocation overflow whenever possible 2017-12-07 16:59:52 -02:00
Roberto Ierusalimschy 46bc7f2bf7 detail (comment) 2017-12-07 16:53:33 -02:00
Roberto Ierusalimschy cc01d46247 new test function 'T.allocount' to restrict number of allocations
before a memory-allocation error
2017-12-07 16:51:39 -02:00
Roberto Ierusalimschy 9fa1baf6de opcodes for order and shift can use several metamethods,
so it is better to use a generic description + metamethod names
in some error messages shown without '__' prefix
2017-12-07 13:44:10 -02:00
Roberto Ierusalimschy 49dfaf7447 avoid using one function for different tasks (malloc, free, etc.) 2017-12-06 16:36:31 -02:00
Roberto Ierusalimschy 348fa1ca56 bug: 'lua_pushcclosure' should not call the garbage collector when
'n' is zero.
2017-12-06 16:20:28 -02:00
Roberto Ierusalimschy ae11e37e53 bug: 'lua_pushcclosure' should not call the GC when 'n' is zero 2017-12-06 16:08:03 -02:00
Roberto Ierusalimschy c7ee7fe026 new opcodes OP_SHLI/OP_SHRI 2017-12-04 15:41:30 -02:00
Roberto Ierusalimschy 421e459684 'luaS_resize' can raise memory errors 2017-12-01 15:38:49 -02:00
Roberto Ierusalimschy 9d28b40152 rehashes string table always allocating a new array instead of
reallocating old one. (Avoids problems if reallocation to a small
size fails.)
2017-12-01 14:40:29 -02:00
Roberto Ierusalimschy e0bece77d6 detail 2017-12-01 13:44:51 -02:00
Roberto Ierusalimschy d0356d5f15 another value for LUAI_MAXCCALLS (must think more about that) 2017-12-01 13:08:14 -02:00
Roberto Ierusalimschy ac78b914b6 warnings from Visual Studio /W3 2017-11-30 13:37:16 -02:00
Roberto Ierusalimschy 10b8c99bbb small peephole optimizations 2017-11-30 11:29:18 -02:00
Roberto Ierusalimschy bdc751ce23 details (comments) 2017-11-30 11:16:43 -02:00
Roberto Ierusalimschy 19c6b375c3 detail (spacing) 2017-11-30 10:03:00 -02:00
Roberto Ierusalimschy 745eb41993 new opcodes OP_RETURN0/OP_RETURN1 2017-11-29 14:57:36 -02:00
Roberto Ierusalimschy c766e4103d 'luaV_execute' gets call info as extra argument (it is always
available on call sites)
2017-11-29 11:02:17 -02:00
Roberto Ierusalimschy 36aecd4548 order opcodes cannot use 'K' operands 2017-11-28 13:26:15 -02:00
Roberto Ierusalimschy 1a5e8c1014 conditional jumps unified in label "condjump' + new variable 'vra'
to avoid excessive use of macro 's2v'
2017-11-28 12:51:00 -02:00
Roberto Ierusalimschy ff5fe51044 using register 'k' for conditions in tests (we only need one bit there) 2017-11-28 10:58:18 -02:00
Roberto Ierusalimschy dfd188ba12 detail (identation of switch) 2017-11-28 09:19:07 -02:00
Roberto Ierusalimschy 093c16b67b new opcodes 'OP_LTI' and 'OP_LEI' 2017-11-27 15:44:31 -02:00
Roberto Ierusalimschy 599f1742c6 detail (typo in comments) 2017-11-23 17:29:04 -02:00
Roberto Ierusalimschy 73abfde2ef small simplifications around 'luaT_callorderTM' 2017-11-23 17:18:10 -02:00
Roberto Ierusalimschy 194a4f9710 small simplifications in 'luaD_poscall' 2017-11-23 16:29:41 -02:00
Roberto Ierusalimschy 196c87c9ce no more 'stackless' implementation; 'luaV_execute' calls itself
recursively to execute function calls. 'unroll' continues all
executions suspended by an yield (through a long jump)
2017-11-23 14:41:16 -02:00
Roberto Ierusalimschy 39f26b1480 more information from 'T.stacklevel' 2017-11-23 13:38:42 -02:00
Roberto Ierusalimschy 3c230cc825 using 'A' for register instead of 'B' in relational opcodes
('R(A)' is already created by default for all instructions.)
2017-11-22 17:15:44 -02:00
Roberto Ierusalimschy 41f2936d8f new opcode 'OP_EQI' for equality with immediate numbers 2017-11-22 16:41:20 -02:00
Roberto Ierusalimschy 14c3aa12b5 more direct implementation for tail calls. 2017-11-21 12:18:03 -02:00
Roberto Ierusalimschy f3ca52bfa9 in order comparison opcodes, fast track for floats too 2017-11-20 10:57:39 -02:00
Roberto Ierusalimschy c47111bd4e 'io.read' accepts multiple formats in a single string argument 2017-11-16 14:28:36 -02:00
Roberto Ierusalimschy e4e5aa85a2 detail ('signal' -> 'sign' in comments) 2017-11-16 11:19:06 -02:00
Roberto Ierusalimschy 4c0e36a46e new instruction 'OP_EQK' (for equality with constants) 2017-11-16 10:59:14 -02:00
Roberto Ierusalimschy 5440b42f43 using 'trap' to stop 'luaV_execute' when necessary (tracing and
to update its copy of 'base' when the stack is reallocated)
2017-11-13 13:36:52 -02:00
Roberto Ierusalimschy 7d4828cc9f avoid accessing wrong union field 2017-11-13 10:26:30 -02:00
Roberto Ierusalimschy 62f3b7c472 detail 2017-11-13 10:20:51 -02:00
Roberto Ierusalimschy fb9be62f79 includes 'stdio.h' to allow prints when testing 2017-11-13 10:19:35 -02:00
Roberto Ierusalimschy 7c0175bc83 removed unused variable 'islocked' 2017-11-09 11:31:29 -02:00
Roberto Ierusalimschy 32fef60743 detail ('Protect' defined as an expression) 2017-11-08 17:01:02 -02:00
Roberto Ierusalimschy 26679ea35b new function 'luaV_flttointeger' to convert floats to integers (without
string coercions) + string operands to bitwise operations handled
by string metamethods
2017-11-08 12:50:23 -02:00
Roberto Ierusalimschy c3e5946fb2 new format for JUMP instructions (to allow larger offsets) 2017-11-07 15:20:42 -02:00
Roberto Ierusalimschy ad0704e40c back to 'CallInfo' (no gains with its removal) 2017-11-07 11:25:26 -02:00
Roberto Ierusalimschy 5a3f26f855 fitting a StackValue structure into 32 bytes (for 64-bit machines) 2017-11-06 15:34:06 -02:00
Roberto Ierusalimschy 93fd67b793 no more 'CallInfo' structure 2017-11-04 10:57:02 -02:00
Roberto Ierusalimschy 6bb3e40a8d 'lua_Debug' not using 'CallInfo' 2017-11-03 18:41:05 -02:00
Roberto Ierusalimschy 7612f7735d removing uses of 'CallInfo' 2017-11-03 17:33:22 -02:00
Roberto Ierusalimschy 472c560705 no more useful fields in CallInfo 2017-11-03 15:22:54 -02:00
Roberto Ierusalimschy 54eb35a8aa more fields moved out of 'CallInfo' 2017-11-03 10:12:30 -02:00
Roberto Ierusalimschy ba36180fd7 new API for 'lua_resume' + cleaning the uses of the 'extra' field in
'CallInfo'
2017-11-02 09:28:56 -02:00
Roberto Ierusalimschy b9e76be8a6 using 'L->func' when possible 2017-11-01 16:20:48 -02:00
Roberto Ierusalimschy c5482468fd baby steps to remove 'CallInfo': keeping 'L->func' correct 2017-10-31 15:54:35 -02:00
Roberto Ierusalimschy ad5dcdcf0f detail: in 'isinstack', check against the whole stack instead
of against the stack frame
2017-10-31 15:14:02 -02:00
Roberto Ierusalimschy de9128d09d do not mess up the debt when the collector is not running 2017-10-31 13:29:28 -02:00
Roberto Ierusalimschy 1d8920dd7f some cleaning in GC parameters 2017-10-11 09:38:45 -03:00
Roberto Ierusalimschy 911f1e3e7f raw operation should not convert strings to numbers 2017-10-10 17:05:40 -03:00
Roberto Ierusalimschy a1ef58b3a5 eplicit 1-bit opcode operand 'k' 2017-10-04 18:56:32 -03:00
Roberto Ierusalimschy 283e7455ff detail 2017-10-04 18:53:03 -03:00
Roberto Ierusalimschy 8fbe9e3470 new opcodes with immediate integer operand for all arithmetic operations 2017-10-04 12:49:24 -03:00
Roberto Ierusalimschy 9ed9f40f1e avoid warning about 'const' 2017-10-04 12:49:05 -03:00
Roberto Ierusalimschy 940472c75c opcode size increased to 7 bits 2017-10-02 19:51:32 -03:00
Roberto Ierusalimschy f3b3d9b5c2 string constants (Kstr) must fit into 'B' register 2017-10-02 19:50:57 -03:00
Roberto Ierusalimschy 7f9a32ad85 new function 'printcode' 2017-10-01 16:17:51 -03:00
Roberto Ierusalimschy bc1b0733b8 avoid the use of bit 'Bk' ('B' will lose this bit soon) 2017-10-01 16:13:43 -03:00
Roberto Ierusalimschy 722bdbe17d no more 'getBMode'-'getCMode' (imprecise + we will need more space
for op mode) + better control of op modes
2017-09-28 13:53:29 -03:00
Roberto Ierusalimschy 1b10033583 new function 'luaT_trybiniTM'
to handle tag methods for instructions with immediate integer arguments
2017-09-27 15:59:08 -03:00
Roberto Ierusalimschy 00e728af88 binary operators use R instead of RK
faster + nobody uses RK(B), so B can be smaller (freeing one bit
for more opcodes, soon)
2017-09-26 15:14:45 -03:00
Roberto Ierusalimschy 13256a4173 detail
put explicit all cases for a switch of an enumeration
2017-09-26 14:10:49 -03:00
Roberto Ierusalimschy abb17cf19b new opcode OP_LOADF (load immediate float) 2017-09-19 15:38:14 -03:00
Roberto Ierusalimschy e0c0e2ee14 comments (documentation about instruction formats) 2017-09-18 13:07:54 -03:00
Roberto Ierusalimschy 022e4427cf detail (keep OP_LOADK and OP_LOADKX together) 2017-09-15 11:19:06 -03:00
Roberto Ierusalimschy 80d9b09f35 jumps do not close upvalues (to be faster and simpler);
explicit instruction to close upvalues; command 'break' not
handled like a 'goto' (to optimize removal of uneeded 'close'
instructions)
2017-09-13 16:50:08 -03:00
Roberto Ierusalimschy 029d269f4d bug: dead keys with nil values can stay in weak tables 2017-08-31 13:14:41 -03:00
Roberto Ierusalimschy ac65bab25f jumps in 'for' loops don't need to be signed 2017-08-14 15:33:14 -03:00
Roberto Ierusalimschy f185c0132e comment in code fragment 2017-08-12 10:12:42 -03:00
Roberto Ierusalimschy b77f792b23 comment 2017-08-12 10:12:21 -03:00
Roberto Ierusalimschy 4053eae9eb bug: Lua does not check GC when creating error messages 2017-07-27 10:55:38 -03:00
Roberto Ierusalimschy 6d998055c8 no more reference 'memerrmsg' + new reference to "n"
(both can be retrieved by 'luaS_newliteral' without creating anything,
because they are fixed, but "n" deserves fast access while 'memerrmsg'
does not)
2017-07-27 10:50:16 -03:00
Roberto Ierusalimschy 11769b203f new version (5.4) 2017-07-27 10:36:54 -03:00
Roberto Ierusalimschy b1daa069ba bug: Lua does not check GC when creating error messages 2017-07-10 14:35:12 -03:00
Roberto Ierusalimschy 4dff277255 coercion string->number in arithmetic operations moved to string
library
2017-07-07 13:34:32 -03:00
Roberto Ierusalimschy 07db10813c 'OP_VARARG' has the vararg parameter as an operand 2017-06-29 12:38:41 -03:00
Roberto Ierusalimschy f96497397a new type 'StackValue' for stack elements
(we may want to put extra info there in the future)
2017-06-29 12:06:44 -03:00
Roberto Ierusalimschy 5a1c8d8ef3 new constant 'LUA_GNAME' for the name of the global table "_G" 2017-06-27 15:32:49 -03:00
Roberto Ierusalimschy 124bfd2081 dumping ints and size_ts compacted 2017-06-27 11:21:12 -03:00
Roberto Ierusalimschy b42430fd3a 'lineinfo' in prototypes saved as differences instead of absolute
values, so that the array can use bytes instead of ints, reducing
its size. (A new array 'abslineinfo' is used when line differences
do not fit in a byte.)
2017-06-27 08:35:31 -03:00
Roberto Ierusalimschy 60a7492d24 new type 'ls_byte' for signed bytes 2017-06-27 08:35:01 -03:00
Roberto Ierusalimschy 73ec04fcf3 no more 'DEADKEY'. Table traversals do not need to consider dead keys;
if the key is dead, it cannot be given to 'next'. Instead, we now
use a 'table' tag without the collectable bit, which makes it
a unique tag good enough to reserve space.
2017-06-12 11:21:44 -03:00
Roberto Ierusalimschy d13a3fb070 detail
(removed empty spaces at the end of lines)
2017-06-09 16:16:41 -03:00
Roberto Ierusalimschy b6f87491af in hash nodes, keys are stored in separate pieces to avoid wasting
space with alignments
2017-06-09 13:48:44 -03:00
Roberto Ierusalimschy 4bb30f461b when assigning to a 'TValue', better assign only exact fields,
to allow us to put stuff after the 'TValuefields' if needed
2017-06-01 17:24:05 -03:00
Roberto Ierusalimschy dad85e4131 macro 'setobj2t' may not be an expression 2017-06-01 17:23:27 -03:00
Roberto Ierusalimschy b029e7ea20 macro 'luaV_fastget' may need protection ({}) to be used inside
'if's
2017-06-01 17:22:33 -03:00
Roberto Ierusalimschy 4bc33d64de avoid overflows in computation of step size 2017-06-01 16:16:34 -03:00
Roberto Ierusalimschy 8821746841 updated GC states in function 'T.gcstate' 2017-05-31 15:54:58 -03:00
Roberto Ierusalimschy 72d82a296c revamping the incremental collector
Some simplifications (not counting bytes, couting only slots visited;
no more 'gcfinnum'); more GC parameters; using vararg in 'lua_gc' to
set parameters in different GC modes
2017-05-26 16:14:29 -03:00
Roberto Ierusalimschy 4804bbd9bb include first standard header files
(Some broken compiler has problems with 'signal.h' being included
without a definition for 'size_t'.)
2017-05-24 18:11:19 -03:00
Roberto Ierusalimschy be0d951be8 bug: cannot reuse a dying upvalue 2017-05-24 15:54:54 -03:00
Roberto Ierusalimschy a9dbc2d641 assert removed in 'luaO_arith'
(nobody calls it with L==NULL)
2017-05-24 10:47:11 -03:00
Roberto Ierusalimschy c25380c28d details (using proper version of 'setobj') 2017-05-23 09:50:11 -03:00
Roberto Ierusalimschy 03094da80c detail (extra closing brackets) 2017-05-22 09:55:16 -03:00
Roberto Ierusalimschy 01c96ad12e handling of inf, -inf, and NaN by string.format'%q' 2017-05-19 13:29:40 -03:00
Roberto Ierusalimschy 1bdc328c75 bug: Lua crashes when building sequences with more than 2^30 elements.
bug: Table length computation overflows for sequences larger than
2^31 elements..
2017-05-19 09:58:40 -03:00
Roberto Ierusalimschy e3d52da144 BUG: in 'computesizes', 'twotoi' overflows when a sequence has
more than 2^30 elements.
2017-05-19 09:57:10 -03:00
Roberto Ierusalimschy e39ee2cc58 'luaH_getn' must return 'lua_Unsigned' (or 'lua_Integer'), to
allow the boundary-search algorithm to use 'maxinteger' when
it cannot find a good upper bound.
2017-05-19 09:48:15 -03:00
Roberto Ierusalimschy 84910e04e2 better implementation for 'hash_search', without using 'size_t'
(simpler to implement and to explain)
2017-05-19 09:47:00 -03:00
Roberto Ierusalimschy de74289049 table field names for dedicated opcodes can be restricted to
small strings for slightly faster access
2017-05-18 16:44:19 -03:00
Roberto Ierusalimschy 92b3deaffa details in OP_CALL + comments 2017-05-18 16:34:39 -03:00
Roberto Ierusalimschy 49f7aab62a 'lua_rawlen' returns 'lua_Unsigned' instead of 'size_t'. (Real
length of strings and userdata are limited by Lua integers,
but table length is hard to compute limiting it to 'size_t'.)
2017-05-18 09:34:58 -03:00
Roberto Ierusalimschy 3d879fbc5d reimplementation of 'luaH_getn', trying to handle numeric limits
properly.
2017-05-16 16:07:08 -03:00
Roberto Ierusalimschy 6d95de83c6 no more field 'base' in CallInfo (base is always equal to 'func + 1',
with old/new vararg implementation)
2017-05-13 10:54:47 -03:00
Roberto Ierusalimschy 5c8770f896 back to old-style vararg system (with vararg table collecting extra
arguments)
2017-05-13 10:04:33 -03:00
Roberto Ierusalimschy 7647d5d13d revamp of fast track for table access (table set uses the same
macros as table get + new macro for integer keys)
2017-05-11 15:57:46 -03:00
Roberto Ierusalimschy 7184f6343a more integer fast tracks (for OP_LT, OP_LE, OP_SETTABLE, and OP_GETTABLE) 2017-05-10 14:32:19 -03:00
Roberto Ierusalimschy b1b7790f7c detail ('1' -> '1u' in unsigned operation) 2017-05-09 11:39:46 -03:00
Roberto Ierusalimschy ab5a650029 details (direct access to 'Ck' bit in instructions) 2017-05-08 13:08:01 -03:00
Roberto Ierusalimschy fb9de1b4d7 detail ('luaT_callbinTM' does not need to be extern) 2017-05-08 12:57:23 -03:00
Roberto Ierusalimschy e8757a73e6 'luaV_execute' keeps local copy of program counter and hook mask,
to avoid excessive access to globals.
2017-05-05 14:16:11 -03:00
Roberto Ierusalimschy 4ce8d2047c bug: Wrong code for a goto followed by a label inside an 'if' 2017-05-05 12:55:36 -03:00
Roberto Ierusalimschy 2376eb6347 barrier for prototype's cache (with new gray list 'protogray' to keep
prototypes to have their caches visited again) + constant 'MAXMISS'
2017-05-04 10:32:01 -03:00
Roberto Ierusalimschy 8634b2a011 added 'cachemiss' field to prototype to avoid wasting time checking
hits that fail too often
2017-04-30 17:43:26 -03:00
Roberto Ierusalimschy 5ecb31003f bug: cannot "skip" labels after if-goto before the jump over the
'then' part
2017-04-29 15:09:17 -03:00
Roberto Ierusalimschy a454e884e0 details in 'findsetreg' 2017-04-29 12:28:38 -03:00
Roberto Ierusalimschy 502a1d1108 new opcodes for table access with constant keys (strings and integers) 2017-04-28 17:57:45 -03:00
Roberto Ierusalimschy 173e41b2eb new opcode OP_ADDI (for immediate integer operand) (Experimental) 2017-04-26 14:46:52 -03:00
Roberto Ierusalimschy a3f9c1a77a detail (using unsigned comparison in range check for LOADI) 2017-04-25 17:01:14 -03:00
Roberto Ierusalimschy 6dbae1b5d9 registers in a VINDEXED expression must be freed in order 2017-04-25 15:28:25 -03:00
Roberto Ierusalimschy cb3d5dce30 opcodes 'OP_GETTABUP'/'OP_SETTABUP' operate only with string keys,
so they can use fast-track table access
2017-04-24 17:26:39 -03:00
Roberto Ierusalimschy 2caecf1b3e type 'L_Umaxalign' replaced by macro 'LUAI_MAXALIGN', which is also added
to the auxlib buffer
2017-04-24 15:06:12 -03:00
Roberto Ierusalimschy f399e6705f ensures that "collectgarbage'step'" in generational mode does a
minor collection
2017-04-24 14:52:18 -03:00
Roberto Ierusalimschy 69371c4b84 'KGC_NORMAL' -> 'KGC_INC' + emergency GC signalled by flag (instead
of mode)
2017-04-24 13:59:26 -03:00
Roberto Ierusalimschy 6a98aa0bb0 new opcode LOADI (for loading immediate integers) 2017-04-20 16:53:55 -03:00
Roberto Ierusalimschy c354211744 small bug in generational control 2017-04-20 15:24:33 -03:00
Roberto Ierusalimschy f748b4bb40 macros to define default parameters for generational collection 2017-04-20 15:22:44 -03:00
Roberto Ierusalimschy 7ae180f8e8 corrected some checks about colors of old objects + new test function
'gcage'
2017-04-19 15:46:47 -03:00
Roberto Ierusalimschy c7bdc0e0e8 first version of control for the generational collector 2017-04-19 14:02:50 -03:00
Roberto Ierusalimschy a45945b6d5 new macro 'lua_pointer2str' to encapsulate use of 'l_sprintf' inside
the kernel
2017-04-19 13:34:35 -03:00
Roberto Ierusalimschy 9e1f1b1f62 detail in usage message for '-l' option 2017-04-19 09:49:17 -03:00
Roberto Ierusalimschy 4679294796 memory check adapted to generational mode 2017-04-18 16:42:12 -03:00
Roberto Ierusalimschy f74b87c3c2 removed initialization of 'GCestimate' (it is initialized during
a GC cycle, when it start counting)
2017-04-12 15:56:25 -03:00
Roberto Ierusalimschy 16001acb15 small corrections + removal of debugging functions 'count' and
'printgray'.
2017-04-12 15:01:40 -03:00
Roberto Ierusalimschy 0c8a7e071b 'mainthread' lives in 'allgc' list, like everybody else 2017-04-11 16:00:27 -03:00
Roberto Ierusalimschy a3d36fe283 Upvalues collected like everything else (with mark-sweep) instead
of reference count (simpler and better for generational mode)
2017-04-11 15:41:09 -03:00
Roberto Ierusalimschy 9569ad6b0d Comments for generational collector 2017-04-10 10:33:04 -03:00
Roberto Ierusalimschy 2331e1beec small changes in 'luaC_upvalbarrier' 2017-04-06 10:08:56 -03:00
Roberto Ierusalimschy e4287da3a6 generational collector (still not complete) 2017-04-05 13:50:51 -03:00
Roberto Ierusalimschy 1a1b2f3d7f added 'return' to calls to 'luaL_error' (to signal to the compiler
that the function cannot continue past that call)
2017-03-14 09:40:44 -03:00
Roberto Ierusalimschy f5f3df3bd1 generational collection: new attempt (still incomplete) 2017-02-23 18:07:34 -03:00
Roberto Ierusalimschy e6c1e6005a comments about gray lists 2017-02-15 16:52:13 -02:00
Roberto Ierusalimschy d266d40dea error when calling close method without arguments (e.g.,
|io.stdin.close()|)
2017-02-09 12:50:05 -02:00
Roberto Ierusalimschy e354c6355e small updates 2017-01-31 19:17:47 -02:00
Roberto Ierusalimschy 94c1b3a8ee Handling of LUA_PATH/LUA_CPATH moved back to 'package' library
to avoid incompatibilites with previous releases
2017-01-12 15:14:26 -02:00
Roberto Ierusalimschy 08199ade4a release 5.3.4 (year 2017) 2016-12-22 13:51:20 -02:00
Roberto Ierusalimschy 2a235312f0 detail (removing spaces at end of lines) 2016-12-22 11:08:50 -02:00
Roberto Ierusalimschy 9903dd52a3 Using LUAI_UAC* types more consistently on vararg calls 2016-12-20 16:37:00 -02:00
Roberto Ierusalimschy 24f6e236a3 'moveresults' and 'luaD_poscall' moved up in the file 2016-12-13 13:52:21 -02:00
Roberto Ierusalimschy 9f594ca6f5 LUA_PATHSUFFIX -> LUA_VERSUFFIX + LUA_VERSUFFIX used in the
definition of LUA_INITVARVERSION, too.
2016-12-13 13:50:58 -02:00
Roberto Ierusalimschy 4df4560bf5 detail (wrong comment) 2016-12-06 12:54:31 -02:00
Roberto Ierusalimschy b2aa2ba046 using constants for "_LOADED" and "PRELOAD" 2016-12-04 18:17:24 -02:00
Roberto Ierusalimschy beec5af201 'luaL_tolstring' uses metatable's "__name" when available 2016-12-04 18:09:45 -02:00
Roberto Ierusalimschy 7b1fba69b7 using 'lastfree == NULL' to signal that table is using the dummy
node for its hash part + new macro 'allocsizenode'
2016-11-07 10:38:35 -02:00
Roberto Ierusalimschy 697593d8d5 bug: When a coroutine tries to resume a non-suspended coroutine,
it can do some mess (and break C assertions) before detecting the error.
2016-10-19 10:34:27 -02:00
Roberto Ierusalimschy e2dc807c6e check whether function is finalizer when finding a name for it +
comments + some instructions can call functions in unespected ways
(e.g., finalizers)
2016-10-19 10:32:10 -02:00
Roberto Ierusalimschy 138d00176c new flag in 'CallInfo.callstatus' to tell whether function is running
as a finalizer
2016-10-19 10:31:42 -02:00
Roberto Ierusalimschy 8edbf57fb8 detail (ANSI C does not accept empty arguments to macros) 2016-09-20 13:37:45 -03:00
Roberto Ierusalimschy 7fe1a4cff3 cleaner and more correct code for 'luaD_shrinkstack' (the old
test "inuse <= LUAI_MAXSTACK" for stack overflow is not correct,
as the real maximum usable size is "LUAI_MAXSTACK - EXTRA_STACK")
2016-09-08 13:36:26 -03:00
Roberto Ierusalimschy dbb6f11e8e bug (with compat on): 'ipairs' can work with any type that provides
an __index; so, 'pairsmeta' should not check for tables. ('pairs'
already checks for tables through 'next'.)
2016-09-05 16:06:34 -03:00
Roberto Ierusalimschy aeb4c6fff1 comments + removed unused variable 2016-09-05 15:53:02 -03:00
Roberto Ierusalimschy 3b91b07fd9 detail (macro 'l_checkmode' reimplemented as function) 2016-09-01 13:14:56 -03:00
Roberto Ierusalimschy 349badabc1 wrong test in '#if' for floating-point type 2016-08-22 14:21:12 -03:00
Roberto Ierusalimschy e4a9e6fcca do not eliminate varargs from functions that do not use varargs
(confuses the debug lib and gains very little in performance)
2016-08-01 16:51:24 -03:00
Roberto Ierusalimschy 9de2bb0d62 bug: When a coroutine tries to resume a non-suspended coroutine,
it coud do some mess (and break C assertions) before detecting the error.
Now it tests for those errors before anything else.
2016-07-29 14:12:44 -03:00
Roberto Ierusalimschy d55fd3455b redefine MAXINDEXRK (for debugging, to force most values to
go through registers)
2016-07-19 14:13:00 -03:00
Roberto Ierusalimschy 0d1c6f4188 MAXINDEXRK can be redefined (for debugging, to force most values to
go through registers)
2016-07-19 14:12:21 -03:00
Roberto Ierusalimschy fc6b32bcaa bug: Lua can generate wrong code in functions with too many constants 2016-07-19 14:12:07 -03:00
Roberto Ierusalimschy de96e26afc bug: 'checkoption' could read past end of string + 'os.date' can
handle embedded zeros
2016-07-18 14:58:58 -03:00
Roberto Ierusalimschy de3fd8ab83 Handling of LUA_PATH/LUA_CPATH moved from package library to stand
alone interpreter (so that 'lua.c' concentrates all handling of
environment variables)
2016-07-18 14:55:59 -03:00
Roberto Ierusalimschy 788109a3de new bug: Checking a format for 'os.date' may read pass the format string 2016-07-15 14:24:09 -03:00
Roberto Ierusalimschy 09c9fa36ea small corrections for C++ compliance 2016-06-27 10:15:08 -03:00
Roberto Ierusalimschy dcb2998aa6 bug: expression list with four or more expressions in
a 'for' loop can crash the interpreter. ('adjust_assign' must
remove extra expresssions from its registers.)
2016-06-22 12:48:25 -03:00
Roberto Ierusalimschy fac00ca023 bug: expression list with four or more expressions in
a 'for' loop can crash the interpreter.
2016-06-21 14:22:34 -03:00
Roberto Ierusalimschy 6487fb11fc all 'static' variables should be 'const' 2016-06-20 16:12:46 -03:00
Roberto Ierusalimschy 644799537f allow more bits in 'callstatus' (use no extra space due to alignments) 2016-06-16 10:36:09 -03:00
Roberto Ierusalimschy aa66ca76ce 'lua_pushglobaltable' returns 'void' 2016-05-30 12:53:28 -03:00
Roberto Ierusalimschy 707b0ba6e2 'string.format("%q")' writes 'math.mininteger' in hexa, to ensure
it is read back as an integer
2016-05-20 11:13:21 -03:00
Roberto Ierusalimschy 10b0b09555 do not convert decimal constants with overflow to integers.
(Therefore, they will be converted as floats)
2016-05-20 11:07:48 -03:00
Roberto Ierusalimschy 4d5ab9baa6 'string.pack("cn")' does not accept strings longer than 'n' 2016-05-18 15:19:51 -03:00
Roberto Ierusalimschy b65252b39b 'singlevaraux' returns result only in 'var->k' 2016-05-13 16:10:16 -03:00
Roberto Ierusalimschy fbd8614bdb comment (FALLTHROUGH) 2016-05-13 16:09:46 -03:00
Roberto Ierusalimschy f3b52a6061 'io.read("n")' accepts both a dot and the locale point as its
radix character + 'MAXRN' -> 'L_MAXLENNUM' + small detail in
'test2'
2016-05-02 11:03:19 -03:00
Roberto Ierusalimschy 0232fbffbe now that 'luaO_str2num' always accepts a dot as a radix character,
the lexer does not need to bother with this issue.
2016-05-02 11:02:12 -03:00
Roberto Ierusalimschy ed110f66c5 'luaO_str2num' (and, therefore, 'lua_stringtonumber', 'number',
and coercions) accepts both the locale point and a dot as its
radix character
2016-05-02 11:00:32 -03:00
Roberto Ierusalimschy 22093f9c6e 'string.format("%q", number)' ensures a dot as decimal point 2016-05-02 10:58:01 -03:00
Roberto Ierusalimschy 792ffaccf2 detail (macro should "use" all its arguments) 2016-05-01 17:06:09 -03:00
Roberto Ierusalimschy 57cdb60429 no more time limits to pattern matching (at least for now) 2016-04-22 13:36:30 -03:00
Roberto Ierusalimschy 89c09c8e40 match time limit defined by variable 'string.pattlimit' 2016-04-19 09:34:08 -03:00
Roberto Ierusalimschy 48baa5e89c 'os.time(t)' normalizes 't' fields 2016-04-18 10:06:55 -03:00
Roberto Ierusalimschy fdd7209688 error handling in 'wrap' does not coerce numbers into string messages 2016-04-11 16:19:55 -03:00
Roberto Ierusalimschy 82a8e06524 details ('error' does not coerce numbers to strings + comments) 2016-04-11 16:18:40 -03:00
Roberto Ierusalimschy c258870c59 diff for last bug was against wrong version 2016-04-11 12:34:21 -03:00
Roberto Ierusalimschy e8e39a277f 'string.format"%q"' now works for all basic types (nil, boolean,
numbers, and strings)
2016-04-08 18:15:02 -03:00
Roberto Ierusalimschy fff7d42a69 LUA_PACKPADBYTE -> LUAL_PACKPADBYTE (it is an internal library
name, not something to be usually configured)
2016-04-07 12:40:07 -03:00
Roberto Ierusalimschy 783aa8a9da new way to avoid infinite loops in empty matches: "Python rule"
("Empty matches for the pattern are replaced only when not
adjacent to a previous match")
2016-03-31 16:07:42 -03:00
Roberto Ierusalimschy 8d4feb504f do not try to ensure that 'sweepgc' points to a live object
when entering sweep phase ('entersweep'); that may be too
expensive to be done still inside the atomic step. Walking
one single object more often than not will work.
2016-03-31 16:02:03 -03:00
Roberto Ierusalimschy d77a7a8c26 detail (comment) 2016-03-31 16:01:21 -03:00
Roberto Ierusalimschy e747491b96 comments 2016-03-23 15:08:26 -03:00
Roberto Ierusalimschy acff3ad88d bug: 'gmatch' iterator fails when called from a coroutine different
from the one that created it
2016-03-23 14:12:17 -03:00
Roberto Ierusalimschy e7b2e01d43 bug: label between local definitions can mix-up their initializations 2016-03-07 16:25:39 -03:00
Roberto Ierusalimschy 03ca6385dc call 'checkGC' *after* creating new objects (this is how 'execute'
does it)
(It increases the changes that 'allgc' start with a non-white
object, which helps 'entersweep')
2016-02-29 11:27:14 -03:00
Roberto Ierusalimschy 7777b412de When available, use metafield '__name' in error messages 2016-02-26 16:20:15 -03:00
Roberto Ierusalimschy c3e9b14d24 '\0' is a control character, no need to check it explicitly 2016-02-25 16:42:55 -03:00
Roberto Ierusalimschy 7d6b78ee79 in 'table.move', destination table can be source table even if
given as an explicit extra argument
2016-02-25 16:41:54 -03:00
Roberto Ierusalimschy 5f3ad5731e simpler yet definition for 'checkoption' 2016-02-09 10:16:11 -02:00
Roberto Ierusalimschy 494e9ba0f4 simpler code for 'checkoption' + added conversion specifiers specific
to Windows
2016-02-08 12:42:46 -02:00
Roberto Ierusalimschy f79b4568ae details (removed silly use of 'luaL_opt' + better error messages
in cases of "table expected")
2016-02-08 10:55:19 -02:00
Roberto Ierusalimschy fd51651684 new macro 'vmfetch' to help changing code to computed goto's (macro
abstracts the code to run before each instruction)
2016-02-05 17:59:14 -02:00
Roberto Ierusalimschy 994374c4df new release number + new year 2016-01-13 15:55:19 -02:00
Roberto Ierusalimschy 62f6652d53 no more extra space in 'luaL_checkstack'. (It was already useless
for the first call, and function works ok without that space
anyway (just error message misses the 'msg' component)
2016-01-08 13:33:09 -02:00
Roberto Ierusalimschy 9945253d57 details (comments + text of error messages) 2016-01-06 11:43:05 -02:00
Roberto Ierusalimschy 1f259be52a 'getcode' -> 'getinstruction' 2016-01-05 14:22:37 -02:00
Roberto Ierusalimschy 1a44e82200 'luaV_fastget' only treats the real fast case (table with a non-nil
value at given key, so that it does not need to check metamethods)
2016-01-05 14:07:21 -02:00
Roberto Ierusalimschy a272fa66f0 bug: Metatable may access its own dealocated field when
it has a self reference in __newindex + some refactoring
2016-01-04 14:44:50 -02:00
Roberto Ierusalimschy b12b635a90 more refactoring 2016-01-04 11:40:57 -02:00
Roberto Ierusalimschy 7cd7c2e0a1 Metatable may access its own dealocated field when
it has a self reference in __newindex.
2016-01-04 11:35:56 -02:00
Roberto Ierusalimschy 07cf8415e3 more comments + reordeing of union inside 'expdesc' to allow
static initialization of a VKINT value
2015-12-30 16:16:13 -02:00
Roberto Ierusalimschy c0836dda74 avoid empty macro arguments (invalid in C89) 2015-12-21 11:02:14 -02:00
Roberto Ierusalimschy 384d1b47b0 comments (*lots* of them) + asserts 2015-12-18 11:53:36 -02:00
Roberto Ierusalimschy 19770b03a9 comments. (More explanation about kinds of expressions.) 2015-12-17 13:44:50 -02:00
Roberto Ierusalimschy a01eba657e reordering of some functions + 'code_label' renamed to 'code_loadbool' 2015-12-17 13:02:44 -02:00
Roberto Ierusalimschy b7446ea88d detail ('while' -> 'for') in 'luaK_patchclose' 2015-12-17 12:52:53 -02:00
Roberto Ierusalimschy a051b3323e comments (about hooks vs signals) 2015-12-16 14:40:07 -02:00
Roberto Ierusalimschy c4e01c568a make 'hook' volatile (as it may be changed in signal handling) 2015-12-16 14:39:38 -02:00
Roberto Ierusalimschy bda090b961 comments + small code changes around stack usage when 'luaL_checkstack'
raises an error (and needs the stack to create the error message...)
2015-12-14 09:59:27 -02:00
Roberto Ierusalimschy e383941652 in 'table.sort': 'typedef' for type of indices + removed stack check
(recursion is in the C stack, not in the Lua stack!)
2015-12-14 09:57:38 -02:00
Roberto Ierusalimschy 656b3cea1b using 'sig_atomic_t' for 'hookmask' (as it can be changed inside
a signal)
2015-12-14 09:54:49 -02:00
Roberto Ierusalimschy 2d1d57bc18 comments 2015-12-14 09:53:27 -02:00
Roberto Ierusalimschy 03412af06e detail (removed fixed argument to function 'callallpendingfinalizers') 2015-12-10 16:12:30 -02:00
Roberto Ierusalimschy 542dbd4c65 detail (moving bodies of 'while' to a separate line) 2015-12-09 13:21:28 -02:00
Roberto Ierusalimschy c25d59a6bd format "%s" in 'string.format' accepts embedded zeros when it
has no modifiers
2015-11-25 14:28:17 -02:00
Roberto Ierusalimschy 5936eb16d8 randomness in 'table.sort' used only when needed (big imbalance in
partition result) + small refactoring
2015-11-25 10:48:57 -02:00
Roberto Ierusalimschy 7dc3ca7b8e handling 'clock_t' and 'time_t' correctly in ISO C point of view 2015-11-24 14:54:32 -02:00
Roberto Ierusalimschy 71344b5cac easy the way to accept other modifiers for 'mode' in 'io.open' 2015-11-23 09:36:11 -02:00
Roberto Ierusalimschy f230898ad6 tiny code refactoring in 'luaS_hash' 2015-11-23 09:32:51 -02:00
Roberto Ierusalimschy 3feb702df8 ensure argument to 'string.format("%s")' does not contain zeros 2015-11-23 09:31:21 -02:00
Roberto Ierusalimschy c5112f7b15 details (comments) 2015-11-23 09:30:45 -02:00
Roberto Ierusalimschy c231a5e2b6 using unsigned int (instead of int) in 'table.sort' to avoid overflows
(when computing the pivot and in original table size)
2015-11-23 09:17:31 -02:00
Roberto Ierusalimschy dc9ac5b8c2 details (merging declarations with initialization) 2015-11-23 09:09:27 -02:00
Roberto Ierusalimschy 146508b28e randomness in pivot for 'table.sort' done by a macro (easier to change) 2015-11-20 10:30:20 -02:00
Roberto Ierusalimschy d103312661 details (typos in comments) 2015-11-19 17:16:22 -02:00
Roberto Ierusalimschy 2e8f8a18e4 detail 2015-11-17 14:00:28 -02:00
Roberto Ierusalimschy f5b0459aba details 2015-11-13 15:19:46 -02:00
Roberto Ierusalimschy d682b3c9ec added separator for bugs in 5.3.1 2015-11-13 15:19:07 -02:00
Roberto Ierusalimschy fc085aa627 new release number (5.3.2) 2015-11-13 15:18:42 -02:00
Roberto Ierusalimschy 9a5d6aedb7 trying to optimize a little 'luaD_poscall' 2015-11-13 11:24:26 -02:00
Roberto Ierusalimschy 89e3a84344 removed field 'n' from 'CallInfo' (not being used right now) 2015-11-13 10:16:51 -02:00
Roberto Ierusalimschy 04587b6256 macro with empty argument can be seen as macro with no argument; better
to avoid that
2015-11-12 16:08:58 -02:00
Roberto Ierusalimschy bde03eeb48 in 'table.sort': tighter checks for invalid order function +
"random" pivot for larger intervals (to avoid attacks with
bad data)
2015-11-12 16:07:25 -02:00
Roberto Ierusalimschy 330d426ffd avoid the use of deprecated functions 'luaL_checkunsigned'/
'lua_pushunsigned'
2015-11-11 17:08:09 -02:00
Roberto Ierusalimschy 02340375be janitor work on 'table.sort': added comments, partition code moved
to a separated function, code conventions updated, etc. No changes
at all in the logic/algorithm
2015-11-06 14:07:14 -02:00
Roberto Ierusalimschy 5100bc8aa1 no need for a special case to get long strings (not that common) 2015-11-03 16:35:21 -02:00
Roberto Ierusalimschy ebb2afa54b allow 'set' macros to be used when 'L' is not available (as it was
needed only for assertions)
2015-11-03 16:33:10 -02:00
Roberto Ierusalimschy 7485512384 added comment and assert about dead keys 2015-11-03 16:10:44 -02:00
Roberto Ierusalimschy 46de77b219 bug: despite its name, 'luaH_getstr' did not work for strings in
general, but only for short strings
2015-11-03 13:47:30 -02:00
Roberto Ierusalimschy d356183402 new function 'luaS_hashlongstr' 2015-11-03 13:36:01 -02:00
Roberto Ierusalimschy e61ee8a036 in 'luaD_call', use two functions instead of one with fixed boolean
argument + stack error handling in 'luaD_call' moved to a separated
function
2015-11-02 16:48:49 -02:00
Roberto Ierusalimschy ff1289a361 in 'luaD_call', use two functions instead of one with fixed boolean
argument
2015-11-02 16:48:07 -02:00
Roberto Ierusalimschy cd73f3ccc5 now that we have a counter for CallInfos, use it for a more
accurate value for the memory used by a thread
2015-11-02 14:19:29 -02:00
Roberto Ierusalimschy 8c1fb91802 macro 'incr_top' replaced by function 'luaD_inctop'. (It is not used
in critical time pathes, can save a few bytes without the macro)
2015-11-02 14:09:30 -02:00
Roberto Ierusalimschy 33b366ec32 added counters for total and individual CallInfo entries (to allow
better syncronization between CallInfo size and stack size)
2015-11-02 14:01:41 -02:00
Roberto Ierusalimschy c5363a1b58 in 'luaD_precall', in vararg functions, complete missing parameters
only after moving them to final place (avoids checking the stack
again)
2015-11-02 12:06:01 -02:00
Roberto Ierusalimschy 332a06bbd1 'luaO_pushvfstring' now uses 'incr_top' to increment top. 2015-11-02 12:02:35 -02:00
Roberto Ierusalimschy ffd0d1232d using more "conventional" loops in 'luaD_poscall' (probably a little
more efficient?)
2015-11-02 09:48:59 -02:00
Roberto Ierusalimschy 07a2dcacbf flag CIST_REENTRY changed to CIST_FRESH (its negation); fresh invocations
seem to be less frequent than reentries. (So, avoid setting flag on
the frequent case.)
2015-11-02 09:43:17 -02:00
Roberto Ierusalimschy c874abac98 with 'fast tracks', there is no need to do raw accesses in 'ipairs' 2015-10-29 13:21:04 -02:00
Roberto Ierusalimschy 789e423b32 corrected comparisons of signed (int) with unsigned (size_t) 2015-10-29 13:11:41 -02:00
Roberto Ierusalimschy 96ec8671b1 macro 'buff2num' replaced by its body (it caused more harm than good
to readability)
2015-10-28 16:51:47 -02:00
Roberto Ierusalimschy cc3a42b190 option 'c' in 'string.pack' accepts any string size (truncating
if larger and padding if smaller)
2015-10-28 15:56:51 -02:00
Roberto Ierusalimschy 6707ce6349 function prepares vararg only if it really uses them (chunks
are always declared vararg but seldom uses them)
2015-10-28 15:28:40 -02:00
Roberto Ierusalimschy 257961c601 OP_SELF can use 'luaV_fastget' specialized for strings, as it
is applied only to string keys
2015-10-28 12:50:09 -02:00
Roberto Ierusalimschy ae515a346c comments for luaD_precall/luaD_poscall 2015-10-28 10:25:36 -02:00
Roberto Ierusalimschy 3cdf1d676b details (avoid 'case' inside block + avoid using one variable for
two roles)
2015-10-28 10:06:45 -02:00
Roberto Ierusalimschy 82129b9266 use macro 'hasjumps' to test whether expression has jumps... 2015-10-26 12:27:47 -02:00
Roberto Ierusalimschy 8004ab756f hook test in 'luaV_execute' reduced to minimum (rest done in
'luaG_traceexec'; no difference in performance for the non-hook
case, but keeps 'luaV_execute' a little simpler) + 'base' updates
replaced by 'Protect' (which serves this rule)
2015-10-22 12:40:47 -02:00
Roberto Ierusalimschy ee5ef0f295 hook test in 'luaV_execute' reduced to minimum (rest done in
'luaG_traceexec'
2015-10-22 12:40:47 -02:00
Roberto Ierusalimschy 5bdee4f810 small changes to allow 'precall' to spend time preserving 'func'
only when needed (that is, when stack actually changes)
2015-10-21 16:40:47 -02:00
Roberto Ierusalimschy 48098c42ff generic definitions for float types moved to before variable definitions
(so that specific cases can redefine these generic definitions if
needed)
2015-10-21 16:17:40 -02:00
Roberto Ierusalimschy 3ad55386c4 'condchangemem' also may need to run 'pre'/'pos' 2015-10-21 16:15:15 -02:00
Roberto Ierusalimschy caf8278710 added comments 2015-10-20 16:00:19 -02:00
Roberto Ierusalimschy f7670781cf cleaner definition for 'luaC_condGC', using 'pre'/'pos' parameters 2015-10-20 15:56:21 -02:00
Roberto Ierusalimschy df8b996bcc 'Protect' in table operations is not needed in the fast track
+ removal of a few dead macros
2015-10-20 15:41:35 -02:00
Roberto Ierusalimschy 75d5a8924c macro 'addbuff' was using external variable name, instead of using
its parameter name inside the macro.
2015-10-20 11:11:05 -02:00
Roberto Ierusalimschy 880f82d089 '*' as a number means stack size, so that "return *" returns
all values in the stack.
2015-10-12 13:38:19 -03:00
Roberto Ierusalimschy 1a741157cb avoid (undefined behavior) integer 'overflow' in left shift 2015-10-08 12:55:35 -03:00
Roberto Ierusalimschy 0c78de0d6d avoid calling write function with empty block 2015-10-08 12:53:49 -03:00
Roberto Ierusalimschy df45f7118b detail (added assertion) 2015-10-08 12:53:31 -03:00
Roberto Ierusalimschy 880df57e52 detail (removed unreacheable 'break') 2015-10-08 12:53:05 -03:00
Roberto Ierusalimschy 8949904783 allow NULL string when length is zero in 'lua_pushlstring' and
'luaL_addlstring'
2015-10-06 13:10:22 -03:00
Roberto Ierusalimschy 9294466234 detail (string cache a bit smaller by default) 2015-10-06 11:29:49 -03:00
Roberto Ierusalimschy e290bd6760 in 'luaL_traceback', print correct number of levels even when
initial level is not 1.
2015-10-02 12:46:49 -03:00
Roberto Ierusalimschy dc4232379d detail (ensure subtraction is done unsigned) 2015-10-02 12:39:23 -03:00
Roberto Ierusalimschy 10fffcd80a 'gmatch' keeps its state in a userdata (keeping the same 'MatchState'
across calls)
2015-09-28 15:05:01 -03:00
Roberto Ierusalimschy 8264dbc2bb implemented counter to abort non-linear behavior in pattern matching 2015-09-26 15:45:03 -03:00
Roberto Ierusalimschy 9fae7b6d3f code for string cache generalized for "associative sets" (compiler
will optimize away or inline the extra loops)
2015-09-22 11:18:24 -03:00
Roberto Ierusalimschy 0f1f51be4b 'table.move' tries to copy elements in increasing order
whenever possible
2015-09-17 12:53:50 -03:00
Roberto Ierusalimschy ee5edb6b68 macros 'getaddrstr' and 'getstr' unified (they do the same thing) 2015-09-17 12:51:05 -03:00
Roberto Ierusalimschy bda83e22c0 'tablib' does not try to use raw operations when possible: fast
track should make standard operations fast enough to forgo
raw accesses
2015-09-09 12:42:30 -03:00
Roberto Ierusalimschy 364cdbdbdb 'setobj2t' incorporated into 'luaV_fastset' + 'invalidateTMcache'
is not needed in the fast track (as it does not create new
entries) + small bug in 'auxsetstr' (calling barrier with wrong
object) + using 'setobj2t' without side effects in its arguments
2015-09-09 10:45:50 -03:00
Roberto Ierusalimschy b91bc93fd3 'setobj2t' incorporated into 'luaV_fastset' + 'invalidateTMcache'
is not needed in the fast track (as it does not create new
entries)
2015-09-09 10:44:07 -03:00
Roberto Ierusalimschy 53be1451a8 new definition for macro 'checkliveness' 2015-09-08 13:55:43 -03:00
Roberto Ierusalimschy eb0be12ceb detail in macro 'checkliveness' + macro 'setobj2t' defined as an
expression (to be used in macro 'luaV_fastset')
2015-09-08 13:54:52 -03:00
Roberto Ierusalimschy 1198d82530 'lua_longassert' defined as an expression (instead of a command) 2015-09-08 13:53:56 -03:00
Roberto Ierusalimschy 6556fcfe5a small janitor work 2015-09-08 12:49:25 -03:00
Roberto Ierusalimschy 41964648ee long strings are created directly in final position when possible
(instead of using an auxiliar buffer to first create the string
and then allocate the final string and copy result there)
2015-09-08 12:41:05 -03:00
Roberto Ierusalimschy 502214f8a5 added assert for NULL pointer in 'lua_pushlstring' 2015-08-25 15:50:37 -03:00
Roberto Ierusalimschy ed19fe766c added ';' at the end of "expression lines" ("return exp;") so that
an extra ";" at the end is enough to stop Lua printing the result
("return exp;;" is not valid)
2015-08-14 16:11:20 -03:00
Roberto Ierusalimschy 8f25d08637 'invalidateTMcache' not needed in all 'settable' uses 2015-08-03 17:40:26 -03:00
Roberto Ierusalimschy 3b795541c4 fast track for 'settable' 2015-08-03 16:50:49 -03:00
Roberto Ierusalimschy 20b9e59441 barrier macros rewritten as expressions 2015-08-03 16:40:42 -03:00
Roberto Ierusalimschy 935d9f7f90 new entry should not be commented out 2015-07-23 11:32:17 -03:00
Roberto Ierusalimschy e247c3ada3 implementation of fast track for gettable operations 2015-07-20 15:24:50 -03:00
Roberto Ierusalimschy b5dc2f9b0c bug: 'io.lines' does not check maximum number of options 2015-07-20 13:37:12 -03:00
Roberto Ierusalimschy 5273477cb9 in 'lua_number2strx', use the call to 'l_sprintf' to add exponent
to result directly
2015-07-20 13:30:22 -03:00
Roberto Ierusalimschy b9db9bd0ef 'lua_Number' added to 'L_Umaxalign' union 2015-07-15 12:57:13 -03:00
Roberto Ierusalimschy 050e8536bb bug: 'io.lines' does not check maximum number of options 2015-07-15 11:40:28 -03:00
Roberto Ierusalimschy 2b61360d82 avoid overflows (detected with 'clang -ftrapv') 2015-07-13 10:30:03 -03:00
Roberto Ierusalimschy 5b6ac971f9 detail (comment) 2015-07-07 14:03:34 -03:00
Roberto Ierusalimschy 403e181d81 'strftime' puts its result directly into 'lua_Buffer' 2015-07-06 12:16:51 -03:00
Roberto Ierusalimschy 4af03c5ae1 better treatment for integer overflows + all errors throw an error
(instead of returning nil)
2015-07-04 13:35:14 -03:00
Roberto Ierusalimschy bde17a419d because of debt, 'totalbytes' can be negative (and therefore its
type must be signed)
2015-07-04 13:33:17 -03:00
Roberto Ierusalimschy 8950e0c049 avoid possibility of subtle arith. overflow 2015-07-04 13:32:34 -03:00
Roberto Ierusalimschy 8217e0d4fe avoid subtle possibility of arithmetic overflow 2015-07-04 13:31:42 -03:00
Roberto Ierusalimschy 319ccfefbc computations in numerical for loop must avoid overflows too 2015-07-04 13:31:03 -03:00
Roberto Ierusalimschy 6a8400ba4f using 'clang' by default + changes in warnings ('old-style-declaration'
removed because it is included in 'extra' + 'strict-aliasing' removed
because it is included in 'all' + 'aggregate-return' removed because
no one would do it by mistake)
2015-07-01 14:52:09 -03:00
Roberto Ierusalimschy 2de3361c6c detail 2015-07-01 14:47:12 -03:00
Roberto Ierusalimschy e89763e964 simpler code for 'luaO_fb2int' 2015-06-26 16:32:07 -03:00
Roberto Ierusalimschy be63d995c1 tiny bug: 'randomseed' was calling 'rand' (instead of 'l_rand')
to discard first value
2015-06-26 16:30:32 -03:00
Roberto Ierusalimschy 2b1fc1b38c with string cache, it is not that important for 'type' to avoid
'lua_pushstring'
2015-06-26 16:25:45 -03:00
Roberto Ierusalimschy f01c12c891 detail (cast to avoid mixing types in conditional expression) 2015-06-25 11:00:01 -03:00
Roberto Ierusalimschy 5aabb7a891 buffer size changed from size_t to int (it is always small) +
comments + assert that printf result fits in given buffer
2015-06-24 15:25:10 -03:00
Roberto Ierusalimschy cb1e451999 detail 2015-06-24 15:23:57 -03:00
Roberto Ierusalimschy 43cff79bf7 detail 2015-06-21 10:50:29 -03:00
Roberto Ierusalimschy 95c3144393 redefine 'l_sprintf' to test correctness of buffer sizes given
to 'snprintf'
2015-06-18 11:27:44 -03:00
Roberto Ierusalimschy 19eb6ae580 using 'snprintf' in C99 (both for documentation of buffer sizes
and some complains from tools)
2015-06-18 11:26:05 -03:00
Roberto Ierusalimschy cbe05b48bb using 'lua_longassert' to avoid warnings 2015-06-18 11:25:26 -03:00
Roberto Ierusalimschy e7f34ad395 better implementation for buffers (reallocated memory directly
with allocation function; generates much less garbage)
2015-06-18 11:23:14 -03:00
Roberto Ierusalimschy a5cbb7c3a7 detail (i + 1 > exp is simply i >= exp) 2015-06-18 11:20:32 -03:00
Roberto Ierusalimschy dcad08b76d details (use original type when saving variable's value) 2015-06-18 11:19:52 -03:00
Roberto Ierusalimschy afbf5c5dab missing ']]' in long string 2015-06-18 11:05:28 -03:00
Roberto Ierusalimschy a1415c0d72 bug in order NaN x int (tests must ensure that NaN does not get
converted to integer)
2015-06-09 12:53:35 -03:00
Roberto Ierusalimschy 2ecaf18138 using macros ('rttype' and 'settt_') to access "private" field 'tt_' 2015-06-09 11:21:42 -03:00
Roberto Ierusalimschy cbef15f3ea comment (FALLTHROUGH position) 2015-06-09 11:21:13 -03:00
Roberto Ierusalimschy 16e8bb360b comment 2015-06-09 11:21:00 -03:00
Roberto Ierusalimschy 6628012e9e new release number (5.3.1) 2015-06-03 10:03:38 -03:00
Roberto Ierusalimschy ed1fe28bb8 When comparing integers with floats, use float as common type when
possible (i.e., when integer fits in a float without losses); seems
to be more efficient in architectures with native support for used
Lua numbers
2015-06-02 16:11:24 -03:00
Roberto Ierusalimschy 6645bb2df4 'strcache' elements as arrays of 1 element hints that cache can
be n-way (instead of direct mapped)
2015-06-01 13:34:37 -03:00
Roberto Ierusalimschy 02aed045de bug: return hook may not see correct values for active local variables
when function returns
2015-05-22 16:32:42 -03:00
Roberto Ierusalimschy 72bd2ef6c5 dependencies updated 2015-05-22 16:29:43 -03:00
Roberto Ierusalimschy d39bb51faa bug: interpreter cannot pop activation frame before calling return
hook (as it may want to access local variables active by the end
of the function)
2015-05-22 14:48:19 -03:00
Roberto Ierusalimschy 6142e663e4 reuse of 'addinfo' by lexical errors 2015-05-22 14:45:56 -03:00
Roberto Ierusalimschy 6dc20ff293 'l <= r' for numbers has its own function, instead of using
'not (r < l)' (seems to be slightly more efficient)
2015-05-20 15:19:11 -03:00
Roberto Ierusalimschy 99391e24ea new configuration macro 'l_mathlim' (simplifies some dependencies
on float type)
2015-05-20 14:39:23 -03:00
Roberto Ierusalimschy 0ec12c1bd1 new semantics for numerical order (following math regardless
representation)
2015-05-20 13:22:55 -03:00
Roberto Ierusalimschy a71c0ab861 detail (removed useless '#include') 2015-05-20 13:22:30 -03:00
Roberto Ierusalimschy 04ba6ea83b new semantics for equality int-float 2015-04-29 15:27:16 -03:00
Roberto Ierusalimschy a1935b9cba error message ("too complex" -> "too many registers") + MAXREGS
changed to 255 (no reason not to use maximum allowed)
2015-04-29 15:24:11 -03:00
Roberto Ierusalimschy 513c639bf9 patch for last bug corrected to be against last released version
(and not against last version in RCS...)
2015-04-13 13:13:25 -03:00
Roberto Ierusalimschy 69b5f7a410 some details in 'luaO_int2fb' + more consistent use of the locale
decimal point
2015-04-11 15:30:08 -03:00
Roberto Ierusalimschy ae76c39712 Bug: suspended '__le' metamethod can give wrong result 2015-04-10 14:56:25 -03:00
Roberto Ierusalimschy 0d4a1f71db re-organization of initial configuration options 2015-04-10 14:41:04 -03:00
Roberto Ierusalimschy 67bf789462 avoid using API functions inside the core 2015-04-06 09:23:48 -03:00
Roberto Ierusalimschy 48d0674c2e more consistent use of locale radix character across Lua 2015-04-03 15:41:57 -03:00
Roberto Ierusalimschy 6ffe006f5c detail (removed unused macro VARBITS) 2015-04-02 18:10:53 -03:00
Roberto Ierusalimschy 4998e852ec new function 'log2' to test 'luaO_ceillog2' (if needed) 2015-04-02 18:10:21 -03:00
Roberto Ierusalimschy 65ac789565 detail (comment) 2015-04-02 18:09:51 -03:00
Roberto Ierusalimschy cfc84c856d 'LUA_REAL_*' -> 'LUA_FLOAT_*' (everywhere else we are using 'float') 2015-03-31 09:00:07 -03:00
Roberto Ierusalimschy 63720a4290 janitor work (comments, variable names, some other details) 2015-03-30 16:51:00 -03:00
Roberto Ierusalimschy 484bf14a6b calls to 'luaC_checkGC' in luaD_precall moved near to 'luaD_checkstack'
(which is what can need memory)
2015-03-30 13:05:23 -03:00
Roberto Ierusalimschy abb2f5511d detail ('b + base' -> 'base + b' to follow all other similar uses) 2015-03-30 12:45:01 -03:00
Roberto Ierusalimschy fcc6e1220e avoid expression with side effect (in debug mode) inside 'sizeof' 2015-03-30 12:43:51 -03:00
Roberto Ierusalimschy 3a91274547 details (avoid 'lint' warnings) 2015-03-30 12:42:59 -03:00
Roberto Ierusalimschy f2a813ae10 details (avoid some 'lint' warnings) 2015-03-28 16:16:55 -03:00
Roberto Ierusalimschy e723c75c02 details (avoid 'lint' warnings) 2015-03-28 16:14:47 -03:00
Roberto Ierusalimschy b436ed58a3 'clearapihash' -> 'luaS_clearcache' and moved to 'lstring.c' (which
keeps all code related to this cache)
2015-03-25 10:42:19 -03:00
Roberto Ierusalimschy 2b37f2150e comments 2015-03-14 14:58:57 -03:00
Roberto Ierusalimschy 331632e8d8 code detail ('if' -> '?:') 2015-03-13 13:24:50 -03:00
Roberto Ierusalimschy 7d930ec694 use 'log2' when available 2015-03-12 11:04:04 -03:00
Roberto Ierusalimschy 0cf3b6495a 'ci_func' don't need to be exported 2015-03-11 13:10:41 -03:00
Roberto Ierusalimschy b66fedadae 'lua_pushliteral' implemented with 'lua_pushstring' (to take
advantage of the cache)
2015-03-10 11:17:51 -03:00
Roberto Ierusalimschy fd6e680e21 detail 2015-03-10 11:15:06 -03:00
Roberto Ierusalimschy 57c0db219b line history keep lines without added 'return' 2015-03-09 18:57:05 -03:00
Roberto Ierusalimschy 4ba0cb4580 always use macros to operate on lua_Numbers 2015-03-07 16:30:16 -03:00
Roberto Ierusalimschy a30c66f0fc macro 'luai_apicheck'/'api_check' back with a 'lua_State' parameter
(some people use it)
2015-03-06 16:49:50 -03:00
Roberto Ierusalimschy bb4baa73ea allocation function is not exactly API (and cannot raise errors
like other API functions); better not use 'api_check' for cheking it.
2015-03-06 16:45:54 -03:00
Roberto Ierusalimschy d7d44b038d detail (use 'lua_pushliteral' to push an empty string) 2015-03-06 16:09:08 -03:00
Roberto Ierusalimschy 297512b34c avoid using 'lua_pushliteral' in a non-zero-terminated string 2015-03-05 13:07:46 -03:00
Roberto Ierusalimschy 2ae2e6408e avoid testing for NULL when marking objects that cannot be NULL 2015-03-04 10:51:55 -03:00
Roberto Ierusalimschy a80cada914 new cache for interning strings 2015-03-04 10:31:21 -03:00
Roberto Ierusalimschy a00013c8d0 'point2int' -> 'point2uint' (to reflect its actual result type) 2015-03-03 16:53:13 -03:00
Roberto Ierusalimschy b9a1f27250 do not attempt emergency collection while building state (it is
useless, and state can be inconsistent)
2015-03-03 15:18:29 -03:00
Roberto Ierusalimschy 29aed28802 detail (use 'luaS_newliteral' when possible) 2015-03-03 15:17:04 -03:00
Roberto Ierusalimschy 951b562cf8 configuration for numerical types through only one #define for
each type
2015-03-02 13:59:01 -03:00
Roberto Ierusalimschy 6408bc0b7f new macros 'chgfltvalue'/'chgivalue' (numerical for loop does
not need to set the type of its internal variable at each iteration)
2015-03-02 13:04:52 -03:00
Roberto Ierusalimschy 91efb4b895 LUA_COMPAT_5_1 needs some options deprecated from 5.2 to 5.3 2015-02-28 16:22:31 -03:00
Roberto Ierusalimschy 27c5b1b237 added patches to two bugs 2015-02-23 16:20:43 -03:00
Roberto Ierusalimschy d51bdc166d bug: 'string.format("%f")' can cause a buffer overflow (with long doubles)
bug: 'debug.getlocal' on a coroutine suspended in a hook can crash
the interpreter
2015-02-20 16:21:29 -02:00
Roberto Ierusalimschy 81245b1ad5 'numisinteger' (for table keys) replaced by 'luaV_tointeger' (old
'tointeger_aux'), which can do the same job.
2015-02-20 12:27:53 -02:00
Roberto Ierusalimschy 397ce11996 make 'hashfloat' configurable 2015-02-20 12:05:01 -02:00
Roberto Ierusalimschy 97f2aa5a44 bug: when manipulating other threads, there is no garanties about
their stack space
2015-02-19 15:06:21 -02:00
Roberto Ierusalimschy 419e2cb01d detail (file does not need 'string.h') 2015-02-16 11:15:00 -02:00
Roberto Ierusalimschy 374f6c4612 detail ('fopen' needs 'stdio.h') 2015-02-16 11:14:33 -02:00
Roberto Ierusalimschy 4bdf9962bf bug: suspended function can have its 'func' field not pointing to
its function, crashing debug functions
2015-02-13 14:01:17 -02:00
Roberto Ierusalimschy e0306e386f some changes in 'hashfloat' to avoid undefined (in ISO C) numerical
conversions
2015-02-13 11:05:34 -02:00
Roberto Ierusalimschy 2e6e53c7cc added API checks to some unprotected 'top' increments 2015-02-11 16:47:22 -02:00
Roberto Ierusalimschy 2a57d2346e detail 2015-02-09 16:05:46 -02:00
Roberto Ierusalimschy 7e425be975 bug (in 5.2): Chunk with too many lines can seg. fault 2015-02-09 15:57:45 -02:00
Roberto Ierusalimschy 0705e7b39f detail (no need to write 'double' in source) 2015-02-09 15:41:54 -02:00
Roberto Ierusalimschy 4ccc4578b3 detail (use 'l_floor' instead of 'l_mathop(floor)') 2015-02-09 13:41:56 -02:00
Roberto Ierusalimschy 5e8c162b6c detail 2015-02-05 15:50:24 -02:00
Roberto Ierusalimschy c8d6cb0136 macros 'luai_num*' (for float arithmetic operations) moved to
llimits.h.
2015-02-05 15:15:33 -02:00
Roberto Ierusalimschy 0edcdf49c0 added comments documenting LUA_NOCVTN2S/LUA_NOCVTS2N 2015-02-05 14:53:34 -02:00
Roberto Ierusalimschy b7dfd18612 make buffer for format specification a little larger (length modifier
can be larger than 2, e.g. "I64")
2015-02-04 10:54:31 -02:00
Roberto Ierusalimschy 8efcd411fe own implementation for 'string.format("%a")' for C89 platforms 2015-02-04 10:52:57 -02:00
Roberto Ierusalimschy 90d016980f detail ('luaL_getmetatable' does not return a boolean, but a tag) 2015-02-03 15:38:24 -02:00
Roberto Ierusalimschy b3996c55f6 LUAL_BUFFERSIZE affects the API, so it is better not to change it
between releases of the same version. (The long double case seems
to be too rare, so that should not be a problem; moreover, that
case is related to a bug)
2015-01-16 15:26:56 -02:00
Roberto Ierusalimschy 438a9fcc78 LUAI_MAXSHORTLEN moved from 'luaconf.h' to 'llimits.h' (does not
affect the API and is seldom modified)
2015-01-16 15:15:52 -02:00
Roberto Ierusalimschy 7e2015a46d size of short strings stored in a single byte, to reduce the size
of struct 'TString'
2015-01-16 14:54:37 -02:00
Roberto Ierusalimschy 5b01cb39b5 larger MINSTRTABSIZE (standard Lua starts with ~230 strings, after
oppening the standard libraries)
2015-01-16 13:41:03 -02:00
Roberto Ierusalimschy a0503305bd comments 2015-01-16 11:26:55 -02:00
Roberto Ierusalimschy 965f74525b removed macro LUAI_FIRSTPSEUDOIDX (that stuff does not need
to be configurable)
2015-01-13 17:50:30 -02:00
Roberto Ierusalimschy 3f2e21f0ea Long double needs a larger LUAL_BUFFERSIZE (because
'string.format("%.99f", 1e4900)' can generate quite long strings),
but otherwise buffer can be 1~2K
2015-01-13 15:24:22 -02:00
Roberto Ierusalimschy 3509914916 BUG (when compiled with long double): buffer overflow when formatting
string.format("%.99f", 1e4930)
2015-01-13 15:18:25 -02:00
Roberto Ierusalimschy ae27be40c9 better check for overflows in 'table.move' (removes restriction that
initial position should be positive)
2015-01-13 14:27:29 -02:00
Roberto Ierusalimschy cdd26700e8 definition for 'MAXUPVAL' moved for a more "private" place and its
value and comment corrected to reflect current implementation
2015-01-13 13:49:11 -02:00
Roberto Ierusalimschy a9a4bf68b0 typo in comment 2015-01-13 11:18:04 -02:00
Roberto Ierusalimschy f31cc8e342 typo in error message 2015-01-12 17:32:32 -02:00
Roberto Ierusalimschy 3c55790ebe 'setkey' -> 'setnodekey' (to avoid conflicts with POSIX) 2015-01-05 11:52:37 -02:00
Roberto Ierusalimschy 0adfa773b9 new macro 'cast_func' adds '__extension__' (in gnu compilers) when
converting void* to function, to avoid warnings
2015-01-05 11:51:39 -02:00
Roberto Ierusalimschy 3317f5c6d9 includes 'stddef.h' (as it uses NULL) 2015-01-05 11:48:33 -02:00
Roberto Ierusalimschy dbf911c516 detail (added -Wconversion as a comment, to be used ocasionally) 2015-01-02 11:03:52 -02:00
Roberto Ierusalimschy 3a29087cb7 'lua_setlocal' should not pop value when failing (to be consistent
with the manual and with 'lua_setupvalue')
2015-01-02 10:52:22 -02:00
Roberto Ierusalimschy 234fb7f695 clearer(?) code (also avoids a warning about 'c' being used
without initialization)
2015-01-02 10:50:28 -02:00
Roberto Ierusalimschy c077d47465 does not define _XOPEN_SOURCE when LUA_USE_C89 is defined + defining
_XOPEN_SOURCE==0 undefines that macro
2014-12-29 14:54:13 -02:00
Roberto Ierusalimschy 8e5290d81e all "divisions" (div,idiv,mod) by zero are not folded, to avoid
problems during compilation + does not fold zero results, as they
can collapse with -0.0 and the ANSI test to distinguish both needs
a division by zero (which we are trying to avoid) + removed macro
'luai_numinvalidop' (as its main use case were divisions by zero)
2014-12-29 14:49:25 -02:00
Roberto Ierusalimschy a1c37f834a detail (macro 'luai_numidiv' uses 'luai_numdiv' to compute the division) 2014-12-29 11:27:55 -02:00
Roberto Ierusalimschy 1a7868c1d5 bug: 'random' limit is 2^31-1, not RAND_MAX 2014-12-27 18:32:26 -02:00
Roberto Ierusalimschy de3933480e details 2014-12-27 18:31:43 -02:00
Roberto Ierusalimschy 50e2eb8954 change in macro 'vmcase', avoding code inside it. (Code inside the
macro harms tools such as debuggers.)
2014-12-27 18:30:38 -02:00
Roberto Ierusalimschy 94eb37dc73 new year (2015) 2014-12-26 15:24:27 -02:00
Roberto Ierusalimschy 900bdd5761 detail (to avoid warnings) 2014-12-26 12:46:07 -02:00
Roberto Ierusalimschy a51069202a removed macro 'luai_numinvalidop' (main motivation removed, as folding
does not handle any division by zero by default)
2014-12-26 12:44:44 -02:00
Roberto Ierusalimschy fb6796ba06 removed useless initializations 2014-12-26 12:43:45 -02:00
Roberto Ierusalimschy 88ef06f4f3 comments were wrong (not updated about several changes) 2014-12-20 11:58:15 -02:00
Roberto Ierusalimschy eb45f3a9b6 details in 'luaM_reallocvchar' 2014-12-19 15:26:14 -02:00
Roberto Ierusalimschy 6321041058 new macro 'luaM_reallocvchar' to allocate arrays of chars (avoids
uneeded tests and respective warnings)
2014-12-19 11:45:40 -02:00
Roberto Ierusalimschy 2b83711fba new macro 'nvalue' (to convert an object to a float when we know
object is a number)
2014-12-19 11:36:32 -02:00
Roberto Ierusalimschy 3ae21a352c detail (in test for 'luai_numinvalidop', use a round float) 2014-12-19 11:33:06 -02:00
Roberto Ierusalimschy 570143bf88 comment 2014-12-19 11:31:12 -02:00
Roberto Ierusalimschy 1465edf341 old Visual Studio versions did not support 'noreturn' attribute 2014-12-19 11:30:23 -02:00
Roberto Ierusalimschy 77e786d436 stupid bug in T.stacklevel (not in use by the tests) 2014-12-18 10:13:42 -02:00
Roberto Ierusalimschy 6d79752e65 Windows uses 'long long' (instead of '__int64') when present; again,
uses macro LLONG_MAX as a proxy for the support for 'long long'.
2014-12-16 15:17:30 -02:00
Roberto Ierusalimschy 75812a517b added macro LUA_USE_I64 for separate control of use of Windows-specific
types
2014-12-16 14:20:01 -02:00
Roberto Ierusalimschy 151dc5cc5f traverse loaded modules (instead of globals) for a name for a function +
removes prefix '_G.' from names (if present)
2014-12-14 16:32:26 -02:00
Roberto Ierusalimschy 0b6cfea005 comments 2014-12-13 15:57:00 -02:00
Roberto Ierusalimschy c8da3fbc35 in traceback names, give preference to 'name' over '_G.name' 2014-12-13 15:47:58 -02:00
Roberto Ierusalimschy c96cd1c647 reinsertion-control macro renamed: lconfig_h -> luaconf_h 2014-12-12 09:49:32 -02:00
Roberto Ierusalimschy 57e91b4159 correct computation for limit in 'getnum' 2014-12-11 12:03:07 -02:00
Roberto Ierusalimschy ef7d29c666 better limits for 'sting.rep' and 'string.packsize' 2014-12-11 11:40:40 -02:00
Roberto Ierusalimschy 81ecaf6178 new specifiers in 'strftime' are defined in C99 (not Posix) 2014-12-10 13:42:42 -02:00
Roberto Ierusalimschy 27ab59bc16 'ipairs' needs an argument 2014-12-10 10:26:42 -02:00
Roberto Ierusalimschy bd8ce7e331 macro 'LUA_C89_NUMBERS' makes a little easier to use C89 numerical types 2014-12-10 09:56:55 -02:00
Roberto Ierusalimschy 5c519a69d3 new function 'string.packsize' 2014-12-10 09:36:03 -02:00
Roberto Ierusalimschy 6f54b07663 give preference to global names in tracebacks 2014-12-10 09:31:32 -02:00
Roberto Ierusalimschy 741ad97e92 new parameter for testC instruction 'pcall' (error handler) 2014-12-10 09:30:51 -02:00
Roberto Ierusalimschy b4633c586b error handler does not need to be a function (can be a callable
object)
2014-12-10 09:30:09 -02:00
Roberto Ierusalimschy 5fae2a5b05 redefinition of LUAI_MAXSTACK to make stack-overflow tests run faster 2014-12-09 15:17:40 -02:00
Roberto Ierusalimschy 36efa6a6b9 no more 'preloadedlibs' when opening libraries (as it is dead code now) 2014-12-09 13:00:17 -02:00
Roberto Ierusalimschy c6e74e41c9 handle case where function was called as a hook 2014-12-08 13:48:23 -02:00
Roberto Ierusalimschy 6909b5a2b4 In 'debug.gethook', does not query hook table (which may not exist) if
there is no hook set
2014-12-08 13:47:25 -02:00
Roberto Ierusalimschy 594d7266af 'assert' checks that it has (at least) one parameter + 'assert' ensures
it passes only one value to 'error'
2014-12-08 13:26:55 -02:00
Roberto Ierusalimschy ab4a890d04 use 'namewhat' when building a traceback 2014-12-08 13:26:09 -02:00
Roberto Ierusalimschy 64e25a6186 avoid octal numerals 2014-12-08 13:12:07 -02:00
Roberto Ierusalimschy 460968353f in test mode, debug library is not predefined (to allow testing
'preloadedlibs')
2014-12-06 18:42:58 -02:00
Roberto Ierusalimschy 32a1f54b9a no more default size for option 'c' in pack/unpack 2014-12-04 14:25:40 -02:00
Roberto Ierusalimschy 6df197ec15 some functions from test module must be exported 2014-11-29 17:45:37 -02:00
Roberto Ierusalimschy 177807f21e casts ('(int)' -> 'cast_int') 2014-11-29 15:38:33 -02:00
Roberto Ierusalimschy 92f02fff11 bug: lua_tounsignedx must cast to lua_Unsigned (of course...) 2014-11-29 15:24:05 -02:00
Roberto Ierusalimschy 125296c83d next release won't be beta 2014-11-28 17:13:39 -02:00
Roberto Ierusalimschy 9c41d9d1df removed unneeded barrier ('from' must be white) 2014-11-27 16:41:43 -02:00
Roberto Ierusalimschy ad79eafe86 details (comments) 2014-11-25 16:21:57 -02:00
Roberto Ierusalimschy fd179ab4b8 clearer notation for "compare" instruction 2014-11-25 12:51:33 -02:00
Roberto Ierusalimschy bf163ea7f0 bug ('#3' causes seg. fault in 5.3-beta) + comments + 'codearith' ->
'codeexpval' (confusion about what operations function accept was
one of the reasons for the bug)
2014-11-24 12:59:22 -02:00
Roberto Ierusalimschy 075661ffde new test for macro 'luai_numinvalidop' 2014-11-24 12:56:56 -02:00
Roberto Ierusalimschy db5ac2fa0d detail (buffer in 'LoadF' is related to files) 2014-11-21 10:17:58 -02:00
Roberto Ierusalimschy 1735c05ac7 avoid memory errors while a file is locked (when reading a line) 2014-11-21 10:17:33 -02:00
Roberto Ierusalimschy 5fbd40dbe5 'x//y' extended to floats 2014-11-21 10:15:57 -02:00
Roberto Ierusalimschy 049cf14cf9 'x//y' extended to floats + more comments about module and floor
division operations
2014-11-21 10:15:00 -02:00
Roberto Ierusalimschy 5d628519d3 simpler definition for 'luaV_tonumber_' 2014-11-19 13:05:15 -02:00
Roberto Ierusalimschy 244646bdf7 detail (LUAL_BUFFERSIZE has a larger variation among different
platforms)
2014-11-19 13:00:42 -02:00
Roberto Ierusalimschy 5bdfefd3a5 allows calling luaL_checkstack with no message (in runC) 2014-11-14 16:15:17 -02:00
Roberto Ierusalimschy 5873786e27 small bug (error of "chunk has too many lines" might use 't.token'
before reading the first token)
2014-11-14 14:06:09 -02:00
Roberto Ierusalimschy cb59019f58 uses return value from luaL_getmetatable 2014-11-12 11:32:27 -02:00
Roberto Ierusalimschy 52c0f9575b uses return value from lua_getfield 2014-11-12 11:31:51 -02:00
Roberto Ierusalimschy 4fde357130 details (matching parameter names with manual) 2014-11-12 11:30:15 -02:00
Roberto Ierusalimschy e5fd1e5fe2 details (match parameter names with lua.h and manual) 2014-11-12 11:28:54 -02:00
Roberto Ierusalimschy 87b179e71d detail (use new returned value from 'lua_getglobal' ) 2014-11-11 17:41:27 -02:00
Roberto Ierusalimschy b401d37188 detail (to avoid a "to avoid warnings" return) 2014-11-11 17:40:20 -02:00
Roberto Ierusalimschy 6624ccff26 independent code for 'printstack' + test for panic function can
ran code there
2014-11-11 15:15:06 -02:00
Roberto Ierusalimschy 9a38c08011 no need to ensure any stack space for panic function + some changes
in 'tryfuncTM' (small simplification)
2014-11-11 15:13:39 -02:00
Roberto Ierusalimschy be87789a6c details 2014-11-11 15:08:19 -02:00
Roberto Ierusalimschy d1d1ddec1e details 2014-11-10 16:41:19 -02:00
Roberto Ierusalimschy bfa0898312 bug: memory error in panic mode does not push error message on
the stack + stack check in tryfuncTM + comments
2014-11-10 15:42:04 -02:00
Roberto Ierusalimschy 79b0d05480 new function 'T.checkpanic' (to check panic errors) 2014-11-10 15:41:36 -02:00
Roberto Ierusalimschy 779381fe9e detail (comment) 2014-11-10 15:24:43 -02:00
Roberto Ierusalimschy b6911c177d luaL_loadbuffer replaced by luaL_loadstring (to test luaL_loadstring)
+ 'rawgetp'/'rawsetp' added to C interpreter
2014-11-10 12:47:29 -02:00
Roberto Ierusalimschy 9212175ffb added missing cases for debug info about tag methods +
better error message for bitwise operators
2014-11-10 12:46:46 -02:00
Roberto Ierusalimschy ad20689feb better error message for bitwise operators (they are not arithmetic...) 2014-11-10 12:46:05 -02:00
Roberto Ierusalimschy e320790154 using address instead of string for key for table 'CLIBS' in the
registry
2014-11-10 12:28:31 -02:00
Roberto Ierusalimschy fee3aa518d using address key (light userdata) for hook table, instead of
string
2014-11-10 12:27:16 -02:00
Roberto Ierusalimschy b58602d93d removed unneeded test (result of b_str2int is already checked
against length)
2014-11-10 12:25:52 -02:00
Roberto Ierusalimschy 74e10b9c3b details (error messages) 2014-11-08 16:12:53 -02:00
Roberto Ierusalimschy b044b8c182 detail (line break) 2014-11-08 15:57:08 -02:00
Roberto Ierusalimschy a113e1498d when checking thread consistency, check its entire stack (always
the entire stack must have valid values)
2014-11-07 16:07:17 -02:00
Roberto Ierusalimschy 17ca3b1763 cleaner test for overflow for range of 'math.random' 2014-11-07 09:31:58 -02:00
Roberto Ierusalimschy 50b18f60cb detail 2014-11-05 16:55:43 -02:00
Roberto Ierusalimschy ad73e5156e more direct way to fill sign-extension extra bytes when packing
integers with sizes larger than lua_Integer + added comments
2014-11-05 16:50:29 -02:00
Roberto Ierusalimschy 720c68dabb removed repeated flags (-Wall/-Wdisabled-optimization) + removed flag
-Wcast-align (Lua does some unconventional casts) + added flag -std=c99
+ added file lprefix.h in dependency lists
2014-11-05 11:02:26 -02:00
Roberto Ierusalimschy 81c39a5244 no need to cast '*s' to unsigned char when we know it is a digit +
no need to call 'luaO_hexavalue' for decimal digits
2014-11-04 17:16:25 -02:00
Roberto Ierusalimschy cfabcbfb17 added macro for configuring padding value in 'string.pack' 2014-11-04 12:34:43 -02:00
Roberto Ierusalimschy bde14c3adc macro to change method of conversion from float to integer (make it
use floor intead of requiring an exact integral value)
2014-11-03 18:07:47 -02:00
Roberto Ierusalimschy 4b839d7c72 Definitions for Lua code that must come before any other header file 2014-11-03 13:12:44 -02:00
Roberto Ierusalimschy c49edc4566 keep "#include <windows.h>" in this file, but without the
previous requirement that it must be included before any other
header file (it doesn't seem to matter)
2014-11-03 13:11:10 -02:00
Roberto Ierusalimschy c5d52a5468 Windows uses "LONGLONG" option, even not having long long (it has __int64) 2014-11-02 17:35:39 -02:00
Roberto Ierusalimschy e75c0148c3 comments (references to "ANSI C" changed to "ISO C", which is the
international name
2014-11-02 17:33:33 -02:00
Roberto Ierusalimschy 28fdbcf393 added include for 'lprefix.h', for stuff that must be added before
any other header file
2014-11-02 17:19:04 -02:00
Roberto Ierusalimschy c25072a246 'lua_load' sets _ENV for any chunk with upvalues (not just those
with exactly one upvalue)
2014-10-31 15:41:51 -02:00
Roberto Ierusalimschy 1a69a3ecea LUA_WIN -> LUA_USE_WINDOWS 2014-10-31 13:54:06 -02:00
Roberto Ierusalimschy dcfc3c9405 new option '=' (native endian) for pack/unpack 2014-10-31 13:53:31 -02:00
Roberto Ierusalimschy 4542fb9f78 comments (a few extra quotes around identifiers) 2014-10-30 16:53:28 -02:00
Roberto Ierusalimschy 80e817719d default changed from C89 to C99 + extra tests before using C99
features (when possible) + LUA_32BITS use 'int' when possible
('long' can be 64 bits)
2014-10-30 16:50:03 -02:00
Roberto Ierusalimschy 96f3a31b24 Better organization of definitions in categories + removed
'_CRT_SECURE_NO_WARNINGS' (useless there) + LUA_ENV/luai_writestring/
luai_writeline/luai_writestringerror/LUA_INT32/LUAI_UMEM/LUAI_MEM
moved to other places (no need to be in luaconf.h) + changed definition
for LUAL_BUFFERSIZE
2014-10-29 16:01:26 -02:00
Roberto Ierusalimschy ff6c034330 configurations for types 'lu_mem'/'l_mem'/'Instruction' moved to here
(from 'luaconf.h'), as they are not needed by the API and probably
will not be changed
2014-10-29 15:07:45 -02:00
Roberto Ierusalimschy 05afee0f50 definitions for 'luai_writestring'/'luai_writeline'/'luai_writestringerror'
moved to 'lauxlib.h' (they do not need to be stable or configurable) +
prefixes changed from 'luai_' to 'lua_' (they are not part of the core)
2014-10-29 14:12:30 -02:00
Roberto Ierusalimschy 351a446ec5 definition for 'LUA_ENV' moved from 'luaconf.h' to here (no need to
be visible outside Lua + no need for easy redefinitions)
2014-10-29 13:38:24 -02:00
Roberto Ierusalimschy e9885efc7c added comment and assert about an (impossible) division by zero 2014-10-29 13:02:53 -02:00
Roberto Ierusalimschy 59fbbf0a65 small simplifications in code for 'lua_strx2number' 2014-10-28 16:41:38 -02:00
Roberto Ierusalimschy 61c3c80177 detail 2014-10-28 16:23:31 -02:00
Roberto Ierusalimschy 9de384e27a removed useless 'include math.h' 2014-10-28 15:27:50 -02:00
Roberto Ierusalimschy 4b526045fa comment 2014-10-28 15:27:41 -02:00
Roberto Ierusalimschy 4870194380 small reorganization of tests around LUA_USE_C99 2014-10-27 17:21:56 -02:00
Roberto Ierusalimschy 41d0e66184 comments + Windows numeric types not used if LUA_ANSI is defined 2014-10-27 16:06:03 -02:00
Roberto Ierusalimschy aa1bd8876c comments 2014-10-27 16:05:37 -02:00
Roberto Ierusalimschy 7314acaa80 'T.limits' reports some more useful limits 2014-10-27 15:00:02 -02:00
Roberto Ierusalimschy 4b2521cd9e better (and safer?) way to test native size of type 'int' 2014-10-27 14:59:31 -02:00
Roberto Ierusalimschy 491103708e 'MAXSTACK' -> 'MAXREGS' and moved to 'lcode.c' (there is no reason
to change that constant...)
2014-10-27 14:29:58 -02:00
Roberto Ierusalimschy fa4d5c8689 pack/unpack do not handle final '\0' as an "option" (it streches
unnecessarily the switch range)
2014-10-27 11:30:24 -02:00
Roberto Ierusalimschy aef2d711b1 detail 2014-10-26 13:45:41 -02:00
Roberto Ierusalimschy bdf566a8a3 `name' in comments changed to 'name' 2014-10-25 09:50:46 -02:00
Roberto Ierusalimschy c3c78030f7 avoid redeclaration of _CRT_SECURE_NO_WARNINGS + 'lua_numtointeger' ->
'lua_numbertointeger'
2014-10-24 09:42:47 -02:00
Roberto Ierusalimschy ff9ca88aa6 added some casts to avoid warnings in some compilers 2014-10-24 09:42:29 -02:00
Roberto Ierusalimschy 463edee2fd 'lua_numtointeger' -> 'lua_numbertointeger' 2014-10-24 09:42:06 -02:00
Roberto Ierusalimschy 88ff582fd8 detail (using 'sizeof' instead of 'strlen' for length of a constant
string)
2014-10-22 14:55:57 -02:00
Roberto Ierusalimschy 6b12b82532 added 'l_' prefix for names that can be redefined externally 2014-10-22 09:44:20 -02:00
Roberto Ierusalimschy d7a0179cd6 use 'opf' (float) variants only when explicitly allowed (LUA_USE_C99) 2014-10-21 12:38:46 -02:00
Roberto Ierusalimschy 6d613817d4 comments 2014-10-20 20:21:05 -02:00
Roberto Ierusalimschy b8d412aa07 error in comment 2014-10-20 16:29:55 -02:00
Roberto Ierusalimschy 961760c9b6 message handler always adds a traceback to messages (even if they
are not strings), unless they have a __tostring method.
2014-10-20 16:19:26 -02:00
Roberto Ierusalimschy 57559547a3 in 'pack'/'unpack', endianness and alignment treated like options +
small changes in names and handling of internal options ('KOption')
2014-10-20 14:44:54 -02:00
Roberto Ierusalimschy cfa84e1232 does not use 'long long' when LUA_ANSI is set 2014-10-20 14:32:05 -02:00
Roberto Ierusalimschy 0d31efb365 'lua_stringtonum' -> 'lua_stringtonumber' 2014-10-17 16:17:55 -03:00
Roberto Ierusalimschy f97c64d7bf macros 'LUA_QL'/'LUA_QL' deprecated 2014-10-17 13:28:21 -03:00
Roberto Ierusalimschy ea3155e380 'debug.sizeof' removed 2014-10-17 08:07:26 -03:00
Roberto Ierusalimschy c172a4f7c2 'dumpint' and related functions replaced by 'string.pack'/'string.unpack' 2014-10-17 07:55:28 -03:00
Roberto Ierusalimschy f8e0d33b25 added "_CRT_SECURE_NO_WARNINGS" for Windows (to avoid warnings about
several standard C functions) + small changes in '#include's
2014-10-15 11:53:20 -03:00
Roberto Ierusalimschy 745618d941 'charpatt' -> 'charpattern' 2014-10-15 11:31:10 -03:00
Roberto Ierusalimschy 89602bf747 'lua_strtonum' -> 'lua_stringtonum' 2014-10-15 11:27:40 -03:00
Roberto Ierusalimschy 56d4537879 '$c' in 'lua_pushfstring' prints non-printable characters with
their codes
2014-10-10 19:23:04 -03:00
Roberto Ierusalimschy 18014ef2fd better handling of systems that do not support 'long long' 2014-10-08 17:32:50 -03:00
Roberto Ierusalimschy ffe7401ceb avoid warnings in macro 'luaM_reallocv' + comments 2014-10-08 17:25:51 -03:00
Roberto Ierusalimschy 65ec3379b1 added some casts for the cases when lua_Number != double 2014-10-08 16:57:31 -03:00
Roberto Ierusalimschy 85fc9ecd5f detail ('G(L)' -> 'g') 2014-10-08 09:20:26 -03:00
Roberto Ierusalimschy 2a21f6c894 'lua_Kcontext' -> 'lua_KContext' 2014-10-07 15:29:13 -03:00
Roberto Ierusalimschy 3670db99b6 comments 2014-10-06 18:34:34 -03:00
Roberto Ierusalimschy e14a02c24f when thread yields, real "func" is in field 'extra', not in 'func' 2014-10-06 14:06:49 -03:00
Roberto Ierusalimschy 15f4150518 alpha -> beta 2014-10-04 19:57:36 -03:00
Roberto Ierusalimschy c5cae9362c added two casts to avoid warnings in VS 2014-10-04 19:57:10 -03:00
Roberto Ierusalimschy 4f4e0e49bb easier way to compile Lua 32 2014-10-03 09:55:44 -03:00
Roberto Ierusalimschy 2f4d429071 details (comments) 2014-10-03 09:54:57 -03:00
Roberto Ierusalimschy 27f7bd2e83 detail 2014-10-01 13:05:06 -03:00
Roberto Ierusalimschy 798660c9cd deprecated "cast macros" ('luaL_checkint', 'luaL_optint', etc.) 2014-10-01 08:54:56 -03:00
Roberto Ierusalimschy 34b6664dcb better to use 'long' to represent UTF-8 code points 2014-10-01 08:52:33 -03:00
Roberto Ierusalimschy d35fff16d5 'ipairs' always stops at first nil element 2014-09-30 10:53:26 -03:00
Roberto Ierusalimschy 56699cd603 small change to avoid bug in some versions of the clang compiler 2014-09-26 11:09:21 -03:00
Roberto Ierusalimschy 8ede2c353c detail in 'report' + message handler always is called with an
argument + 'report' already handles non-string error messages
2014-09-25 11:20:37 -03:00
Roberto Ierusalimschy 6384475ec4 'luaL_getmetafield' returns type of metafield (instead of a boolean) 2014-09-22 03:42:15 -03:00
Roberto Ierusalimschy 3a15c7ce43 size for array part of a table ('sizearray') changed from 'int' to
'unsigned int', which allows twice as many elements in the array part
2014-09-04 15:15:29 -03:00
Roberto Ierusalimschy 0a6b58c3aa weak tables that must be retraversed are kept in 'grayagain' list
until atomic phase (instead of going to their special lists) +
more comments
2014-09-03 13:54:41 -03:00
Roberto Ierusalimschy 979a663d2a detail (error message from 'coroutine.status') 2014-09-01 15:00:04 -03:00
Roberto Ierusalimschy 22952d8973 'T.gccolor' classify dead objects too 2014-09-01 14:58:55 -03:00
Roberto Ierusalimschy df608f842a 'linktable' -> 'linkgclist' (and used for all links with 'gclist') 2014-09-01 14:37:11 -03:00
Roberto Ierusalimschy 001bb46ae1 bug: Ephemeron table can wrongly collect entry with strong key 2014-09-01 13:56:01 -03:00
Roberto Ierusalimschy 9b25347a67 detail 2014-08-27 11:59:33 -03:00
Roberto Ierusalimschy e401513086 new option 'p' for 'debug.sizeof' (size of a pointer) 2014-08-22 13:22:42 -03:00
Roberto Ierusalimschy 7f1a2ad699 new functions 'lua_geti/lua_seti' (non raw) 2014-08-21 17:07:56 -03:00
Roberto Ierusalimschy a1ab5ab396 'table.copy' -> 'table.move' + optional parameter moved to the end +
several functions operate on "virtual" tables too
2014-08-21 16:13:55 -03:00
Roberto Ierusalimschy 01549fb1ed 'Csize' -> 'sizeof' + removed its 'b' option 2014-08-21 16:12:40 -03:00
Roberto Ierusalimschy 4fba117433 [un]'dumpint' -> [un]'dumpinteger' 2014-08-20 19:06:41 -03:00
Roberto Ierusalimschy 2be88d5084 'lua_Ctx' -> 'lua_Kcontext' 2014-08-01 14:33:08 -03:00
Roberto Ierusalimschy f5c690b684 details in comments 2014-08-01 14:24:02 -03:00
Roberto Ierusalimschy 61fa462535 added cast to avoid warning 2014-08-01 14:22:57 -03:00
Roberto Ierusalimschy fba9050d3d release changed to (5.3) alpha 2014-07-31 10:44:30 -03:00
Roberto Ierusalimschy d861706620 new macro 'cvt2num' to better control whether strings are convertible
to numbers
2014-07-30 11:42:44 -03:00
Roberto Ierusalimschy 34ac039fb8 new macro 'cvt2str' to better control whether numbers are convertible
to strings
2014-07-30 11:00:14 -03:00
Roberto Ierusalimschy 1aa5262634 do not assume numbers are coercible to strings 2014-07-30 10:59:24 -03:00
Roberto Ierusalimschy 07c7fdb9df simpler definition for 'setobj' (trust the compiler for the assignment) 2014-07-29 13:22:24 -03:00
Roberto Ierusalimschy 3ccbae84d2 added some casts between integral types (to avoid warnings) 2014-07-29 13:01:00 -03:00
Roberto Ierusalimschy 255d59ed5e some janitorial work (comments, small refactoring) 2014-07-28 14:47:53 -03:00
Roberto Ierusalimschy 925d1b59f9 new function 'math.ult' (unsigned less than) 2014-07-28 14:35:47 -03:00
Roberto Ierusalimschy 03bbe1baf1 first implementation for 'table.copy' 2014-07-25 15:46:00 -03:00
Roberto Ierusalimschy f9037ae8c1 'ipairs' respects metamethods 2014-07-24 16:33:29 -03:00
Roberto Ierusalimschy 57d8424146 extra space for new threads is initialized with a copy of the main
thread, not of the creator thread.
2014-07-24 13:17:56 -03:00
Roberto Ierusalimschy baa0e23456 better support for extra user space associated with a Lua state 2014-07-24 11:00:16 -03:00
Roberto Ierusalimschy 55a710545c detail (extra byte in LUAI_EXTRASPACE to test proper alignment of
a lua_State)
2014-07-23 14:16:50 -03:00
Roberto Ierusalimschy 753f2c1da4 better(?) alignment for some structures (pointers first) 2014-07-23 14:15:43 -03:00
Roberto Ierusalimschy b3b8580606 comments + proper undef of compatibility macros + no need to undef
internal macros (this is the first definition)
2014-07-23 13:47:47 -03:00
Roberto Ierusalimschy 73ad16b5c6 no need for type 'pCallInfo' 2014-07-23 13:44:30 -03:00
Roberto Ierusalimschy 97e299c395 'lua_replace' implemented as a macro using 'lua_copy' 2014-07-22 15:07:47 -03:00
Roberto Ierusalimschy c697aa30bc more precise type for argument to 'aux_upvalue' 2014-07-21 13:02:57 -03:00
Roberto Ierusalimschy 17ee57f8e0 'iswhite' and related macros now can work directly on any object
(no need to convert to 'GCObject')
2014-07-21 13:02:10 -03:00
Roberto Ierusalimschy 3c6d0aaa7d 'iswhite' and related macros now can work directly on any object
(no need to convert to 'GCObject')
2014-07-19 12:14:46 -03:00
Roberto Ierusalimschy e43612aaf6 put the restriction that 'luaC_barrierback' works only on tables
in its prototype
2014-07-19 12:09:37 -03:00
Roberto Ierusalimschy 2898e2fd12 removed useless assertion (gcstate != GCSpause already implied by
other assertions) and wrong assertion (setmetatable uses this barrier
for tables too)
2014-07-19 11:44:19 -03:00
Roberto Ierusalimschy 8704fca0c9 in 'luaL_checkversion_' check numeric types first. (Other tests
depend on correct numeric type.)
2014-07-19 11:37:09 -03:00
Roberto Ierusalimschy 325e44d87e no more "-2" for limits. (Limits should be precise; safety is in
the code that handles these limits.)
2014-07-18 15:29:12 -03:00
Roberto Ierusalimschy 54ac253343 detail (no need to define LUAI_USER_ALIGNMENT_T when it is not
defined; simpler to define 'L_Umaxalign' directly)
2014-07-18 15:18:45 -03:00
Roberto Ierusalimschy bb12903120 type 'Udata' refers directly to structure inside the union (union
used only for aligning purposes now)
2014-07-18 11:46:47 -03:00
Roberto Ierusalimschy ca41b43f53 type 'TString' refers directly to the structure inside the union
(union used only for size purposes)
2014-07-18 10:36:14 -03:00
Roberto Ierusalimschy 3511e186cd ensure size for LUAI_USER_ALIGNMENT_T in tests is larger than the
structures it is aligning (in most architectures)
2014-07-18 10:27:45 -03:00
Roberto Ierusalimschy 56137d58ff added check for conversion 'obj2gco' (and corrections for small
problems detected by this check)
2014-07-18 09:17:54 -03:00
Roberto Ierusalimschy 9aec500a26 no need for field 'gch' anymore 2014-07-17 14:27:49 -03:00
Roberto Ierusalimschy 5a9cc57a5e change in GCObject: instead of being a union, it is now a structure
with the common header of all collectable objects; union is used
only for conversions. (Goal is to be able to check that the cast
'obj2gco' can have a check to ensure that object being converted
is really a collectable object.). This is the first step in the
change.
2014-07-17 14:09:50 -03:00
Roberto Ierusalimschy 1aa4f69b51 new type 'lua_Ctx' for continuation-function contexts (to allow type
to be configurable)
2014-07-17 10:53:37 -03:00
Roberto Ierusalimschy 8bb272a3e3 new conversion float->integer: conversion is valid only when
float has an exact representation as an integer
2014-07-17 09:30:53 -03:00
Roberto Ierusalimschy c229ed597f 'requiref' checks 'package.loaded' before loading a module 2014-07-16 11:51:36 -03:00
Roberto Ierusalimschy 16b4110521 function 'type' keeps type names as upvalues to avoid creating strings
everytime it is called
2014-07-16 10:56:59 -03:00
Roberto Ierusalimschy f14662fca6 detail (added placeholders for non-function fields to preallocate
space for them)
2014-07-16 10:56:14 -03:00
Roberto Ierusalimschy a9af12bbe7 Table library now respects '__index'/'__newindex' metamethods 2014-07-16 09:44:52 -03:00
Roberto Ierusalimschy 5bbb4a06a6 removed unused parameter Ä'L' in macro 'api_check' and company 2014-07-15 18:26:50 -03:00
Roberto Ierusalimschy d4fb848be7 added api check in 'lua_typename' (tag is valid) 2014-07-15 18:14:49 -03:00
Roberto Ierusalimschy b9dcf9974d detail (typos in comments) 2014-06-30 16:48:08 -03:00
Roberto Ierusalimschy a77d263e86 unsigned-manipulation functions (lua_puhsunsigned, lua_tounsigned, etc.)
deprecated
2014-06-26 15:38:28 -03:00
Roberto Ierusalimschy 7cc40851e1 emergency collection can happen even when collector is stopped 2014-06-26 15:29:05 -03:00
Roberto Ierusalimschy 08a9c9faa3 detail (comment) 2014-06-26 15:28:24 -03:00
Roberto Ierusalimschy 84fe52dbeb unsigned-manipulation functions (lua_puhsunsigned, lua_tounsigned, etc.)
deprecated
2014-06-26 14:25:11 -03:00
Roberto Ierusalimschy 10200585a7 var-arguments to the script come from 'arg' table (not from original
'argv' array)
2014-06-26 14:08:52 -03:00
Roberto Ierusalimschy c94f11d783 'IntPoint' -> 'point2int' + ensure that casted value fits in
destination type
2014-06-26 13:17:35 -03:00
Roberto Ierusalimschy 54ac5960a8 LUA_MAXUNSIGNED was only used to define 2.0^intnumbits (and that
definition was not strictly portable), so it was removed and
replaced by a more correct and direct definition for 2.0^intnumbits
(only where it was needed)
2014-06-24 14:02:00 -03:00
Roberto Ierusalimschy 0e6229a953 use proper macros to convert 'GCObject' to other objects + better
type cheking in 'set*value' macros
2014-06-19 15:39:36 -03:00
Roberto Ierusalimschy d2ab1aef31 detail (avoid too large macro) 2014-06-19 15:29:30 -03:00
Roberto Ierusalimschy 89b56e7d84 more precision between closure types ('LClosure' x 'CClosure') 2014-06-19 15:27:20 -03:00
Roberto Ierusalimschy 14929f5764 use appropriate macros to convert GCObject to specific types 2014-06-18 19:59:29 -03:00
Roberto Ierusalimschy 7021cc9bc8 allows different 'source' for each prototype, but inherits it from
parent when they are equal (only possible case for chunks created
by the parser)
2014-06-18 15:35:43 -03:00
Roberto Ierusalimschy 04da0a40c0 added assertion about sources being the same for all protos in a chunk 2014-06-18 10:54:31 -03:00
Roberto Ierusalimschy eb67828236 changed macro for compatibility options + details 2014-06-18 10:24:01 -03:00
Roberto Ierusalimschy 94266dfdbd source for all prototypes must be equal in a chunk; no need to store
each one separated
2014-06-18 10:21:12 -03:00
Roberto Ierusalimschy e3871abe95 'math.ifloor' is back 2014-06-18 09:35:53 -03:00
Roberto Ierusalimschy 3fc25ff15b macro 'checkobjref' accepts NULL (as all its uses checked for NULL
before) + user value from a userdata may not be a GC object
2014-06-17 14:13:29 -03:00
Roberto Ierusalimschy fa3113ffbf cleaner way to handle bit CIST_OAH (with auxiliar macros) 2014-06-12 16:07:30 -03:00
Roberto Ierusalimschy d94bb6c273 janitor work on 'lua_resume' and related code 2014-06-11 13:01:55 -03:00
Roberto Ierusalimschy 5784331768 new items in default path for Windows 2014-06-10 16:21:20 -03:00
Roberto Ierusalimschy 88a9e51f34 bit-field CIST_YIELDED removed (it was never consulted) 2014-06-10 16:18:50 -03:00
Roberto Ierusalimschy 8b5940e7ca must also reset CIST_OAH if necessary (CallInfo is not a fresh one) 2014-06-10 16:13:26 -03:00
Roberto Ierusalimschy 1a3656e56e more relaxed rules for __eq metamethod (more similar to other
operators)
2014-06-10 15:53:18 -03:00
Roberto Ierusalimschy 542b6cfc02 no need for field 'status' in structure 'CallInfo' (after removal
of 'lua_getctx') + field 'old_allowhook' can be packed into a single
bit
2014-06-10 15:51:21 -03:00
Roberto Ierusalimschy 6f6fd96e3b new type lua_KFunction + no more 'lua_getctx' 2014-06-10 14:41:38 -03:00
Roberto Ierusalimschy 35a6aad0d7 added comments 2014-06-09 13:32:18 -03:00
Roberto Ierusalimschy 23f0ff9517 lots of janitor work (including comments) + 'arg' table created
before running any script + changes in the parameters and return
of 'collectargs'
2014-06-05 17:42:06 -03:00
Roberto Ierusalimschy 355037528c 'math.mof' works with integers, too 2014-06-02 20:09:28 -03:00
Roberto Ierusalimschy 9e68c047ae 'assert' does not assume that the error object is a string 2014-06-02 00:06:26 -03:00
Roberto Ierusalimschy e9d86eddf3 if numeral overflows the reading buffer, signal it as invalid input
(resulting in nil)
2014-06-02 00:00:51 -03:00
Roberto Ierusalimschy 11aefa4478 details (comments) 2014-06-01 21:03:16 -03:00
Roberto Ierusalimschy 5ebdd326b6 detail (to avoid warnings of unused variable) 2014-05-29 16:30:07 -03:00
Roberto Ierusalimschy 84db17b6fc more "religious" definition for 'lua_numtointeger' 2014-05-27 10:59:03 -03:00
Roberto Ierusalimschy 456806f25c no more 'math.ifloor' + new semantics for 'math.floor'/'math.ceil' 2014-05-26 14:13:52 -03:00
Roberto Ierusalimschy c98f195eb9 function 'luaV_numtointeger' changed to a global macro
'lua_numtointeger' (tricky, small, and useful in several places)
2014-05-26 14:10:22 -03:00
Roberto Ierusalimschy 4d696c45b9 simpler handling of 'GCScallfin' state + more comments 2014-05-25 16:08:32 -03:00
Roberto Ierusalimschy 36715ab7c1 detail (comment) 2014-05-23 15:32:21 -03:00
Roberto Ierusalimschy e966e53791 no more use of 'scanf' for reading numbers 2014-05-21 12:24:21 -03:00
Roberto Ierusalimschy c4eff10322 small improvements concerning 'check_next' 2014-05-21 12:22:02 -03:00
Roberto Ierusalimschy 8a0acf0898 comments 2014-05-20 11:12:59 -03:00
Roberto Ierusalimschy e2be310a85 better(?) implementation for 'pcall'/'xpcall' (regarding the insertion
of the boolean first result)
2014-05-16 15:54:01 -03:00
Roberto Ierusalimschy 17159b491c more direct implementation of 'table.pack' 2014-05-16 15:53:25 -03:00
Roberto Ierusalimschy 0aa32fa0cb small changes in field order in some structs to reduce padding 2014-05-15 17:41:27 -03:00
Roberto Ierusalimschy 8927c14317 removed macro 'luai_checknum' (as NaN trick is not doable now) 2014-05-15 17:28:39 -03:00
Roberto Ierusalimschy 3e977f02ac added a few comments 2014-05-15 17:08:32 -03:00
Roberto Ierusalimschy a73da6112d deprecated library throws an error if called (instead of silently
not loading itself)
2014-05-15 16:28:34 -03:00
Roberto Ierusalimschy 6a5d87771f added lots of new comments + small changes in code 2014-05-15 16:27:33 -03:00
Roberto Ierusalimschy 15e8405731 'LUA_COMPAT_ALL' -> 'LUA_COMPAT_5_1'/'LUA_COMPAT_5_2' + "@*" in
comments replaced by "@@". ("@*" is too distracting)
2014-05-15 12:24:32 -03:00
Roberto Ierusalimschy fd1672ba98 avoid non-conformant pointer arithmetic in api check for 'lua_rotate' 2014-05-15 12:22:45 -03:00
Roberto Ierusalimschy 1ddb251d86 using a more conventional handling of stack space in 'io_readline' 2014-05-15 12:21:06 -03:00
Roberto Ierusalimschy f8daddba50 added a compat option (although it will be off by default) to
the addition of '.0' to float->string conversions
2014-05-14 16:47:11 -03:00
Roberto Ierusalimschy e58ef8d0bb missing macro 'LUAMOD_API' in function to open library 2014-05-14 15:33:37 -03:00
Roberto Ierusalimschy e3b9569e04 function 'reverse' uses appropriate variants of 'setobj' for better
documentation
2014-05-14 15:32:30 -03:00
Roberto Ierusalimschy 8b66040e34 several functions deprecated (cosh, sinh, atanh, pow, frexp, ldexp) 2014-05-14 13:59:27 -03:00
Roberto Ierusalimschy 965993da07 comments added to 'lua_rotate' 2014-05-14 11:20:17 -03:00
Roberto Ierusalimschy 5a5a834975 new API function 'lua_rotate' 2014-05-13 16:40:28 -03:00
Roberto Ierusalimschy 45c430eac0 addition of '.0' to float representation done by the kernel 2014-05-12 18:44:17 -03:00
Roberto Ierusalimschy 27d9219cf3 no more integer exponentiation 2014-05-12 18:22:05 -03:00
Roberto Ierusalimschy 12bd01c567 added comments to several functions 2014-05-12 16:13:32 -03:00
Roberto Ierusalimschy 626124d2d8 old POSIX systems need '<sys/types.h>' for 'off_t' 2014-05-11 11:46:19 -03:00
Roberto Ierusalimschy 5018104a60 better error message for unfinished long strings/comments 2014-05-11 11:45:43 -03:00
Roberto Ierusalimschy ec11d132db comments 2014-05-11 10:03:48 -03:00
Roberto Ierusalimschy 06dc893f88 in 'for' loops, make the limit an integer whenever initial value and
step are integers
2014-05-09 11:20:52 -03:00
Roberto Ierusalimschy a09bd59615 'T.totalmem' accepts 0 for unlimited memory 2014-05-08 16:08:46 -03:00
Roberto Ierusalimschy 42ff788e53 comments 2014-05-08 15:58:46 -03:00
Roberto Ierusalimschy 1bd70a8e40 new function 'lua_isyieldable' (and 'coroutine.isyieldable') 2014-05-08 10:52:20 -03:00
Roberto Ierusalimschy ef83457427 updated several 'fix' fields 2014-05-07 13:57:27 -03:00
Roberto Ierusalimschy 4833fb8273 marks for releases 5.2.2 and 5.2.3 + correction in last bug's description 2014-05-07 13:35:24 -03:00
Roberto Ierusalimschy 77e7ebca0a better alignments (for 64-bit arquitectures) for structures 'Table' and
'TString'
2014-05-07 08:12:51 -03:00
Roberto Ierusalimschy 6d5324f92f 'math.fmod' handles integers as integers 2014-05-02 13:36:51 -03:00
Roberto Ierusalimschy 4fe11ae232 'lua_getuservalue' returns type of user value 2014-05-01 15:21:32 -03:00
Roberto Ierusalimschy c549d4fe64 'lua_strtonum' (and 'luaO_str2num') now return string size, instead of
receiving it
2014-05-01 15:18:06 -03:00
Roberto Ierusalimschy ddff6ecf30 function 'limittointeger' no needed (now that 'tointeger_aux' handles
integers too)
2014-04-30 16:29:51 -03:00
Roberto Ierusalimschy 6b630c0fa0 debug.numbits replaced by debug.Csize 2014-04-30 15:59:15 -03:00
Roberto Ierusalimschy 1a6ef098b0 'luaO_str2d' + 'luaO_str2int' replaced by 'luaO_str2num' plus proper
conversion from strings to integers
2014-04-30 13:50:16 -03:00
Roberto Ierusalimschy 5388aa9fc0 'luaO_str2d' + 'luaO_str2int' replaced by 'luaO_str2num' (which converts
to float or integer according to the string syntax)
2014-04-30 13:48:44 -03:00
Roberto Ierusalimschy b123a88673 merge of common parts from 'limittointeger' and 'luaV_tointeger_' 2014-04-29 17:06:05 -03:00
Roberto Ierusalimschy ffa43df3cd 'setnvalue' -> 'setfltvalue' (for consitency with 'fltvalue') 2014-04-29 15:14:16 -03:00
Roberto Ierusalimschy 9c4398de8f 'for' loop tries to convert limit to integer when initial value and
step are integers
2014-04-29 15:11:57 -03:00
Roberto Ierusalimschy a0d4f0fc8a template for 'mkstemp' is configurable (via LUA_TMPNAMTEMPLATE) 2014-04-29 14:05:13 -03:00
Roberto Ierusalimschy 68616c6669 using lua_Unsigned (instead of lua_Integer) for bit manipulation 2014-04-27 11:42:26 -03:00
Roberto Ierusalimschy e98ba351ce n^-m gives float result (instead of error) 2014-04-27 11:41:11 -03:00
Roberto Ierusalimschy cbe4998bc2 'math.random(n,m)' interval restricted in size, to avoid using conversion
between 'double' and 'unsigned' (which can be slow and unreliable)
2014-04-17 13:09:40 -03:00
Roberto Ierusalimschy 0172c9552c comment 2014-04-17 11:41:11 -03:00
Roberto Ierusalimschy 3d4913f703 back to larger sizes for 'dumpint/undumpint' (small Lua should
be able to dump/undump long-long integers)
2014-04-16 15:48:31 -03:00
Roberto Ierusalimschy c27ef1b79c correct integer limits for Windows + small adjustments for short
option
2014-04-16 15:45:51 -03:00
Roberto Ierusalimschy 4422b97472 keep 'luaL_checkversion_' with its signature in version 5.2, for
correct error messages in case of version mixings
2014-04-15 15:25:49 -03:00
Roberto Ierusalimschy 2f02d264e9 initial '*' in 'io.read' formats is deprecated 2014-04-15 13:46:45 -03:00
Roberto Ierusalimschy 037a70dfea cast_u2s/cast_s2u renamed l_castS2U/l_castU2S to be configurable from
outside (mostly for testing)
2014-04-15 13:32:49 -03:00
Roberto Ierusalimschy 8f961da3db macros cast_integer/cast_unsigned replaced by cast_u2s/cast_s2u, that
should be used only between lua_Integer and lua_Unsigned
2014-04-15 11:29:30 -03:00
Roberto Ierusalimschy 5c46b7b8cf instructions in 'runC' sorted alphabetically + new instructions
'tointeger'/'tounsigned'
2014-04-14 15:42:44 -03:00
Roberto Ierusalimschy a2c094fe2d size of strings in 'string.rep' should be limited by the size of
lua_Integer, not of 'int'
2014-04-14 13:59:46 -03:00
Roberto Ierusalimschy f767f29d87 using predefined limits (instead of computing min/max values for each
type) + some comments
2014-04-14 13:58:54 -03:00
Roberto Ierusalimschy 675530c4d8 maximum size of array part of a table now is restricted not only by
the size of an 'int', but also by the size of a 'lua_Integer'
2014-04-13 18:11:19 -03:00
Roberto Ierusalimschy ab964ad7c6 new macro LUA_MAXUNSIGNED + support for 'short' integers (for tests only) 2014-04-12 11:51:53 -03:00
Roberto Ierusalimschy ef789d4161 new global macro 'LUA_MAXUNSIGNED' 2014-04-12 11:45:10 -03:00
Roberto Ierusalimschy b390d7c168 detail (avoid "casting down" in case lua_Integer is smaller than int) 2014-04-12 11:43:50 -03:00
Roberto Ierusalimschy 218f358461 errors like 1e100 << "2" were giving wrong messages 2014-04-11 17:17:39 -03:00
Roberto Ierusalimschy bf06e22b6a correct definition for 'MAX_SIZE' (using singed integers as the limit,
not unsigned ones) + new type 'l_uacInt'
2014-04-11 16:56:04 -03:00
Roberto Ierusalimschy d99ffa920d new type 'LUAI_UACINT' (result of an 'usual argument conversion' of
a lua_Integer)
2014-04-11 16:53:45 -03:00
Roberto Ierusalimschy 2771050dfa 'MIN/MAX_INTEGER' replaced by 'LUA_MIN/MAXINTEGER' 2014-04-11 16:02:16 -03:00
Roberto Ierusalimschy e1daf10e4c details in comments 2014-04-11 15:19:07 -03:00
Roberto Ierusalimschy 115fa77009 maximum size for dump of integers is size of lua_Integer (which
means that there is no overflows when undumping)
2014-04-10 16:45:43 -03:00
Roberto Ierusalimschy 561030c211 pack/unpack functions renamed dump/undump 2014-04-10 15:24:12 -03:00
Roberto Ierusalimschy 5336cc9d6a math.random: use 'random' when available + changes to work correctly
for any integer interval (up to [minint,maxint])
2014-04-10 14:53:33 -03:00
Roberto Ierusalimschy fdd137276b more precision for PI + no more RADIANS_PER_DEGREE +
'min/maxint' -> 'min/maxinteger'
2014-04-09 14:29:46 -03:00
Roberto Ierusalimschy a8aede68c7 new definition for 'luai_nummod' (using 'fmod') 2014-04-09 14:05:11 -03:00
Roberto Ierusalimschy c7859a046d using 'volatile' in 'tofloat' to ensure result has the same precision
(lua_Number) of other computations
2014-04-08 11:28:04 -03:00
Roberto Ierusalimschy 4a24883674 'GCmemtrav' does not need to track the entire collection, only each
single step individually
2014-04-04 14:01:04 -03:00
Roberto Ierusalimschy 9737832641 'int' -> 'lua_Integer' in several functions 2014-04-04 13:38:11 -03:00
Roberto Ierusalimschy 8b45d9806a new constants 'math.maxint'/'math.minint' 2014-04-03 11:18:19 -03:00
Roberto Ierusalimschy be52f784d9 new macros LUA_MAXINTEGER/LUA_MININTEGER 2014-04-03 11:18:02 -03:00
Roberto Ierusalimschy 144afa4d47 several changes in 'utf8.offset' 2014-04-03 10:45:09 -03:00
Roberto Ierusalimschy 007f66408d bug: compiler can optimize away overflow check in 'table.concat' 2014-04-03 10:30:23 -03:00
Roberto Ierusalimschy 48c745a611 avoid constant overflow when shifting left signed integers until
their last bit
2014-04-03 10:29:24 -03:00
Roberto Ierusalimschy 3a044de5a1 new implementation for 'utf8.len' 2014-04-02 14:01:22 -03:00
Roberto Ierusalimschy 7d514af0bc bug (in work version): comparisons should not try to convert
strings to numbers
2014-04-02 13:54:20 -03:00
Roberto Ierusalimschy f61ceee708 LUAI_FUNC is being used only in header files 2014-04-02 13:44:42 -03:00
Roberto Ierusalimschy 5aeb57f11f detail (error message for conversion from float to integer) 2014-04-01 15:55:06 -03:00
Roberto Ierusalimschy 493b3fdd65 added an 'api_check' for negative sizes in 'lua_checkstack' 2014-04-01 15:51:23 -03:00
Roberto Ierusalimschy 315c5bf7b7 bug: compiler could optimize away overflow check (+ changing indices
from 'int' to 'lua_Integer')
2014-04-01 15:50:34 -03:00
Roberto Ierusalimschy 607be77ec8 some details to avoid warnings 2014-04-01 11:39:55 -03:00
Roberto Ierusalimschy 0d745ed04c more precise estimation (GCestimate) for total bytes in use after
a GC cycle
2014-04-01 11:06:59 -03:00
Roberto Ierusalimschy 3d1c6730da detail ('1U' -> '1u', like other unsigned constants in the code) 2014-03-31 16:18:24 -03:00
Roberto Ierusalimschy 66b7b9b582 math.abs, math.max, and math.min work for integers, too. 2014-03-31 16:00:52 -03:00
Roberto Ierusalimschy 8ef9117924 fancier way to do sign extension 2014-03-31 15:38:26 -03:00
Roberto Ierusalimschy ea69f17d98 macro 'tostring' is used only by 'luaV_concat' 2014-03-31 15:37:52 -03:00
Roberto Ierusalimschy 420cc62fac missplelling in comments/function names (endianess -> endianness) 2014-03-27 12:58:05 -03:00
Roberto Ierusalimschy 1a3ebc203a definition of LUA_REAL_* and LUA_INT_* moved to the beginning of
configurations
2014-03-21 11:27:16 -03:00
Roberto Ierusalimschy 2d5e2212d4 native lua_Number may be neither float nor double (in pack/unpackfloat) 2014-03-21 11:26:44 -03:00
Roberto Ierusalimschy da4811238a details (typos in comments) 2014-03-21 10:52:33 -03:00
Roberto Ierusalimschy f96872a534 copyright year -> 2014 2014-03-20 16:42:35 -03:00
Roberto Ierusalimschy 738b3b64af detail (to avoid warnings with '-O3') 2014-03-20 16:36:02 -03:00
Roberto Ierusalimschy 363b525c23 does not create library when it is deprecated 2014-03-20 16:22:16 -03:00
Roberto Ierusalimschy 469daa16ee configuration for Lua type corresponding to 'time_t' 2014-03-20 16:18:54 -03:00
Roberto Ierusalimschy 7707f3e7c3 'posrelat' -> 'u_posrelat' (to avoid name conflict in 'one.c') 2014-03-20 11:11:00 -03:00
Roberto Ierusalimschy 16f8e44924 with 64-bit integers, file offsets do not need to be floats 2014-03-19 15:57:42 -03:00
Roberto Ierusalimschy 2f5f77788f removed function 'luaS_eqstr' (not used anywhere) 2014-03-19 15:51:42 -03:00
Roberto Ierusalimschy ed795d5ff4 detail (removed unused prototype) 2014-03-19 15:51:16 -03:00
Roberto Ierusalimschy 282d67d8fc bitlib has been deprecated 2014-03-18 15:27:08 -03:00
Roberto Ierusalimschy 114d10cbc5 detail (comment) 2014-03-15 09:29:48 -03:00
Roberto Ierusalimschy 9f3f5b6f41 details 2014-03-14 13:54:08 -03:00
Roberto Ierusalimschy a39489194e changing prefix of configurable macros from "lua_" to "l_" 2014-03-13 17:07:18 -03:00
Roberto Ierusalimschy a3addae036 lua_gettable and similars return type of gotten value 2014-03-12 17:57:40 -03:00
Roberto Ierusalimschy ad40bb1181 detail in string.rep: allow large repetitions of the empty string (no
possibility of overflows)
2014-03-12 15:09:06 -03:00
Roberto Ierusalimschy 80fe8504f5 make all dumps/loads go trhough Load/DumpVector (so it is easier
to adapt the code to correct endianess, if needed)
2014-03-11 15:56:27 -03:00
Roberto Ierusalimschy e976384213 keep chunk's headers compatible at least up to LUAC_VERSION (to be
able to detect correctly version mismatches)
2014-03-11 15:05:46 -03:00
Roberto Ierusalimschy 68f4ccdd00 make sure that LUAC_INT is a lua_Integer and that LUAC_NUM is
a lua_Number
2014-03-11 11:22:54 -03:00
Roberto Ierusalimschy 342a936599 detail (breaking too long lines) 2014-03-10 16:52:47 -03:00
Roberto Ierusalimschy 901da539e5 no need to avoid negative ints in 'LoadInt' 2014-03-10 16:50:19 -03:00
Roberto Ierusalimschy 197e249433 "indent -kr -i2 -br -brf -nut" plus a few manual formating 2014-03-10 14:56:32 -03:00
Roberto Ierusalimschy 2aff75f58e small bug (from revision 2.80): LUA_OP* constants are not from
enumeration 'Opcode' (they are integers)
2014-03-09 16:21:34 -03:00
Roberto Ierusalimschy cd12410195 new macro 'cast_void' 2014-03-07 13:19:00 -03:00
Roberto Ierusalimschy c5bb3643ab simpler code to read a line from a file (using 'getc' or, if present,
'getc_unlocked')
2014-03-06 14:12:02 -03:00
Roberto Ierusalimschy 5ff1c18a71 back with 'L' for macros 'luai_num*', but now with a new macro
'luai_numinvalidop' to protect constant folding
2014-03-06 13:15:18 -03:00
Roberto Ierusalimschy 99ac4a260f 'constfolding' passes a proper Lua state to 'luaO_arith' 2014-03-06 10:58:28 -03:00
Roberto Ierusalimschy fa7e77fd38 detail ('codearith' uses 'LUA_OP*' constants instead of 'OP_*') 2014-03-06 10:39:05 -03:00
Roberto Ierusalimschy f69e0ade19 no need to store a full 'size_t' fo the size of (frequent) small strings 2014-03-01 12:18:44 -03:00
Roberto Ierusalimschy 99a1c06ea3 more regularity with vectors + sizeof computed by the macros themselves 2014-02-28 13:13:01 -03:00
Roberto Ierusalimschy 93e28031de all chars used in binary dumps are unsigned ('lu_byte') 2014-02-28 09:25:12 -03:00
Roberto Ierusalimschy de84b3fecb store number of upvalues of main function in front of the dump,
so that undump can create initial closure before reading its prototype
2014-02-27 15:56:15 -03:00
Roberto Ierusalimschy 054179c2ff more explicit handling of headers for binary chunks 2014-02-27 13:56:20 -03:00
Roberto Ierusalimschy 986c11daa6 removal of weird construction in definition of LUA_STRFTIMEOPTIONS
(two empty strings concatenated as in "" "")
2014-02-26 12:55:58 -03:00
Roberto Ierusalimschy c6c41e85b2 more uniformity for defining system-dependent features 2014-02-26 12:27:56 -03:00
Roberto Ierusalimschy 87c930676f detail (comments) 2014-02-26 09:39:30 -03:00
Roberto Ierusalimschy 11e762dbcd added macro MAX_UINTEGER 2014-02-26 09:38:43 -03:00
Roberto Ierusalimschy 5c9cb5f0b1 detail (comment) 2014-02-26 09:38:18 -03:00
Roberto Ierusalimschy fed236ca7f detail (unknown lines are marked as -1, not 0) 2014-02-25 11:31:16 -03:00
Roberto Ierusalimschy 295f7ac04e added 'stip' parameter to lua_dump/string.dump 2014-02-25 11:30:21 -03:00
Roberto Ierusalimschy 6318de80d3 added 'strip' parameter to lua_dump/string.dump 2014-02-25 11:30:21 -03:00
Roberto Ierusalimschy 5715de344f 'read_all' does not need to grow buffer, as 'luaL_prepbuffsize'
already does that
2014-02-21 11:39:50 -03:00
Roberto Ierusalimschy c86b9da022 userdata can have any Lua value as uservalue 2014-02-19 10:52:42 -03:00
Roberto Ierusalimschy a4c6dcf999 detail (better error messages for light userdata) 2014-02-19 10:48:53 -03:00
Roberto Ierusalimschy 3f78de256e no need to keep threads in a different GC list, now that there is the
'twups' list
2014-02-18 10:46:26 -03:00
Roberto Ierusalimschy d764cc5522 new list 'twups' to allow traversal of upvalues from dead threads
(+ fixed some problems with cycles involving those upvalues)
2014-02-18 10:39:37 -03:00
Roberto Ierusalimschy ffa96d988d field 'op' renamed to 'open' 2014-02-15 11:12:01 -02:00
Roberto Ierusalimschy 6a24bd17a8 no more second result from 'collectgarbage"count"' (as Lua seldom
will need lua_Number to be an integer)
2014-02-14 14:45:38 -02:00
Roberto Ierusalimschy 1cce3e6842 change in the way 'collectgarbage("step", size)' interprets 'size'
(mimicking the way the GC itself behaves when Lua allocates 'size'
Kbytes)
2014-02-14 14:43:14 -02:00
Roberto Ierusalimschy 0b04c561f5 new syntax for Unicode escape '\u{012F}' 2014-02-14 13:23:51 -02:00
Roberto Ierusalimschy 90b0ac6495 limit to 'gcstepmul' imposed by 'lua_gc' (+ some details in 'lgc.c') 2014-02-13 15:25:20 -02:00
Roberto Ierusalimschy de3b1c9b53 better control for number of finalizers called at each GC cycle
(increases progressively)
2014-02-13 12:46:38 -02:00
Roberto Ierusalimschy 733c58595b no more local collection 2014-02-13 10:11:34 -02:00
Roberto Ierusalimschy 4a1ed6e6e5 new field '__name' in metatables to help better error messages 2014-02-11 15:39:15 -02:00
Roberto Ierusalimschy 6b30774469 detail (better presentation for 'luaC_step') 2014-02-11 10:28:47 -02:00
Roberto Ierusalimschy ba3586cc90 keep a single list of objects to be finalized (with local and non-local
objects), to ensure finalization order
2014-02-11 10:18:12 -02:00
Roberto Ierusalimschy 68df7c6279 added proper headers for a standard lib file 2014-02-06 18:03:24 -02:00
Roberto Ierusalimschy 19ad78d713 C++ needs casts for arithmetic with enums 2014-02-06 17:55:55 -02:00
Roberto Ierusalimschy 6ccf150039 new library: utf8 2014-02-06 15:32:33 -02:00
Roberto Ierusalimschy 4ea60463f5 UTF-8 encoding exported as format '%U' in 'lua_pushfstring' 2014-02-06 13:59:24 -02:00
Roberto Ierusalimschy d438e1379d insertion of ".0" in floats with integer values done by "luaL_tolstring",
not by the core
2014-02-05 17:14:53 -02:00
Roberto Ierusalimschy 1721d09ac8 still accepts initial '=' for expressions, for compatibility with old
versions (and old habits...)
2014-02-05 12:22:55 -02:00
Roberto Ierusalimschy 2f3da00e51 added support for UTF-8 escapes 2014-02-04 16:57:34 -02:00
Roberto Ierusalimschy 5a73e3ad9e simpler way to create messages for errors in escape sequences 2014-01-31 13:14:22 -02:00
Roberto Ierusalimschy 86dd8bf3f5 no more 'L' in macros "luai_num*" (several places that use those macros
cannot throw errors anyway...)
2014-01-27 11:34:32 -02:00
Roberto Ierusalimschy 67c5de9283 comment 2014-01-27 11:28:45 -02:00
Roberto Ierusalimschy 0a850e641d larger limit + better error messages for loop detection in inheritance 2014-01-22 18:02:04 -02:00
Roberto Ierusalimschy 916bd874ad added explicit default options to string.pack/unpack functions 2014-01-09 14:21:28 -02:00
Roberto Ierusalimschy cd848cab6b first implementation for string.pack/unpackfloat + try not to assume
that chars have 8 bits
2014-01-08 16:34:34 -02:00
Roberto Ierusalimschy 29256e8960 first implementation of string.packint/string.unpackint 2014-01-05 12:05:58 -02:00
Roberto Ierusalimschy 438c534ff4 'arg' arguments (previously called 'narg', 'nArg', 'numArg', etc.)
renamed all to 'arg'
2014-01-05 12:04:46 -02:00
Roberto Ierusalimschy 1ea2d20f74 first implementation of '<<', '>>', and '~' (bitwise not) 2013-12-30 18:47:58 -02:00
Roberto Ierusalimschy f5133aa1a5 small change in handling of unary operations 2013-12-18 16:44:42 -02:00
Roberto Ierusalimschy c0edab0f6d first implementation of bitwise operators '&' (band), '|' (bor),
and '~' (bxor)
2013-12-18 12:12:03 -02:00
Roberto Ierusalimschy a948054a19 new order for binary operations (grouping them by type of result) 2013-12-16 17:06:52 -02:00
Roberto Ierusalimschy a8f8c7fd80 integer exponentiation with negative exponent is invalid 2013-12-16 12:30:22 -02:00
Roberto Ierusalimschy 1a19893d6f new "calculator mode"; no need to add '=' to print expressions 2013-12-16 12:27:17 -02:00
Roberto Ierusalimschy 88e23f508c details 2013-12-13 13:42:08 -02:00
Roberto Ierusalimschy c8585efc78 use goto to implement a tail call in 'reallymarkobject' 2013-12-13 13:17:00 -02:00
Roberto Ierusalimschy 16493b777f 'lua_sethook' returns void 2013-12-09 12:21:10 -02:00
Roberto Ierusalimschy cac1ebd1e0 detail ('ttisuserdata' renamed to 'ttisfulluserdata') 2013-12-04 10:15:22 -02:00
Roberto Ierusalimschy 73c5515e00 details (comments) 2013-11-21 15:23:14 -02:00
Roberto Ierusalimschy e34c35abcf new bug: Resuming the running coroutine makes it unyieldable 2013-11-08 16:23:16 -02:00
Roberto Ierusalimschy 7a8eb83b4a bug: attempting to resume the running coroutine makes it unyieldable 2013-11-08 16:16:33 -02:00
Roberto Ierusalimschy ab5fa213b3 added patch for last bug 2013-11-08 15:45:10 -02:00
Roberto Ierusalimschy 39929384c6 new macro 'luai_userstateclose' (to test it is being called correctly) 2013-11-08 15:36:05 -02:00
Roberto Ierusalimschy de7cf8e63a bug: should call 'luai_userstateclose' only when 'luai_userstateopen'
has been called before
2013-11-08 15:34:22 -02:00
Roberto Ierusalimschy 124598917f "./?/init.lua" added to default path 2013-10-10 12:45:03 -03:00
Roberto Ierusalimschy c5fcba1a17 detail (changing some names of macros) 2013-10-07 11:20:31 -03:00
Roberto Ierusalimschy 4c6dfc342b CallInfo lists shrinks together with their associated stacks 2013-09-17 12:40:06 -03:00
Roberto Ierusalimschy 686e57cf9c GC local pause configurable 2013-09-13 13:21:52 -03:00
Roberto Ierusalimschy 06156e7575 detail (setmetatable do not need to use a back GC barrier) 2013-09-11 17:15:31 -03:00
Roberto Ierusalimschy 2e2c109daf type of 'refcount' changed to lu_mem (to ensure there will be no
overflows)
2013-09-11 12:17:00 -03:00
Roberto Ierusalimschy 6ca7b63bce check for shrinking string table done only at the end of a GC cycle 2013-09-11 11:56:15 -03:00
Roberto Ierusalimschy 4eeb1831be new names and better order for GC states (sweep first lists that
can have dead objects)
2013-09-11 11:47:08 -03:00
Roberto Ierusalimschy dd373a8f66 threads are kept in a separated GC list, linked after the main thread 2013-09-11 11:09:55 -03:00
Roberto Ierusalimschy 7061fe1d56 detail: 'sweepstep' checks end of phase after calling 'sweeplist', so
that phases with small lists return 0 at the first call to 'sweepstep'
2013-09-11 10:24:55 -03:00
Roberto Ierusalimschy d8aa8dd97e objects in list 'tobefnz' have a GC life-cycle like all others
(specifically they are cleaned during sweep phase)
2013-09-11 09:47:48 -03:00
Roberto Ierusalimschy 1150873447 'luaC_newobj' does not handle special cases; only special case
now is threads, which do not use 'luaC_newobj' anymore.
2013-09-11 09:26:14 -03:00
Roberto Ierusalimschy 79ab21be90 more invariants added to memory check 2013-09-11 09:26:14 -03:00
Roberto Ierusalimschy d3bbb34c24 back to open hashing for the string table (but with a different
'hnext' field, to strings are still collected like all other
objects)
2013-09-05 16:31:49 -03:00
Roberto Ierusalimschy 0ad15fc100 better (and correct!) control of 'maybedead' 2013-09-04 12:34:24 -03:00
Roberto Ierusalimschy aeff4f79fa local collection now calls finalizers 2013-09-03 12:37:10 -03:00
Roberto Ierusalimschy 1bf4faec64 new GC state to sweep 'localgc' list + small changes in sweep control 2013-08-30 16:14:26 -03:00
Roberto Ierusalimschy 8ef9e8460e bug (GC can collect long identifier during parser) + change (using
a single constant table for all functions in a chunk)
2013-08-30 13:01:37 -03:00
Roberto Ierusalimschy 4f292d753c bug: GC can collect a long string still in use during parser 2013-08-30 12:51:12 -03:00
Roberto Ierusalimschy 26629d0af1 details (a few casts moved from macro invocation to macro definition) 2013-08-29 10:49:57 -03:00
Roberto Ierusalimschy b5e75fde4e bug: local collection must clear rest of stack 2013-08-29 10:34:16 -03:00
Roberto Ierusalimschy 9a871dd3db tables and userdata all go to local list, too 2013-08-28 15:30:26 -03:00
Roberto Ierusalimschy 90972ff136 LOCALBLACK changed to LOCALMARK and used also to control whether object
is in 'localgc' list + luaC_newobj by default puts object in 'localgc'
list
2013-08-27 17:04:00 -03:00
Roberto Ierusalimschy af35c7f398 upvalues collected by reference count 2013-08-27 15:53:35 -03:00
Roberto Ierusalimschy 742b7377d3 Lua closures go to local, too 2013-08-26 09:41:10 -03:00
Roberto Ierusalimschy 50955e27f5 C functions and strings now go to the local list; first version
of the local collector
2013-08-23 10:34:54 -03:00
Roberto Ierusalimschy 33c49f7fa0 some details over new implementation of string table 2013-08-22 12:21:48 -03:00
Roberto Ierusalimschy 0df6635711 "fixed" objects kept in a separated list (instead of being kept in
'allgc' list with a bit marking them)
2013-08-21 17:09:51 -03:00
Roberto Ierusalimschy ae800656c9 change in string table: string table is now independent of GC lists; all
strings live in 'normal' GC lists
2013-08-21 16:21:16 -03:00
Roberto Ierusalimschy 8c68863960 initial size of string table (MINSTRTABSIZE) should be large enough
to hold all strings needed by an empty Lua state
2013-08-21 16:02:30 -03:00
Roberto Ierusalimschy 8f6b80aa1d GC bits SEPARATED and FINALIZEDBIT mixed in FINALIZEDBIT (with simpler
control)
2013-08-20 14:46:34 -03:00
Roberto Ierusalimschy 9eff921f8f "barrier" for link prototype->cache changed to be consistent with
GC behavior (link is cleared to preserve invariant)
2013-08-19 11:18:43 -03:00
Roberto Ierusalimschy 8e6b7ef9ab new function 'isgclocal' + test for GC consistency of prototype's caches 2013-08-19 11:16:33 -03:00
Roberto Ierusalimschy caceeab750 'next' field for tables changed from pointer to integer (for better
alignment on 64-bit machines)
2013-08-18 13:12:18 -03:00
Roberto Ierusalimschy 3991312b94 details 2013-08-16 16:02:31 -03:00
Roberto Ierusalimschy 439d74e29f added 'local' bit (true => object is only refered by local variables) 2013-08-16 15:55:49 -03:00
Roberto Ierusalimschy 3679d33b02 barrier conditions rewritten to test first 'isblack' and then 'iswhite'
(during a pause all objects are white, so 'isblack' fails much more
often than 'iswhite')
2013-08-13 14:36:44 -03:00
Roberto Ierusalimschy 78b941039d change to allow collector to stop when it goes to the atomic phase
(just for debugging)
2013-08-07 12:39:09 -03:00
Roberto Ierusalimschy 623e388bb4 double-linked list of all upvalues elliminated and changed to a
traversal of all non-marked threads
2013-08-07 09:18:11 -03:00
Roberto Ierusalimschy 677d90165f no more generational collection !!! 2013-08-05 13:58:28 -03:00
Roberto Ierusalimschy 4244da96bf 'debug.subtype' -> 'math.type' (to distinguish integers and floats) 2013-07-22 13:05:53 -03:00
Roberto Ierusalimschy fcf99bf788 'math.isfloat' replaced by 'debug.subtype' 2013-07-10 17:57:05 -03:00
Roberto Ierusalimschy 98d76cdcae bug: Wrong error message in some short-cut expressions 2013-07-10 17:32:36 -03:00
Roberto Ierusalimschy 2f8c51a552 use unsigneds for unary minus, too 2013-07-10 14:15:12 -03:00
Roberto Ierusalimschy b5f5fcd782 use different constants (instead of different values for the same constant)
to define number sizes (LUA_INT_INT/LUA_INT_LONG/LUA_INT_LONGLONG and
LUA_REAL_FLOAT/LUA_REAL_DOUBLE/LUA_REAL_LONGDOUBLE) + use __int64 and
I64 instead of long long (and ll) for Windows
2013-07-09 15:31:35 -03:00
Roberto Ierusalimschy 2ef9bcfd11 avoid undefined shift of LUA_NBITS in rotate operation 2013-07-09 15:31:01 -03:00
Roberto Ierusalimschy 5fa680d47f no need for type 'b_uint' (lua_Unsigned must have at least 32 bits) 2013-07-09 14:49:50 -03:00
Roberto Ierusalimschy 48735da0d0 When loading a file, Lua may call the reader function again after
it returned end of input + luac listings choke on long strings
2013-07-05 15:02:28 -03:00
Roberto Ierusalimschy 2b4bd21585 'tonumber': base must be a number 2013-07-05 11:39:15 -03:00
Roberto Ierusalimschy beff5b078a 'tonumber': does not accept numbers when given a base + convertion from
strings to numbers with a base moved to a separated function (more
modular)
2013-07-05 11:35:49 -03:00
Roberto Ierusalimschy 5519c98655 'lua_cvtonum' -> 'lua_strtonum'; converts only strings to numbers 2013-07-05 11:29:51 -03:00
Roberto Ierusalimschy cbe164191c new function 'ifloor' 2013-07-03 14:23:19 -03:00
Roberto Ierusalimschy 66d046833d no need to check "bad conversion number->int;" in luaL_checkversion,
as now Lua does not use tricks for the conversion, but there is a
need to check the sizes of number types, as they can be different
in two modules
2013-06-27 15:32:33 -03:00
Roberto Ierusalimschy 15fdbd26fe 'numbits' moved from 'math' to 'debug' library 2013-06-25 16:37:00 -03:00
Roberto Ierusalimschy 2b4975dca7 LUA_SMALL_* changed to LUA_*SIZE + added support for long double + better
support for ANSI systems
2013-06-25 16:04:40 -03:00
Roberto Ierusalimschy e39da66c8c macro 'lua_strx2number' does not need to be global 2013-06-25 15:58:32 -03:00
Roberto Ierusalimschy 483c2ccd0f avoid using raw representation of numbers for hashing, as number may
not use all its space (e.g., long double can have sizeof=12 but
use only 10 bytes)
2013-06-25 15:57:18 -03:00
Roberto Ierusalimschy 982aa7058f 'luaL_len' returns lua_Integer instead of 'int' 2013-06-25 11:05:26 -03:00
Roberto Ierusalimschy 80cdf39d0e avoid using 'modf' in the implementation of 'math.modf', to avoid
problems with 'double*'. (When using 'float' as lua_Number,
'float*' is not compatible with 'double*'...)
2013-06-25 11:02:18 -03:00
Roberto Ierusalimschy 45f3797a5b 'long' may have more than 32 bits in some machines; use 'int' for
small lua_Integer unless necessary to use 'long'
2013-06-21 14:42:28 -03:00
Roberto Ierusalimschy de6e5a5919 small bugs uncovered in a 64-bit machine (where 'long' has 64 bits) 2013-06-21 14:27:24 -03:00
Roberto Ierusalimschy 81102d3689 try to avoid warnings when converting int to pointer 2013-06-20 18:59:13 -03:00
Roberto Ierusalimschy 6579bd4190 reorganization of warnings + update of explicit dependencies (gcc -MM) 2013-06-20 15:56:51 -03:00
Roberto Ierusalimschy f45177f2d3 In the table that hashes constants, use a light userdata as keys
to integer values to avoid collisions with floats with the same
numerical value
2013-06-20 14:37:31 -03:00
Roberto Ierusalimschy d6f5fb2d2c avoid warning for unary minus over an unsigned value 2013-06-20 12:12:43 -03:00
Roberto Ierusalimschy 7c4cc505db added "reasonable" limit for 'string.rep' (otherwise it is too easy
to crash the machine)
2013-06-20 12:06:51 -03:00
Roberto Ierusalimschy 453450d687 new macro 'l_floor' (allows 'floorf' even when other math operations
do not have an 'f' variant)
2013-06-20 12:02:49 -03:00
Roberto Ierusalimschy 55f566bd22 use lua_Integer for integer parameters to avoid truncation 2013-06-19 11:29:01 -03:00
Roberto Ierusalimschy 130c0e40e0 new constant 'MAX_SIZE', distinct from 'MAX_SIZET', for sizes visible
from Lua; these must fit in a lua_Integer
2013-06-19 11:27:00 -03:00
Roberto Ierusalimschy c72fb1cf8e detail (removed 'assert') 2013-06-14 17:46:40 -03:00
Roberto Ierusalimschy 138e69cc55 correct error message for floating-point values out of (integer) range 2013-06-14 15:34:49 -03:00
Roberto Ierusalimschy 53210d7e5b correct way (I hope) to convert floats to unsigned int 2013-06-14 15:32:45 -03:00
Roberto Ierusalimschy 0394314c7a avoid using a negative value to test 'lua_tounsigned' 2013-06-14 15:12:53 -03:00
Roberto Ierusalimschy 0beeb4f6fa configuration of number sizes goes "mainstream" 2013-06-13 16:35:08 -03:00
Roberto Ierusalimschy 788b251157 'math.random' operates with integers when used for integer results
(1 or 2 parameters)
2013-06-13 16:32:52 -03:00
Roberto Ierusalimschy 318575627f avoid adding '.0' to "numbers" like "nan" and "inf" 2013-06-07 16:02:05 -03:00
Roberto Ierusalimschy a14992992a new version (5.3) 2013-06-07 16:01:50 -03:00
Roberto Ierusalimschy 48adb6984c 'io.write' writes integers directly (and correctly) 2013-06-07 16:01:35 -03:00
Roberto Ierusalimschy c5069528e1 details ('Type* id' -> 'Type *id') 2013-06-07 11:51:10 -03:00
Roberto Ierusalimschy 6fb0b11350 string contatenation handles conversion of integers to strings +
floats always format as floats (with decimal dot or exponent)
2013-06-04 16:36:42 -03:00
Roberto Ierusalimschy 932e7fb0e1 'lua_tounsigned' takes number modulo 2^numbits as a result when
number is a float
(That may change...)
2013-06-04 16:34:51 -03:00
Roberto Ierusalimschy 188192ce9a 'luai_hashnum' "inlined" into 'hashfloat' 2013-05-29 11:05:03 -03:00
Roberto Ierusalimschy fc083f1138 removed all tricks for conversions + 'luai_hashnum' moved to ltable.c 2013-05-29 11:04:15 -03:00
Roberto Ierusalimschy ee865b9fe7 new implementation for 'lua_strx2number' to correct small
problems with numbers like 0x10000...000p-100
2013-05-27 14:42:38 -03:00
Roberto Ierusalimschy d630daca1a "legal" way to convert a float to an integer in C 2013-05-27 09:43:37 -03:00
Roberto Ierusalimschy 8c883cb4e8 'objlen' can return integers 2013-05-26 11:47:51 -03:00
Roberto Ierusalimschy c75cca0559 detail (case '%d' of 'luaO_pushvfstring' should use integers) 2013-05-26 11:43:35 -03:00
Roberto Ierusalimschy 1414b7123c support for the case when 'l_mathop' does not conform to lua_Number
(problem with pointers to lua_Number solved by a typedef selected
automatically by 'l_mathop')
2013-05-26 10:45:24 -03:00
Roberto Ierusalimschy 3563b3f519 first version of control for number sizes (still in 'local' section) 2013-05-26 10:35:52 -03:00
Roberto Ierusalimschy d46ed54646 no more IEEE tricks 2013-05-26 10:26:34 -03:00
Roberto Ierusalimschy e2c8c756ee removed 'IEEE tricks' (should not be needed in Lua with integers) 2013-05-23 18:27:06 -03:00
Roberto Ierusalimschy 5ca5086c19 'tonumber' now works with integers too 2013-05-16 15:35:57 -03:00
Roberto Ierusalimschy 2d6a0ae149 added patch to last bug 2013-05-16 13:03:50 -03:00
Roberto Ierusalimschy b5ec26101f new API function 'lua_cvtonum' to convert a value (number or string)
to a number, following the rules of the language to create integers
or floats
2013-05-14 13:00:11 -03:00
Roberto Ierusalimschy 36e8771076 'luaO_str2int' more generic: accepts white spaces around the numeral
and handles signal
2013-05-14 12:59:04 -03:00
Roberto Ierusalimschy 27f09415e3 new read format "*i" for reading integers 2013-05-14 12:57:43 -03:00
Roberto Ierusalimschy 4ad9970649 uses integers for time 2013-05-14 12:57:11 -03:00
Roberto Ierusalimschy bef345a4b8 bug: Wrong error message in some short-cut expressions 2013-05-13 13:17:47 -03:00
Roberto Ierusalimschy 0ce3018109 'pushnum' pushes a "number" (float) + new C instruction 'pushint' 2013-05-07 16:01:16 -03:00
Roberto Ierusalimschy 0233ce0815 new function 'math.numbits' (not a final decision) 2013-05-06 14:22:55 -03:00
Roberto Ierusalimschy 1f2b82bf25 correct way to avoid compile-time errors in integer divisions 2013-05-06 14:22:16 -03:00
Roberto Ierusalimschy f2043b7a58 correct error message for conversion errors from float to int 2013-05-06 14:21:59 -03:00
Roberto Ierusalimschy 2b1c2c61b0 bug: Wrong assert when reporting concatenation errors. 2013-05-06 14:21:28 -03:00
Roberto Ierusalimschy fa6ea831b3 macro 'nvalue' removed (direct conversion from integer to double,
without an intermediate variable, can cause "excessive precision"
2013-05-06 14:17:09 -03:00
Roberto Ierusalimschy b22a4280c6 macro 'nvalue' removed + cast to void added to avoid warnings
with 'clang'
2013-05-06 14:17:09 -03:00
Roberto Ierusalimschy 29fe3abda2 new function 'math.isfloat' 2013-05-02 14:31:54 -03:00
Roberto Ierusalimschy 6347004be9 stack overflow in vararg functions + garbage collector in recursive loops 2013-05-02 13:13:27 -03:00
Roberto Ierusalimschy 67532d5a10 constant folding and API arithmetic with integers 2013-05-02 09:37:24 -03:00
Roberto Ierusalimschy 6920a7f2e3 new macro 'intop' (to perform integer arithmetic on unsigned types) 2013-05-02 09:31:26 -03:00
Roberto Ierusalimschy 88bf2f83c0 new function 'tointeger' + 'luaV_arith' replaced by 'luaT_trybinTM' 2013-04-29 14:12:50 -03:00
Roberto Ierusalimschy 8fff05f6d0 integer division operates only on integers 2013-04-29 14:12:12 -03:00
Roberto Ierusalimschy 9b9becf384 added 'const' to parameters of 'luaG_concaterror' 2013-04-29 13:58:10 -03:00
Roberto Ierusalimschy 00744a2729 'luaO_arith' -> 'luaO_numarith' 2013-04-29 13:57:48 -03:00
Roberto Ierusalimschy b4be507578 new function 'luaT_trybinTM' 2013-04-29 13:56:50 -03:00
Roberto Ierusalimschy 360587f319 favoring 'tonumber' over 'nvalue' 2013-04-26 16:51:17 -03:00
Roberto Ierusalimschy eee51492e2 dumping and undumping integers 2013-04-26 15:48:35 -03:00
Roberto Ierusalimschy c37b7b3cca bug: garbage collector can trigger too many times in recursive loops,
because it was not computing the size of CallInfo structures in threads
2013-04-26 15:26:49 -03:00
Roberto Ierusalimschy f79584faca detail 2013-04-26 13:06:53 -03:00
Roberto Ierusalimschy 4abe99dc34 new interface for 'tonumber' 2013-04-26 13:03:50 -03:00
Roberto Ierusalimschy d4e6b75098 "integer" keys in tables are now lua_Integer, not 'int'. 2013-04-26 12:39:25 -03:00
Roberto Ierusalimschy a2f5c28a80 new operation '//' (integer division) 2013-04-26 10:08:29 -03:00
Roberto Ierusalimschy a80a2b5e56 new cast macros for lua_Integer and lua_Unsigned 2013-04-25 18:15:37 -03:00
Roberto Ierusalimschy bb1851ce98 'for' loop uses integers when possible 2013-04-25 16:50:02 -03:00
Roberto Ierusalimschy 5951c79ae1 default increment for 'for' loop is an integer (1, not 1.0) 2013-04-25 16:35:19 -03:00
Roberto Ierusalimschy e381c582de integer handling for order comparisons, power, and modulo operations 2013-04-25 16:12:41 -03:00
Roberto Ierusalimschy 9600c60df3 functions 'get_equalTM' and 'call_orderTM' moved to other files
to make 'lvm.c' smaller
2013-04-25 13:07:52 -03:00
Roberto Ierusalimschy 32bf6c9b27 functions 'traceexec', 'callTM', and 'call_binTM' moved to other
files to make 'lvm.c' a little smaller
2013-04-25 12:59:42 -03:00
Roberto Ierusalimschy 9c43d6a24e new format "%I" in 'lua_pushfstring' for lua_Integer 2013-04-25 10:53:13 -03:00
Roberto Ierusalimschy 01b6fe0cbf new API function 'lua_isinteger' 2013-04-25 10:52:49 -03:00
Roberto Ierusalimschy 944709c77b more definitions to support integer formatting 2013-04-25 10:52:13 -03:00
Roberto Ierusalimschy 52cb90ec75 detail 2013-04-24 16:41:48 -03:00
Roberto Ierusalimschy fa3b126a23 BUG: stack overflow in vararg functions with many fixed
parameters called with few arguments
2013-04-19 18:05:04 -03:00
Roberto Ierusalimschy 1294b09d8e first implementation of literal integers (no constant folding yet) 2013-04-16 15:46:28 -03:00
Roberto Ierusalimschy d4f0c4435d a few more operations supporting integers (minus, umin, mult) 2013-04-16 15:43:05 -03:00
Roberto Ierusalimschy 44358e0206 extra trim applied to 'replace' argument (in case lua_Unsigned is
larger than 32 bits)
2013-04-16 15:39:37 -03:00
Roberto Ierusalimschy 07f861385e first steps in the support of integers: basic representation + table indexing + basic API ops (tointeger/pushinteger) + equality + a few extra stuff 2013-04-15 12:44:46 -03:00
Roberto Ierusalimschy 7a543cfae6 2013-04-15 12:43:34 -03:00
Roberto Ierusalimschy 24689927f2 dependencies updated (with 'gcc -MM') 2013-04-15 11:13:38 -03:00
Roberto Ierusalimschy 8f8665fffa 'ttypenv' -> 'ttnov' 2013-04-12 16:07:09 -03:00
Roberto Ierusalimschy 49c1607157 _FILE_OFFSET_BITS usually also needs _LARGEFILE_SOURCE + easier to
use default definition for 'l_fseek' in ansi systems
2013-04-11 15:34:06 -03:00
Roberto Ierusalimschy c8e96d6e91 logic for checking mode for 'fopen' moved to macro 'lua_checkmode' 2013-03-21 10:57:27 -03:00
Roberto Ierusalimschy af8efcc762 detail (avoid unnecessary "unconst" in cast) 2013-03-21 10:54:57 -03:00
Roberto Ierusalimschy 3f6f78ea0b detail (error message) 2013-03-20 16:40:07 -03:00
Roberto Ierusalimschy e3a7104b40 detail (avoiding warnings) 2013-03-19 10:19:12 -03:00
Roberto Ierusalimschy 76492b4bb2 macro 'lua_checkmode' + typos in comments 2013-03-16 18:10:18 -03:00
Roberto Ierusalimschy 75250a237c typos in comments 2013-03-16 18:10:18 -03:00
Roberto Ierusalimschy 437a49be5e cast to avoid warnings 2013-03-15 15:33:36 -03:00
Roberto Ierusalimschy 4f0c716c8e added two more commented warning options (just to know about them) 2013-03-15 11:00:08 -03:00
Roberto Ierusalimschy 70b0ee6310 export 'lua_ident' to avoid it being removed by C++ linker 2013-03-15 10:04:22 -03:00
Roberto Ierusalimschy 8830901a9c second parameter to 'ldexp' is an integer 2013-03-07 15:21:32 -03:00
Roberto Ierusalimschy 15a3738b49 no need to handle 0 as a special case in 'table.remove' 2013-03-07 15:17:24 -03:00
Roberto Ierusalimschy a83ed55f1e added 'return' (when possible) to calls to error functions 2013-02-21 10:44:53 -03:00
Roberto Ierusalimschy b559aed2d3 'l_tg' was renamed to 'l_mathop' and this use was not corrected at
the time
2013-02-20 11:08:56 -03:00
Roberto Ierusalimschy d0c038da07 typo in comment 2013-02-20 11:08:21 -03:00
Roberto Ierusalimschy db424053e8 new release number + copyright year 2013-02-19 15:39:04 -03:00
Roberto Ierusalimschy ad56721948 details (5.2 corrected to 5.2.0) 2013-02-07 13:57:47 -02:00
Roberto Ierusalimschy f4e762f688 better error checking for 'table.insert' and 'table.remove' 2013-02-06 16:29:03 -02:00
Roberto Ierusalimschy 1ce57628b2 comments 2013-02-06 11:37:39 -02:00
Roberto Ierusalimschy 181a837cac small improvement in the support of 'float' as lua_Number 2013-01-29 14:00:40 -02:00
Roberto Ierusalimschy 0730a56d38 detail 2013-01-08 12:06:55 -02:00
Roberto Ierusalimschy eecc1491f3 added some comments 2012-12-05 17:57:00 -02:00
Roberto Ierusalimschy 7ea68d84c4 added comment 2012-12-05 17:49:55 -02:00
Roberto Ierusalimschy 0e9167bc72 missing brackets in 'if' body (no bug, only 'luaC_checkfinalizer' is
called to do nothing)
2012-12-05 17:09:23 -02:00
Roberto Ierusalimschy 65e31fb179 Bug: load/loadfile returns wrong result when given an environment
for a binary chunk with no upvalues
2012-12-03 18:18:02 -02:00
Roberto Ierusalimschy f993771c70 avoids warning with 'clang' + comment explaining macro 2012-11-14 15:21:34 -02:00
Roberto Ierusalimschy 52f9ccd298 removed unreacheable 'lua_unlock' 2012-11-04 18:08:17 -02:00
Roberto Ierusalimschy a799ed5af9 more precise control for GC pause (based on threshold) 2012-10-19 16:00:33 -03:00
Roberto Ierusalimschy 4082c77ff2 error message for 'bad self' includes original 'extramsg' 2012-10-19 12:55:01 -03:00
Roberto Ierusalimschy bc84180d12 error message in 'os.rename' does not include file name, because error
may be caused both by 'fromname' or 'toname'
2012-10-19 12:54:02 -03:00
Roberto Ierusalimschy ad5da6ba14 API functions get acceptable indices except when not possible (when
they modify the value at that index) + new macro 'ispseudo' +
specific test 'api_checkstackindex'
2012-10-19 12:52:46 -03:00
Roberto Ierusalimschy 86b39206d9 open upvalues cannot be old if thread is not old; when thread is old,
their list is not traversed anymore, and therefore can contain dead
elements.
2012-10-03 09:36:46 -03:00
Roberto Ierusalimschy fdae4b9453 removed commented-out line (for debugging) 2012-10-03 09:36:17 -03:00
Roberto Ierusalimschy 84b6581287 cast to avoid warning in some compilers (size_t x unsigned int) 2012-10-02 14:41:50 -03:00
Roberto Ierusalimschy c6b6024a9d cast in 'luai_makeseed' now casts to needed type 2012-10-02 14:40:53 -03:00
Roberto Ierusalimschy d58ce8106e macro 'lua_number2unsigned' also needs proper definition if
lua_Number is float
2012-10-02 14:32:44 -03:00
Roberto Ierusalimschy 31f7d553e4 LUA_CORE condition removed from definition of some 'tricks' (as it
controlled only a few other defines) + MS_ASMTRICK renamed to
LUA_MSASMTRICK
2012-10-01 11:14:45 -03:00
Roberto Ierusalimschy adaba04059 'pcall' may not restore previous error function when
inside coroutines + Check for garbage collector in function calls
does not cover all paths
2012-10-01 11:05:31 -03:00
Roberto Ierusalimschy b157f3546e BUG: 'pcall' may not restore previous error function when
inside coroutines
2012-10-01 11:05:04 -03:00
Roberto Ierusalimschy ab7086e209 pops the string from 'get_prompt' only after using it 2012-09-29 17:07:06 -03:00
Roberto Ierusalimschy 7a3de1aba3 typo in comment 2012-09-24 19:57:26 -03:00
Roberto Ierusalimschy 8287a0db55 detail 2012-09-11 16:37:16 -03:00
Roberto Ierusalimschy cf160abcf9 no more macro 'changenvalue' 2012-09-11 15:21:44 -03:00
Roberto Ierusalimschy ae1d318822 small bug: generational mode is always in 'propagate' mode only
outside the collector: during collection of course it must go to
other modes.
2012-09-11 09:53:08 -03:00
Roberto Ierusalimschy 2038073975 more regularity for field 'fix' 2012-09-11 09:42:14 -03:00
Roberto Ierusalimschy 2dc91ca5ee checks garbage collector every time it calls a function (as the
stack can grow and so allocates more memory)
2012-08-28 15:30:45 -03:00
Roberto Ierusalimschy a3e1c40d6d remove of unecessary luaD_checkstack. (In some cases, C should
ensure stack space; in others, Lua can use the extra slots for
temporary values.)
2012-08-16 14:34:28 -03:00
Roberto Ierusalimschy c1a2a646c8 details (no need to use lua_pushfstring for plain strings) 2012-08-16 14:32:20 -03:00
Roberto Ierusalimschy 53480f1163 details (remove of some extra spaces) 2012-08-14 15:12:34 -03:00
Roberto Ierusalimschy 233eac4d3a detail (avoid being picky about conversion from 'unsigned char'
to 'int')
2012-08-06 10:36:34 -03:00
Roberto Ierusalimschy 6625cbecd1 Bug: Some patterns can overflow the C stack, due to recursion
(Took the opportunity to refactor function 'match')
2012-07-31 14:48:42 -03:00
Roberto Ierusalimschy 4ac55997ec typo 2012-07-13 11:54:14 -03:00
Roberto Ierusalimschy 763f84c84c Some patterns can overflow the C stack, due to recursion. 2012-07-13 11:53:38 -03:00
Roberto Ierusalimschy e4f609d0ee collector in generational mode must be in 'propagate' state when
not running a collection
2012-07-04 12:52:38 -03:00
Roberto Ierusalimschy 5ac56a94dd collector in generational mode should never be in 'pause' state 2012-07-02 12:38:36 -03:00
Roberto Ierusalimschy 4fc15bbfb7 major collections in generational mode are triggered by comparison with
the memory estimate from last major collection
2012-07-02 10:40:05 -03:00
Roberto Ierusalimschy f7ec36ab16 comment 2012-07-02 10:37:04 -03:00
Roberto Ierusalimschy b926472312 change in error message 2012-06-29 16:23:33 -03:00
Roberto Ierusalimschy 78d9865900 bugs: Internal Lua values may escape through the debug API +
Problems when yielding from debug hooks
2012-06-11 14:49:37 -03:00
Roberto Ierusalimschy cc2a60ecb7 bugs in yields inside debug hooks 2012-06-08 12:14:04 -03:00
Roberto Ierusalimschy 43bfb60ac8 new auxiliary function 'luaI_printinst' (to print a single instruction) 2012-06-07 15:52:47 -03:00
Roberto Ierusalimschy c510d94549 includes counts from 'sweeptolive' in cost of atomic step 2012-05-31 18:28:59 -03:00
Roberto Ierusalimschy 4dd0622d0c bug in luaL_getsubtable (calling lua_absindex not with original stack) 2012-05-31 17:28:45 -03:00
Roberto Ierusalimschy ab2c3d5cde small bug in error handling of finalizers (cannot call lua_tostring
inside the core) + small bug in luaC_checkfinalizer (when avoiding
remove object being sweeped from sweep list) + small changes in GC
pace control (for the atomic part)
2012-05-31 17:26:14 -03:00
Roberto Ierusalimschy 01e5f358bd small improvement in lua_checkmemory (only allow dead objects in
part of the sweep list not yet sweeped)
2012-05-31 17:25:42 -03:00
Roberto Ierusalimschy 69c775de21 update of 'lua_checkmemory' 2012-05-30 13:40:29 -03:00
Roberto Ierusalimschy 6fcdfc6d4f bug: object being moved to 'finobj' list might not be sweeped by
the collector
2012-05-30 13:01:10 -03:00
Roberto Ierusalimschy b77a90681e typos in comments 2012-05-30 09:33:44 -03:00
Roberto Ierusalimschy 6efffb9acd only count in 'atomic' objects marked for the first time 2012-05-29 14:52:17 -03:00
Roberto Ierusalimschy 51e8f08e60 more efficient way to apply 'stepmul' + some changes in GC parameters 2012-05-28 17:41:00 -03:00
Roberto Ierusalimschy 5adb5a4812 definition for 'MAX_LMEM' 2012-05-28 17:32:28 -03:00
Roberto Ierusalimschy e29f3a5751 definition of 'GCSTEPSIZE' moved to header file + small changes 2012-05-23 12:43:14 -03:00
Roberto Ierusalimschy 21ed264a38 compensate for 'GCSTEPSIZE' in GC steps 2012-05-23 12:42:27 -03:00
Roberto Ierusalimschy e131eb0d9a removed debug code 2012-05-23 12:41:53 -03:00
Roberto Ierusalimschy 054c20cd5b spaces -> tabs in #defines 2012-05-23 12:37:09 -03:00
Roberto Ierusalimschy 8e7149f496 detail ('char' should be 'const char') 2012-05-22 15:38:56 -03:00
Roberto Ierusalimschy 086da10dac merge of fields 'lastmajormem' (used in gen. mode) and 'estimate'
(used in inc. mode)
2012-05-22 14:50:39 -03:00
Roberto Ierusalimschy b36b4b521f try to avoid sweeping new objects created with new white (and
therefore not collectable in the current cycle)
2012-05-22 14:32:25 -03:00
Roberto Ierusalimschy 398811a313 simpler macro 'luaC_condGC' + better 'step' in 'lua_gc' +
micro bug in 'luaC_checkfinalizer' (current sweep object could be
removed from 'allgc' list)
2012-05-21 10:18:10 -03:00
Roberto Ierusalimschy 2a66b34f72 revamp of the GC pace control; more like 5.1: any X Kbytes allocated
makes the GC handle f(X) Kbytes of objects
2012-05-20 17:36:44 -03:00
Roberto Ierusalimschy 8d0e1ed52f extend optimization of 'if a then break end' for the case
'if a then break; end'
2012-05-20 11:51:23 -03:00
Roberto Ierusalimschy 3ac595da8a allow "long double" precision for PI constant if needed 2012-05-18 14:47:53 -03:00
Roberto Ierusalimschy ea980fdeef removed 'stringmark' trick 2012-05-14 14:52:56 -03:00
Roberto Ierusalimschy 5654763797 macro 'checkGC' takes care of setting 'top' to limit stack live values 2012-05-14 14:50:49 -03:00
Roberto Ierusalimschy edfa9e007d details (header comments) 2012-05-14 10:34:18 -03:00
Roberto Ierusalimschy 31829ad177 test for whether collector is running moved from function to
macro 'luaC_condGC'.
2012-05-11 16:22:33 -03:00
Roberto Ierusalimschy c2361e0b61 definition for 'LUAI_MAXSHORTLEN' moved to luaconf.h (too important) 2012-05-11 11:14:42 -03:00
Roberto Ierusalimschy 77cbd817d1 better(?) handling of '#define's for IEEE-related tricks + avoid using
IEEE trick for 64-bit integer types (lua_Integer on 64-bit machines)
2012-05-11 11:10:50 -03:00
Roberto Ierusalimschy 4ec7d6de95 bug: wrong handling of 'nCcalls' in coroutines 2012-05-11 11:10:28 -03:00
Roberto Ierusalimschy f6a12948ca useless parameter in macro 'luai_makeseed' 2012-05-11 11:06:07 -03:00
Roberto Ierusalimschy 3cadc37f47 no more 'Proto' objects on the stack. Protos are anchored on outer
Protos or on a Closure, which must be created before the Proto.
2012-05-08 10:53:33 -03:00
Roberto Ierusalimschy bb1146dc39 wrong error message when 'coroutine.create' or 'coroutine.wrap' are
called with no arguments (new thread is assumed to be the missing
argument).
2012-04-27 15:59:04 -03:00
Roberto Ierusalimschy fc24a3a6c4 small bug: a reader function should not modify the Lua stack 2012-04-27 11:13:19 -03:00
Roberto Ierusalimschy a94ce68e0a bug: wrong handling of 'nCcalls' in coroutines 2012-04-26 17:41:18 -03:00
Roberto Ierusalimschy ec22fc963a detail (separate code to create 'searchers' table into a new function) 2012-04-26 16:38:52 -03:00
Roberto Ierusalimschy c54f5f64c9 primaryexp -> suffixedexp; prefixexp -> primaryexp + more 'syntactical'
way to distinguish between function calls and assignments
2012-04-20 16:20:05 -03:00
Roberto Ierusalimschy 4cca1a436d details (using lua_setglobal/lua_getglobal instead of explicit
use of the global table)
2012-04-20 14:05:17 -03:00
Roberto Ierusalimschy 8df0198178 release 5.2.1 2012-04-20 10:18:26 -03:00
Roberto Ierusalimschy 048be9cf27 different scheme to check arguments to '%d', '%x', etc. Old scheme
did not work well when lua_Number is an integer.
2012-04-20 10:16:48 -03:00
Roberto Ierusalimschy 1485ea2ee7 Finalizers may call functions from a dynamic library after
the library has been unloaded
2012-04-12 13:25:25 -03:00
Roberto Ierusalimschy b10dbe5c72 bug: C libraries must be unloaded after all other finalizers have run,
because a finalizer may use a C function from a C library
2012-04-11 13:35:32 -03:00
Roberto Ierusalimschy 462375ba47 'if' to avoid empty 'memcpy' (may be expensive) 2012-04-03 16:06:19 -03:00
Roberto Ierusalimschy cfbe2333a4 string hash may not use all bytes (but this is configurable now) +
small other changes
2012-03-28 15:28:25 -03:00
Roberto Ierusalimschy afc3fcf952 definition for 'LUA_MAXSHORTLEN' moved to 'lstring.c' (used only there) 2012-03-28 15:27:25 -03:00
Roberto Ierusalimschy 99bd1a000f error function can be 'l_noret' 2012-03-19 19:58:09 -03:00
Roberto Ierusalimschy 3e66d3b4be cleaner code (avoids loop with empty body) 2012-03-19 19:57:14 -03:00
Roberto Ierusalimschy 29a28693e5 'luaL_checkversion' called by 'luaL_setfuncs' 2012-03-18 13:52:49 -03:00
Roberto Ierusalimschy 678c1255c9 random seed used in the hash of all strings to avoid intentional
collisions
2012-02-01 19:57:15 -02:00
Roberto Ierusalimschy a4b96ce9a3 first implementation of long strings 2012-01-25 19:05:40 -02:00
Roberto Ierusalimschy 291f564485 field 'reserved' -> 'extra' (may be used for other purposes too) 2012-01-23 21:05:51 -02:00
Roberto Ierusalimschy 9f1a8dbdd3 'eqstr' -> 'luaS_eqstr' 2012-01-23 21:05:18 -02:00
Roberto Ierusalimschy d19f1da6ef new macro 'isreserved' + 'eqstr' -> 'luaS_eqstr' (may be a function) 2012-01-23 21:04:07 -02:00
Roberto Ierusalimschy f88806a1fb "default: lua_assert(0)" in switches helps debugging + uses
non-variant types in binary files
2012-01-23 21:02:10 -02:00
Roberto Ierusalimschy fb6eee2805 Lua never uses Ã'assert' (it is always 'lua_assert') 2012-01-23 20:59:02 -02:00
Roberto Ierusalimschy 0010ec68b1 documentation comment (small correction about strings being
gray)
2012-01-23 18:29:12 -02:00
Roberto Ierusalimschy 28f8ed9113 new macro 'checktype' 2012-01-20 20:47:11 -02:00
Roberto Ierusalimschy fd22ccd6d0 object tag keeps variant bits too -> no need for 'isC' field in
Closures + more strick typing for closure variants
2012-01-20 20:05:50 -02:00
Roberto Ierusalimschy 76eab106df bug: Lexical gets confused with some combination of arithmetic
operators and hexadecimal numbers
2012-01-20 16:35:36 -02:00
Roberto Ierusalimschy 81ed85ecfb BUG: memory hoarding when creating Lua hooks for coroutines
BUG: Lexical gets confused with some combination of arithmetic
operators and hexadecimal numbers
2012-01-20 16:32:13 -02:00
Roberto Ierusalimschy 7dcc02b165 BUG: coroutine hooks were not collected together with coroutine 2012-01-19 18:14:44 -02:00
Roberto Ierusalimschy e2fc2ce8df new way to handle -E option (write a mark in the registry to avoid
reading environment variables)
2011-12-12 14:34:03 -02:00
Roberto Ierusalimschy a241b6cb3c removed redundant definition for FILEHANDLE 2011-12-08 10:11:37 -02:00
Roberto Ierusalimschy f0d143f30f avoid a few warnings (casts) 2011-12-07 16:03:47 -02:00
Roberto Ierusalimschy c82087b8dd cast from 'bool' to 'int' (for C++) 2011-12-07 12:43:55 -02:00
Roberto Ierusalimschy 138be5b843 no more explicit support for 'luaall_c': unifying file can do
the work
2011-12-06 14:58:36 -02:00
Roberto Ierusalimschy e320b5b672 small bug: format '%d' for lua_Number argument 2011-12-06 14:33:55 -02:00
Roberto Ierusalimschy ca9c405fef some compilers (e.g., gcc C++) do not accept NULL as a pointer in
that context
2011-12-02 11:26:54 -02:00
Roberto Ierusalimschy e2feb886d6 macro 'luaL_getmetatable' seems more appropriate when getting
metatables in registry
2011-12-02 11:25:57 -02:00
Roberto Ierusalimschy 5999e14ad9 old error messages may be misleading 2011-12-02 11:23:56 -02:00
Roberto Ierusalimschy 01747f2c24 error message: "tag method" -> "metamethod" 2011-12-02 11:18:41 -02:00
Roberto Ierusalimschy 7377fbdebc function prototype did not match one in .h 2011-11-30 17:30:16 -02:00
Roberto Ierusalimschy f1d2ac3a98 allow non-integer arguments to integer formats (%d, %x, etc.),
but check range
2011-11-30 16:24:56 -02:00
Roberto Ierusalimschy c5da4f4cd0 unused variable removed 2011-11-30 11:03:24 -02:00
Roberto Ierusalimschy 7bcb2462e4 comments 2011-11-30 10:58:57 -02:00
Roberto Ierusalimschy 0bd99b327b avoid "unreachable" 'break' 2011-11-30 10:44:26 -02:00
Roberto Ierusalimschy 6d8b672094 more uses of 'l_noret' 2011-11-30 10:43:51 -02:00
Roberto Ierusalimschy e21b26a964 avoid 'return' "to avoid warnings" 2011-11-30 10:42:49 -02:00
Roberto Ierusalimschy 0f388193b3 'lUA' -> 'LUA' 2011-11-30 10:35:05 -02:00
Roberto Ierusalimschy 7948b8568e when available, use '*_r' versions of 'gmtime' and 'localtime' 2011-11-29 15:15:42 -02:00
Roberto Ierusalimschy 61b1d9a466 another try to avoid warnings about unreachable 'return' after 'exit' 2011-11-29 13:55:51 -02:00
Roberto Ierusalimschy 3617e04e97 'lua_load' has an extra argument 'mode' 2011-11-29 13:55:08 -02:00
Roberto Ierusalimschy 8c62bde36f comment 2011-11-29 13:54:38 -02:00
Roberto Ierusalimschy 51650eac78 small change to avoid warnings of non-specified order of access
to volatile fields
2011-11-29 13:39:48 -02:00
Roberto Ierusalimschy aea68e5c54 explicit option RTLD_LOCAL instead of 0 (Posix does not fix
a default for dlopen)
2011-11-28 15:27:51 -02:00
Roberto Ierusalimschy ece042fef0 'table.pack' does not return 'n' (may be confusing when
using table.pack as last argument in a call)
2011-11-28 15:26:30 -02:00
Roberto Ierusalimschy 217b65e6d9 avoid some warnings about converting 32-bit shifts into 64-bit results 2011-11-28 15:25:48 -02:00
Roberto Ierusalimschy 8119374e74 avoid warnings of unreacheable 'break's 2011-11-28 15:25:16 -02:00
Roberto Ierusalimschy 3a997eefb5 MS_ASMTRICK is only valid on MS compilers (not any Windows compiler) 2011-11-25 10:52:27 -02:00
Roberto Ierusalimschy 5184ff2096 'LUA_DL_DLL' is not yet defined before the inclusion of 'lua.h' 2011-11-25 10:52:03 -02:00
Roberto Ierusalimschy b0cbe77816 '_fseeki64' and family not available in all Windows platforms 2011-11-25 10:50:03 -02:00
Roberto Ierusalimschy 6e899850b9 details 2011-11-24 11:25:41 -02:00
Roberto Ierusalimschy fded7bef19 options for 'collectgarbage' renamed: "inc" -> "incremental";
"gen" -> "generational"
2011-11-23 15:29:04 -02:00
Roberto Ierusalimschy b5d7255034 small changes to avoid some warnings 2011-11-16 16:51:36 -02:00
Roberto Ierusalimschy 6cce5c0601 new function 'luaL_loadfilex' 2011-11-14 15:10:24 -02:00
Roberto Ierusalimschy eb70f58279 'luaIO_Stream' -> 'luaL_Stream' 2011-11-14 14:55:35 -02:00
Roberto Ierusalimschy ef900f224c strutcture for file handles exported in 'lauxlib.h' 2011-11-11 17:59:17 -02:00
Roberto Ierusalimschy 3105febf9a using Lua buffers to build error messages 2011-11-10 09:42:58 -02:00
Roberto Ierusalimschy 7133e20c94 make treatment of 'pcall' and 'xpcall' more similar 2011-11-09 17:38:00 -02:00
Roberto Ierusalimschy 888d39ea75 refactoring of common parts of 'pcall' and 'xpcall' + avoids
stack errors on these functions (return error code instead)
2011-11-09 17:28:27 -02:00
Roberto Ierusalimschy eef22fa4ce create error messages with a single concat, to avoid problems with
creating strings piecemeal
2011-11-09 17:11:20 -02:00
Roberto Ierusalimschy eda87f1156 in 'luaL_checkstack', include extra stack space in test to allow
correct execution of error routines, if necessary
2011-11-09 17:08:55 -02:00
Roberto Ierusalimschy e0e406ead3 extra argument to instruction 'checkstack' (in 'testC') 2011-11-09 17:08:07 -02:00
Roberto Ierusalimschy 30cea671a7 configurable 'directory separator' in 'package.searchpath' 2011-11-09 13:18:04 -02:00
Roberto Ierusalimschy a716ae1f50 avoids including 'stdio.h' everywhere (because of definitions for
luai_writestring/luai_writeline)
2011-11-09 12:47:14 -02:00
Roberto Ierusalimschy ea382b0be1 small bug: error message in 'io.lines' is not the error number 2011-11-09 12:10:43 -02:00
Roberto Ierusalimschy 6d8d282e0f avoid calling "extra value" as if it were a function option 2011-11-06 11:59:12 -02:00
Roberto Ierusalimschy 00c8a17a2d by default, do not use Windows' goodies in Windows CE build 2011-11-05 13:29:05 -02:00
Roberto Ierusalimschy 166ce15512 cannot apply macro 'getstr' over NULL 2011-10-31 15:48:51 -02:00
Roberto Ierusalimschy 87cf2bf711 extra comments about what fields are optional debug information 2011-10-31 15:48:22 -02:00
Roberto Ierusalimschy fd8a849621 detail (avoid applying macro 'getstr' with a function-call argument) 2011-10-31 15:46:04 -02:00
Roberto Ierusalimschy 5a568a3b01 detail (comment) 2011-10-25 10:01:20 -02:00
Roberto Ierusalimschy 475e6c5352 'lua_setglobal/lua_getglobal' implemented as functions to avoid
problems with stack indices
(e.g., lua_getglobal(L, lua_tostring(L, -1)) )
2011-10-24 14:53:05 -02:00
Roberto Ierusalimschy af00a0772c new functions lua_rawsetp/lua_rawgetp 2011-10-24 12:54:05 -02:00
Roberto Ierusalimschy 6819c2a98a silly bug in 5.2 beta: assignment conflict code did not test to check
whether variable was a table element
2011-10-24 12:51:44 -02:00
Roberto Ierusalimschy 1dd8af67b6 BUG: parser may collect a prototype while building it. 2011-10-21 17:34:23 -02:00
Roberto Ierusalimschy 1350a2bcb5 more macros to try to make NaN trick work with other sizes of
IEEE float numbers. (It has not been tested with such different
sizes...)
2011-10-17 12:46:13 -02:00
Roberto Ierusalimschy 217e67cb22 new type 'l_noret' for function that do not return 2011-10-07 17:45:19 -03:00
Roberto Ierusalimschy 9bbfe9f3fd avoid the word 'TRICKLE' in macro name (as it has nothing to do
with its meaning)
2011-10-07 16:53:05 -03:00
Roberto Ierusalimschy 788a0ecd27 'luaC_separateudata' renamed to 'separatetobefnz' and called only
from 'lgc.c'
2011-10-03 14:54:25 -03:00
Roberto Ierusalimschy 6d86b937e4 'luaC_separateudata' called from 'luaC_freeallobjects' + removed
extra 'luaF_close' (already being called by 'close_state')
2011-10-03 14:54:25 -03:00
Roberto Ierusalimschy bc90cf4b83 retraverse all gray lists together to avoid traversing some weak
tables twice (as they may change lists when traversed)
2011-10-03 13:22:05 -03:00
Roberto Ierusalimschy d79190e27f missing 'LUA_CORE' definition 2011-10-03 13:19:23 -03:00
Roberto Ierusalimschy 9caf5b4f79 lint (unused definition) 2011-09-30 09:46:06 -03:00
Roberto Ierusalimschy 50cddefeeb lint (wrong identation) 2011-09-30 09:45:45 -03:00
Roberto Ierusalimschy e24f1ee9ff lint (unreachable code) 2011-09-30 09:44:45 -03:00
Roberto Ierusalimschy f3b0eb3ecf lint (unused macros) 2011-09-30 09:44:19 -03:00
Roberto Ierusalimschy 162ce8256e lint (unused struct field) 2011-09-30 09:43:54 -03:00
Roberto Ierusalimschy ad90447eb6 detail: new macros for non-valid values 2011-09-26 17:17:27 -03:00
Roberto Ierusalimschy 87912786af dead objects are not collectable. 2011-09-24 18:12:01 -03:00
Roberto Ierusalimschy 5645a84368 detail about 'trick' function (nil turn it off) 2011-09-24 18:11:29 -03:00
Roberto Ierusalimschy 95ed6c1127 better(?) scheme for cleaning weak tables; all ressurected objects
are removed from weak values before finalization
2011-09-24 18:00:40 -03:00
Roberto Ierusalimschy 12ab78aca6 detail in extra trace code: total bytes is given by 'gettotalbytes',
not by 'totalbytes' counter.
2011-09-20 16:25:23 -03:00
Roberto Ierusalimschy 45c346645c avoid clearing ephemeron tables that have nothing to be cleaned
(no white elements)
2011-09-19 14:03:38 -03:00
Roberto Ierusalimschy 68ce878292 cannot compute 'mainposition' before checking whether key is nil 2011-09-15 14:09:02 -03:00
Roberto Ierusalimschy 500336efd0 small bug in if-goto optimization: block must be closed ('leaveblock')
*before* the jump out ('escapelist')
2011-09-14 14:40:26 -03:00
Roberto Ierusalimschy 5ea8f108e1 using 'long' versions of 'fseek'/'ftell' when available 2011-09-13 18:09:04 -03:00
Roberto Ierusalimschy 2275030b86 details (and missing 'break's) 2011-09-13 15:05:59 -03:00
Roberto Ierusalimschy 05de314701 upvalue names always can be NULL (if debug info was removed), so
always check for that case
2011-09-13 14:40:20 -03:00
Roberto Ierusalimschy d281d23f8d detail (make 'lua_assert' a valid expression even when turned off) 2011-09-13 14:39:23 -03:00
Roberto Ierusalimschy ec431ce5db comment 2011-09-12 17:33:03 -03:00
Roberto Ierusalimschy c8f47c2934 optimization for |if cond then goto| 2011-08-30 13:38:58 -03:00
Roberto Ierusalimschy ca458f1f52 'luaK_goiffalse' exported 2011-08-30 13:26:41 -03:00
Roberto Ierusalimschy 121dc8af66 cleaner code for 'if' construct 2011-08-25 10:45:24 -03:00
Roberto Ierusalimschy a8675966ec detail: centralize all tests for Windows on variable 'LUA_WIN' 2011-08-23 14:25:42 -03:00
Roberto Ierusalimschy 3dc5475e23 'nCcalls' should be local to each thread, as each thread may have its
own C stack (with LuaThreads or something similar)
2011-08-23 14:24:34 -03:00
Roberto Ierusalimschy 8a008a2057 bug: __newindex metamethod may not work if metatable is its own
metatable.
2011-08-17 17:38:51 -03:00
Roberto Ierusalimschy 89b59eee73 bug: __newindex metamethod may not work if metatable is its own
metatable + luaV_settable does not create entry when there is a
metamethod (and therefore entry is useless)
2011-08-17 17:26:47 -03:00
Roberto Ierusalimschy 166dd0261a new option '-E' to avoid environment variables 2011-08-17 17:19:52 -03:00
Roberto Ierusalimschy 51471ba748 comments about use of 'luaH_set' 2011-08-15 16:41:58 -03:00
Roberto Ierusalimschy 0b65cb74cd new implementation for 'getobjname': first search for relevant
instruction (new function 'findsetreg') and then try to build
a meaningful name
2011-08-12 17:01:44 -03:00
Roberto Ierusalimschy ea46b750dc comment 2011-08-11 14:06:12 -03:00
Roberto Ierusalimschy 92afcf2823 no more 'luaH_setstr (used only once) + 'luaH_setint' receives value
to be set.
2011-08-09 17:58:29 -03:00
Roberto Ierusalimschy b5bf7d9ef4 'string.format' checks whether values for integer formats are
actually integers
2011-08-09 17:58:29 -03:00
Roberto Ierusalimschy 6a5d89b39f detail (using array instead of several variables to keep track of
enabled command-line options)
2011-08-04 15:16:16 -03:00
Roberto Ierusalimschy ae14adc272 better error message when trying to open files 2011-08-02 15:00:01 -03:00
Roberto Ierusalimschy ff98f17d27 detail: factoring in common code for opening files and checking for
errors
2011-07-28 15:41:15 -03:00
Roberto Ierusalimschy 59bcd137ae reducing even more use of C stack by the parser: struct 'FuncState'
does not need field 'L' + number of labels/gotos in a chunk may be
limited to SHRT_MAX. (Also removed some non-needed 'unsigned's.)
2011-07-27 15:09:01 -03:00
Roberto Ierusalimschy 5ab6d36d99 no more field 'L' in 'FuncState' 2011-07-27 15:07:37 -03:00
Roberto Ierusalimschy 43c873895f tonumber: base 10 is not special, no base is 2011-07-27 09:14:06 -03:00
Roberto Ierusalimschy 03a078493e refuse things like 'inf' or 'Nan' as numerals 2011-07-27 09:13:08 -03:00
Roberto Ierusalimschy bae57ea088 'M_IX86' -> '_M_IX86' 2011-07-25 14:20:47 -03:00
Roberto Ierusalimschy 2557107e91 removed unused variable 'found' (in 'findfield') + removed legacy
test for 'what' being "tail"
2011-07-25 14:18:49 -03:00
Roberto Ierusalimschy 32a12e2f3f detail (cleaned whitespaces at end of lines) 2011-07-15 09:50:29 -03:00
Roberto Ierusalimschy 559bb554c9 no more 'zungetc' (better not to read next char) 2011-07-15 09:48:03 -03:00
Roberto Ierusalimschy fd5e810e08 macro 'char2int' replaced by 'cast_uchar' (used by other files) 2011-07-15 09:35:32 -03:00
Roberto Ierusalimschy 067f761739 better code for numerical escapes 2011-07-15 09:30:41 -03:00
Roberto Ierusalimschy 7978a8d8b2 added '_M_IX86' in NaN trick 2011-07-08 17:07:11 -03:00
Roberto Ierusalimschy 32e09c2a16 detail 2011-07-08 17:01:38 -03:00
Roberto Ierusalimschy df19931ddc error on invalid escape sequences 2011-07-08 16:17:30 -03:00
Roberto Ierusalimschy b5084fdafe detail (comment) 2011-07-06 13:45:14 -03:00
Roberto Ierusalimschy d8200d5f3c '\*' -> '\z' + '\?' is not an official escape sequence 2011-07-05 16:13:45 -03:00
Roberto Ierusalimschy 79cbc3468c removed and deprecated functions really removed from the code base 2011-07-05 09:49:35 -03:00
Roberto Ierusalimschy 9e89a55a4f NILCONSTANT also depends no endianess (with NaN trick) 2011-07-04 17:29:02 -03:00
Roberto Ierusalimschy b707e81c3d comments about some compiler options that should be tested once in a while 2011-07-04 13:10:15 -03:00
Roberto Ierusalimschy ee37ee50d6 'table.pack' also returns 'n' + 'deprecated' changed to 'removed' 2011-07-02 13:01:44 -03:00
Roberto Ierusalimschy ad1a54b5c0 reordering of some defines (more logical grouping) 2011-07-02 13:00:15 -03:00
Roberto Ierusalimschy 88c29c0cd5 compilation warning about integer size x pointer size 2011-07-02 12:59:17 -03:00
Roberto Ierusalimschy d93df22bf6 small simplifications (and assert was wrongly written) 2011-07-02 12:58:14 -03:00
Roberto Ierusalimschy 5017cc6ba2 simpler 'luai_apicheck' (and avoids compilation error...) 2011-07-02 12:57:25 -03:00
Roberto Ierusalimschy 2f125ebc33 'deprecated' x 'removed' (they are not the same thing) 2011-07-02 12:56:43 -03:00
Roberto Ierusalimschy 49a01c0991 'package.loaders' -> 'package.searchers' 2011-06-28 14:14:12 -03:00
Roberto Ierusalimschy 17526ed2fe no more errors on accesses to 'string' and strings 2011-06-28 14:13:52 -03:00
Roberto Ierusalimschy f180822fa6 back to internal table for 'ctype', no more locale manipulation 2011-06-28 12:42:04 -03:00
Roberto Ierusalimschy 594220c624 use standard "underscore + uppercases" for reserved keys in the registry 2011-06-27 16:42:31 -03:00
Roberto Ierusalimschy 3dd68624dc comments 2011-06-27 15:27:18 -03:00
Roberto Ierusalimschy f9eea453b7 avoid "magic constant" 32 (the difference from 'A' to 'a') 2011-06-27 15:22:46 -03:00
Roberto Ierusalimschy 374773748b back to "one-label-per-block" 2011-06-27 15:18:59 -03:00
Roberto Ierusalimschy 29644366fc useless assignments removed (macros already do the assignment) 2011-06-24 11:36:21 -03:00
Roberto Ierusalimschy 6eadedbfa1 resort to standard C ctype for non-ASCII systems + 'ltoupper' replaced
by 'ltolower'
2011-06-24 09:25:33 -03:00
Roberto Ierusalimschy 1978094b3a resort to standard C ctype for non-ASCII systems 2011-06-24 09:25:33 -03:00
Roberto Ierusalimschy 5acc5b0c1e using 'tolower' instead of 'toupper' (slightly simpler to implement) 2011-06-24 09:25:02 -03:00
Roberto Ierusalimschy 59547c6cda macro 'ltoupper' instead of 'lisupper' (more usefull for Lua) 2011-06-23 13:01:06 -03:00
Roberto Ierusalimschy 3d3355b4f3 label syntax changed to '::label::' 2011-06-23 11:54:48 -03:00
Roberto Ierusalimschy 801f43f09a change in the representation of file handles 2011-06-21 10:43:48 -03:00
Roberto Ierusalimschy 719c01359f label syntax changed to '::label::' 2011-06-20 13:52:48 -03:00
Roberto Ierusalimschy 43f13729a2 comment 2011-06-20 13:50:59 -03:00
Roberto Ierusalimschy 136f8e148d added cast to void to calls to 'setlocale' (to easy redefining it as
a constant)
2011-06-20 13:36:03 -03:00
Roberto Ierusalimschy f90a130b07 typo in message 2011-06-20 13:35:23 -03:00
Roberto Ierusalimschy cb4950a6d8 parser must work with C locale, but external locale must be preserved 2011-06-18 14:08:58 -03:00
Roberto Ierusalimschy fdede85419 label names must be unique inside a function 2011-06-16 13:36:39 -03:00
Roberto Ierusalimschy beab626061 correct length for LUA_COPYRIGHT (without trailing '\0') 2011-06-16 11:30:58 -03:00
Roberto Ierusalimschy 817f8674af avoid warning about -unsigned value 2011-06-16 11:14:31 -03:00
Roberto Ierusalimschy cf0562e1e7 detail (missing cast to unsigned char when converting char to int) 2011-06-16 11:13:22 -03:00
Roberto Ierusalimschy 22e1c5ebad avoid conversion from 'const char*' to 'void *' (warning about 'const') 2011-06-16 11:12:24 -03:00
Roberto Ierusalimschy 470dd56a89 'os.execute' (and similars) should return 'exit' and code in case
of success, too.
2011-06-16 11:11:04 -03:00
Roberto Ierusalimschy 20d30bcd33 declarations should be present only when implementations are 2011-06-16 11:10:12 -03:00
Roberto Ierusalimschy 44b6f496b5 just in case, avoid side effects in 'ctype' macros 2011-06-15 11:35:55 -03:00
Roberto Ierusalimschy fd80e63468 configuration for NaN trick big-endian + macro 'luai_checknum' to
ensure numbers comming from C are not "improper" (some kinds of
signaling NaNs)
2011-06-13 11:13:06 -03:00
Roberto Ierusalimschy f62565abea avoid warnings with -Wstrict-overflow 2011-06-09 15:24:22 -03:00
Roberto Ierusalimschy c9d1d9f9c6 better way to test overflows with string indices 2011-06-09 15:22:47 -03:00
Roberto Ierusalimschy 35391d9b1a macro 'NNMARK' (mark for non-number values using the NaN trick) 2011-06-09 15:21:25 -03:00
Roberto Ierusalimschy 99b1b8e918 first version with 'NANTRICK' (packing all Lua values inside a 'double') 2011-06-07 16:02:33 -03:00
Roberto Ierusalimschy 3b44821334 stricter control (using tag variants) over closure kinds (Lua x C) 2011-06-02 16:31:40 -03:00
Roberto Ierusalimschy 0214dab989 yet another macro ('num_') 2011-05-31 16:15:01 -03:00
Roberto Ierusalimschy 821bd7025e more uniform names for 'equalobj'-related functions 2011-05-31 15:27:56 -03:00
Roberto Ierusalimschy 9b7dddad7d no need for two different implementations for equality (one raw and
one with metamethods)
2011-05-31 15:24:36 -03:00
Roberto Ierusalimschy 3f04a9f2c0 code is simpler without 'goto' here 2011-05-30 13:36:38 -03:00
Roberto Ierusalimschy 2a59a999d4 yet another macro abstracting TValue representation 2011-05-26 14:12:31 -03:00
Roberto Ierusalimschy ee7d0c2649 new macro 'luai_writeline' to print newlines (and flush 'stdout') 2011-05-26 13:09:40 -03:00
Roberto Ierusalimschy aa13c591f5 avoid use of 'ifdef/ifndef'; use 'defined' instead (simpler and
more powerful)
2011-05-25 11:12:28 -03:00
Roberto Ierusalimschy 6c8a32217a changes by lhf (better control of chars x bytes) 2011-05-17 09:42:43 -03:00
Roberto Ierusalimschy cb09f4fef4 details 2011-05-06 13:00:23 -03:00
Roberto Ierusalimschy 3cf1729a02 new macro 'lua_longassert' that is equivalent to an assertion without
a stringfication of the condition, to avoid too long string literals
(limited by C90 to ~510 characters)
2011-05-05 16:43:14 -03:00
Roberto Ierusalimschy 74b0bb3a45 macro 'checkconsistency' moved to this file, as it is used only
here
2011-05-05 16:42:25 -03:00
Roberto Ierusalimschy e4076fe6d9 break long assertion in two shorter ones 2011-05-05 13:18:53 -03:00
Roberto Ierusalimschy 81952e6884 avoid using expression as argument to unsafe macro 'l_isfalse' 2011-05-05 13:16:33 -03:00
Roberto Ierusalimschy 25b4e35ee8 new macros abstracting TValue representation (to easy change to
other representations)
2011-05-05 12:53:23 -03:00
Roberto Ierusalimschy 7e1facaa4e detail in assertion 2011-05-04 14:04:06 -03:00
Roberto Ierusalimschy ad2531a0ee more complete (and hopefuly more correct) handling of 'sizeof(char)' 2011-05-03 13:01:57 -03:00
Roberto Ierusalimschy bc1c718cc0 removed TOKEN_LEN (useless) 2011-05-03 12:51:16 -03:00
Roberto Ierusalimschy c9ce754e38 comment 2011-05-02 14:33:01 -03:00
Roberto Ierusalimschy d34271fe42 MacOS 'strtod' handles hexa formats too 2011-04-29 10:56:28 -03:00
Roberto Ierusalimschy d120ec29ca bug in OP_SELF when method name goes to a register 2011-04-28 11:00:11 -03:00
Roberto Ierusalimschy 2aff901c93 Mac OS defines LUA_USE_AFORMAT and LUA_USE_LONGLONG by default 2011-04-20 15:25:54 -03:00
Roberto Ierusalimschy bad231c481 'LUA_USELONGLONG' -> 'LUA_USE_LONGLONG' 2011-04-20 13:36:28 -03:00
Roberto Ierusalimschy a2b1c279f1 'LUA_USELONGLONG' on by default on Linux + LUA_USE_HEXAFLOAT renamed
to LUA_USE_STRTODHEX (as Lua 5.2 always *uses*  hexa floats)
2011-04-19 15:31:30 -03:00
Roberto Ierusalimschy 2f128c5130 'luaL_setfuncs' does not need to accept a NULL list. (If there is
no list, there is no reason to call this function.)
2011-04-19 15:29:41 -03:00
Roberto Ierusalimschy 4758113043 change in opcode OP_LOADNIL: B is used as a counter instead of a
register. (Avoids an assignment to R(B), not present in any other
instruction.)
2011-04-19 13:22:13 -03:00
Roberto Ierusalimschy a4e644add2 small bug (masked by wrong entry for OP_TEST in opcodes.c) 2011-04-18 16:49:13 -03:00
Roberto Ierusalimschy 05ca63642b added macro for code checking 2011-04-18 16:48:53 -03:00
Roberto Ierusalimschy f17e3624ef local function name only visible to debug info after being initialized 2011-04-18 16:48:24 -03:00
Roberto Ierusalimschy 2e9b8476ca detail ('luai_apicheck' should be used always through macro 'api_check') 2011-04-18 12:02:37 -03:00
Roberto Ierusalimschy c31f4946e9 copyright updated to 2011 2011-04-18 11:15:48 -03:00
Roberto Ierusalimschy c86586e866 small corrections in description of OP_TEST and OP_LOADKX 2011-04-12 14:27:35 -03:00
Roberto Ierusalimschy 19fbdf6cae 'luaL_findtable' -> 'luaL_getsubtable' 2011-04-08 16:17:36 -03:00
Roberto Ierusalimschy 427ee519db new instruction OP_LOADKX (to replace OP_LOADK with extra argument) 2011-04-07 15:14:12 -03:00
Roberto Ierusalimschy a958b711f5 cleaner scheme of bits for variant types (light C functions) and
collectable types
2011-04-07 13:11:57 -03:00
Roberto Ierusalimschy 1ffdd0bc7a detail (should use macro 'ttisdeadkey') 2011-04-05 15:32:28 -03:00
Roberto Ierusalimschy 5286650894 new macro 'ttisequal' 2011-04-05 15:32:06 -03:00
Roberto Ierusalimschy 0fb1644c60 2nd operand for unary tag methods does not need to be 'nil' 2011-04-05 11:26:23 -03:00
Roberto Ierusalimschy 119d5e46d5 lua_arith gets no fake operand for unary minus 2011-04-05 11:26:23 -03:00
Roberto Ierusalimschy 83abbac946 all names used internally by macros end with '_' 2011-04-05 11:24:07 -03:00
Roberto Ierusalimschy a25416a8d5 use of 'luaL_tolstring' for option '%s' in 'string.format' 2011-03-18 16:02:33 -03:00
Roberto Ierusalimschy 682cce3813 macro 'mark' renamed 'EOFMARK' ('mark' is too easy to confict, e.g.
in alllua.c)
2011-03-14 12:39:42 -03:00
Roberto Ierusalimschy d806710ab5 returns for file-related functions and process-related functions
unified in 'auxlib'
2011-03-03 13:34:46 -03:00
Roberto Ierusalimschy e049abb69a loaders receive an extra argument returned by the searcher
(typically the file name)
2011-03-01 14:01:53 -03:00
Roberto Ierusalimschy 98816d0ce5 small problems with 'luaone.c' 2011-02-28 14:32:10 -03:00
Roberto Ierusalimschy 7482e8f914 no need of lookahead in Zio 2011-02-23 10:13:10 -03:00
Roberto Ierusalimschy 03b769053a correct interpretation of return value from pclose 2011-02-21 16:12:54 -03:00
Roberto Ierusalimschy 3c710f056b small bug: may call reader function again after it returned end
of input
2011-02-17 15:34:16 -02:00
Roberto Ierusalimschy c0a865fa54 error for repeated label + jumps allowed to labels followed by
'no-op' statements
2011-02-14 14:36:34 -02:00
Roberto Ierusalimschy 0009ac1f3a 'break' does not need to be last statement in a block +
'explist1' -> 'explist' + moving a few functions around
2011-02-14 12:59:28 -02:00
Roberto Ierusalimschy 7b968bb514 p-close returns "correct" status plus type of termination 2011-02-10 13:35:50 -02:00
Roberto Ierusalimschy bf8b08295a 'break' coded as 'goto' + small bug when closing multiple gotos
to the same label
2011-02-10 12:50:41 -02:00
Roberto Ierusalimschy 3f5b56c48b simpler code for repeat-until 2011-02-09 15:03:18 -02:00
Roberto Ierusalimschy e7192dfdbb corrected 'follow' for checking whether label is last statement
in a block
2011-02-09 14:51:28 -02:00
Roberto Ierusalimschy 0539f48661 small changes in goto-related error messages 2011-02-09 12:45:19 -02:00
Roberto Ierusalimschy e7a9c45a48 trying to avoid assumption that sizeof(char)==1 2011-02-07 17:15:24 -02:00
Roberto Ierusalimschy fd6c1f4898 ensures that all local variables are declared inside some block,
opening a new block at 'open_func'
2011-02-07 17:00:30 -02:00
Roberto Ierusalimschy f079749287 some reorganization of dynamic data structures used by the parser 2011-02-07 15:14:50 -02:00
Roberto Ierusalimschy f8d677f94c no more 'OP_CLOSE' instructions (use jumps to close upvalues) 2011-02-07 10:28:27 -02:00
Roberto Ierusalimschy 094a7d0290 detail in 'print_usage' 2011-02-07 10:27:13 -02:00
Roberto Ierusalimschy 7cc0e63d8a first implementation of 'goto' 2011-02-04 15:34:43 -02:00
Roberto Ierusalimschy a4a8914c20 new reserved word 'goto' 2011-02-02 12:55:17 -02:00
Roberto Ierusalimschy 06c7efb4a9 avoid extra increment to 'savedpc' when jumping 2011-02-01 16:32:55 -02:00
Roberto Ierusalimschy dd547c55c8 new scheme to close upvalues in 'break'; jump instructions may
do the close, avoiding the need for a OP_CLOSE instruction
2011-02-01 16:03:10 -02:00
Roberto Ierusalimschy f6bd8b1147 better control for GC running or stopped 2011-02-01 14:52:38 -02:00
Roberto Ierusalimschy a7faa557fa bug: problem with optimizations of short-circuit logic 2011-01-31 12:52:32 -02:00
Roberto Ierusalimschy 026a7e92be bug in some short-circuit optimizations 2011-01-31 12:28:41 -02:00
Roberto Ierusalimschy c4ea0c3b29 detail (cleaning trailing spaces) 2011-01-26 14:30:02 -02:00
Roberto Ierusalimschy 7106c491dd 'sep' argument to 'string.rep' + 'string.rep' preallocates entire
buffer before creating resulting string
2011-01-12 18:36:01 -02:00
Roberto Ierusalimschy a10d495b18 'luaL_findtable' returns boolean about whether it created a new
table (to easy initializing table)
2011-01-10 13:51:42 -02:00
Roberto Ierusalimschy c2e3cc4c89 using 'luaL_findtable' to manage hook table 2011-01-10 13:51:19 -02:00
Roberto Ierusalimschy 67feed49f1 optional argument 'sep' to 'searchpath' 2011-01-07 16:54:49 -02:00
Roberto Ierusalimschy b63b0928cf prototype for 'luaO_ceillog2' was different from definition 2011-01-07 13:46:27 -02:00
Roberto Ierusalimschy 511679313f new function 'rawlen' 2011-01-07 10:41:48 -02:00
Roberto Ierusalimschy 868ff40339 full collection does not restart collector + avoid changing GC
state if an error happens in a step
2010-12-29 16:00:23 -02:00
Roberto Ierusalimschy aa6faa6331 own implementation of 'tunumber', so that it works correctly with
numbers outside the 'int' range
2010-12-27 16:00:38 -02:00
Roberto Ierusalimschy 0b3f4e254e more efficient hash for numbers in IEEE754 machines 2010-12-23 13:38:28 -02:00
Roberto Ierusalimschy 551b076f1c change in the relationship between totalbytes and GCdebt - luaM_realloc_
is too critical to update two counters
2010-12-20 17:40:07 -02:00
Roberto Ierusalimschy 737f119187 better control for GC running or stopped 2010-12-20 16:17:46 -02:00
Roberto Ierusalimschy 8980c630bf error when indexing strings with invalid keys 2010-12-20 15:25:36 -02:00
Roberto Ierusalimschy 8d579c5bc5 'debug.setmetatable' returns object (like 'setmetatable') 2010-12-20 15:24:15 -02:00
Roberto Ierusalimschy d51743b0c7 removed 'newproxy' 2010-12-17 13:14:58 -02:00
Roberto Ierusalimschy 1a92c2b354 allows number of bits used by the library to be changed from outside 2010-12-17 11:26:38 -02:00
Roberto Ierusalimschy fe0d54d37e table library respects '#' metamethods 2010-12-17 10:15:34 -02:00
Roberto Ierusalimschy c9af0768fc GC does not mark dead registers inside activation record 2010-12-17 10:05:37 -02:00
Roberto Ierusalimschy 7e0caa7d61 new closures are always created on "next" register (so that GC knows
stack limit)
2010-12-17 10:03:41 -02:00
Roberto Ierusalimschy a40768e5ea new macro 'luaC_condGC' to allow extra code to be run in case
of GC steps
2010-12-17 10:02:29 -02:00
Roberto Ierusalimschy 4a83fe569c comment 2010-12-15 17:13:29 -02:00
Roberto Ierusalimschy b83b6ba015 'loadin' -> 'load' 2010-12-13 14:38:00 -02:00
Roberto Ierusalimschy af119c8b55 official support for floating hexa numerals 2010-12-10 17:03:46 -02:00
Roberto Ierusalimschy 1aead7f553 'hexafloat' moved to 'lobject.c' (hexa conversion needs it too) 2010-12-10 12:53:15 -02:00
Roberto Ierusalimschy 75d8470f0f new macro 'cast_uchar' 2010-12-10 11:40:22 -02:00
Roberto Ierusalimschy 81646af13b 'loadstring' deprecated; use 'load' instead 2010-12-08 10:58:04 -02:00
Roberto Ierusalimschy 233b71c092 comment 2010-12-07 09:40:42 -02:00
Roberto Ierusalimschy ccc4fc9cf0 detection of erroneous numeric strings with \0 (such as "1\0") 2010-12-06 19:08:36 -02:00
Roberto Ierusalimschy c79b4a97aa using 'strspn' to skip spaces in 'tonumber' 2010-12-06 14:25:48 -02:00
Roberto Ierusalimschy ac3afc7cd4 'printf' replaced by 'luai_writestring' 2010-12-03 15:20:50 -02:00
Roberto Ierusalimschy 350cc4bcb6 'micro' bug: when closing state, old objects are finalized (breaking
assertion)
2010-12-03 09:48:25 -02:00
Roberto Ierusalimschy 35931bbed4 comments 2010-12-02 17:51:15 -02:00
Roberto Ierusalimschy 12779b2b71 getlocal/setlocal can access vararg parameters 2010-11-30 15:17:51 -02:00
Roberto Ierusalimschy 7ca1bd639f new functions 'extract' and 'replace' 2010-11-29 13:19:28 -02:00
Roberto Ierusalimschy 9b7a12c46d finalizers (__gc) for tables 2010-11-26 12:32:31 -02:00
Roberto Ierusalimschy 5b33e39855 removed deprecated functions getn-foreach-foreachi 2010-11-23 15:21:14 -02:00
Roberto Ierusalimschy a64cf8fac9 'test' -> 'btest' 2010-11-22 16:06:33 -02:00
Roberto Ierusalimschy 092fa71ddd conventional names for bitwise operators 2010-11-22 14:39:20 -02:00
Roberto Ierusalimschy a2eaad5d81 'gfind' was deprecated in 5.1 2010-11-19 14:25:51 -02:00
Roberto Ierusalimschy 54771c5afa keep 'seminfo->ts' even for reserved words, just in case
(some lhf's tools need this)
2010-11-18 16:38:44 -02:00
Roberto Ierusalimschy bcce769d29 avoid "unreacheable code" warnings 2010-11-18 16:38:27 -02:00
Roberto Ierusalimschy 24baa919c1 small bug: 'find' did not detect magic chars after a \0 in a pattern
and did a plain search in those cases
2010-11-16 18:39:41 -02:00
Roberto Ierusalimschy d1c0efdb7d comment about compatibility-only functions 2010-11-16 17:20:01 -02:00
Roberto Ierusalimschy 566758de79 'getuservalue' accepts any type of argument 2010-11-16 16:01:28 -02:00
Roberto Ierusalimschy 50334faad6 no more compatibility with (veryyyy) old ref system 2010-11-16 15:43:29 -02:00
Roberto Ierusalimschy cee7a8e1ec -DLUA_COMPAT_ALL is the default 2010-11-16 09:39:42 -02:00
Roberto Ierusalimschy 8c21f463ed 'debug' library is loaded by default 2010-11-12 13:48:30 -02:00
Roberto Ierusalimschy a1952d9c41 'l_tvar' renamed to 'l_tg' 2010-11-12 13:47:34 -02:00
Roberto Ierusalimschy 1a46a713d2 new macro 'l_tvar' to easy the use of mathlib with other floating
types (float and long double)
2010-11-11 13:39:12 -02:00
Roberto Ierusalimschy 23b9ceb0a4 allows larger array parts in tables (no need to restrict it to 2^26) 2010-11-11 13:38:43 -02:00
Roberto Ierusalimschy 0a6a6b9d9d no more sentinel to detect loops in module dependencies;
usual message for infinite recursion is good enough.
2010-11-10 18:00:04 -02:00
Roberto Ierusalimschy 1b54197491 better error message when light userdata is used instead of a
full userdata
2010-11-10 16:06:10 -02:00
Roberto Ierusalimschy c97aa9485c new function 'luaL_setmetatable' 2010-11-10 16:05:36 -02:00
Roberto Ierusalimschy e885b91326 'luaL_typeerror' deprecated 2010-11-10 15:38:10 -02:00
Roberto Ierusalimschy fa1f724378 when reading blocks with given size, try to read whole block
at once
2010-11-09 14:57:49 -02:00
Roberto Ierusalimschy 2a966116b1 detail (message) 2010-11-09 09:04:15 -02:00
Roberto Ierusalimschy 43ec354722 added support for conditional use of %Lg when using long double 2010-11-08 15:38:37 -02:00
Roberto Ierusalimschy 700b003fb5 when reading large files, double buffer size at each iteration 2010-11-08 15:27:22 -02:00
Roberto Ierusalimschy f722ba6890 code should not use "defined" types, but "typedef"s types when they
are available (i.e., after including lua.h) + small changes to make
conversions more portable across diferent types for lua_Number
(long double) and lua_Unsigned (long long unsigned)
2010-11-08 14:33:20 -02:00
Roberto Ierusalimschy c7d4da8746 correction to allow lua_Unsigned larger than usigned int 2010-11-08 14:31:22 -02:00
Roberto Ierusalimschy f1629217f1 code for conversion macros moved from luaconf to llimits + 'uint'
renamed to 'unsigned' in those macros
2010-11-03 13:16:17 -02:00
Roberto Ierusalimschy fdd5f2f7a3 comment typos 2010-10-29 15:52:46 -02:00
Roberto Ierusalimschy c6ef3e2672 bug: by-one error when creating short source names (luaO_chunkid) 2010-10-29 13:54:55 -02:00
Roberto Ierusalimschy ba8dca00ac detail (ununsed parameter) 2010-10-29 12:35:09 -02:00
Roberto Ierusalimschy 9be89a1864 'luaL_checkversion' also checks convertions (number to integer types) 2010-10-29 10:52:21 -02:00
Roberto Ierusalimschy b9f371a3c2 added another option for ieeeendian 2010-10-29 09:13:21 -02:00
Roberto Ierusalimschy 4834de8427 comment typo 2010-10-29 09:13:14 -02:00
Roberto Ierusalimschy 94043a3a1a more robust implementation for 'luaO_str2d' 2010-10-28 13:39:03 -02:00
Roberto Ierusalimschy e642cc4206 correct handling of negative numbers in non-10 bases by 'tonumber'
(e.g., tonumber(-34, 8))
2010-10-28 13:36:30 -02:00
Roberto Ierusalimschy da57477c3d added more platforms for ieeeendianess + small comments 2010-10-28 13:18:25 -02:00
Roberto Ierusalimschy f39034889d stricter control over number of bits in each operation 2010-10-28 13:17:29 -02:00
Roberto Ierusalimschy 6b053a63cb added check for architectures with known endianess (only i386 now) 2010-10-27 15:16:37 -02:00
Roberto Ierusalimschy 572e5e6b28 new names for bit functions (mimicking assembler) 2010-10-27 14:50:32 -02:00
Roberto Ierusalimschy 6098e06e09 better organization for coercion functions between lua_Number and
integer types + IEEE trick to be used in most platforms, by default
2010-10-26 17:32:19 -02:00
Roberto Ierusalimschy c6b64ffe65 new type lua_Unsigned and corresponding projection/injection functions 2010-10-25 18:31:11 -02:00
Roberto Ierusalimschy 4590a89b32 corrected warnings from different compilers (mostly casts and small
details)
2010-10-25 17:01:37 -02:00
Roberto Ierusalimschy 1475cb59bf version from lhf 2010-10-25 12:33:38 -02:00
Roberto Ierusalimschy 9e8e60dd5f bitlib renamed to 'bit32' + new function for arithmetic shift 2010-10-25 12:32:36 -02:00
Roberto Ierusalimschy d72ec210c7 POS_A replaced by POS_Ax (which is more "precise") 2010-10-25 10:24:55 -02:00
Roberto Ierusalimschy c77baf752c comment 2010-10-25 10:24:36 -02:00
Roberto Ierusalimschy a122688091 better error message for 'lua -e -i' 2010-10-18 14:06:33 -02:00
Roberto Ierusalimschy f3026c36c2 details in opcode list 2010-10-13 13:45:54 -03:00
Roberto Ierusalimschy cd0ebd0a80 'proto->source' may be NULL (if dump strips debug information) 2010-10-11 17:24:42 -03:00
Roberto Ierusalimschy 8bc33a088c 'os.exit' acceps booleans as status (for EXIT_SUCESS and EXIT_FAILURE) 2010-10-05 09:18:03 -03:00
Roberto Ierusalimschy c3eb89544f 'luaL_loadlib' accepts Utf8 BOM in the beginning of files 2010-10-01 15:53:00 -03:00
Roberto Ierusalimschy ffff9a49da 'nresults' in CallInfo now refers to number of results that the current
function returns (and not what it expects from a call)
2010-09-30 14:21:31 -03:00
Roberto Ierusalimschy b22356e5c5 hexadecimal constants may be floating values too 2010-09-13 18:49:58 -03:00
Roberto Ierusalimschy a289a62717 'loadin' should not check whether upvalue is called '_ENV',
because its name may be unknown when there is no debug information.
2010-09-07 16:38:36 -03:00
Roberto Ierusalimschy e3eabcf913 'lua_[gs]etupvalue' may work even without debug information
(that is, without upvalue names)
2010-09-07 16:35:04 -03:00
Roberto Ierusalimschy 0df2238063 name "_ENV" configurable through 'luaconf.h' 2010-09-07 16:21:39 -03:00
Roberto Ierusalimschy 6828f6d427 new parameter 'majorinc' to control frequency of major collections
in generational mode
2010-09-03 11:14:01 -03:00
Roberto Ierusalimschy daa5fe3e31 'loadin' should accept any value for the environment (not only tables) +
it should check whether chunk has upvalue named '_ENV'
2010-08-23 15:03:11 -03:00
Roberto Ierusalimschy 8d9ea59d28 'pushclosure' -> 'codeclosure' (as there is another 'pushclosure' in
'lvm.c) + small detail
2010-08-23 14:32:34 -03:00
Roberto Ierusalimschy 5e7dbd0b8b api checks to ensure that thread is OK when using lua_call/lua_pcall 2010-08-04 15:40:28 -03:00
Roberto Ierusalimschy cd6c276e41 use index 0 for header of list of free references 2010-08-03 17:21:16 -03:00
Roberto Ierusalimschy fd4b4a2a68 detail: registry._PRELOAD must be a table, no need to check 2010-08-02 14:14:48 -03:00
Roberto Ierusalimschy d447945685 'module'/'luaL_register' and associates are deprecated 2010-07-28 12:51:59 -03:00
Roberto Ierusalimschy 78f9635111 several new comments 2010-07-26 12:53:23 -03:00
Roberto Ierusalimschy 8b7cf8c62d 'lua_[gs]etenv' -> 'lua_[gs]etuservalue' 2010-07-25 12:18:19 -03:00
Roberto Ierusalimschy 73b0a3451d environment variables consulted by Lua may be version-specific 2010-07-25 12:03:37 -03:00
Roberto Ierusalimschy 85c1461422 new macros LUA_VERSION_{MAJOR/MINOR/RELEASE} 2010-07-25 12:02:41 -03:00
Roberto Ierusalimschy 5ba556d27a using curly brackets to mark blocks of '#if/#else/#endif's 2010-07-18 11:34:45 -03:00
Roberto Ierusalimschy 81dd13f4c6 new way to distinguish between indexing tables in registers and
tables in upvalues (+ fixed small bug when checking conflicts in
multiple assignments)
2010-07-07 13:27:29 -03:00
Roberto Ierusalimschy 6a02bbe1e2 better organization for fields in struct 'expdesc' 2010-07-02 17:42:40 -03:00
Roberto Ierusalimschy 7631c29b2f comand-line option '-l' creates global with given name after
requiring module
2010-07-02 14:36:32 -03:00
Roberto Ierusalimschy a9dc7c8828 functions lua_tonumber/lua_tointeger replaced by lua_tonumberx/lua_tointegerx
that have an extra out parameter with conversion status
2010-07-02 14:35:06 -03:00
Roberto Ierusalimschy 7192afafee new module policy: C modules do not create globals and do not register
themselves with 'require' (let 'require' do its work); new auxiliary
functions luaL_newlib/luaL_newlibtable/luaL_setfuncs/luaL_requiref.
Old luaL_register will be deprecated.
2010-07-02 08:38:13 -03:00
Roberto Ierusalimschy a139e2e003 old (and complex) luaL_findtable now used only in compatibility code
inside lauxlib.c
2010-06-30 14:40:27 -03:00
Roberto Ierusalimschy a71c5f6f53 typo in comments 2010-06-30 11:11:17 -03:00
Roberto Ierusalimschy d9ea6eca7c macro 'key2tal' replaced by 'gkey' (as both were equal) 2010-06-25 09:18:10 -03:00
Roberto Ierusalimschy ca3865cf1b 'getlocal' gets information about parameters of Lua functions 2010-06-21 13:30:12 -03:00
Roberto Ierusalimschy bef5980744 no more support for old Mac OS systems 2010-06-18 14:23:02 -03:00
Roberto Ierusalimschy 409741e900 'what' may be NULL in 'kname' 2010-06-16 10:44:36 -03:00
Roberto Ierusalimschy b98de30b8f 'ipair' is back 2010-06-13 16:41:34 -03:00
Roberto Ierusalimschy 9f48712c15 use ANSI versions of DLL functions in Windows 2010-06-13 16:36:17 -03:00
Roberto Ierusalimschy bd262d591f 'coroutine' library separated from 'baselib' 2010-06-10 18:30:26 -03:00
Roberto Ierusalimschy 0d116c3ada unused '#include' removed 2010-06-10 18:27:09 -03:00
Roberto Ierusalimschy 79f11fb2bb back with #-comments for binary files 2010-06-09 14:53:59 -03:00
Roberto Ierusalimschy fabe4ec487 better barrier for prototypes 2010-06-07 13:55:34 -03:00
Roberto Ierusalimschy 575074fd85 Lua closures are cached for reuse 2010-06-04 10:25:10 -03:00
Roberto Ierusalimschy 545f43065f 'luaF_newLclosure' gets prototype of new closure as argument 2010-06-04 10:06:15 -03:00
Roberto Ierusalimschy 3819c30e55 better names for barrier macros 2010-06-04 10:05:29 -03:00
Roberto Ierusalimschy e94fac8956 bug: generational collection was not running collector! (must write
a test for this...)
2010-06-02 15:36:58 -03:00
Roberto Ierusalimschy 2c1a5d678d factoring out common code in 'module' and 'luaL_openlib' 2010-05-31 13:34:19 -03:00
Roberto Ierusalimschy bd619b9311 new macro MAXUPVAL (maximum number of upvalues per closure) 2010-05-31 13:08:55 -03:00
Roberto Ierusalimschy aca84ee1a0 correct definition for 'lua_cpcall' (tested) 2010-05-28 11:27:07 -03:00
Roberto Ierusalimschy 5038e3c58c corrected compatibility macro 'lua_cpcall' (untested) 2010-05-27 09:06:42 -03:00
Roberto Ierusalimschy 5a7dee0c5d added class '%g' in patterns (for graphical characters) 2010-05-24 16:34:57 -03:00
Roberto Ierusalimschy ddf1f2a053 GC should not run when stopped, even in hard tests 2010-05-24 16:29:46 -03:00
Roberto Ierusalimschy e34d3c06b0 it is better to call open functions with lua_call to not mess
the caller stack
2010-05-20 09:57:59 -03:00
Roberto Ierusalimschy e8a2c36909 more comments 2010-05-18 14:32:19 -03:00
Roberto Ierusalimschy 3c39a0e8cb bug: loadfile of binary files read first character twice 2010-05-18 14:21:24 -03:00
Roberto Ierusalimschy 3d45a8eb1c really stop collection during finalizers 2010-05-17 17:39:31 -03:00
Roberto Ierusalimschy 3d80aeab5a lua_pushstring may reallocate the stack, making 'o' a dangling
pointer
2010-05-17 17:10:17 -03:00
Roberto Ierusalimschy 3811e23b32 detail (comment) 2010-05-17 15:30:27 -03:00
Roberto Ierusalimschy 12c764ed1e semicolons now represent the empty statement 2010-05-15 10:32:02 -03:00
Roberto Ierusalimschy e99e9a9473 patches for last two bugs (string.format and io.read) 2010-05-14 12:34:57 -03:00
Roberto Ierusalimschy f35ac38e1d updated depenency lists + eliminated duplication of definitions
for MYCFLAGS, MYLDFLAGS, and MYLIBS.
2010-05-14 12:08:10 -03:00
Roberto Ierusalimschy 058279d548 comments 2010-05-14 12:03:43 -03:00
Roberto Ierusalimschy 69ba1ac441 new "instruction" 'absindex' 2010-05-14 10:15:54 -03:00
Roberto Ierusalimschy 4a925c1552 in 'absindex', do not need to call gettop (can inline it) 2010-05-14 10:15:26 -03:00
Roberto Ierusalimschy cf531912f2 one more macro (mvdispatch) to easy experiments with alternative
dispatch methods
2010-05-13 16:53:05 -03:00
Roberto Ierusalimschy 0d00729e31 detail (breaking a long line) 2010-05-13 09:03:26 -03:00
Roberto Ierusalimschy b6e9fcbd70 use of macro ('vmcase') to format all cases in main switch of
'luaV_execute' (to facilitate experiences with direct threading)
2010-05-12 17:40:35 -03:00
Roberto Ierusalimschy 8554baeacf small changes in 'luaV_execute' to make cases more regularly formatted 2010-05-12 17:31:33 -03:00
Roberto Ierusalimschy f5b7f077ec added comments to '#else' and '#endif' in long conditionals 2010-05-12 11:17:36 -03:00
Roberto Ierusalimschy e924a7f9ea new API function 'lua_absindex' 2010-05-12 11:09:20 -03:00
Roberto Ierusalimschy 4fd76b8148 avoid "strong" cast 2010-05-11 17:49:26 -03:00
Roberto Ierusalimschy de0f51a02c wrong type being assigned (not detected because of obj2gco macro) 2010-05-11 17:48:36 -03:00
Roberto Ierusalimschy 0567221848 udata in 'tobefnz' list be have old bit on (it will be cleared
when udata is moved to 'allgc' list)
2010-05-10 15:24:36 -03:00
Roberto Ierusalimschy 1c1a98e872 corrected some places where an old object could end up in front
of a new one + minimal documentation about this problem
2010-05-10 15:23:45 -03:00
Roberto Ierusalimschy c006f085d9 new macro 'resetoldbit' 2010-05-10 13:46:49 -03:00
Roberto Ierusalimschy a48e330f37 macros 'lua_number2int' and 'lua_number2uint' for Visual Studio
corrected and tested
2010-05-10 13:38:58 -03:00
Roberto Ierusalimschy dcc070683c avoid reserving LUA_RIDX_LAST slots in any table used by reference
system. Store free list in a field indexed by a unique name,
instead of using a numerical index.
2010-05-10 12:25:02 -03:00
Roberto Ierusalimschy 2d81cfa4e1 corrected definition of 'lua_register' (there is no LUA_ENVIRONINDEX
anymore)
2010-05-10 10:50:20 -03:00
Roberto Ierusalimschy 0bccf03d7e slightly better definition for 'changenvalue' 2010-05-07 15:44:46 -03:00
Roberto Ierusalimschy ad2b5decc8 'lua_assert' can be empty when assertions are off 2010-05-07 15:44:12 -03:00
Roberto Ierusalimschy 32c1764b5d slightly better definition for 'isgray' 2010-05-07 15:43:51 -03:00
Roberto Ierusalimschy de97177744 avoid 'else assert' (which may result in an empty else) 2010-05-07 15:43:24 -03:00
Roberto Ierusalimschy fa2ddb070a details (to avoid too long strings in assertions) 2010-05-07 15:23:17 -03:00
Roberto Ierusalimschy 0fac33da9e bug: incremental sweep was not cleaning old bits (as it stopped in the
first old object) + bug: moving udata to 'udgc' list might put old
object in front a new one + some new macros + generational mode may
be in 'pause' state (it just skips 'markroot')
2010-05-07 15:19:36 -03:00
Roberto Ierusalimschy 8e1bdda66a stupid bug when calling 'luaC_changemode' (in function lua_gc) 2010-05-07 15:10:01 -03:00
Roberto Ierusalimschy 9c1347e647 more tests in 'lua_checkmemory' + more information in function
'gccolor'
2010-05-07 15:09:23 -03:00
Roberto Ierusalimschy b373a40133 new macro 'isgenerational' + new macro 'isold' + better deffinition
for 'isdead', compatible with the code used by 'sweeplist'
2010-05-07 15:08:05 -03:00
Roberto Ierusalimschy 25951e0ea5 some cleaning in 'sweeplist' (threads do not need to be traversed
if they are going to be collected + use of bit masks to unify
differences in generational and incremental modes)
2010-05-06 15:18:07 -03:00
Roberto Ierusalimschy a4f20e3c8b comments 2010-05-06 15:17:22 -03:00
Roberto Ierusalimschy 8c583c61a3 more tests in 'lua_checkmemory' 2010-05-06 15:16:57 -03:00
Roberto Ierusalimschy d2ea5b00b7 new function 'luaC_changemode' +
bug: objects entering the 'allgc' list must have their OLDBIT cleared
(upvalues being cleared) + bug: in 'checkSizes', KGC_EMERGENCY is
stored in 'gckind' field, not in 'gcstate' + current white changes when
entering sweep phase (so there are dead objects only in that phase)
2010-05-05 15:58:36 -03:00
Roberto Ierusalimschy d77898597e new function 'luaC_changemode' 2010-05-05 15:53:41 -03:00
Roberto Ierusalimschy 237f755dca typos in comments 2010-05-05 15:49:56 -03:00
Roberto Ierusalimschy 7444b5a1d5 better documentation of GC costs 2010-05-05 10:39:58 -03:00
Roberto Ierusalimschy e7ce7e1850 changes in patch to monitor garbage collection 2010-05-04 15:10:02 -03:00
Roberto Ierusalimschy 3e662cec89 full GC must run finalizers only after finishing everything else
(including a return to generational mode if needed)
2010-05-04 15:09:06 -03:00
Roberto Ierusalimschy fde866e303 details (comments) 2010-05-04 14:25:19 -03:00
Roberto Ierusalimschy 2d7a81a204 missing parentheses in declaration 2010-05-04 14:21:08 -03:00
Roberto Ierusalimschy 658ea8752b no need to handle '\0' differently from other control chars in
format '%q'
2010-05-04 14:20:33 -03:00
Roberto Ierusalimschy aa73403ba4 no need of a KGC_FORCED collection kind; it has the same behavior of
a normal collection
2010-05-03 14:39:48 -03:00
Roberto Ierusalimschy 0c27de2e7b no more 'finalize' phase in GC; finalizers are called along the
entire cycle
2010-05-03 14:33:39 -03:00
Roberto Ierusalimschy d25f7f9d78 items in 'tobefnz' are kept black (as before recent change) and changed
to white only when needed (being moved to 'allgc' when not keeping
invariant).
2010-05-03 08:55:40 -03:00
Roberto Ierusalimschy 85555646e3 invariant must be kept in atomic 'phase' too 2010-05-03 08:24:30 -03:00
Roberto Ierusalimschy 4d871ee973 "gray lists" only need to be valid when 'keepinvariant' is true 2010-04-30 15:37:14 -03:00
Roberto Ierusalimschy b9e1dec2cb added comment explaining a bit about the invariants of the collector 2010-04-30 15:36:45 -03:00
Roberto Ierusalimschy dc2b8a0073 detail 2010-04-30 15:36:22 -03:00
Roberto Ierusalimschy 9a9fe42deb wrong comment 2010-04-30 15:17:24 -03:00
Roberto Ierusalimschy 0062db1e06 default PAUSE should be 200 (differences may be corrected in
internal multiplers)
+ check for unbilt stack equal the one used by lgc.c
2010-04-30 11:22:23 -03:00
Roberto Ierusalimschy 23001d8607 nasty GC bug: upvalue must be turned white when not keeping invariant,
but barrier was not being called when uv->v were already white.
2010-04-29 18:43:36 -03:00
Roberto Ierusalimschy 5d79c6684b removed commented-out debugging code 2010-04-29 18:42:33 -03:00
Roberto Ierusalimschy 3410dcd375 new way to control GC speed 2010-04-29 14:35:10 -03:00
Roberto Ierusalimschy 5a7a0c72d8 'luaC_linkupval' embedded into call site 2010-04-29 14:34:35 -03:00
Roberto Ierusalimschy ee7478e884 improved 'lua_checkmemory', with better control over gray objects 2010-04-29 14:33:51 -03:00
Roberto Ierusalimschy aaa5d7adab 'luaC_linkupval' moved into 'lfunc.c' code + new way to control GC speed 2010-04-29 14:32:40 -03:00
Roberto Ierusalimschy 3eb1788bb4 new way to control GC speed (keeping a 'debt' counter) 2010-04-29 14:31:31 -03:00
Roberto Ierusalimschy 00114a95b2 lots of new comments + small changes in loop controls + other small
"janitor work"
2010-04-26 14:58:00 -03:00
Roberto Ierusalimschy 4aaf0ef75c "to-be-finalized" objects marked and sweeped like all other objects 2010-04-20 17:15:30 -03:00
Roberto Ierusalimschy ed720d09f3 upvalue barriers for Lua functions must act on the upvalue itself,
not on its closure
2010-04-20 17:14:50 -03:00
Roberto Ierusalimschy 376e939ef6 missing parentheses around 'luaL_pushresultsize' declaration 2010-04-19 15:52:15 -03:00
Roberto Ierusalimschy 9d28e2b3e5 bug with io.read(op, "*n") 2010-04-19 15:04:58 -03:00
Roberto Ierusalimschy 49ca1f7083 allows thread switches (when/if there are thread switches) in the same
places that finalizers can run (so they should be safe...)
2010-04-19 14:58:46 -03:00
Roberto Ierusalimschy 4db6f20770 ensure that 'luai_userstatethread' is always called (even if
'stack_init' throws a memory error)
2010-04-19 14:40:13 -03:00
Roberto Ierusalimschy cca71912e6 'gcinfo' was deprecated in version 5.0. 2010-04-19 14:02:02 -03:00
Roberto Ierusalimschy 8003e9544d 'string.format' may get buffer as an argument when there are
missing arguments and format string is too long
2010-04-19 13:39:25 -03:00
Roberto Ierusalimschy 973d81efb3 complete control over number of each kind of object allocated 2010-04-19 13:38:25 -03:00
Roberto Ierusalimschy 26d4a73962 with light C functions, 'pairs' does not need to keep 'next' as an
upvalue.
2010-04-19 13:36:06 -03:00
Roberto Ierusalimschy 99a39f6f4a tells the allocation function that the first block is a thread 2010-04-19 13:34:46 -03:00
Roberto Ierusalimschy 1bb407e494 in lua_gc/step, 'luaC_step' changes GCthreshold, so there was little
control over the real step size.
2010-04-19 13:33:19 -03:00
Roberto Ierusalimschy 53f9499f7f "light C function" is a better name than "C-function pointer" 2010-04-18 10:22:48 -03:00
Roberto Ierusalimschy 575befc394 comparsion tag methods follow the same rule as other binary TMs 2010-04-18 10:15:11 -03:00
Roberto Ierusalimschy e7ffb1b501 macro LUA_USE_LONGJMP allows choosing longjmp when compiling Lua as
C++ code
2010-04-18 09:41:35 -03:00
Roberto Ierusalimschy c066ac10a9 better line numbers for function calls and unary/binary operators +
null statement + no more "ambiguous syntax" restriction
2010-04-17 09:46:32 -03:00
Roberto Ierusalimschy 1e6940f291 'gcstate' now also runs collector until given state + small changes
in 'testC' to test 'lua_topointer' and 'lua_tocfunction'
2010-04-16 14:42:49 -03:00
Roberto Ierusalimschy d8d81ba891 new escape sequence '\*' + several comments + moving options from
switch default into cases (as now locale is fixed)
2010-04-16 09:31:07 -03:00
Roberto Ierusalimschy cf22133b69 no need to avoid calling ctype functions as now they are implemented
by us (no inefficiencies due to accessing locale information)
2010-04-15 16:44:43 -03:00
Roberto Ierusalimschy b7be05ad27 invalid instructions "cannot" happen 2010-04-15 16:43:43 -03:00
Roberto Ierusalimschy afdb19ac82 no more 'ccall' nor 'cpcall' functions. (With light C functions they
are obsolete.)
2010-04-14 12:14:21 -03:00
Roberto Ierusalimschy 7dfa4cd655 first implementation of light C functions 2010-04-14 12:13:48 -03:00
Roberto Ierusalimschy fc6203ee43 BUG: 'string.format' may get buffer when there are missing arguments 2010-04-12 13:13:02 -03:00
Roberto Ierusalimschy b2dd246b7a better control in 'totalmem' over choosing counters 2010-04-12 13:07:39 -03:00
Roberto Ierusalimschy d20ff60615 new macro LUA_NUMTAGS 2010-04-12 13:07:29 -03:00
Roberto Ierusalimschy d41b467320 check memory allows strings to live in the main GC list (it should
work ok).
2010-04-12 09:42:07 -03:00
Roberto Ierusalimschy 4541243355 patterns now accept '\0' as a regular character 2010-04-12 09:00:50 -03:00
Roberto Ierusalimschy 9100f7479a new implementation for Generic Buffer manipulation (using userdata as
temporary buffer space)
2010-04-09 13:14:46 -03:00
Roberto Ierusalimschy 055104f5b6 keep memory-error message in the global state, so that its use
does not depend on Lua internalizing strings to avoid a string
creation on memory errors
2010-04-08 14:16:46 -03:00
Roberto Ierusalimschy 28aa733c15 macro 'eqstr' was being used to compare non-string entities 2010-04-08 14:06:33 -03:00
Roberto Ierusalimschy 6abde1b05a no need to keep "_ENV" name in global state (can be kept in lex state) 2010-04-05 13:35:37 -03:00
Roberto Ierusalimschy d394d5536a new macro 'eqstr' 2010-04-05 13:26:37 -03:00
Roberto Ierusalimschy a2f98314a3 'lua_pushstring' now uses 'luaS_new' 2010-04-05 11:21:38 -03:00
Roberto Ierusalimschy a09c8d7beb cannot sweep main thread in sweepstring phase 2010-04-05 11:15:35 -03:00
Roberto Ierusalimschy f80ff7a336 'luaS_new' changed from macro to function 2010-04-03 17:24:18 -03:00
Roberto Ierusalimschy a08fc34ee4 avoid using 'luaS_new' when can use 'luaS_newlstr' 2010-04-02 12:39:07 -03:00
Roberto Ierusalimschy d00d2eaf51 small changes in 'luaO_pushvfstring' 2010-04-02 12:30:27 -03:00
Roberto Ierusalimschy 11126422d9 option to return GC to normal (incremental, non generational) mode 2010-04-02 12:19:19 -03:00
Roberto Ierusalimschy e54668b696 added proper code to trace garbage collection 2010-04-02 11:37:41 -03:00
Roberto Ierusalimschy 9eb832de54 work related to hooks moved from 'luaV_execute' to 'traceexec' 2010-03-29 17:45:49 -03:00
Roberto Ierusalimschy 82a1f5d354 comments 2010-03-29 14:44:31 -03:00
Roberto Ierusalimschy a8d3aa14fd global table now is only kept in the registry 2010-03-29 14:43:14 -03:00
Roberto Ierusalimschy 064e406f67 no more fenvs! 2010-03-26 17:58:11 -03:00
Roberto Ierusalimschy 5c87f61e6b major collections in generational mode 2010-03-25 16:37:23 -03:00
Roberto Ierusalimschy 3aa9598177 'mainthread' is not inserted in the 'allgc' list anymore, but swept
separately.
2010-03-25 10:06:36 -03:00
Roberto Ierusalimschy 64d39ed1b6 generational mode no longer sweep old objects 2010-03-24 12:51:10 -03:00
Roberto Ierusalimschy 4433dbb5f5 userdata with finalizers are kept in a separated list ('udgc'), instead
of at the end of 'rootgc' (which was renamed to 'allgc', as it is not
"root" in the usual meaning for collectors)
2010-03-24 10:07:01 -03:00
Roberto Ierusalimschy 5cb128ea54 BUG: emergency collector might resize 'strt' (string table) when
creating a new string
+ atomic and markroot steps has some cost
+ full collection must leave collector in proper state when mode
is generational
2010-03-23 17:16:06 -03:00
Roberto Ierusalimschy 74123e9686 draft version of a generational mode for garbage collection. (Not well
tested; no major collections; ...)
2010-03-22 15:28:03 -03:00
Roberto Ierusalimschy 9c196bebad detail (wrong comment about LUAI_GCPAUSE) 2010-03-22 14:45:55 -03:00
Roberto Ierusalimschy 28b2566c97 'lua_assert' not visible from libraries 2010-03-22 14:28:31 -03:00
Roberto Ierusalimschy caf74dd731 'cpcall' renamed to 'ccall' as it does not do a protected call 2010-03-19 18:04:17 -03:00
Roberto Ierusalimschy 62840c5fad 'ipairs' is deprecated 2010-03-19 12:52:48 -03:00
Roberto Ierusalimschy 5ca7cdd709 for compatibility only: 'module' changes the first upvalue of
calling function to affect its environment
2010-03-19 12:02:34 -03:00
Roberto Ierusalimschy 1514e49d43 avoid using function environments in C libraries (as it probably will
be deprecated)
2010-03-17 18:37:37 -03:00
Roberto Ierusalimschy 22ef84b6c8 '_ENV' name permanently stored in global state for easier access 2010-03-13 12:55:42 -03:00
Roberto Ierusalimschy 63a2b62468 must include 'string.h' because a macro uses 'strlen' 2010-03-13 12:55:01 -03:00
Roberto Ierusalimschy 489253d753 better definitions for lua_[gs]etglobal + less uses of ENVIRONINDEX 2010-03-13 00:57:46 -03:00
Roberto Ierusalimschy 25c557ec63 first version of _ENV; no more global variables 2010-03-12 16:14:06 -03:00
Roberto Ierusalimschy f292760f12 small optimization in luaL_addlstring (avoid adding chars one by one)
(suggested by Chuck Coffing)
2010-03-12 15:59:32 -03:00
Roberto Ierusalimschy 1124cb1247 first step towards _ENV: all chunks have an puvalues _ENV with the
global table
2010-03-08 13:55:52 -03:00
Roberto Ierusalimschy c295147874 when finding a 'name' for a function, handle the case when the function
is a for iterator
2010-03-05 11:01:29 -03:00
Roberto Ierusalimschy e560ac4862 when searching for a variable name, look existing upvalues before
goingg to upper levels
2010-03-04 15:12:57 -03:00
Roberto Ierusalimschy 915a9a912c just in case, better to flush error messages 2010-03-03 15:53:02 -03:00
Roberto Ierusalimschy ae0a5e2142 new option '*L' for io.read + options for io.lines 2010-03-03 15:48:57 -03:00
Roberto Ierusalimschy 347f0c33d1 avoid 'continue' unless necessary 2010-02-27 18:16:24 -03:00
Roberto Ierusalimschy 622e448710 removed useless test (argv[i] cannot be NULL when i<argc) 2010-02-27 18:15:36 -03:00
Roberto Ierusalimschy 0fe2576a39 new instructions to optimize indexing on upvalues 2010-02-26 17:40:29 -03:00
Roberto Ierusalimschy d08d237a49 detail: in loadfile read function, no need to return NULL on EOF;
size ==0 is enough to signal EOF.
2010-02-18 17:37:57 -02:00
Roberto Ierusalimschy 64a7ec987c avoid using 'ungetc' in loadfile 2010-02-18 17:32:41 -02:00
Roberto Ierusalimschy 4274738e81 new macro 'luai_writestringerror' 2010-02-18 17:18:41 -02:00
Roberto Ierusalimschy 0d7d559dcc no need to flush either stderr or \n-terminated outputs 2010-02-11 15:12:27 -02:00
Roberto Ierusalimschy af512ad6da use of 'conventional' names for shift and rotate operations +
right/left versions for them
2010-02-11 13:55:29 -02:00
Roberto Ierusalimschy d27108ccd5 removed support for '#fist-line comment' on binary files (as binary
files do not have lines...)
2010-02-11 13:52:50 -02:00
Roberto Ierusalimschy a838b3b496 better usage messages, showing entire offending argument 2010-02-09 09:58:57 -02:00
Roberto Ierusalimschy 4c54cd3a10 when yielding, original 'func' value must be kept and restored so
that 'poscall' puts results in the right slot.
2010-02-09 09:56:29 -02:00
Roberto Ierusalimschy c8ff7de7f0 field 'oldtop' renamed to 'extra', as it can be used for other
purposes
2010-02-09 09:55:37 -02:00
Roberto Ierusalimschy 3bae8e047c typo (thanks to Gavin) 2010-02-05 17:09:09 -02:00
Roberto Ierusalimschy 4f5f2fe367 new function 'luaL_cpcall' 2010-01-21 14:49:21 -02:00
Roberto Ierusalimschy 01586d539e typo in comment 2010-01-21 14:31:24 -02:00
Roberto Ierusalimschy c8ab34ab7a better messages for invalid options 2010-01-21 14:31:06 -02:00
Roberto Ierusalimschy 36ab1ee10c __unm metamethod gets nil as its 2nd parameter 2010-01-15 14:23:58 -02:00
Roberto Ierusalimschy 193ce46970 table.pack was locking last result, avoiding its collection 2010-01-13 17:59:10 -02:00
Roberto Ierusalimschy b678f246a4 HINSTANCE -> HMODULE (they are the same thing, but the MS documentation
uses the latter) + LoadLibrary -> LoadLibraryEx with optional arguments,
to allow the option LOAD_WITH_ALTERED_SEARCH_PATH
2010-01-13 14:30:27 -02:00
Roberto Ierusalimschy f270e7f044 warnings that are not compatible with C++ separated from other warning
options
2010-01-13 14:19:54 -02:00
Roberto Ierusalimschy 070d3743a7 "no value" added to array luaT_typenames + occurrences of "userdata"
in that array unified in a single address
2010-01-13 14:18:25 -02:00
Roberto Ierusalimschy 0c7de97d47 correct error message when yielding from outside a coroutine 2010-01-13 14:17:32 -02:00
Roberto Ierusalimschy 900b7d4514 on 64-bit machines, an address may not fit into a 'long', so it
is better to convert from pointer to void to pointer to function
directly, even if ANSI C does not like it.
2010-01-13 14:09:05 -02:00
Roberto Ierusalimschy 91f0b20a0e missing standard defines 2010-01-12 17:40:02 -02:00
Roberto Ierusalimschy e4b4623abc 'searchpath' changes dots into directory separators 2010-01-11 15:55:25 -02:00
Roberto Ierusalimschy cef96b73e1 added casts from int to enumerations to follow C++ rules 2010-01-11 15:38:30 -02:00
Roberto Ierusalimschy 427e01eb63 removed useless initialization 2010-01-11 15:37:59 -02:00
Roberto Ierusalimschy d320c908d0 conversion from pointer to void to pointer to function seems more
"correct" if done through an integral type (because conversions
between pointers and numbers are allowed, only "implementation
defined").
2010-01-11 15:34:59 -02:00
Roberto Ierusalimschy 8bfc696676 missing 'external' in variable declaration 2010-01-11 15:33:09 -02:00
Roberto Ierusalimschy 97a35e70af pathes corrected to 5.2 2010-01-11 15:15:30 -02:00
Roberto Ierusalimschy 03b556b963 corrected copyright notice to 2010 2010-01-11 15:15:11 -02:00
Roberto Ierusalimschy 572b94bbcb include of 'windows.h' moved to where it is needed 2010-01-11 15:11:24 -02:00
Roberto Ierusalimschy 692209fa8d Dynamic C functions should be created with the global table as their
initial environments
2010-01-11 15:06:31 -02:00
Roberto Ierusalimschy 953d499ea2 changed macro lua_number2int for Windows (added brackets; some recent
compilers complain about the old format) + added missing definition
for 'lua_number2int' in Windows case.
2010-01-11 14:35:20 -02:00
Roberto Ierusalimschy a541ada194 "-"-trick in C packages now accept name-v13... 2010-01-11 14:10:47 -02:00
Roberto Ierusalimschy 55d3138397 removed old prototype for 'luaI_openlib' (which does not exist anymore) 2010-01-11 14:00:45 -02:00
Roberto Ierusalimschy e74e56f2b1 better may to force recompilation when makefile changes 2010-01-08 18:05:36 -02:00
Roberto Ierusalimschy 1ebf109c53 'setobj' must assing fields one by one, to allow trick of using
pad space in table keys
2010-01-08 18:00:20 -02:00
Roberto Ierusalimschy f75be1cb28 removed parentheses around some function names in their definitions 2010-01-08 13:16:56 -02:00
Roberto Ierusalimschy 16d2ad88fe some changes in compatibility macros: added LUA_COMPAT_ALL + compatibility
macros from lua.h and lauxlib.h moved to luaconf.h
2010-01-06 13:15:04 -02:00
Roberto Ierusalimschy f3a6815000 compatibility code removed or moved to luaconf.h 2010-01-06 13:14:15 -02:00
Roberto Ierusalimschy 19f8c87375 compatibility code moved to luaconf.h 2010-01-06 13:08:00 -02:00
Roberto Ierusalimschy 5bcfe0c700 new debug info 'isvararg' and 'nparams' 2010-01-06 12:42:35 -02:00
Roberto Ierusalimschy 8cd395564c no need to use two different defines (LUA_DL_DLOPEN and LUA_USE_DLOPEN) 2010-01-06 12:35:17 -02:00
Roberto Ierusalimschy 389c890ed3 again changing macro to function to save a few bytes 2010-01-06 09:48:02 -02:00
Roberto Ierusalimschy e3866afa97 macro 'luaY_checklimit' changed into a function (and renamed 'checklimit').
It makes no sense to trade space for time in the parser.
2010-01-05 16:46:58 -02:00
Roberto Ierusalimschy 25189b420d field 'nups' in struct 'lua_Debug' changed from 'int' to 'unsigned
char' to save some space (even C functions cannot have more than
maxchar upvalues).
2010-01-05 16:33:26 -02:00
Roberto Ierusalimschy cec25167d1 new api_check that 'pcallk' cannot be called inside hooks 2010-01-04 16:17:51 -02:00
Roberto Ierusalimschy 1fd4c482a0 reorganization of switch in function 'match' (details) 2010-01-04 14:37:19 -02:00
Roberto Ierusalimschy 35e729fa6d comments + small details 2010-01-04 14:36:39 -02:00
Roberto Ierusalimschy 0dc09cb42e 'unpack' moved to table library (and therefore "renamed" to
'table.unpack'.
2009-12-28 14:30:31 -02:00
Roberto Ierusalimschy cc1cbd19a0 'lua_cpcall' is deprecated + other small changes in 'pmain' (comments
and reordering to check arguments before running any Lua code)
2009-12-22 14:47:12 -02:00
Roberto Ierusalimschy cb3f95d516 'lua_cpcall' is deprecated 2009-12-22 14:47:00 -02:00
Roberto Ierusalimschy f84b575cfa no more pseudoindex LUA_GLOBALSINDEX; global table now accessible
through registry
2009-12-22 13:32:50 -02:00
Roberto Ierusalimschy 3cb343efd6 code for error message for 'setn' removed 2009-12-18 14:53:12 -02:00
Roberto Ierusalimschy ec0fc1a13b missing parentheses around 'lua_version' + moving typdef's before
the extra include
2009-12-18 13:32:36 -02:00
Roberto Ierusalimschy c3a6f3fa1c 'lua_objlen' replaced by 'lua_rawlen', 'lua_len', and 'luaL_len' 2009-12-17 14:20:01 -02:00
Roberto Ierusalimschy 0bbdddc86b allocator function receives the tag of object being allocated in 'osize'
when 'ptr' is NULL.
2009-12-17 13:46:44 -02:00
Roberto Ierusalimschy b3b8dfaaea yet more options moved from luaconf.h into internal files 2009-12-17 11:08:51 -02:00
Roberto Ierusalimschy adc6a4865b macro name change: LUA_INIT->LUA_INIT_VAR 2009-12-17 11:07:41 -02:00
Roberto Ierusalimschy 2108754e46 macro name change: LUA_PATH->LUA_PATH_VAR, LUA_CPATH->LUA_CPATH_VAR,
LUA_PATHSEP->LUA_PATH_SEP, LUA_EXECDIR->LUA_EXEC_DIR
2009-12-17 11:06:47 -02:00
Roberto Ierusalimschy 46f1429936 more options moved from luaconf.h into internal files 2009-12-17 10:50:20 -02:00
Roberto Ierusalimschy e0f9d1c8f5 removed export of function only for coco 2009-12-17 10:28:57 -02:00
Roberto Ierusalimschy de6fc75d63 several configuration options that do not change often moved out of
luaconf.h and into more internal files
2009-12-17 10:26:09 -02:00
Roberto Ierusalimschy 2af0d3b459 allocator function receives the tag of object being allocated in 'osize'
when 'ptr' is NULL.
2009-12-16 14:42:58 -02:00
Roberto Ierusalimschy 9fbe0690fb base-level C use global table as its environment 2009-12-15 09:25:36 -02:00
Roberto Ierusalimschy a25b8ff69c detail ('lua_tolstring' instead of lua_objlen) 2009-12-15 09:25:16 -02:00
Roberto Ierusalimschy 15b823ce4f cleaner way to add extra space in a lua state. 2009-12-14 13:27:30 -02:00
Roberto Ierusalimschy 8da245bfd2 better to keep GC state numbers sequential, to optimize switch in
'singlestep'
2009-12-11 19:31:14 -02:00
Roberto Ierusalimschy a2a2abcba4 new function 'luaC_runtilstate' to advance GC until a "valid" state 2009-12-11 17:14:59 -02:00
Roberto Ierusalimschy 2e51792596 avoid using deprecated macros lua_[gs]etglobal 2009-12-11 11:40:44 -02:00
Roberto Ierusalimschy 3a9ae612a4 macro 'ngcotouv' is the same as 'gco2uv', so it was removed 2009-12-11 11:39:34 -02:00
Roberto Ierusalimschy 9db693a57c detail (comment) 2009-12-10 17:00:33 -02:00
Roberto Ierusalimschy 1375435e4a several new features in testC to allow better testing of lua_resume
at the C API level
2009-12-10 16:21:28 -02:00
Roberto Ierusalimschy 2bb19ccf08 reordering of some functions + cleaner way to code lua_resume/resume +
small bug in lua_resume (in case of calling errors lua_resume should
remove only new arguments from the stack and push error message).
2009-12-10 16:20:07 -02:00
Roberto Ierusalimschy 64d5df7772 detail (lua_resume should empty coroutine stack even if they do not
fit into caller stack)
2009-12-10 16:17:37 -02:00
Roberto Ierusalimschy 2643da67c6 error messages from 'lua_resume' must be generated in protected mode,
to avoid raising memory errors
2009-12-08 16:59:24 -02:00
Roberto Ierusalimschy ed117bb42a lua_checkstack does not raise memory errors (instead it signals them) 2009-12-08 14:15:43 -02:00
Roberto Ierusalimschy a4472490bc new 'table.pack' function 2009-12-07 13:50:27 -02:00
Roberto Ierusalimschy 86312e1a7d lua_objlen calls __len metamethod on tables (if present) 2009-12-07 13:49:47 -02:00
Roberto Ierusalimschy df1dc3f1f5 strings in C scripts may be delimited by quotes + new functionality to
set C scripts as C hooks
2009-12-01 14:49:48 -02:00
Roberto Ierusalimschy 513d0258d9 details 2009-12-01 14:31:04 -02:00
Roberto Ierusalimschy cfa8bc3ca4 continuations may be upvalues too 2009-11-27 13:39:31 -02:00
Roberto Ierusalimschy a654e82f5c coroutines may have C bodies 2009-11-27 13:38:51 -02:00
Roberto Ierusalimschy 3e41afcec5 extra api checks for number of returns of C functions and for lua_yield 2009-11-27 13:37:59 -02:00
Roberto Ierusalimschy 3acf5ec5a1 update of file dependencies (gcc -MM) 2009-11-27 12:39:31 -02:00
Roberto Ierusalimschy 93695db903 'table.maxn' deprecated 2009-11-26 15:35:13 -02:00
Roberto Ierusalimschy 9107dd115c no more compatibility code for 'string.gfind' 2009-11-26 14:49:28 -02:00
Roberto Ierusalimschy dc4c459546 a few new warnings 2009-11-26 14:36:55 -02:00
Roberto Ierusalimschy 19a6c38745 detail in 'currentpc' (only needs to work for Lua functions) 2009-11-26 13:34:15 -02:00
Roberto Ierusalimschy 3c4d970a7b comment typos 2009-11-26 09:39:20 -02:00
Roberto Ierusalimschy b0f2b288a6 new scheme for debug info about tail calls: no more 'fake' stack entries,
but stack entry knows whether it was tail called
2009-11-25 13:27:51 -02:00
Roberto Ierusalimschy 2b25489b47 'notail' -> 'noextrachars' ('notail' may confuse with tail calls) 2009-11-24 16:05:12 -02:00
Roberto Ierusalimschy a6f465f558 new mark LUAMOD_API for all luaopen_* functions 2009-11-24 10:05:44 -02:00
Roberto Ierusalimschy 9a41506b8f 'os.exit' should close state only when second argument is true 2009-11-23 16:20:38 -02:00
Roberto Ierusalimschy 9a6d9ea57a GC may get stuck during a parser and avoids proper resizing of the
string table, making its lists grow too much and degrading performance.
2009-11-23 12:59:30 -02:00
Roberto Ierusalimschy 062e809e54 new macros 'LUAI_DDEC'/'LUAI_DDEF' to better control declarations and
definitions of non-static variables
2009-11-19 17:06:52 -02:00
Roberto Ierusalimschy b4c1824824 'luaV_arith' must be marked 'LUAI_FUNC' (as all non-static functions) 2009-11-19 17:04:58 -02:00
Roberto Ierusalimschy 2e5ef6a9fb new macro 'isdummy' 2009-11-19 15:54:07 -02:00
Roberto Ierusalimschy 1dea393058 small corrections for 'luaall.c' 2009-11-19 14:26:52 -02:00
Roberto Ierusalimschy 45dec34597 comments 2009-11-19 14:26:29 -02:00
Roberto Ierusalimschy b40a38a8ac remove declaration of removed function 2009-11-19 14:24:41 -02:00
Roberto Ierusalimschy ac899a6307 'debug.joinupvalue' -> 'debug.upvaluejoin' 2009-11-18 13:50:18 -02:00
Roberto Ierusalimschy ce444bff33 (huge) simplification of GC management 2009-11-18 11:13:47 -02:00
Roberto Ierusalimschy 2d5931ebc8 ensure that reader function cannot yield during parsing 2009-11-17 14:46:44 -02:00
Roberto Ierusalimschy 35fa276099 parser/scanner keep GC running 2009-11-17 14:33:38 -02:00
Roberto Ierusalimschy b51d76ce8d when doing hard memory tests, perform a full GC at every possible step 2009-11-17 09:56:03 -02:00
Roberto Ierusalimschy 95020afb63 'module' returns the new module (to be used with lexical environments) 2009-11-16 13:51:19 -02:00
Roberto Ierusalimschy c5050b1c41 functions 'getfenv' and 'setfenv' are deprecated 2009-11-16 13:51:03 -02:00
Roberto Ierusalimschy b9063a08f5 new function 'loadin' 2009-11-13 15:01:40 -02:00
Roberto Ierusalimschy 7fe405739c renaming: 'lua_upvaladdr' -> 'lua_upvalueid',
'lua_upvaljoin' -> 'lua_upvaluejoin'
2009-11-09 17:10:48 -02:00
Roberto Ierusalimschy 1ce819333d new option 'isrunning' for 'lua_gc' (and 'collectgarbage') 2009-11-09 16:55:17 -02:00
Roberto Ierusalimschy 88eb901f81 registry and global table may be changed through the API without a
write barrier, so GC should visit them in the atomic phase.
2009-11-09 16:29:21 -02:00
Roberto Ierusalimschy 2583bac3d3 several small changes to simplify changing TValue if needed 2009-11-06 15:09:27 -02:00
Roberto Ierusalimschy 63a3b1a1eb macro 'checkvalref' redefined as function (to avoid too long macros) 2009-11-06 15:08:43 -02:00
Roberto Ierusalimschy fbf866a1a5 macro 'gkey' returns a "real" TValue* 2009-11-06 15:07:48 -02:00
Roberto Ierusalimschy 49a67c6d3f new macro 'NILCONSTANT' to initialize nil constants 2009-11-06 15:07:12 -02:00
Roberto Ierusalimschy a921d81033 avoid using 'ttype' when there is an explicit test + macro 'checkdeadkey'
to avoid repetitions
2009-11-06 15:06:19 -02:00
Roberto Ierusalimschy 155dd01163 avoid using 'ttype' when there is an explicit test 2009-11-06 15:05:34 -02:00
Roberto Ierusalimschy 599789a907 better to enclose macros in 'if' bodies with brackets 2009-11-06 15:03:37 -02:00
Roberto Ierusalimschy 9756f56354 better control over accesses to TValue fields 2009-11-05 15:43:54 -02:00
Roberto Ierusalimschy b7d5f18d71 api functions to manipulate upvalues do not need to check their
arguments (the caller must check them before calling)
2009-11-05 15:26:00 -02:00
Roberto Ierusalimschy 5598b2bc55 new functions to identify and join upvalues 2009-11-05 14:48:31 -02:00
Roberto Ierusalimschy 77077b39d5 comment explaining OP_VARARG was wrong (and corresponding code was not
very clear)
2009-10-28 10:20:07 -02:00
Roberto Ierusalimschy 5bc91c6405 no more one environment per thread: all threads share a single global
environment
2009-10-23 17:12:19 -02:00
Roberto Ierusalimschy f5073de0a7 'ipairs' goes until length of array instead of stopping at the first nil 2009-10-23 10:50:25 -02:00
Roberto Ierusalimschy f6ed285cf2 new hash for doubles based on frexp, to avoid low-level tricks 2009-10-23 10:31:12 -02:00
Roberto Ierusalimschy 1448e736f0 better documentation for constructor syntax 2009-10-14 13:43:11 -03:00
Roberto Ierusalimschy 6e415e9387 local function definition does not need to correct debug information 2009-10-13 16:35:42 -03:00
Roberto Ierusalimschy b114c99a60 two small bugs: 'debug.getinfo' did not consider negative indices as out
of range + 'debug.[gs]etlocal' crash on tail calls
2009-10-13 16:07:40 -03:00
Roberto Ierusalimschy 916587508c parser keeps list of active local variables in a single dynamic array,
therefore saving C stack space
2009-10-11 17:02:19 -03:00
Roberto Ierusalimschy a5382b763c new function lua_copy 2009-10-05 13:44:33 -03:00
Roberto Ierusalimschy ba21aa8b2b 'cpcall' must ensure correct environment for called function 2009-09-30 17:49:47 -03:00
Roberto Ierusalimschy d119cf3035 a few more instructions to testC (func2udata and getfield) 2009-09-30 17:49:25 -03:00
Roberto Ierusalimschy 0ac3d07ea6 first implementation of lexical environments 2009-09-30 12:38:37 -03:00
Roberto Ierusalimschy 5938212748 information about upvalues (where they come from) kept in Proto structure,
instead of sequence of pseudo-opcodes after OP_CLOSURE
2009-09-28 13:32:50 -03:00
Roberto Ierusalimschy 1829911d7c some operations may shrink g->totalbytes so g->estimate must be
more flexible
2009-09-28 10:50:34 -03:00
Roberto Ierusalimschy bed2cb725a initialize g->estimate (just in case) 2009-09-28 10:50:19 -03:00
Roberto Ierusalimschy ab75bd23ee handle extended opcodes (with OP_EXTRAARG) when checking metamethod
calls
2009-09-28 09:37:17 -03:00
Roberto Ierusalimschy cee94df6e0 function list in luaL_register may be NULL for an empty list 2009-09-28 09:36:40 -03:00
Roberto Ierusalimschy fcc46467fa limit of constants per function changed to 2^26 using extra arguments
to opcodes LOADK, GETGLOBAL, and SETGLOBAL
2009-09-23 17:33:05 -03:00
Roberto Ierusalimschy f8e354e240 detail (space between function name and its parameter list) 2009-09-23 17:14:00 -03:00
Roberto Ierusalimschy a650378822 'cpcall' reimplemented as a predefined value in the registry 2009-09-21 09:09:52 -03:00
Roberto Ierusalimschy 99182c6872 references must start after predefined values in the registry 2009-09-18 15:58:45 -03:00
Roberto Ierusalimschy 67cae2854c 'lua_mainthread' replaced by new preregistered value LUA_RIDX_MAINTHREAD 2009-09-17 15:04:21 -03:00
Roberto Ierusalimschy 0e45ffb8e4 first implementation of 'lua_yieldk' (yield with continuation) 2009-09-14 11:30:39 -03:00
Roberto Ierusalimschy 071e54ae0b extra facilities to testC: comments + commands print, callk and yield +
Cfunc with extra upvalues
2009-09-09 17:44:10 -03:00
Roberto Ierusalimschy a68494fb32 'debug.[gs]etupvalue' should be able to access C upvalues too 2009-09-09 17:32:19 -03:00
Roberto Ierusalimschy 4b44793dc5 "bug": lua_createtable with sizes changed (array <-> record) 2009-09-07 11:24:12 -03:00
Roberto Ierusalimschy 90e2a716c8 details + comments 2009-09-05 09:39:29 -03:00
Roberto Ierusalimschy d9fbbe1f23 "file:write" returns "file" in case of success 2009-09-01 16:10:48 -03:00
Roberto Ierusalimschy 4a714cebd1 API checks now have explanatory messages 2009-08-31 11:26:28 -03:00
Roberto Ierusalimschy 5b6be84106 ensures that argument 'mode' to 'io.open' matches "[rwa]%+?b?", to
avoid passing invalid modes to 'fopen'.
2009-08-28 10:51:57 -03:00
Roberto Ierusalimschy b2bb2f7f59 better machinery to test continuations in the C API 2009-08-26 14:41:26 -03:00
Roberto Ierusalimschy f096ab5421 correct way to check arguments to 'strftime' 2009-08-25 16:58:08 -03:00
Roberto Ierusalimschy 4e1ffc482a test for 'fs' being NULL at the end of 'close_func' is useless ('fs'
cannot be NULl and the new ls->fs can only be NULL when the token
is EOS, in which case anchor_token has no effect).
2009-08-10 17:41:04 -03:00
Roberto Ierusalimschy bc439e21cd avoid an unprotected call to 'lua_tostring' which theoretically may
cause a panicked exit
2009-08-10 13:23:19 -03:00
Roberto Ierusalimschy 1b4480003b "stange numbers" (-0 and NaN) also go to the constant table (as
strings with their binary representation). Therefore, constant
folding may produce these results.
2009-08-10 12:31:44 -03:00
Roberto Ierusalimschy 42167804b8 luaH_[gs]etnum renamed to luaH_[gs]etint (as they only accept integers,
not generic numbers).
2009-08-07 14:53:28 -03:00
Roberto Ierusalimschy 3135a6bbab luaH_[gs]etnum renamed to luaH_[gs]etint (as they only accept integers,
not generic numbers)
2009-08-07 13:17:41 -03:00
Roberto Ierusalimschy 95cbc402dc "But" -> "Bug" (misspelling) 2009-08-05 10:09:38 -03:00
Roberto Ierusalimschy decada8dc2 'debug.getfenv' does not check whether it has an argument 2009-08-04 15:51:19 -03:00
Roberto Ierusalimschy ee5d03b42a small bug: debug.getfenv should check whether it has an argument 2009-08-04 15:27:57 -03:00
Roberto Ierusalimschy 323f33d014 'collectgarbage"count"' returns a second argument with the count%1024. 2009-08-04 15:20:18 -03:00
Roberto Ierusalimschy 55dc7fb240 bug: stack must be cleared until its end (including extra size) +
control of stack size moved to 'ldo.c'
2009-07-16 13:26:09 -03:00
Roberto Ierusalimschy 11d7ba79f2 tail calls do not need to move whole new frame down, only its slice
up to last parameter (the rest has not been used yet)
2009-07-15 15:38:16 -03:00
Roberto Ierusalimschy bd5fa9cc8f new macro 'getproto' 2009-07-15 15:37:19 -03:00
Roberto Ierusalimschy 2658c94925 detail (comment: 'correspoding' -> 'corresponding') 2009-07-15 14:57:30 -03:00
Roberto Ierusalimschy 215885768c 'index2adr' -> 'index2addr' (correct spelling) 2009-07-15 14:57:03 -03:00
Roberto Ierusalimschy a5f68589c0 avoid using 'UNUSED' (not defined outside the kernel) 2009-07-15 14:49:48 -03:00
Roberto Ierusalimschy 28419c4383 'luaL_tolstring' uses 'lua_tolstring' instead of 'lua_tostring' and
'lua_objlen'
2009-07-15 14:47:34 -03:00
Roberto Ierusalimschy 5bff2aaf47 calls with LUA_MULTRET may leave no free slots in the stack 2009-07-15 14:35:20 -03:00
Roberto Ierusalimschy f76f4cb79d new way to control stack overflow, controling only total size of the stack 2009-07-15 14:26:14 -03:00
Roberto Ierusalimschy abb85fc059 new definition for 'luaD_checkstack' to avoid possible overflows 2009-07-08 13:06:51 -03:00
Roberto Ierusalimschy aabe3ddbf4 errors in 'resume' should be all protected 2009-07-08 13:06:07 -03:00
Roberto Ierusalimschy 0c258c8492 smart use of varargs may create functions that return too
many arguments and overflow the stack of C functions.
2009-07-02 16:57:34 -03:00
Roberto Ierusalimschy d57c9cdefc BUG: 'luaV_settable' may invalidate a reference to a table and try
to reuse it.
2009-07-01 18:10:33 -03:00
Roberto Ierusalimschy afb3f7e754 bug: 'luaV_settable' may invalidate a reference to a table and try
to reuse it.
2009-07-01 17:31:25 -03:00
Roberto Ierusalimschy 88564c3aec Standard library for bitwise operations 2009-07-01 13:17:08 -03:00
Roberto Ierusalimschy 3abe3da9fb new module 'lbitlib.c' for bitwise operations 2009-07-01 13:16:40 -03:00
Roberto Ierusalimschy eb8499c8e0 use of LUAI_UINT32 replaced by 'unsigned LUA_INT32' (one less
definition needed)
2009-07-01 13:14:15 -03:00
Roberto Ierusalimschy 47c562435b better error messages for luaL_checkversion 2009-06-19 11:21:57 -03:00
Roberto Ierusalimschy 02504d86d3 l_version may be local to 'lua_version' 2009-06-19 11:21:23 -03:00
Roberto Ierusalimschy 4a818f068a 'checkversion' implemented in the auxiliary library 2009-06-18 15:59:58 -03:00
Roberto Ierusalimschy 1d6ebce296 new function 'lua_version' (so that 'checkversion' can be implemented
in the auxiliary library)
2009-06-18 15:59:18 -03:00
Roberto Ierusalimschy bc3e02a1b7 default paths have dot option as the last one (to improve security) 2009-06-18 15:19:36 -03:00
Roberto Ierusalimschy f4eed60ca9 better treatment of integer formats in string.format 2009-06-18 13:51:03 -03:00
Roberto Ierusalimschy c1de1fdac6 small optimization in 'lua_arith' (avoids overhead in the common case
of both arguments being numbers)
2009-06-18 13:36:40 -03:00
Roberto Ierusalimschy a36c8e1718 new macro 'changenvalue' 2009-06-18 13:36:40 -03:00
Roberto Ierusalimschy d7872dcf91 small optimization (reorder of BinOpr enum to unify some cases
in switches)
2009-06-18 13:35:05 -03:00
Roberto Ierusalimschy 14115170bc lua_objlen should not work for numbers (according to the manual) 2009-06-17 15:38:54 -03:00
Roberto Ierusalimschy ec52149485 'lua_lessthan' replaced by more generic 'lua_compare' 2009-06-17 14:53:50 -03:00
Roberto Ierusalimschy 6980cb1aa7 new functions 'lua_arith' and 'lua_compare' 2009-06-17 14:53:14 -03:00
Roberto Ierusalimschy 59a59fafc6 exports luaV_arith to be used by lua_arith 2009-06-17 14:51:07 -03:00
Roberto Ierusalimschy 2bdd194f43 exports luaV_arith to be used by lua_arith + uses 'luaO_arith' to
perform basic arith. operations
2009-06-17 14:50:09 -03:00
Roberto Ierusalimschy 96fa34ec32 constant folding uses 'luaO_arith' to perform basic operations 2009-06-17 14:49:09 -03:00
Roberto Ierusalimschy 6a024df440 new function 'luaO_arith' to perform basic arithmetic operations 2009-06-17 14:48:34 -03:00
Roberto Ierusalimschy 77fd93188e 'lessequal' renamed 'luaV_lessequal' and exported to be used by
'lua_compare'
2009-06-17 13:17:14 -03:00
Roberto Ierusalimschy a21c89ddc8 new API function 'lua_mainthread' 2009-06-15 16:51:31 -03:00
Roberto Ierusalimschy 49b88b1c39 patch for wrong code generation for some particular boolean expressions 2009-06-15 11:12:59 -03:00
Roberto Ierusalimschy 3db5f60547 BUG: "(((1 or false) and true) or false)" gives wrong result 2009-06-15 10:52:08 -03:00
Roberto Ierusalimschy 2258ec6bc9 'getline' renamed to 'getfuncline' (to avoid problems with POSIX) 2009-06-10 13:57:53 -03:00
Roberto Ierusalimschy 2598138ece new function 'luaK_codek' (detail) 2009-06-10 13:52:03 -03:00
Roberto Ierusalimschy 4a67e48611 new macro 'condmovestack' instead of 'condhardstacktests' 2009-06-08 16:35:59 -03:00
Roberto Ierusalimschy 5cdec7d124 added "\n" at the end of 'package.config' (so that the string
is a sequence of complete lines)
2009-06-04 16:34:24 -03:00
Roberto Ierusalimschy 9423e22aa3 no more L->base + ci->base only for Lua functions (C functions may use
'func')
2009-06-01 16:09:26 -03:00
Roberto Ierusalimschy 57f8414de1 small bug in 'luaV_concat' (L->top was left incorrect in some cases) 2009-05-27 14:11:27 -03:00
Roberto Ierusalimschy 139d562861 type of 'luai_ctype_' array changed to unsigned (safer for bitwise
operations)
2009-05-27 13:51:15 -03:00
Roberto Ierusalimschy eea6d10866 details (use ci->base instead of L->base when possible) 2009-05-22 12:19:54 -03:00
Roberto Ierusalimschy 019ebcb85f errors in finalizers are propagated with code LUA_ERRGCMM (ERRor in
__gc MetaMethod)
2009-05-21 17:06:11 -03:00
Roberto Ierusalimschy 889284ebd0 hexadecimal escape sequences in strings + better error messages for
bad decimal escape sequences
2009-05-18 14:28:04 -03:00
Roberto Ierusalimschy 6956331093 new macro 'zungetc' 2009-05-18 14:26:25 -03:00
Roberto Ierusalimschy 92479f1a8b new property 'lisupper' (needed to compute values for hexa digits) 2009-05-18 14:15:14 -03:00
Roberto Ierusalimschy e67dc3a227 'symbexec' merged with 'getobjname' (as only use for symbolic execution
now is to find a "good" name for an object)
2009-05-04 15:26:21 -03:00
Roberto Ierusalimschy 0cc3add9f8 variable renaming: 'lualibs' -> 'loadedlibs'; 'luareqlibs' ->
'preloadedlibs'
2009-05-01 10:46:35 -03:00
Roberto Ierusalimschy 71c2eeff98 comments 2009-05-01 10:37:11 -03:00
Roberto Ierusalimschy d7bc346d7a no more code checking 2009-04-30 14:42:21 -03:00
Roberto Ierusalimschy 673c456cba resize string hash table only when new size is smaller than current one 2009-04-29 14:09:41 -03:00
Roberto Ierusalimschy ea44570883 hash table for strings is rehashed in place 2009-04-29 14:09:41 -03:00
Roberto Ierusalimschy e091a254df new way to GC stacks: the entire stack must be correct all the times;
the 'dead' part of a stack (after the top) must have only nil's, so
that 'top' may go up without cleaning the stack.
2009-04-28 16:04:36 -03:00
Roberto Ierusalimschy 58c3aa8b5f malicious zero-length string in binary code may segfault Lua +
wrong code generation for some particular boolean expressions
2009-04-27 17:11:11 -03:00
Roberto Ierusalimschy c1f78ff3d3 unused arguments removed 2009-04-27 15:58:31 -03:00
Roberto Ierusalimschy e5249b9fb5 'exit' changed to 'abort' in case of panic (+ some extra comments)
'abort' seems more in line with panic ("abnormal termination")
2009-04-26 18:55:35 -03:00
Roberto Ierusalimschy d3037d97ec several small improvements based on 'ci' being fixed now (including
erasing savedpc from lua_State)
2009-04-17 19:00:01 -03:00
Roberto Ierusalimschy c6b442bd36 'luaM_freearray' does not need array type as argument 2009-04-17 11:40:13 -03:00
Roberto Ierusalimschy 4f88418170 'CallInfo' stack implemented as double-linked list instead of an array 2009-04-17 11:28:06 -03:00
Roberto Ierusalimschy 311e9f3ceb 'nresults' is saved in CallInfo from the caller, not the called 2009-04-15 13:53:39 -03:00
Roberto Ierusalimschy 8775f25830 new function 'T.makeCfunc' (for later use) 2009-04-14 16:10:17 -03:00
Roberto Ierusalimschy 70a63fa5ad first implementation of yieldable 'pcall' 2009-04-08 15:04:33 -03:00
Roberto Ierusalimschy fffbaede75 detail 2009-04-03 12:58:03 -03:00
Roberto Ierusalimschy ae9ad6c694 added comment explaining why the 'feof' test when loading a file 2009-04-02 16:54:06 -03:00
Roberto Ierusalimschy 83d2dbb15d Lua will abort anyway, so 'panic' does not need to. 2009-03-31 14:25:08 -03:00
Roberto Ierusalimschy 4e43741943 in 'lua_call', avoid preparing a continuation when thread cannot yield. 2009-03-30 15:39:20 -03:00
Roberto Ierusalimschy a274596ecc avoid making 'lastfree' an invalid pointer 2009-03-30 15:38:24 -03:00
Roberto Ierusalimschy 7e9bc41fe7 'loadlib(lib, "*")' loads 'lib' with global names exported to all 2009-03-26 19:25:05 -03:00
Roberto Ierusalimschy b1e1c15ced small bug: EOZ is a valid character to be tested 2009-03-26 15:53:52 -03:00
Roberto Ierusalimschy 3dbf305408 no more support for old-style varargs 2009-03-26 09:57:01 -03:00
Roberto Ierusalimschy 6d0ae11c57 'context' added to suspendable calls 2009-03-23 11:26:12 -03:00
Roberto Ierusalimschy 3ca739b418 'math.random' uses lua_Number to manage its arguments (there is no
reason to lose range).
2009-03-17 14:55:39 -03:00
Roberto Ierusalimschy 9e613b8583 missing argument to 'assert' raises "assertion failed" error 2009-03-16 13:30:50 -03:00
Roberto Ierusalimschy 9428ec42d0 new optional argument to 'load', to control allowed modes (binary or
textual chunks)
2009-03-13 12:50:03 -03:00
Roberto Ierusalimschy 6ffcf21367 ctype 'lalpha' includes '_' (as '_' behaves as a letter from the
point of view of Lua)
2009-03-11 10:27:32 -03:00
Roberto Ierusalimschy 6427c61e7c added macro 'lisxdigit' (just in case :) 2009-03-10 14:42:33 -03:00
Roberto Ierusalimschy ba484b9eb1 yielding across lua_call (first version) 2009-03-10 14:14:37 -03:00
Roberto Ierusalimschy f9d015523e better notes about some opcodes (comments only) 2009-03-09 12:27:56 -03:00
Roberto Ierusalimschy 1817dfc301 initial separation, in CallInfo, of what is relevant only to Lua
functions or only to C functions
2009-03-04 10:32:29 -03:00
Roberto Ierusalimschy 7837e34e56 new states have a reasonable panic function +
testC may run code on different threads +
rename of some testC operations ('rawcall'->'call', 'call'->'pcall')
2009-03-03 15:52:36 -03:00
Roberto Ierusalimschy 910310d3ba if thread has no error handling, try main thread handler before panicking 2009-03-03 15:51:24 -03:00
Roberto Ierusalimschy facfcd497f detail 2009-03-02 13:34:23 -03:00
Roberto Ierusalimschy b403317325 error functions search global space for a name for a function when
no other name is available
2009-02-27 15:18:19 -03:00
Roberto Ierusalimschy 9bf05e7364 code section 'Traceback' moved to the beginning of the file 2009-02-27 15:17:13 -03:00
Roberto Ierusalimschy e39e758a73 closing a "popen" file returns the process exit status 2009-02-20 10:50:27 -03:00
Roberto Ierusalimschy 5438d77221 global array of ctypes renamed to 'luai_ctype_' (extern names must
use a "lua" prefix...)
2009-02-20 10:11:15 -03:00
Roberto Ierusalimschy 6905ae900b Lua now uses "homemade" lctype (instead of ctype.h from ANSI C) 2009-02-19 14:33:51 -03:00
Roberto Ierusalimschy ada82930fd "homemade" version of ctype.h 2009-02-19 14:18:25 -03:00
Roberto Ierusalimschy f36e319658 'fputs' changed to 'luai_writestring' + use of 'lua_checkversion' 2009-02-19 14:15:35 -03:00
Roberto Ierusalimschy 0cea28a785 better error messages for 'lua_checkversion' 2009-02-19 14:15:13 -03:00
Roberto Ierusalimschy d2ebdc045b new macro 'lua_checkversion' to check whether core and application are
compatible
2009-02-18 14:20:56 -03:00
Roberto Ierusalimschy 81ede6bfce using light userdata to represent "remote" states 2009-02-18 11:52:51 -03:00
Roberto Ierusalimschy 2b579b4b83 panic mode does not reset stack (so that panic function can gather
debug information from it)
2009-02-18 11:52:03 -03:00
Roberto Ierusalimschy a1d0e1a11a 'log10' is deprecated now 2009-02-18 10:17:10 -03:00
Roberto Ierusalimschy 8975739839 better precision for log(x, 10) 2009-02-18 10:06:05 -03:00
Roberto Ierusalimschy d07abcc6c7 finalizers always called protected 2009-02-17 16:47:58 -03:00
Roberto Ierusalimschy 189378142a buffer creation ensures buffer space plus MINSTACK in the stack 2009-02-17 11:31:16 -03:00
Roberto Ierusalimschy 82749b765e 'db_errorfb' changed to 'db_traceback' for consistency 2009-02-17 10:21:28 -03:00
Roberto Ierusalimschy 2b590aea40 no more '__len' metamethod for strings 2009-02-16 17:09:28 -03:00
Roberto Ierusalimschy 547e47649f 'luaL_typeerror' spelled right 2009-02-13 17:39:34 -02:00
Roberto Ierusalimschy 41dd32e18e comment (should not use 'go trhough' when simply using multiple labels) 2009-02-11 16:25:20 -02:00
Roberto Ierusalimschy 5d3cc5def8 'writestring' changed into a configurable macro 2009-02-07 10:23:15 -02:00
Roberto Ierusalimschy 53db607963 avoid using 'fputs' in 'print' to avoid problems with embedded zeros 2009-02-06 16:38:47 -02:00
Roberto Ierusalimschy cbf0c7a103 check for invalid use of '%' in replacement string in 'string.gsub' 2009-02-03 17:39:19 -02:00
Roberto Ierusalimschy 4c399c5dfb detail (MAXSRC changed to LUA_IDSIZE) 2008-12-26 09:55:57 -02:00
Roberto Ierusalimschy b472098493 concat TM can yield 2008-11-06 10:43:51 -02:00
Roberto Ierusalimschy 84b3daebbd generic for coded as two dedicated instructions to simplify resumption 2008-10-30 13:39:30 -02:00
Roberto Ierusalimschy f6978173e0 yields accross metamethods and for iterators (except for __concat) 2008-10-28 14:53:16 -02:00
Roberto Ierusalimschy e02483dbc0 whole build depends on 'makefile' itself + better format for warning
options
2008-10-28 14:52:00 -02:00
Roberto Ierusalimschy 9e58e0df8f some cleaning 2008-10-28 10:55:00 -02:00
Roberto Ierusalimschy 690efef3de detail (added 'UNUSED' to unused argument) 2008-10-28 10:54:25 -02:00
Roberto Ierusalimschy b9e92c8b0d updating header dependencies 2008-10-03 13:40:56 -03:00
Roberto Ierusalimschy 4376c9bc5f more specific test to avoid calling luaF_close when function returns 2008-09-09 10:53:02 -03:00
Roberto Ierusalimschy f94cd2201c better control of call status through CallInfo 2008-08-26 10:27:42 -03:00
Roberto Ierusalimschy fdbb243ff9 first steps towards yielding through longjump 2008-08-13 14:02:42 -03:00
Roberto Ierusalimschy c1565c16ed small bug: lua_resume returning LUA_YIELD is not an error 2008-08-13 14:02:12 -03:00
Roberto Ierusalimschy 394646891c new field 'status' in CallInfo structure 2008-08-13 14:01:33 -03:00
Roberto Ierusalimschy d69aa51088 added missing parentheses around function names 2008-08-13 11:08:49 -03:00
Roberto Ierusalimschy afe849c9b4 change in error message 2008-08-06 10:38:32 -03:00
Roberto Ierusalimschy ccd678ea3e 'module' may change the environment of a C function +
internal macro 'svalue' is wrong
2008-08-06 10:32:45 -03:00
Roberto Ierusalimschy bb92ef23cb bug: string at the end of TString must consider the entire TString
entity, not only its 'tsv' part
2008-08-05 16:26:23 -03:00
Roberto Ierusalimschy bb48f456d9 bug: 'module' now checks that is caller is a Lua function 2008-08-05 16:25:42 -03:00
Roberto Ierusalimschy df802dc74b larger alignment requirement helps to uncover some kinds of bugs 2008-08-05 16:24:46 -03:00
Roberto Ierusalimschy e23da9edee GC step does not unblock collector (when it is blocked by "stop") 2008-08-01 14:01:16 -03:00
Roberto Ierusalimschy 4db2cddeee LUA_COMPAT -> LUA_COMPAT_API (more specific) 2008-07-18 16:58:10 -03:00
Roberto Ierusalimschy f9dec5fc84 do not use compatibility macros in Lua 2008-07-11 14:51:01 -03:00
Roberto Ierusalimschy 6b8725b0ee new macro LUA_COMPAT to control some compatibility macros 2008-07-11 14:50:31 -03:00
Roberto Ierusalimschy 6955666290 'string.byte' gets confused with some out-of-range negative indices +
user-requested GC step may loop forever
2008-07-11 14:27:41 -03:00
Roberto Ierusalimschy 5298392c5a bug: GC step could loop forever under very particular circumstances 2008-07-04 15:27:11 -03:00
Roberto Ierusalimschy 1ceec74370 useless test removed (pointed by lint) 2008-07-03 11:25:05 -03:00
Roberto Ierusalimschy 2a84c29bc3 comment about exported function not used by Lua 2008-07-03 11:24:36 -03:00
Roberto Ierusalimschy 4d8a1103d3 useless #define removed (pointed by lint) 2008-07-03 11:24:11 -03:00
Roberto Ierusalimschy 202de59254 useless #include removed (pointed by lint) 2008-07-03 11:23:35 -03:00
Roberto Ierusalimschy f858a155c2 identation error (pointed by lint) 2008-07-03 11:21:41 -03:00
Roberto Ierusalimschy 9e7de9473c message from -v option goes to stdout, as it is not an error message 2008-06-26 16:47:51 -03:00
Roberto Ierusalimschy 0c8f5fc2fd simplification in the handling of finalizers: no more 'tmudata' list +
no more GCSsweeptmu collector's state
2008-06-26 16:42:45 -03:00
Roberto Ierusalimschy 1527d8f00d GC called after errors now are called after showing error message (to
avoid problems when there are other errors during GC itself)
2008-06-26 16:40:12 -03:00
Roberto Ierusalimschy 8efaf8af81 added a comment about warnings for __attribute__(visibility) in some
elf targets
2008-06-25 12:27:12 -03:00
Roberto Ierusalimschy c3525610fe bug: when closing the state, 'luaC_separateudata' might mark
userdata in the wrong phase of collection, therefore avoiding
their traversal
2008-06-23 19:07:44 -03:00
Roberto Ierusalimschy 7ba62e2985 code reorganization (only changed comments and order of functions) 2008-06-23 13:51:28 -03:00
Roberto Ierusalimschy 8fd28611d5 outdated comment 2008-06-23 13:51:08 -03:00
Roberto Ierusalimschy 93869acb2c "test trick" seems more useful with pointers instead of integers 2008-06-23 13:50:34 -03:00
Roberto Ierusalimschy 480a1da34a when error is 'bad self' original message probably makes no sense, so
it is better not to show it.
2008-06-13 15:45:35 -03:00
Roberto Ierusalimschy 59e2973335 removed static variable lua_state (not used) 2008-06-13 14:07:10 -03:00
Roberto Ierusalimschy 5d09be4832 by default, 'os.exit' closes current state 2008-06-13 13:59:00 -03:00
Roberto Ierusalimschy 860e285f31 'luaL_gsub' moved into 'testC' (all auxlib should be tested through 'testC') 2008-06-13 11:15:59 -03:00
Roberto Ierusalimschy eb8ac6e2a0 'luaL_testudata' does not leave garbage on the stack in case of failure 2008-06-12 11:37:27 -03:00
Roberto Ierusalimschy b1203e036d 'posrelat' avoids problems with -(-2^31) 2008-06-12 11:21:18 -03:00
Roberto Ierusalimschy 92a0d4c67f extra options in 'testC' for newmetatable and testudata 2008-06-12 11:20:49 -03:00
Roberto Ierusalimschy 5fa55df2ca updated years in some comments/strings 2008-05-09 13:51:44 -03:00
Roberto Ierusalimschy a3af42de8e patch for "blow stack" bug 2008-05-08 13:55:08 -03:00
Roberto Ierusalimschy 198be23f36 added structure for local-variable information to allow extra
checkings if needed
2008-05-08 12:44:51 -03:00
Roberto Ierusalimschy 24359ae294 'string.find' cannot find things after subject's end 2008-04-14 12:54:59 -03:00
Roberto Ierusalimschy 6c84722afa make default GC behavior a little more agressive
(to avoid falling behind memory consumption)
2008-04-07 15:58:42 -03:00
Roberto Ierusalimschy facb0519a0 two bugs: invalid boolean values in constant table + too deep recursion
when reading nested functions
2008-04-07 15:44:23 -03:00
Roberto Ierusalimschy ffdca3522e 'table.sort' detects invalid order function before calling it
for nil elements
2008-04-07 15:43:00 -03:00
Roberto Ierusalimschy 4d7469b610 avoid constant folding for -0 (to avoid it colapsing to 0) 2008-04-07 15:41:47 -03:00
Roberto Ierusalimschy 2b84e36b93 patches for some bugs 2008-04-04 22:31:59 -03:00
Roberto Ierusalimschy 85bda9eef5 bugs: precheck must use check (instead of assert) and ensures that
code size is at least 1
2008-04-02 16:14:16 -03:00
Roberto Ierusalimschy a4d3080fe3 SETLIST extra argument now is an "instruction" (OP_EXTRAARG) 2008-04-02 14:38:54 -03:00
Roberto Ierusalimschy 5627d51e05 corrected error message ("too many constants" -> "too many functions") 2008-04-02 14:19:22 -03:00
Roberto Ierusalimschy e64b0cada8 several bugs related to precompiled code 2008-04-01 16:17:48 -03:00
Roberto Ierusalimschy 7316d61a66 'coroutine.running' should work for the main thread too 2008-02-25 11:33:57 -03:00
Roberto Ierusalimschy e2b366c760 userdata with finalizers are kept in a separated list 2008-02-19 15:55:09 -03:00
Roberto Ierusalimschy fa19baab7f proxies must be created with a __gc field in their metatables to work
properly with new semantics for finalizers
2008-02-19 15:54:09 -03:00
Roberto Ierusalimschy 2f8351fe48 turn off optimizations when testing 2008-02-15 15:44:34 -02:00
Roberto Ierusalimschy 32d42bdcdc bugs: lua_checkstack may have arithmetic overflow for large 'size' +
unpack with maximum indices may crash due to arithmetic overflow
2008-02-14 14:51:57 -02:00
Roberto Ierusalimschy 843d53aabb 'table.concat' may get confused with too large limits 2008-02-14 14:03:27 -02:00
Roberto Ierusalimschy 5ac3386888 bug: unpack with maximum indices may crash due to arithmetic overflow 2008-02-14 14:03:09 -02:00
Roberto Ierusalimschy 6d182faab6 bug: lua_checkstack may have arithmetic overflow for large 'size' 2008-02-14 14:02:58 -02:00
Roberto Ierusalimschy f86f4116c8 micro-optimization: avoid one API call in 'read_chars' 2008-02-12 15:05:36 -02:00
Roberto Ierusalimschy 7f69f0efb0 remove of useless test in 'read_chars' (if n == 0 then the resulting
string cannot be empty).
2008-02-12 14:51:03 -02:00
Roberto Ierusalimschy f6cab9666c corrected name of 'Patrick Donnelly' 2008-02-12 14:42:46 -02:00
Roberto Ierusalimschy 3deb38814d added assertions checking maximum number of upvalues 2008-02-12 11:34:12 -02:00
Roberto Ierusalimschy 3b5b14a085 LUAI_MAXCSTACK must be smaller than -LUA_REGISTRYINDEX +
coroutine.resume pushes element without ensuring stack size
2008-02-11 17:18:21 -02:00
Roberto Ierusalimschy aec671c126 maximum C stack should reserve some values for pseudo-indices 2008-02-11 17:17:19 -02:00
Roberto Ierusalimschy dd92af69db bug: pseudo-indices should be linked to maximum C stack size 2008-02-11 17:16:02 -02:00
Roberto Ierusalimschy 015e973899 bug: auxresume should reserve stack space for boolean result 2008-02-11 17:14:52 -02:00
Roberto Ierusalimschy 163f58dac5 in 'testC', booleans should be represented by booean values 2008-02-11 17:04:16 -02:00
Roberto Ierusalimschy dcee7d2fe0 new instructions 'newtable' and 'checkstack' in 'testC' 2008-02-11 16:04:26 -02:00
Roberto Ierusalimschy 5f0a2f6248 more options for 'kinds' of Garbage Collection + more agressive
shrinking of stacks and string hash
2008-02-11 13:46:03 -02:00
Roberto Ierusalimschy a73930228a more options for 'kinds' of Garbage Collection 2008-02-11 13:45:30 -02:00
Roberto Ierusalimschy a76fa25199 'ceillog2' now is exported (other modules may need it) 2008-01-30 16:05:23 -02:00
Roberto Ierusalimschy dd3519ab89 comment (LUA_GLOBALSINDEX does not need write barrier in lua_replace) 2008-01-25 11:42:12 -02:00
Roberto Ierusalimschy 3a515df086 debug.sethook/gethook may overflow the thread's stack 2008-01-21 12:41:19 -02:00
Roberto Ierusalimschy 74897bc52f bug: debug.sethook/gethook may overflow thread's stack 2008-01-21 11:37:08 -02:00
Roberto Ierusalimschy e7c989baf1 avoid calling "tail return" hooks if the hook itself turns off the event 2008-01-18 20:36:50 -02:00
Roberto Ierusalimschy 7a3c8314ac small bug (see http://lua-users.org/lists/lua-l/2007-08/msg00350.html) 2008-01-18 15:14:47 -02:00
Roberto Ierusalimschy 6f8257ec5f it seems useless trying to avoid this warning... 2008-01-18 13:37:10 -02:00
Roberto Ierusalimschy 87b0191753 better definition for LUAI_MAXCSTACK 2008-01-17 14:24:38 -02:00
Roberto Ierusalimschy 56c17ba4c7 detail 2008-01-17 14:24:30 -02:00
Roberto Ierusalimschy daddc57abd luaL_tostring -> luaL_tolstring (more generic) 2008-01-03 15:07:59 -02:00
Roberto Ierusalimschy f9cdd09191 larger limit for MAXCSTACK (plus removing of some useless definitions) 2008-01-02 14:36:19 -02:00
Roberto Ierusalimschy 47b4858357 detail ('name' of baselib is "_G") 2008-01-02 14:16:28 -02:00
Roberto Ierusalimschy b8d23d6e07 option to use Sun compiler (on lhf account) 2007-12-27 10:59:43 -02:00
Roberto Ierusalimschy fdecdd0cec stand-alone interpreter shows incorrect error message when the
'message' is a coroutine (already fixed in 5.2)
2007-12-27 10:58:29 -02:00
Roberto Ierusalimschy fabdaa37b6 'lua_pushfstring' raises an error if called with invalid format 2007-12-19 15:24:38 -02:00
Roberto Ierusalimschy bc82b4d78a new function 'package.searchpath' 2007-12-12 12:36:12 -02:00
Roberto Ierusalimschy dae850e0ee details 2007-12-08 09:54:32 -02:00
Roberto Ierusalimschy abcc124df0 BUG: lua_setfenv may crash if called over an invalid object 2007-11-28 16:27:38 -02:00
Roberto Ierusalimschy b4164a9aa7 details 2007-11-28 16:25:17 -02:00
Roberto Ierusalimschy 9f0d62ad9f BUG: table.remove removes last element of a table when given
an out-of-bound index
2007-11-26 14:57:33 -02:00
Roberto Ierusalimschy 64ecf24210 detail 2007-11-26 14:56:11 -02:00
Roberto Ierusalimschy 658e7caf92 use prefix in extern names, even those in test files 2007-11-12 14:28:45 -02:00
Roberto Ierusalimschy 788506dd58 detail 2007-11-12 12:10:09 -02:00
Roberto Ierusalimschy 62790ab15d detail 2007-11-09 16:55:07 -02:00
Roberto Ierusalimschy ad60b3ead7 avoid the use of "exotic" libc functions 2007-11-09 16:54:25 -02:00
Roberto Ierusalimschy 5e8dd55574 first implementation of ephemerons 2007-10-31 13:41:19 -02:00
Roberto Ierusalimschy 0e961ad47a some changes toward ephemerons 2007-10-29 14:51:20 -02:00
Roberto Ierusalimschy c06cc60946 BUG: 'gsub' may go wild when wrongly called without its third
> argument and with a large subject.
2007-10-29 13:51:10 -02:00
Roberto Ierusalimschy 2fa476655f detail 2007-10-25 17:31:05 -02:00
Roberto Ierusalimschy 7a78495f31 avoid problems with 'ptrdiff_t' 2007-10-25 17:30:36 -02:00
Roberto Ierusalimschy 3138afbe2e parser should not call 'luaX_lexerror' 2007-10-25 14:45:47 -02:00
Roberto Ierusalimschy 4eef0aaad1 detail 2007-10-18 09:01:52 -02:00
Roberto Ierusalimschy ab09732986 new metamethods for '__pairs' and '__ipairs' 2007-10-17 15:26:39 -02:00
Roberto Ierusalimschy b7fa64565a 27 is not a prime number :( 2007-09-30 10:09:43 -03:00
Roberto Ierusalimschy 2622ed2528 better way to handle redefinitions of 'localeconv' 2007-09-14 10:27:04 -03:00
Roberto Ierusalimschy 9cb0607f6f avoid warnings about exit; return 2007-09-14 10:26:28 -03:00
Roberto Ierusalimschy 8998032f66 detail 2007-09-14 10:26:03 -03:00
Roberto Ierusalimschy 80b4753539 better error message for 'concat' 2007-09-12 17:53:24 -03:00
Roberto Ierusalimschy fe0838cd1c tables and strings respect __len metamethod 2007-09-10 14:59:32 -03:00
Roberto Ierusalimschy 8acaa2ce07 An error in a module loaded through the '-l' option
shows no traceback.
2007-09-05 14:18:27 -03:00
Roberto Ierusalimschy c676f13e1a stand-alone error-message details 2007-09-05 14:17:39 -03:00
Roberto Ierusalimschy 9b47cee8b2 better to flush all files before starting new process with popen 2007-08-30 13:13:13 -03:00
Roberto Ierusalimschy 47e666c090 no need for ctype.h 2007-08-10 09:56:02 -03:00
Roberto Ierusalimschy 3059579253 detail 2007-08-09 17:29:15 -03:00
Roberto Ierusalimschy 72c2f75648 detail (LUA_COPYRIGHT includes release number) 2007-08-07 13:53:40 -03:00
Roberto Ierusalimschy ec68ed66ed detail 2007-08-01 09:17:29 -03:00
Roberto Ierusalimschy f6a81dbe97 BUG: too many variables in an assignment may cause a C stack overflow 2007-07-31 16:39:52 -03:00
Roberto Ierusalimschy 3904a66ab0 'debug' library must be required before being used 2007-06-22 13:59:11 -03:00
Roberto Ierusalimschy ffc5f78229 detail 2007-06-22 12:39:34 -03:00
Roberto Ierusalimschy 3f78748ef3 traceback function moved to auxlib 2007-06-22 12:33:54 -03:00
Roberto Ierusalimschy d26bfb5ae4 "spacial" reorganization to keep related functions in groups 2007-06-21 11:09:59 -03:00
Roberto Ierusalimschy 8d3dd04137 clearing some old compatibility code 2007-06-21 10:52:27 -03:00
Roberto Ierusalimschy 791d8d8585 detail 2007-06-21 10:50:53 -03:00
Roberto Ierusalimschy e85515958b clearing some old compatibility code 2007-06-21 10:48:04 -03:00
Roberto Ierusalimschy dc59444cd1 strong collision for very small numbers used as table keys 2007-06-19 17:23:29 -03:00
Roberto Ierusalimschy 6c042e17b1 avoid boolean equality (tricky for some compilers) 2007-06-19 16:48:15 -03:00
Roberto Ierusalimschy 18a583306b patch may be a little simpler 2007-05-29 16:05:25 -03:00
Roberto Ierusalimschy fc8d077612 bug: wrong error message in some concatenations 2007-05-29 15:59:59 -03:00
Roberto Ierusalimschy e64fcb9d94 bug: recursive coroutines may overflow C stack 2007-05-25 14:13:47 -03:00
Roberto Ierusalimschy 6c0a9a272e assignment of nil to parameter may be optimized away
__concat metamethod converts numbers to strings
loadlib.c should not access Lua internals
code generated for "-nil", "-true", and "-false" is wrong
Count hook may be called without being set
2007-05-16 12:39:08 -03:00
Roberto Ierusalimschy 01fa1bc114 luaL_testudata (a luaL_checkudata that does not raise errors) is
very needed.
2007-05-15 15:46:12 -03:00
Roberto Ierusalimschy aa003eba8e details 2007-05-11 14:28:56 -03:00
Roberto Ierusalimschy becf19feef better names for metamethods in debug information 2007-05-09 12:49:36 -03:00
Roberto Ierusalimschy 81fc3c4f45 bug: code generated for "-nil", "-true", and "-false" is wrong 2007-05-04 15:41:49 -03:00
Roberto Ierusalimschy e7fb0d8a6f 'os.date' checks arguments before passing them to 'strftime' 2007-05-03 17:49:29 -03:00
Roberto Ierusalimschy 4eb49163c6 error handler in 'lua.c' tries '__tostring' metamethod if error
message is not a string
2007-04-26 17:39:38 -03:00
Roberto Ierusalimschy 79cb336d74 does not allow standard files to be closed 2007-04-19 17:22:32 -03:00
Roberto Ierusalimschy 38063345ae several details 2007-04-19 17:21:53 -03:00
Roberto Ierusalimschy ae00b3a76f another way to normalize -0 that avoids problems with very small
numbers (adding 1 turns them all into 1)
2007-04-18 16:24:35 -03:00
Roberto Ierusalimschy 619be354c8 lua_pushstring/pushlstring return string 2007-04-17 10:19:53 -03:00
Roberto Ierusalimschy 94d40f3980 luaO_log2 can be private to ltable.c 2007-04-10 09:18:17 -03:00
Roberto Ierusalimschy 585b81f91e remove of a non-used test function 2007-04-10 09:17:52 -03:00
Roberto Ierusalimschy 5f4f0d4a63 no more optimization to avoid LOADNIL at function start 2007-03-27 11:11:38 -03:00
Roberto Ierusalimschy 8e36e1fe49 details (randomseed calls rand once to dischard first value) 2007-03-27 09:37:00 -03:00
Roberto Ierusalimschy 97505caa64 detail 2007-03-26 15:35:34 -03:00
Roberto Ierusalimschy df50c84ee0 BUG: loadlib should not use Lua internals (lobject.h) 2007-03-26 12:57:35 -03:00
Roberto Ierusalimschy 1a455acc81 two small bugs: some metamethods do not accept callable non-function
objects + __concat converts numbers to strings before calling metamethod
2007-03-26 12:56:23 -03:00
Roberto Ierusalimschy 60bc151ed7 patch for last bug 2007-03-09 15:51:32 -03:00
Roberto Ierusalimschy 3b19bd4d57 bug: wrong code when constant is coded after it should be 2007-03-09 15:50:56 -03:00
Roberto Ierusalimschy 08f902cf49 better documentation for auxiliary functions (that should be called only
through specific macros).
2007-02-09 11:04:52 -02:00
Roberto Ierusalimschy d3c304e92e BUG: setfenv accepts invalid argument 2007-02-09 10:40:21 -02:00
Roberto Ierusalimschy 3bf0292cd5 two new bugs + one new patch 2007-02-09 10:39:52 -02:00
Roberto Ierusalimschy a7861d9d66 new year... 2007-02-07 15:54:52 -02:00
Roberto Ierusalimschy d62a21b9d3 when formatting with '%q', all control characters are coded
as \nnn.
2007-02-07 15:53:08 -02:00
Roberto Ierusalimschy cf86576a83 new function luaL_tostring 2007-02-07 15:51:21 -02:00
Roberto Ierusalimschy 92dc64e121 more regularity in the use of quotes in error messages 2007-02-07 15:49:18 -02:00
Roberto Ierusalimschy 593bfc9668 should not manipulate NULL pointers (even without accessing them) 2007-02-07 15:48:52 -02:00
Roberto Ierusalimschy 850c60e81b detail for windows 2007-02-07 15:46:20 -02:00
Roberto Ierusalimschy 3d480b04a5 more specific ident labels 2007-02-07 12:28:00 -02:00
Roberto Ierusalimschy c36e2265d9 detail (tab->space) 2006-11-30 09:25:40 -02:00
Roberto Ierusalimschy a68df3898d detail 2006-11-22 09:43:47 -02:00
Roberto Ierusalimschy 4d7cfff6df comments 2006-11-22 09:02:03 -02:00
Roberto Ierusalimschy be822a5f1c xpcall now may get arguments to function to be called 2006-10-24 16:46:12 -03:00
Roberto Ierusalimschy 9f5a052c27 error message 2006-10-24 10:31:48 -03:00
Roberto Ierusalimschy fc875334fd detail 2006-10-20 16:30:53 -03:00
Roberto Ierusalimschy 80a267b130 avoid $URL for ident; it is reserved in subversion 2006-10-17 17:00:07 -03:00
Roberto Ierusalimschy 3182ac69a7 towards 5.2 + detail in authors + avoiding reverse plicks 2006-10-17 16:59:04 -03:00
Roberto Ierusalimschy dead3858b8 detail 2006-10-16 11:38:38 -03:00
Roberto Ierusalimschy afa0d0ac0d new constant LUA_OK 2006-10-10 14:40:17 -03:00
Roberto Ierusalimschy 742b8be0c1 detail 2006-10-10 14:39:00 -03:00
Roberto Ierusalimschy 285f926140 avoid using index 0 for free list of references (because it is not
as efficient as index 1...)
2006-09-25 12:35:00 -03:00
Roberto Ierusalimschy 3c8865cf66 detail 2006-09-22 17:24:38 -03:00
Roberto Ierusalimschy 569a326931 small optimization for ""..x 2006-09-19 11:06:45 -03:00
Roberto Ierusalimschy d1ef7e0ec6 avoid local "pc" in interpreter loop (tricky optimization with no real gain) 2006-09-19 10:57:50 -03:00
Roberto Ierusalimschy d513c3c66b bug: os.date throws error when result is the empty string 2006-09-19 10:57:08 -03:00
Roberto Ierusalimschy 93d3c8450c bug: string.format("%") reads past the string 2006-09-18 13:33:14 -03:00
Roberto Ierusalimschy 8667f29c3b behavior of 'strchr(x, 0)' is ill defined. 2006-09-18 13:06:41 -03:00
Roberto Ierusalimschy d22526ec30 'lua_strlen' is for compatibility only 2006-09-18 11:03:18 -03:00
Roberto Ierusalimschy bd869c7b31 details 2006-09-14 15:42:28 -03:00
Roberto Ierusalimschy d5a23dde90 little better error messages for internal arrays overflows 2006-09-14 09:59:06 -03:00
Roberto Ierusalimschy a7c9e45c64 avoid trailing white spaces 2006-09-11 11:07:24 -03:00
Roberto Ierusalimschy cedd2092eb 'coroutine.running' should return nil (instead of nothing) for main thread 2006-09-11 11:07:24 -03:00
Roberto Ierusalimschy c473818017 avoid "too complex" conditional expression (some compilers get confused...) 2006-09-11 09:44:56 -03:00
Roberto Ierusalimschy 6087e67771 no more compatibility option for long strings 2006-08-30 10:19:58 -03:00
Roberto Ierusalimschy 93bf618504 BUG: there is only one C stack, so nCcalls must be global 2006-08-15 16:59:20 -03:00
Roberto Ierusalimschy dfe2f1eeff macros luai_num* take a state L (when available) as argument, to allow
them to generate errors (and other facilities)
2006-08-07 16:14:30 -03:00
Roberto Ierusalimschy ca7e5b5cb6 wrong message error in some cases involving closures 2006-08-07 16:04:06 -03:00
Roberto Ierusalimschy 5019b2dd20 math.log now accepts an optional base 2006-08-07 16:01:56 -03:00
Roberto Ierusalimschy 33e7bc88f8 comment 2006-08-04 10:34:37 -03:00
Roberto Ierusalimschy fa0c03aaa6 details 2006-07-14 13:22:24 -03:00
Roberto Ierusalimschy 3fa47c5dc1 bugs now are against 5.1.1 2006-07-13 11:37:36 -03:00
Roberto Ierusalimschy 0782416a74 bug: wrong limit for list constructors 2006-07-12 16:02:50 -03:00
Roberto Ierusalimschy 3ca9af51a4 emergency garbage collector (core forces a GC when allocation fails) 2006-07-11 12:53:29 -03:00
Roberto Ierusalimschy c7b89dd280 small bug: should not use string after popping it 2006-07-03 17:16:49 -03:00
Roberto Ierusalimschy 74832b2a10 detail 2006-06-23 13:09:15 -03:00
Roberto Ierusalimschy ee41bc03ab details 2006-06-22 13:12:59 -03:00
Roberto Ierusalimschy 98194db429 details 2006-06-09 14:31:14 -03:00
Roberto Ierusalimschy fad7582c9a explicit test for common error (due to compatibility issue) 2006-06-07 09:37:17 -03:00
Roberto Ierusalimschy a62fca1ebb BUG: debug hooks may get wrong when mixed with coroutines 2006-06-05 16:36:45 -03:00
Roberto Ierusalimschy 2b5c1f99e5 small simplifications 2006-06-05 16:35:57 -03:00
Roberto Ierusalimschy e2dc5f5d15 extra assertion 2006-06-05 12:58:59 -03:00
Roberto Ierusalimschy ed64346b9d details 2006-06-05 12:57:59 -03:00
Roberto Ierusalimschy 475b0ecbf1 new macro LUA_RELEASE 2006-06-02 12:34:00 -03:00
Roberto Ierusalimschy 414359b2f1 new version number 2006-05-31 13:50:40 -03:00
Roberto Ierusalimschy 0079efc479 bug: collector did not compensate enough for userdata with finalizers 2006-05-24 11:34:06 -03:00
Roberto Ierusalimschy ad0765b4f0 subtle problem with the garbage collector 2006-05-24 11:33:49 -03:00
Roberto Ierusalimschy 20f4bbdc3a does not accept garbage after options (e.g., -ixxx) 2006-05-24 11:16:39 -03:00
Roberto Ierusalimschy c408158047 only destroy state after running all finalizers 2006-05-24 11:15:50 -03:00
Roberto Ierusalimschy 55e323190e files should not be operated after fclose, even when fclose fails 2006-05-08 17:14:16 -03:00
Roberto Ierusalimschy fe8f4c06f1 detail (better error message for invalid format) 2006-04-26 17:41:19 -03:00
Roberto Ierusalimschy c351392940 details 2006-04-26 15:19:49 -03:00
Roberto Ierusalimschy 18330b6091 lua_dostring/lua_dofile should return any values returned by the chunk 2006-04-12 17:31:15 -03:00
Roberto Ierusalimschy 8487913697 BUG: option '%q' for string.format does not handle '\r' correctly 2006-04-12 17:13:52 -03:00
Roberto Ierusalimschy 672bb67ee6 environment variable names should be configurable 2006-04-10 15:27:23 -03:00
Roberto Ierusalimschy 90df6b7a54 detail 2006-03-23 15:23:32 -03:00
Roberto Ierusalimschy 0238a0b01e BUG: luaL_checkudata may show wrong error message 2006-03-21 16:31:09 -03:00
Roberto Ierusalimschy 1ae0b6c0bf BUG: should copy the union, not (some of) its fields 2006-03-21 16:28:49 -03:00
Roberto Ierusalimschy e1dda047b2 unused macro 2006-03-21 16:28:03 -03:00
Roberto Ierusalimschy 2c8206d448 bug in Lua 4.0.2: weak tables that survive one collection are never collected 2006-03-20 09:49:30 -03:00
Roberto Ierusalimschy ae76307847 comment 2006-03-14 16:04:44 -03:00
Roberto Ierusalimschy 3d61c31e5a 'lparser.h' should not include 'ltable.h' 2006-03-09 15:15:48 -03:00
Roberto Ierusalimschy 44a9bd6a8c detail 2006-03-09 15:08:22 -03:00
Roberto Ierusalimschy 69ea087dff small change to strip file names when stripping debug information 2006-02-17 13:51:03 -02:00
Roberto Ierusalimschy c05aaf3bf0 avoid warning in OS X - ansi 2006-02-10 15:44:06 -02:00
Roberto Ierusalimschy 298ae7e230 complete support for hexadecimal constants 2006-02-10 15:43:52 -02:00
Roberto Ierusalimschy 6316a866a3 compiler warning 2006-02-06 16:28:16 -02:00
Roberto Ierusalimschy ea2cc2bc47 small improvements for allignments 2006-02-06 16:27:59 -02:00
Roberto Ierusalimschy 64205e91a3 empty string may cause out-of-bound access 2006-01-28 10:59:13 -02:00
Roberto Ierusalimschy 8173688542 detail 2006-01-27 11:54:39 -02:00
Roberto Ierusalimschy 3ef5a6797f detail 2006-01-23 18:06:19 -02:00
Roberto Ierusalimschy 9e6e43984d details 2006-01-23 17:51:43 -02:00
Roberto Ierusalimschy baffc37f5c detail 2006-01-18 09:49:12 -02:00
Roberto Ierusalimschy 440113bbe8 unused macro removed 2006-01-18 09:37:34 -02:00
Roberto Ierusalimschy 73ebc5d8f6 compat code should keep compatibility 2006-01-16 10:42:21 -02:00
Roberto Ierusalimschy a666752b1d detail 2006-01-13 17:36:28 -02:00
Roberto Ierusalimschy f8b7a5581e avoid unnecessary exports 2006-01-10 11:13:06 -02:00
Roberto Ierusalimschy ffb798e1e2 avoids type punning for table keys 2006-01-10 10:51:53 -02:00
Roberto Ierusalimschy fa936f8fa9 detail 2006-01-10 10:50:13 -02:00
Roberto Ierusalimschy dd1221582b details 2006-01-10 10:50:00 -02:00
Roberto Ierusalimschy bfdcbbcd76 small optimizations (lua_newtable -> lua_createtable) 2005-12-29 14:23:32 -02:00
Roberto Ierusalimschy 30eebb2d1c detail (stop collector while openning libraries) 2005-12-29 10:30:16 -02:00
Roberto Ierusalimschy 0fd6466957 lua_assert is an internal matter, not to be configured 2005-12-27 15:12:00 -02:00
Roberto Ierusalimschy 6a516878e9 collectgarbage"count" returns kilobytes (where K = 1024) 2005-12-27 15:10:11 -02:00
Roberto Ierusalimschy a486090a5c copyright will be 2006 2005-12-27 15:09:50 -02:00
Roberto Ierusalimschy 0160591998 removal of dead code 2005-12-26 11:35:47 -02:00
Roberto Ierusalimschy c505f341d6 small changes in casts 2005-12-22 14:19:56 -02:00
Roberto Ierusalimschy 428325baec detail 2005-12-21 10:59:43 -02:00
Roberto Ierusalimschy 0561f71f0f (much) better error messages for 'require' 2005-12-19 18:56:39 -02:00
Roberto Ierusalimschy 9fbefdf69c integer formats in 'string.format' may need to operate with larger-than-int
types
2005-12-15 16:53:34 -02:00
Roberto Ierusalimschy 43c61fc113 details 2005-12-15 16:17:49 -02:00
Roberto Ierusalimschy ea6b1b42c7 more robust way to test for decimal point separator 2005-12-08 13:50:54 -02:00
Roberto Ierusalimschy 87024e257d details 2005-12-07 13:43:05 -02:00
Roberto Ierusalimschy 6cd461633d clearer error message for uninstalled loadlib 2005-12-07 13:42:32 -02:00
Roberto Ierusalimschy 16fd4abaf6 corrects decimal point to follow current locale 2005-12-07 13:33:27 -02:00
Roberto Ierusalimschy f26b85c5b7 small detail 2005-12-02 16:42:08 -02:00
Roberto Ierusalimschy 3592c08a2c avoid printing two copyright messages with '-v -i' options 2005-11-28 12:44:48 -02:00
Roberto Ierusalimschy db724e14e0 new macro luai_numisnan 2005-11-25 11:29:32 -02:00
Roberto Ierusalimschy 1702953293 new macro LUA_WIN + new macro luai_numisnan 2005-11-25 11:29:11 -02:00
Roberto Ierusalimschy 33b4dec1cb no more "auto-detection" 2005-11-16 14:25:08 -02:00
Roberto Ierusalimschy 7dd10a1d7e new macro LUA_USE_POSIX to control POSIX-related macros 2005-11-16 09:56:28 -02:00
Roberto Ierusalimschy 521a452f28 'mod' may also raise an error when applied to zero 2005-11-16 09:55:27 -02:00
Roberto Ierusalimschy 2753134a38 new versions by lhf 2005-11-16 09:55:07 -02:00
Roberto Ierusalimschy cbbde11a8a better position for lua_number2int (it is related to lua_Number) 2005-11-08 17:45:58 -02:00
Roberto Ierusalimschy 7b89cf3aeb unused include's 2005-11-08 17:45:36 -02:00
Roberto Ierusalimschy d2811e8097 simpler checking for numbers (strtod does the rest) 2005-11-08 17:45:14 -02:00
Roberto Ierusalimschy e43e95553f more privacy 2005-11-08 17:44:31 -02:00
Roberto Ierusalimschy 930018e273 lua_getlocal/setlocal work also for C locals and temporaries 2005-11-01 14:08:52 -02:00
Roberto Ierusalimschy a160266c3d details 2005-11-01 14:08:45 -02:00
Roberto Ierusalimschy d4c99b2673 new function 'getregistry' 2005-11-01 14:08:32 -02:00
Roberto Ierusalimschy 88f9843eee better error message 2005-10-26 11:28:19 -02:00
Roberto Ierusalimschy 9b5ae6faf9 better control of which values macros use 2005-10-25 11:36:28 -02:00
Roberto Ierusalimschy caf3cfc6ac try to ensure that macros actually use their arguments 2005-10-24 15:39:21 -02:00
Roberto Ierusalimschy ff7638b0ed VC warnings 2005-10-24 15:38:47 -02:00
Roberto Ierusalimschy 8e48ebb638 no more L in numer-operator macros (some functions that use those macros
have no access to L)
2005-10-24 15:37:52 -02:00
Roberto Ierusalimschy c2bd68d2c3 detail 2005-10-24 15:37:33 -02:00
Roberto Ierusalimschy 201288b4df small bug 2005-10-23 15:52:42 -02:00
Roberto Ierusalimschy 62367dda44 string.gsub accepts a table as the replacement value 2005-10-23 15:46:30 -02:00
Roberto Ierusalimschy 056b6a8ef4 more robust implementation for table.insert 2005-10-23 15:38:15 -02:00
Roberto Ierusalimschy 502d8f9a06 comments 2005-10-23 15:37:55 -02:00
Roberto Ierusalimschy 7f376e6ea8 do a complete garbage collection in case of errors 2005-10-21 11:48:31 -02:00
Roberto Ierusalimschy 053e873145 new macro luaL_opt to avoid evaluating defaults when no needed 2005-10-21 11:47:42 -02:00
Roberto Ierusalimschy 9f4211310f more precision for gc count 2005-10-20 09:35:50 -02:00
Roberto Ierusalimschy 515d556832 access to metamethods and metafields should be raw 2005-10-20 09:35:25 -02:00
Roberto Ierusalimschy ed7039024d avoid some warnings 2005-10-19 11:05:11 -02:00
Roberto Ierusalimschy 5511bf6b9d avoid comparisons between (void *) and (int *) 2005-10-17 16:01:51 -02:00
Roberto Ierusalimschy 86704cffe9 detail in usage message 2005-10-14 15:34:23 -03:00
Roberto Ierusalimschy fa41fafa6e reorganization of argument handling 2005-10-14 15:15:46 -03:00
Roberto Ierusalimschy ebf646efb5 detail 2005-10-14 13:24:11 -03:00
Roberto Ierusalimschy b3f81f1d1d small bug when debugging dead threads 2005-10-14 13:23:33 -03:00
Roberto Ierusalimschy a24eb3ef17 different organization for platform dependencies 2005-10-13 09:22:53 -03:00
Roberto Ierusalimschy 4385e2ada4 "conceptually", OP_TEST may change reg. A 2005-10-13 09:22:05 -03:00
Roberto Ierusalimschy e9b06c506f small optimization 2005-10-13 09:21:51 -03:00
Roberto Ierusalimschy cd12ab2597 details (more uniform coding) 2005-10-13 09:21:26 -03:00
Roberto Ierusalimschy e251e84e0f constant folding optimizations 2005-10-09 17:05:48 -03:00
Roberto Ierusalimschy e6bfbc38b5 'luaopen_package' was missing in new states 2005-10-06 17:47:32 -03:00
Roberto Ierusalimschy d31c04c049 missing macros 'luai_userstate*' 2005-10-06 17:46:25 -03:00
Roberto Ierusalimschy 522481a788 avoid some warnings 2005-10-06 17:46:10 -03:00
Roberto Ierusalimschy 37b49aa451 detail 2005-10-06 17:44:22 -03:00
Roberto Ierusalimschy 0fa9b16148 details 2005-10-06 17:43:44 -03:00
Roberto Ierusalimschy e41fb9a604 registry._LOADED created "on demand" 2005-10-03 11:36:45 -03:00
Roberto Ierusalimschy 5fc92cce12 registry._LOADED created "on demand" and baselib created as module _G 2005-10-03 11:36:45 -03:00
Roberto Ierusalimschy 6dd0c6ccbc numeral expressions keep their values in struct 'expdesc' 2005-10-03 11:02:40 -03:00
Roberto Ierusalimschy a77413acd0 include of math.h depends on luaconf 2005-10-03 11:01:26 -03:00
Roberto Ierusalimschy 5dbb870815 small optimization for local declarations without initializations 2005-09-30 11:23:33 -03:00
Roberto Ierusalimschy ede19c9138 2005-09-30 11:21:56 -03:00
Roberto Ierusalimschy 9e88b336b4 unused assignment 2005-09-30 10:50:05 -03:00
Roberto Ierusalimschy 0fae476ed4 new function 'table.maxn' 2005-09-20 14:56:47 -03:00
Roberto Ierusalimschy 361a9adba7 smaller initial tables (for programs that create many states) 2005-09-20 14:55:53 -03:00
Roberto Ierusalimschy d8f1cca16e new function 'lua_setallocf' 2005-09-20 14:55:10 -03:00
Roberto Ierusalimschy bf96d3fdd9 'string.find' as it was in 5.0 2005-09-19 10:49:12 -03:00
Roberto Ierusalimschy c8c2e06899 'select' accepts negative indices 2005-09-16 15:22:48 -03:00
Roberto Ierusalimschy 8dcc6bc532 avoid the use of global lock 2005-09-14 14:48:57 -03:00
Roberto Ierusalimschy 38f585d271 separated macros for thread creation and state creation 2005-09-14 14:44:48 -03:00
Roberto Ierusalimschy 6887f91799 ":" is not a good mark as it is not valid in Windows file names 2005-09-14 14:23:03 -03:00
Roberto Ierusalimschy 7fbbf1adc6 explicit macro to control use of _longjmp 2005-09-09 15:24:42 -03:00
Roberto Ierusalimschy 6dd3a73ca2 detail (macro evaluates twice its arguments) 2005-09-09 15:23:35 -03:00
Roberto Ierusalimschy 1e6a559b29 does not set isdst when undefined 2005-09-09 15:22:46 -03:00
Roberto Ierusalimschy 2d2f955763 detail 2005-09-09 15:16:28 -03:00
Roberto Ierusalimschy 669f6306be small corrections 2005-09-06 14:21:03 -03:00
Roberto Ierusalimschy 2bcbd3c725 avoid 'PathRemoveFileSpec' (not very portable) 2005-09-06 14:20:25 -03:00
Roberto Ierusalimschy 5fa6604f00 detail 2005-09-06 14:20:11 -03:00
Roberto Ierusalimschy ce67a9be31 avoid exporting undefined functions 2005-09-06 14:19:51 -03:00
Roberto Ierusalimschy 506c89cef8 just in case, flush all output 2005-09-06 14:19:33 -03:00
Roberto Ierusalimschy 8ead2ec358 wrong syntax for Windows-specific options 2005-09-02 16:53:25 -03:00
Roberto Ierusalimschy c3cc4de3fd small bug (zero is not error code) 2005-09-01 14:42:22 -03:00
Roberto Ierusalimschy 351f7dad6b default for 'module' is opaque (with option 'seeall') 2005-08-31 20:17:29 -03:00
Roberto Ierusalimschy 3b19af44b0 new method to handle tests without values (negative values) 2005-08-29 17:49:21 -03:00
Roberto Ierusalimschy 3390f9a35a detail 2005-08-26 14:36:32 -03:00
Roberto Ierusalimschy 9273fbd131 no more 'luaL_get/setfield' (replaced by more direct luaL_findtable) 2005-08-26 14:32:05 -03:00
Roberto Ierusalimschy be666a662b detail 2005-08-25 16:55:38 -03:00
Roberto Ierusalimschy 39cdbce23e no more '-w' option + new way to check module existence 2005-08-25 12:39:16 -03:00
Roberto Ierusalimschy 8974b59e40 no more compatibility for {;} and similar syntax 2005-08-24 14:41:10 -03:00
Roberto Ierusalimschy 4ff1e5b4e1 details 2005-08-24 14:06:36 -03:00
Roberto Ierusalimschy 98296f6b45 some bugs related to stack reallocation 2005-08-24 13:15:49 -03:00
Roberto Ierusalimschy 23b79c5945 small changes to facilitate external C coroutines 2005-08-22 16:58:29 -03:00
Roberto Ierusalimschy 6fcd334ca0 small improvements 2005-08-22 15:54:49 -03:00
Roberto Ierusalimschy 43ad0637ca small optimizations 2005-08-22 15:54:32 -03:00
Roberto Ierusalimschy 027e9e99ca simpler implementation for userdata types 2005-08-18 17:36:26 -03:00
Roberto Ierusalimschy 3b828d9e48 luaL_setfield does a non-raw set 2005-08-18 13:04:05 -03:00
Roberto Ierusalimschy 68548a02d3 fancier code ;) 2005-08-17 17:09:31 -03:00
Roberto Ierusalimschy 2f2b4a42a9 luaL_checkudata raises an error if value is not correct
(like other luaL_check functions)
2005-08-17 16:05:04 -03:00
Roberto Ierusalimschy 074352911f new coding for while and repeat (with new scoping for repeat) 2005-08-17 15:32:09 -03:00
Roberto Ierusalimschy 5e8a9e324c luaL_openlib -> luaL_register, luaL_putchar -> luaL_addchar 2005-08-15 11:12:32 -03:00
Roberto Ierusalimschy 16ddf86168 luaL_openlib -> luaL_register and new function luaL_loadstring 2005-08-15 11:12:32 -03:00
Roberto Ierusalimschy e4d369c9b7 comments 2005-08-12 10:34:15 -03:00
Roberto Ierusalimschy 42a662334a simpler implementation for unary minus 2005-08-10 17:20:13 -03:00
Roberto Ierusalimschy 39c0f391c6 detail 2005-08-10 15:47:09 -03:00
Roberto Ierusalimschy c7b4f44772 correct name to open package library 2005-08-10 15:06:58 -03:00
Roberto Ierusalimschy 44b19075c0 small changes (to easy integration with Coco) 2005-08-09 16:49:04 -03:00
Roberto Ierusalimschy ab3dfa5594 store some configuration information 2005-08-09 14:58:09 -03:00
Roberto Ierusalimschy 62f786e08c new version (and new copyright)... 2005-08-09 14:57:54 -03:00
Roberto Ierusalimschy bbfd28959d attempt to better control use of _longjmp 2005-08-09 14:57:29 -03:00
Roberto Ierusalimschy 894cd31c52 #string is primitive 2005-08-09 14:42:02 -03:00
Roberto Ierusalimschy f01a95d4a0 detail 2005-08-09 09:30:19 -03:00
Roberto Ierusalimschy 680fc88cc2 a small bug 2005-08-04 10:37:38 -03:00
Roberto Ierusalimschy d96f088a26 'lua_lock' and similars should be hard to use 2005-08-04 10:37:10 -03:00
Roberto Ierusalimschy d8be9a6326 small changes 2005-08-01 12:05:09 -03:00
Roberto Ierusalimschy 95f3eefa5b small optimization 2005-08-01 01:22:23 -03:00
Roberto Ierusalimschy e82bdb24f3 new loader for "all-in-one" C packages 2005-08-01 01:21:17 -03:00
Roberto Ierusalimschy 1a343814d8 details 2005-07-31 14:12:32 -03:00
Roberto Ierusalimschy 280f7becb8 "%0" stands for the whole pattern (in gsub) 2005-07-31 13:47:34 -03:00
Roberto Ierusalimschy d6ff5d9f46 searchpath is "private affair" of loadlib 2005-07-13 16:02:42 -03:00
Roberto Ierusalimschy a05190fa3b elimination of common code + better error message 2005-07-12 18:17:46 -03:00
Roberto Ierusalimschy a569099b70 no more path for loadfile + function lists sorted 2005-07-12 15:15:11 -03:00
Roberto Ierusalimschy 20131e54d3 no more "getc" when testing if file exists 2005-07-12 11:32:48 -03:00
Roberto Ierusalimschy 80ac5e83fd details (alphabetical order for list of functions) 2005-07-12 11:32:08 -03:00
Roberto Ierusalimschy 289b5dc67a details (function list in alphabetical order) 2005-07-11 20:58:35 -03:00
Roberto Ierusalimschy c2f065f405 detail 2005-07-11 15:48:02 -03:00
Roberto Ierusalimschy b261cd110f new macro for conversion double->int + small changes 2005-07-11 14:10:35 -03:00
Roberto Ierusalimschy e4324f54b9 ';;' in a path is replaced by default path + '!' (in Windows) is
replaced by executable's directory
2005-07-11 13:41:57 -03:00
Roberto Ierusalimschy 3d08aa591d details 2005-07-11 13:41:51 -03:00
Roberto Ierusalimschy 0f30d00c87 warnings from Visual C 2005-07-11 11:01:37 -03:00
Roberto Ierusalimschy e86dab2dae details 2005-07-11 11:01:28 -03:00
Roberto Ierusalimschy 64b57db377 new test function for conversion from num to int 2005-07-11 11:00:59 -03:00
Roberto Ierusalimschy 575637319e better recovery at panic 2005-07-11 11:00:31 -03:00
Roberto Ierusalimschy 87be01598b warnings Visual C 2005-07-11 10:59:03 -03:00
Roberto Ierusalimschy e84b11a494 avoid names starting with '_' 2005-07-09 10:22:34 -03:00
Roberto Ierusalimschy bbf2cea9a1 more "polite" way to change a thread's environment 2005-07-07 12:48:29 -03:00
Roberto Ierusalimschy b3f7a43019 lua_setfenv/lua_getfenv should also manipulate threads 2005-07-06 15:07:30 -03:00
Roberto Ierusalimschy 7f97ec286e parent modules are also imported toghether with the module itself 2005-07-05 16:29:03 -03:00
Roberto Ierusalimschy e82b41aac2 several small improvements 2005-07-05 11:31:45 -03:00
Roberto Ierusalimschy ee1edd5734 detail 2005-07-05 11:31:20 -03:00
Roberto Ierusalimschy 8efb44b5e0 changes in 'string.find' and 'string.gfind' (new 'string.match' and
'string.gmatch')
2005-07-05 11:30:38 -03:00
Roberto Ierusalimschy f7720bebe3 more precise way to check incomplete lines 2005-06-28 10:01:50 -03:00
Roberto Ierusalimschy 69cc0a12fe small bug 2005-06-28 10:01:31 -03:00
Roberto Ierusalimschy 2f0955b99b detail 2005-06-27 14:24:40 -03:00
Roberto Ierusalimschy 999d55d887 several updates 2005-06-13 18:20:28 -03:00
Roberto Ierusalimschy 1f9f97e3cf 'math.mod' -> 'math.fmod' 2005-06-13 18:20:14 -03:00
Roberto Ierusalimschy 34aac33c15 detail 2005-06-13 18:17:59 -03:00
Roberto Ierusalimschy 3c2cf9db67 some extra consistency checks 2005-06-13 11:39:19 -03:00
Roberto Ierusalimschy 0b71bfd6af syntax for length changed from '*' to '#' 2005-06-13 11:25:29 -03:00
Roberto Ierusalimschy 0d1685d751 bug: last tag is not the number of tags... 2005-06-13 11:19:00 -03:00
Roberto Ierusalimschy bf2b342ac1 better control for compatibility code for varargs 2005-06-13 11:15:54 -03:00
Roberto Ierusalimschy 5fa2bec1f0 bug: current line should work for call hook 2005-06-13 11:15:22 -03:00
Roberto Ierusalimschy 746a1d612b small bug (type error) 2005-06-07 15:53:45 -03:00
Roberto Ierusalimschy 3ad03b331d optional size for 'setvbuf' 2005-06-06 15:42:21 -03:00
Roberto Ierusalimschy 86add535d8 'popen' is back 2005-06-06 10:30:52 -03:00
Roberto Ierusalimschy d987cf1f81 new mark LUAI_DATA for extern data 2005-06-06 10:30:25 -03:00
Roberto Ierusalimschy eca9fa02d2 small improvement 2005-06-03 17:16:16 -03:00
Roberto Ierusalimschy e33d7bae45 __STRICT_ANSI__ -> LUA_ANSI (definition is independent of gcc) 2005-06-01 14:07:45 -03:00
Roberto Ierusalimschy d628795940 lua_objsize -> lua_objlen (more compatible with use of `len´ in other
places [opcode name, metamethod index, etc.])
2005-05-31 11:34:02 -03:00
Roberto Ierusalimschy 05348d834b better error message 2005-05-31 11:31:50 -03:00
Roberto Ierusalimschy 90de38bf1f warnings in VS .Net 2005-05-31 11:25:18 -03:00
Roberto Ierusalimschy e8a7ecb982 luaL_findstring -> luaL_checkoption 2005-05-25 10:21:26 -03:00
Roberto Ierusalimschy 38da9d568a better use defined/undefined as flag values for macros 2005-05-20 16:09:05 -03:00
Roberto Ierusalimschy f21e9c172f details 2005-05-20 12:53:42 -03:00
Roberto Ierusalimschy 67578ec51f several small details 2005-05-17 16:49:15 -03:00
Roberto Ierusalimschy c2bb9abcec better quotes for strings in error messages 2005-05-16 18:19:00 -03:00
Roberto Ierusalimschy da32450c3d new API function `lua_tolstring' 2005-05-16 16:21:11 -03:00
Roberto Ierusalimschy a2b78aad49 debug information for active lines 2005-05-16 15:45:15 -03:00
Roberto Ierusalimschy c6293a76cc LUA_DL_DLOPEN is for internal use; makefile should use LUA_USE_DLOPEN 2005-05-09 10:14:14 -03:00
Roberto Ierusalimschy 1ab2b93462 debug information for last line of a function definition 2005-05-05 17:47:02 -03:00
Roberto Ierusalimschy 6cf85dcc90 metatables for all types 2005-05-05 12:34:03 -03:00
Roberto Ierusalimschy 65f4a0f636 no more compatibility code for traversing tables 2005-05-04 17:42:28 -03:00
Roberto Ierusalimschy 12acca7bd8 comments 2005-05-04 13:36:23 -03:00
Roberto Ierusalimschy d5fd44d747 corrected definition of lua_number2int for Windows 2005-05-03 16:30:17 -03:00
Roberto Ierusalimschy b0abc2ca03 better control of local variables in luaV_execute 2005-05-03 16:01:17 -03:00
Roberto Ierusalimschy b320d37a80 better tests for correctness of `savedpc' 2005-05-03 16:01:17 -03:00
Roberto Ierusalimschy 9b8d136e1c `*' operator is primitive only for tables 2005-05-02 14:49:43 -03:00
Roberto Ierusalimschy 9832f6b186 small bug 2005-04-29 10:54:05 -03:00
Roberto Ierusalimschy 8e696dd14a detail 2005-04-29 10:53:59 -03:00
Roberto Ierusalimschy c3939f5786 comment 2005-04-29 09:43:47 -03:00
Roberto Ierusalimschy bcc4089a7d comment 2005-04-27 15:53:53 -03:00
Roberto Ierusalimschy cf5d1bdd76 nesting of long strings only in compatibility mode 2005-04-27 15:37:51 -03:00
Roberto Ierusalimschy 8718fda9b2 added LUAI_FUNC to functions not in the API 2005-04-25 16:24:10 -03:00
Roberto Ierusalimschy 8c3c3e7691 small bug for tail-recursive debugging 2005-04-14 10:30:47 -03:00
Roberto Ierusalimschy 04f657c7f8 new protocol to open standard libraries 2005-04-13 14:24:20 -03:00
Roberto Ierusalimschy 2873d4efff stack could overflow with too many command-line arguments 2005-04-11 15:01:35 -03:00
Roberto Ierusalimschy a7ea0c71e8 detail 2005-04-11 15:01:29 -03:00
Roberto Ierusalimschy b1957b1e8e detail for Windows (untested) 2005-04-07 10:52:45 -03:00
Roberto Ierusalimschy a17e1fe124 new organization using only one library 2005-04-07 10:52:19 -03:00
Roberto Ierusalimschy fabf5db237 C stack is the same for the parser and the interpreter, so depth
control should be unified in both parts.
2005-04-07 10:09:07 -03:00
Roberto Ierusalimschy de0bfe33b7 new definition for `lua_number2int' for Windows (not tested yet!) 2005-04-06 14:30:13 -03:00
Roberto Ierusalimschy 9768e2f681 detail 2005-04-05 12:57:59 -03:00
Roberto Ierusalimschy 71eb824036 details 2005-04-05 12:35:15 -03:00
Roberto Ierusalimschy 7b6c3b463e small optimizations 2005-04-05 10:41:29 -03:00
Roberto Ierusalimschy 0316308c0d removed dirt optimizations that gave small gains 2005-04-04 15:12:51 -03:00
Roberto Ierusalimschy 409ee99900 detail 2005-04-01 10:51:37 -03:00
Roberto Ierusalimschy 445eda7ead details 2005-03-30 16:50:29 -03:00
Roberto Ierusalimschy 092dc95b06 using require' to implement -l' 2005-03-29 13:47:48 -03:00
Roberto Ierusalimschy e6e543a534 better control for compatibility code 2005-03-29 13:20:48 -03:00
Roberto Ierusalimschy 1c9c886974 standard configuration should run out-of-the-box in "any" system 2005-03-29 11:30:16 -03:00
Roberto Ierusalimschy ade585bdf9 no more LUA_FIRSTINDEX 2005-03-28 14:17:53 -03:00
Roberto Ierusalimschy 04c41444e2 wrong comment corrected 2005-03-28 09:53:40 -03:00
Roberto Ierusalimschy 03fb3c39d4 change #ifdef' for #if defined' 2005-03-23 14:51:11 -03:00
Roberto Ierusalimschy 8af1ca02e0 LUA_USERCONFIG is no longer necessary 2005-03-23 14:50:49 -03:00
Roberto Ierusalimschy f1eb79fdf4 some line-edit facilities must free the line after its use 2005-03-22 13:55:35 -03:00
Roberto Ierusalimschy 408cb71795 avoid name conflict with some spurious included header files 2005-03-22 13:54:29 -03:00
Roberto Ierusalimschy 390256edf7 better name for GC pause 2005-03-22 13:04:29 -03:00
Roberto Ierusalimschy ad24cff0f1 lua_gc(STEP) returns whether collection cycle finished 2005-03-21 15:12:21 -03:00
Roberto Ierusalimschy 6d475731ca cleaner configuration for lua.c 2005-03-21 15:12:07 -03:00
Roberto Ierusalimschy f41fc0eb0e small bug: a GC step was not proportional to its "size" 2005-03-18 17:11:28 -03:00
Roberto Ierusalimschy d872090248 small errors in previous `ci' of luaconf.h. 2005-03-18 15:55:45 -03:00
Roberto Ierusalimschy fb0f95a2b7 call limit may be larger than shorts 2005-03-18 15:55:09 -03:00
Roberto Ierusalimschy d3a6d95b9a more cleaning on configurations 2005-03-18 15:02:04 -03:00
Roberto Ierusalimschy 47984a0cc2 internal definitions have prefix `luai_' 2005-03-18 15:01:37 -03:00
Roberto Ierusalimschy 086d6b09ce avoid name colision with `close' function 2005-03-18 15:01:14 -03:00
Roberto Ierusalimschy bfe2905618 avoid too much configuration options 2005-03-18 13:38:43 -03:00
Roberto Ierusalimschy 2cbd9eecfb try to avoid warnings 2005-03-18 13:38:02 -03:00
Roberto Ierusalimschy 4494094031 detail 2005-03-16 17:02:48 -03:00
Roberto Ierusalimschy 04bbd01171 new operation *t (for size of t) (may yet be removed...) 2005-03-16 13:59:21 -03:00
Roberto Ierusalimschy 9ffae705ee new "primitive" getn 2005-03-16 13:58:41 -03:00
Roberto Ierusalimschy 6bfef60e77 bug: rawset/rawget do not ignore extra arguments 2005-03-11 12:51:08 -03:00
Roberto Ierusalimschy 370d31a559 luac´ -> luai' (to avoid confusion with other luac stuff) 2005-03-09 13:28:07 -03:00
Roberto Ierusalimschy f8df21bd20 `luaconf.h´ exports all its definitions always (so all of them
must have a lua/LUA prefix).
2005-03-08 17:10:05 -03:00
Roberto Ierusalimschy d3902cfa81 entries `{[...] = ...}' need space too. 2005-03-08 15:16:45 -03:00
Roberto Ierusalimschy b5b230d95c fewer #include's in luaconf.h 2005-03-08 15:09:16 -03:00
Roberto Ierusalimschy 7d57ea70bc new mod' (%') operator 2005-03-08 15:00:16 -03:00
Roberto Ierusalimschy 2d5b923759 details 2005-03-08 10:37:55 -03:00
Roberto Ierusalimschy 192d185492 C module names may have an optional `l' prefix 2005-03-08 10:27:36 -03:00
Roberto Ierusalimschy e010ef8948 detail 2005-03-07 15:27:34 -03:00
Roberto Ierusalimschy 1e48b20ce0 loadlib' not global anymore (packaged inside package') 2005-03-07 15:07:34 -03:00
Roberto Ierusalimschy d1ed6e4c07 small bug: must use original (previous) base 2005-03-07 13:59:01 -03:00
Roberto Ierusalimschy b6a7983b65 USHRT_MAX may not fit in a (16-bit) int 2005-03-07 13:58:27 -03:00
Roberto Ierusalimschy 49f90ffdeb new functions (to complete math.h) 2005-03-04 15:57:03 -03:00
Roberto Ierusalimschy dcabf721f8 "coroutine.current" -> "running" (compatible with "running" status) 2005-02-28 14:24:41 -03:00
Roberto Ierusalimschy 5eeff89f32 comments 2005-02-28 12:59:11 -03:00
Roberto Ierusalimschy d6143b1d7b avoid access to undefined global variables 2005-02-28 12:58:48 -03:00
Roberto Ierusalimschy d55bb795fa details 2005-02-23 14:30:22 -03:00
Roberto Ierusalimschy d84cc9d2db small bug 2005-02-18 10:50:08 -02:00
Roberto Ierusalimschy 7d45a5f48f C functions and userdata also have environments 2005-02-18 10:40:02 -02:00
Roberto Ierusalimschy 73d7640244 more secure way to stop GC cycles during finalizers 2005-02-14 11:19:50 -02:00
Roberto Ierusalimschy a9af455b32 detail 2005-02-14 11:19:44 -02:00
Roberto Ierusalimschy 678d2fb2ac all collected userdata must go to the end of the list of finalizers 2005-02-11 18:03:35 -02:00
Roberto Ierusalimschy af39352632 LUA_PATH_SEP -> LUA_PATHSEP 2005-02-10 15:12:02 -02:00
Roberto Ierusalimschy 4df8800a01 cleaner way to free all objects 2005-02-10 11:25:02 -02:00
Roberto Ierusalimschy 0e60572606 values holded in open upvalues of suspended threads may be
incorrectly collected
2005-01-19 15:03:47 -02:00
Roberto Ierusalimschy 621ef9f767 better control over GC collors of upvalues 2005-01-19 13:54:26 -02:00
Roberto Ierusalimschy d89a56f869 small warning in C++ 2005-01-18 15:23:25 -02:00
Roberto Ierusalimschy 334ba8132b cleaner way to remark open upvalues 2005-01-18 15:18:09 -02:00
Roberto Ierusalimschy ac71a0891d detail 2005-01-17 21:50:55 -02:00
Roberto Ierusalimschy 8e346d875a auxiliar patch to monitor garbage collection 2005-01-14 12:21:16 -02:00
Roberto Ierusalimschy 5be517602e no more generational collector (and no more `noinc' mode) 2005-01-14 12:19:42 -02:00
Roberto Ierusalimschy d2bda8046c new implementation for loaders 2005-01-14 12:17:18 -02:00
Roberto Ierusalimschy a72fbf794d detail 2005-01-10 17:16:29 -02:00
Roberto Ierusalimschy 8ddfe3df29 macros for all arithmetic operations over lua_Numbers 2005-01-10 16:17:39 -02:00
Roberto Ierusalimschy 6eb68ba57a all function declarations surround name with parentheses 2005-01-10 15:31:50 -02:00
Roberto Ierusalimschy a27497aa03 debug.traceback' gets an optional initial level' parameter 2005-01-10 15:21:10 -02:00
Roberto Ierusalimschy 0480ea0886 gets `debug.traceback' current when error occurs 2005-01-10 15:21:10 -02:00
Roberto Ierusalimschy 162b66624d no more `lua_userinit' macro 2005-01-10 14:31:30 -02:00
Roberto Ierusalimschy e791f025c0 no more `_TRACEBACK' variable 2005-01-10 14:30:59 -02:00
Roberto Ierusalimschy f61d435a7d a^b calls `pow´ (from math.h) directly 2005-01-07 18:00:33 -02:00
Roberto Ierusalimschy 071b2ae0e1 details 2005-01-07 17:53:32 -02:00
Roberto Ierusalimschy e2498e079e change in hash algorithm so that it does not need empty slot
(tables can be 100% full)
2005-01-05 16:20:51 -02:00
Roberto Ierusalimschy 65726f3e2e cleaner interface to `ltable' 2005-01-04 13:55:12 -02:00
Roberto Ierusalimschy 9fe2d0266a better configuration for Windows 2005-01-04 10:46:04 -02:00
Roberto Ierusalimschy e22cdf7752 better error messages when require fails for C module 2004-12-29 16:56:34 -02:00
Roberto Ierusalimschy a5eb48a3e6 redesigned loadlib (Windows version not tested yet) 2004-12-27 13:58:15 -02:00
Roberto Ierusalimschy 49fe79e9fd small change 2004-12-27 13:58:15 -02:00
Roberto Ierusalimschy 96727c61b8 several improvements/corrections 2004-12-22 15:43:27 -02:00
Roberto Ierusalimschy d5ebc3ff6d small changes 2004-12-22 11:05:33 -02:00
Roberto Ierusalimschy 3d19aee78f `luac' may generate code without upvalue names 2004-12-20 13:50:00 -02:00
Roberto Ierusalimschy 4194de70e7 details 2004-12-20 11:47:29 -02:00
Roberto Ierusalimschy c6254dceff a different option for the GC 2004-12-13 10:15:11 -02:00
Roberto Ierusalimschy a56d889f72 corrections for `absent' implementation 2004-12-13 10:14:21 -02:00
Roberto Ierusalimschy 2ec4fc4295 simpler code for `print' 2004-12-07 16:31:34 -02:00
Roberto Ierusalimschy 70751dd27c details 2004-12-07 16:31:16 -02:00
Roberto Ierusalimschy 39a8082f50 more options for controling the GC 2004-12-06 15:53:42 -02:00
Roberto Ierusalimschy 531874f6ce better (correct?) way to handle `next' over removed keys 2004-12-04 16:10:22 -02:00
Roberto Ierusalimschy 61a888518f details 2004-12-03 18:54:12 -02:00
Roberto Ierusalimschy c78940f21a static names do not need `luaX_' prefix 2004-12-03 18:50:25 -02:00
Roberto Ierusalimschy 8b239eeba1 details 2004-12-03 18:44:19 -02:00
Roberto Ierusalimschy a5330b77f3 static names do not need `luaX_' prefix 2004-12-03 18:35:33 -02:00
Roberto Ierusalimschy e1c2fb6eed details 2004-12-02 10:59:10 -02:00
Roberto Ierusalimschy 12dacd3c0e added an `L' parameter to macros L_TRY & L_THROW (someone may need it). 2004-12-01 13:52:54 -02:00
Roberto Ierusalimschy 23b38176a7 `LUA_FIRSTINDEX' should not be configurable 2004-12-01 13:50:18 -02:00
Roberto Ierusalimschy 97e2dab1fb better control of overflows in size computations 2004-12-01 13:46:18 -02:00
Roberto Ierusalimschy 0ed8519127 detail 2004-12-01 13:46:06 -02:00
Roberto Ierusalimschy 0e002005b1 better names for `luaM_free...' macros 2004-11-24 17:20:21 -02:00
Roberto Ierusalimschy 1d99a7360b details 2004-11-24 17:16:03 -02:00
Roberto Ierusalimschy 2f82bf6fe9 better support for 64-bit machines 2004-11-24 16:55:56 -02:00
Roberto Ierusalimschy 087df82a61 detail 2004-11-24 16:55:42 -02:00
Roberto Ierusalimschy 10e48b9160 details 2004-11-19 14:59:08 -02:00
Roberto Ierusalimschy 6f1ea817f5 better control over memory-size overflows 2004-11-19 13:52:40 -02:00
Roberto Ierusalimschy cdcb236747 needs to include stdlib.h' to access getenv' 2004-11-19 13:52:12 -02:00
Roberto Ierusalimschy 9be5844713 first full implementation of new package system 2004-11-18 17:53:49 -02:00
Roberto Ierusalimschy 497f042fad detail 2004-11-17 10:02:41 -02:00
Roberto Ierusalimschy 2ed07ea8c1 towards "requiring" C libraries 2004-11-11 13:42:57 -02:00
Roberto Ierusalimschy cfd7bc478f better patch for buffer overflow error 2004-11-03 10:22:39 -02:00
Roberto Ierusalimschy 737ec947d3 better implementation for `floating-point bytes' 2004-11-01 12:06:50 -03:00
Roberto Ierusalimschy 45d566f676 small corrections (thanks to Mike Pall) 2004-11-01 11:33:33 -03:00
Roberto Ierusalimschy cfb79b1751 more secure way to compute final string length 2004-10-28 14:45:51 -03:00
Roberto Ierusalimschy 3e1a1f2836 better configuration for loadlib + tested Mac OS X version 2004-10-18 15:07:31 -03:00
Roberto Ierusalimschy b32e9a46d2 better configuration for loadlib 2004-10-18 15:07:31 -03:00
Roberto Ierusalimschy e5cfa7a367 use of parentheses around macro parameters in call lists, to avoid
problems with comma expressions
2004-10-18 09:51:44 -03:00
Roberto Ierusalimschy aae1612747 avoid name chash in `all.c' 2004-10-08 15:57:16 -03:00
Roberto Ierusalimschy 8050e75f9d bug: gc metamethod must disable GC steps (to avoid nested calls) 2004-10-08 13:00:34 -03:00
Roberto Ierusalimschy 3bec76abe3 first version of loadlib for Mac OS X (not tested yet!!) 2004-10-07 14:27:20 -03:00
Roberto Ierusalimschy 5cb6037d49 cannot jump to a setlist count 2004-10-07 14:27:00 -03:00
Roberto Ierusalimschy f1c2dd3aed detail 2004-10-06 15:34:47 -03:00
Roberto Ierusalimschy bd38017ddf small optimization for table size in machines with double allignment 2004-10-06 15:34:16 -03:00
Roberto Ierusalimschy 652f885c30 detail 2004-10-04 16:07:42 -03:00
Roberto Ierusalimschy f7e9465a0c new format for SETLIST opcode 2004-10-04 16:04:34 -03:00
Roberto Ierusalimschy 5ee87acd6b small optimization for boolean constants + new format for SETLIST opcode 2004-10-04 16:01:53 -03:00
Roberto Ierusalimschy 5d834bdf57 function constants may include boolean values 2004-10-04 16:01:12 -03:00
Roberto Ierusalimschy 67391a35da details 2004-09-29 18:03:42 -03:00
Roberto Ierusalimschy 36541dec9b towards new package system 2004-09-29 18:03:14 -03:00
Roberto Ierusalimschy cf2a194edc better API for luaL_getfield/setfield 2004-09-29 18:00:25 -03:00
Roberto Ierusalimschy 66845f415f small optimizations 2004-09-27 15:54:45 -03:00
Roberto Ierusalimschy b2820f39a2 long string delimiter changed from [*[' to [=[' 2004-09-22 11:02:00 -03:00
Roberto Ierusalimschy 8b5bb6056b removal of unused variable 2004-09-22 09:37:52 -03:00
Roberto Ierusalimschy 4973682294 small bug with coroutine tracebacks 2004-09-21 14:58:06 -03:00
Roberto Ierusalimschy 6acfb91c8d new auxiliary functions to implement new package system 2004-09-21 13:54:32 -03:00
Roberto Ierusalimschy 2419f2bf02 cleaner API for coroutines 2004-09-15 17:39:42 -03:00
Roberto Ierusalimschy 0e54d2be36 bug: barrier was wrong for generational phase 2004-09-15 17:38:15 -03:00
Roberto Ierusalimschy 226c57fec0 simpler configuration to turn on all asserts 2004-09-10 14:30:46 -03:00
Roberto Ierusalimschy 0de2065f4e tighter tests for stack overflow 2004-09-08 11:23:09 -03:00
Roberto Ierusalimschy ee165043ef two bugs related to varargs 2004-09-03 12:48:56 -03:00
Roberto Ierusalimschy 3c394b12f9 detail 2004-09-03 10:17:14 -03:00
Roberto Ierusalimschy 79fc7dea43 simpler implementation for generic reader 2004-09-03 10:16:48 -03:00
Roberto Ierusalimschy 9c34e23214 new libs loslib´ and linit´ 2004-09-01 10:49:20 -03:00
Roberto Ierusalimschy 2aba14b623 details 2004-09-01 10:47:31 -03:00
Roberto Ierusalimschy 1dd8c9b6b6 detail 2004-08-31 14:57:33 -03:00
Roberto Ierusalimschy 7d309480dd new way to handle _PATH (old LUA_PATH) 2004-08-30 15:35:14 -03:00
Roberto Ierusalimschy bcb2cb59ac select' returns all values after given n' 2004-08-30 12:28:32 -03:00
Roberto Ierusalimschy 0b06241483 better control for GC cycles 2004-08-30 10:44:44 -03:00
Roberto Ierusalimschy 857253cdfc detail 2004-08-30 10:44:04 -03:00
Roberto Ierusalimschy 5dcd908add detail 2004-08-26 11:19:55 -03:00
Roberto Ierusalimschy 32d4f304db first implementation of generational GC 2004-08-24 17:12:06 -03:00
Roberto Ierusalimschy 4b12eff801 small correction (less conservative write barrier for tables) 2004-08-24 17:09:11 -03:00
Roberto Ierusalimschy 271e05917f bug: lua_getupvalue and setupvalue do not check for index too small. 2004-08-17 14:45:45 -03:00
Roberto Ierusalimschy fe8c365281 default state (created by `luaL_newstate´) has a default panic function 2004-08-13 16:52:53 -03:00
Roberto Ierusalimschy 2d8b099274 better checking for read errors (with `ferror´) 2004-08-13 16:52:13 -03:00
Roberto Ierusalimschy ff4f8fe59a small bug: calls to upvalues were not correctly traced 2004-08-13 15:02:36 -03:00
Roberto Ierusalimschy a7c74c06b9 small bug: lua_gc(count) was falling through to next option 2004-08-12 14:02:51 -03:00
Roberto Ierusalimschy c7dda42c2f bug (due to new handling of varargs) 2004-08-12 11:19:51 -03:00
Roberto Ierusalimschy 26ae992129 less conservative write barrier for tables 2004-08-10 16:17:23 -03:00
Roberto Ierusalimschy f87057690b `io.lines' also can give the file name in its error message 2004-08-09 11:35:59 -03:00
Roberto Ierusalimschy 9e6aa878c9 string.byte truncates indices out of range 2004-08-09 10:30:33 -03:00
Roberto Ierusalimschy c0fdaf5842 string.byte may return multiple values 2004-08-06 14:35:38 -03:00
Roberto Ierusalimschy 2430d3cb28 small changes (due to Rici Lake) to allow testing non-supported OS functions 2004-08-05 16:30:37 -03:00
Roberto Ierusalimschy 6bddbbde7a details (opcode may not be the first field) 2004-08-04 17:18:13 -03:00
Roberto Ierusalimschy 31e48f26ed small bug 2004-07-16 10:30:53 -03:00
Roberto Ierusalimschy 0d9007b642 no more LUA_OPNAMES 2004-07-16 10:17:00 -03:00
Roberto Ierusalimschy 9609236fbb no more LUA_OPNAMES; it is simpler to "waste" 400 bytes 2004-07-16 10:15:32 -03:00
Roberto Ierusalimschy 942496d767 small bug 2004-07-13 17:11:32 -03:00
Roberto Ierusalimschy a535ad6fee several small changes (mainly function names) 2004-07-13 16:56:44 -03:00
Roberto Ierusalimschy 4206d7ed60 `lua_Chunkwriter' returns 0 in case of success 2004-07-09 15:24:41 -03:00
Roberto Ierusalimschy 7a796a0682 new macro `luaL_typename' 2004-07-09 15:23:17 -03:00
Roberto Ierusalimschy 76d8b8db06 lua_pushfstring' now supports %p' option too 2004-07-09 13:01:38 -03:00
Roberto Ierusalimschy ce455481ab separation between io lib and os lib 2004-07-09 12:47:48 -03:00
Roberto Ierusalimschy 85f1d70e68 OS lib (finally separated from io lib) 2004-07-09 12:47:48 -03:00
Roberto Ierusalimschy 31f6540fba back with an "open all libs" function 2004-07-09 11:29:29 -03:00
Roberto Ierusalimschy eab1965c05 bug: `lua_setfenv' needs a write barrier 2004-07-09 11:20:22 -03:00
Roberto Ierusalimschy 3d5187f6e5 require' uses its private reference to _LOADED' table 2004-07-02 15:09:11 -03:00
Roberto Ierusalimschy 80ec81926c `lua.c' also needs the default path, so auxlib should provide it 2004-07-01 11:26:28 -03:00
Roberto Ierusalimschy 96917ff42a "step" option in lua_gc also need to lock Lua. 2004-06-30 11:15:23 -03:00
Roberto Ierusalimschy a6179adf12 detail 2004-06-30 09:58:44 -03:00
Roberto Ierusalimschy 02a2c01ccd new way to code RK values 2004-06-29 15:49:02 -03:00
Roberto Ierusalimschy 23e08a68f5 detail 2004-06-29 14:05:00 -03:00
Roberto Ierusalimschy 0f5a497ed9 new interface for search-path function + small changes in require 2004-06-29 13:58:17 -03:00
Roberto Ierusalimschy 753625c3f3 new interface for search-path function 2004-06-29 13:57:56 -03:00
Roberto Ierusalimschy 42b74ccf1d libraries may want to use `lua_assert' too... 2004-06-23 12:57:29 -03:00
Roberto Ierusalimschy 0c49857c1a new scheme to search paths 2004-06-21 17:05:29 -03:00
Roberto Ierusalimschy 6b41e84da5 `assert' returns all its parameters (not only the first) 2004-06-21 13:45:09 -03:00
Roberto Ierusalimschy 359840c2f8 new coroutines inherit hook from creator 2004-06-17 11:25:31 -03:00
Roberto Ierusalimschy dba17070ac optional error for accesss to undefined variables/fields 2004-06-17 11:06:52 -03:00
Roberto Ierusalimschy 569eefbf73 detail 2004-06-16 17:22:43 -03:00
Roberto Ierusalimschy 5e4ea9a831 `setn' returns its "self" (the table) 2004-06-15 10:37:21 -03:00
Roberto Ierusalimschy 6311e3109f `setfenv' returns "self" 2004-06-15 10:31:30 -03:00
Roberto Ierusalimschy 9b854e6dbc BUG: string concatenation may cause arithmetic overflow, leading
to a buffer overflow.
2004-06-08 13:23:58 -03:00
Roberto Ierusalimschy 2b2d8ecd7a details 2004-06-08 11:31:15 -03:00
Roberto Ierusalimschy 75057dfced 2004-06-08 11:31:00 -03:00
Roberto Ierusalimschy 345379b5ff option for garbage-collector `step' 2004-06-04 12:30:53 -03:00
Roberto Ierusalimschy 118e471fa0 details 2004-06-02 16:09:36 -03:00
Roberto Ierusalimschy ba9878fcb8 lock stuff defined in `luaconf.h' 2004-06-02 16:09:21 -03:00
Roberto Ierusalimschy fa38421cea `testC' can operate on other states 2004-06-02 16:08:52 -03:00
Roberto Ierusalimschy e8d4fe7236 new macro lua_threadyield' + lock stuff in luaconf.h' + details 2004-06-02 16:07:55 -03:00
Roberto Ierusalimschy b8691f13a8 `getn' uses binary search if it has to count elements 2004-06-02 16:06:14 -03:00
Roberto Ierusalimschy f4718544de what is provided by lauxlib.c should be defined at lauxlib.h 2004-06-02 14:37:03 -03:00
Roberto Ierusalimschy 50f9cd201e no more `__fenv' 2004-06-02 11:20:08 -03:00
Roberto Ierusalimschy 9d8426bab4 better error messages for `loadfile' 2004-06-02 10:50:46 -03:00
Roberto Ierusalimschy 557f0009c4 clear definition for `lua_number2int' 2004-06-02 10:24:43 -03:00
Roberto Ierusalimschy 0dfd04eb60 lua_strlen' upgraded to lua_objsize' (which also works with userdata) 2004-05-31 16:41:52 -03:00
Roberto Ierusalimschy 1e0aaf2156 luaL_dofile' and luaL_dostring' are deprecated 2004-05-31 16:27:14 -03:00
Roberto Ierusalimschy 616438fe9a new way to use vararg' parameters (with ...') 2004-05-31 15:51:50 -03:00
Roberto Ierusalimschy 47eda6ebd8 main must return status from original main! 2004-05-31 15:50:48 -03:00
Roberto Ierusalimschy 0f49b3e62d new function `select' 2004-05-31 15:50:30 -03:00
Roberto Ierusalimschy 0733c83b8c other modules may need FILEHANDLE definition 2004-05-28 15:35:05 -03:00
Roberto Ierusalimschy e9844a4f1d `popen' is not ANSI and therefore was removed from the basic library 2004-05-28 15:32:51 -03:00
Roberto Ierusalimschy c61bb89dba details 2004-05-17 09:34:00 -03:00
Roberto Ierusalimschy 0bda88e6cd small steps towards yields in iterators and tag methods 2004-05-14 16:25:09 -03:00
Roberto Ierusalimschy 7966a4acae avoid name clashes among different files 2004-05-11 13:52:08 -03:00
Roberto Ierusalimschy 37cd986532 in time', uses default if isdst' is absent 2004-05-10 17:26:37 -03:00
Roberto Ierusalimschy a17dd24b34 no more USE_DEGREES option 2004-05-10 15:11:32 -03:00
Roberto Ierusalimschy b072e4ea0b tinsert' and tremove' also use LUA_FIRSTINDEX 2004-05-10 15:06:14 -03:00
Roberto Ierusalimschy 7e41612eb2 code parameterized by LUA_FIRSTINDEX (first index of an array) 2004-05-10 14:50:51 -03:00
Roberto Ierusalimschy b0f341ee52 LUAL_BUFFERSIZE is used in `lauxlib.h' and so everybody may need it 2004-05-10 10:58:26 -03:00
Roberto Ierusalimschy 1c459b881f accept `\r' as newline when looking for line end 2004-05-03 09:30:41 -03:00
Roberto Ierusalimschy 9629508a98 configuration file for Lua project 2004-05-03 09:28:43 -03:00
Roberto Ierusalimschy 763b8fba1b more stuff goes to configuration file 2004-05-03 09:28:43 -03:00
Roberto Ierusalimschy b4cd38ba6c new scheme for configuration through `luaconf.h' 2004-04-30 17:13:38 -03:00
Roberto Ierusalimschy 079facab40 ensures own top is corrected after calling function with multiple results 2004-04-05 11:43:17 -03:00
Roberto Ierusalimschy 4c5d7b2ddd small optimization for {f()} 2004-03-26 11:02:41 -03:00
Roberto Ierusalimschy d7cb622866 `unpack' has two optional arguments (to give a range) 2004-03-26 10:25:17 -03:00
Roberto Ierusalimschy 26a9b249db details 2004-03-24 12:46:49 -03:00
Roberto Ierusalimschy 227bddafe8 new copyright year 2004-03-24 10:55:46 -03:00
Roberto Ierusalimschy 5008e3d7d1 new states must use controlled malloc, too 2004-03-23 14:07:53 -03:00
Roberto Ierusalimschy 21bc05c920 write barrier for C upvalues 2004-03-23 14:07:34 -03:00
Roberto Ierusalimschy 29a13b4128 detail 2004-03-23 13:38:43 -03:00
Roberto Ierusalimschy ef8c0d7d90 better message for errors with upvalues 2004-03-23 10:10:16 -03:00
Roberto Ierusalimschy 178246062c reuse `sweeplist' for all lists 2004-03-23 09:57:12 -03:00
Roberto Ierusalimschy 24f2d1183c detail 2004-03-16 09:31:40 -03:00
Roberto Ierusalimschy 8e1f25e3f8 bug in `dofile' 2004-03-15 18:09:55 -03:00
Roberto Ierusalimschy 48a8d78102 new tests to check memory consistency (for incremental GC) 2004-03-15 18:04:54 -03:00
Roberto Ierusalimschy a4e1230f95 better way to control open upvalues 2004-03-15 18:04:33 -03:00
Roberto Ierusalimschy 9804467eeb detail 2004-03-13 10:32:09 -03:00
Roberto Ierusalimschy a003e89125 better error messages for some limits 2004-03-12 16:53:56 -03:00
Roberto Ierusalimschy b876ec61c0 new (temporary?) API for garbage collector 2004-03-09 14:34:35 -03:00
Roberto Ierusalimschy 898e8a6794 added include to stdarg.h (as it uses vararg facilities) 2004-02-20 13:01:05 -03:00
Roberto Ierusalimschy 1edea34666 details 2004-02-18 10:40:03 -03:00
Roberto Ierusalimschy 2aaf7394ad more and better tools (assertions & inspectors) to check incremental GC 2004-02-16 16:09:52 -03:00
Roberto Ierusalimschy b3ce450529 avoid calling `memcmp' with a NULL argument 2004-01-15 10:40:26 -02:00
Roberto Ierusalimschy 24434b59f7 '%' must be '%%' to avoid formatting problems 2004-01-02 09:54:14 -02:00
Roberto Ierusalimschy beb2aa5a46 atomic operations are not GC "states" 2003-12-12 16:29:34 -02:00
Roberto Ierusalimschy 47fc57a252 TObject' renamed to TValue' + other name changes and better assertions
for incremental garbage collection
2003-12-10 10:13:36 -02:00
Roberto Ierusalimschy 4d5fe1f54b detail 2003-12-10 09:04:54 -02:00
Roberto Ierusalimschy df429f163a First version of incremental GC 2003-12-09 14:56:11 -02:00
Roberto Ierusalimschy fe595a45c2 `grayagain' list 2003-12-04 16:52:23 -02:00
Roberto Ierusalimschy 9db1942bac sweep of strings also incremental 2003-12-04 15:22:42 -02:00
Roberto Ierusalimschy c6eac44a94 two different white flags (to distinguish dead elements from new ones) 2003-12-03 18:03:07 -02:00
Roberto Ierusalimschy 8878554b85 single list for all collectible objects, with udata separated at the
end of the list
2003-12-03 10:30:41 -02:00
Roberto Ierusalimschy af850484a9 default metatable can be NULL 2003-12-01 16:22:56 -02:00
Roberto Ierusalimschy 1d10acb355 incremental GC phases 2003-12-01 14:33:30 -02:00
Roberto Ierusalimschy da61624756 avoid overflow when doubling size 2003-11-27 16:18:37 -02:00
Roberto Ierusalimschy 8b97b072cd details 2003-11-27 16:05:14 -02:00
Roberto Ierusalimschy 5ee63257f9 macros for closure sizes are global 2003-11-24 16:50:36 -02:00
Roberto Ierusalimschy 8bc6c68021 details 2003-11-19 17:59:18 -02:00
Roberto Ierusalimschy 57b6ed6815 initial implementation of white/gray/black coloring 2003-11-19 17:41:57 -02:00
Roberto Ierusalimschy 9b9cdfee8b gclist for upvalues must be available even when upvalue is still open 2003-11-19 17:41:30 -02:00
Roberto Ierusalimschy 366e4af3c9 towards incremental GC 2003-11-18 12:55:11 -02:00
Roberto Ierusalimschy 53c7f86194 details 2003-11-18 08:44:53 -02:00
Roberto Ierusalimschy ab7d9bfd0c cleaner code for manipulation of `marked' field 2003-11-17 17:50:05 -02:00
Roberto Ierusalimschy 921b1723e2 comments 2003-11-11 14:34:17 -02:00
Roberto Ierusalimschy fa198197a0 lua_(set)getglobal are ok to use 2003-11-05 09:59:14 -02:00
Roberto Ierusalimschy 1e944de6cb towards a "stackless" call of metamethods (?) 2003-10-27 17:14:31 -02:00
Roberto Ierusalimschy 275c150b17 error()' (and error(nil)') generates errors with no error messages 2003-10-23 16:06:22 -02:00
Roberto Ierusalimschy d6d896b953 lua_set(get)global may use lua_set(get)field 2003-10-21 08:58:58 -02:00
Roberto Ierusalimschy 07201066bd core does not look for function name in globals (too particular) 2003-10-20 16:42:28 -02:00
Roberto Ierusalimschy 97b838d9ab new semantics for setn/getn (no more changes to `n') 2003-10-20 16:32:55 -02:00
Roberto Ierusalimschy c51bcf4796 it's ok to dump functions with upvalues 2003-10-20 15:42:41 -02:00
Roberto Ierusalimschy 03bab90303 new function `lua_getallocf' to retrieve allocation function and data 2003-10-20 10:25:23 -02:00
Roberto Ierusalimschy 8502331f69 `luaX_errorline' was used only in one place 2003-10-20 10:24:34 -02:00
Roberto Ierusalimschy 9914e1bcdd detail 2003-10-20 10:24:26 -02:00
Roberto Ierusalimschy 10de467c79 new function `lua_createtable' 2003-10-10 10:29:28 -03:00
Roberto Ierusalimschy 533737f26e new functions lua_getfield' and lua_setfield' 2003-10-10 09:57:55 -03:00
Roberto Ierusalimschy a41d60e1d1 debugger can only see `local function' after it has a meaningful value 2003-10-09 14:56:23 -03:00
Roberto Ierusalimschy f04fe526cd new functions `lua_tointeger' and lua_pushinteger' 2003-10-07 17:13:41 -03:00
Roberto Ierusalimschy 21947deddc new bug + correction in path for coroutine bug 2003-10-07 09:34:21 -03:00
Roberto Ierusalimschy 3087636c76 detail 2003-10-03 13:07:44 -03:00
Roberto Ierusalimschy 7b8504840f buffer should better use `size_t' for its size 2003-10-03 13:05:34 -03:00
Roberto Ierusalimschy 3a508b8bd7 avoid the use of `strlen' (strings are literals) 2003-10-03 13:04:24 -03:00
Roberto Ierusalimschy 6becdb3e70 details 2003-10-03 13:04:11 -03:00
Roberto Ierusalimschy b97fb932ec Lua kernel does not use malloc/free functions. 2003-10-02 17:31:17 -03:00
Roberto Ierusalimschy c7cf92e6f3 avoid unecessary includes of `stdlib' 2003-10-02 16:21:09 -03:00
Roberto Ierusalimschy a62d39aa1c detail: `luaL_where' does not use the name information 2003-10-01 13:50:53 -03:00
Roberto Ierusalimschy 5d4bf35ec9 bug: syntax `local function' does not increment stack size 2003-09-29 13:41:35 -03:00
Roberto Ierusalimschy 6063c5c61f bug: cannot invalidate a running coroutine 2003-09-05 11:30:59 -03:00
Roberto Ierusalimschy 2a70107581 detail 2003-09-05 11:00:27 -03:00
Roberto Ierusalimschy 7dae7899b1 main thread and global state are allocated in a single block 2003-09-04 17:19:07 -03:00
Roberto Ierusalimschy 30e51f09b9 some changes in error reporting 2003-09-04 17:00:28 -03:00
Roberto Ierusalimschy 994a37c8e8 IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate
up to 60 characters in a `printf'. That causes a buffer overflow in
`tostring'..
2003-08-29 13:50:02 -03:00
Roberto Ierusalimschy 0ff1596476 new form of long strings: `[***[...]***]' 2003-08-29 13:48:14 -03:00
Roberto Ierusalimschy b27664e0db simpler manipulation of buffer count in scanner 2003-08-28 11:38:46 -03:00
Roberto Ierusalimschy beb896b082 new function (generic) `load' 2003-08-27 18:02:08 -03:00
Roberto Ierusalimschy 8332d5c8a5 parser fully reentrant(!) 2003-08-27 18:01:44 -03:00
Roberto Ierusalimschy 885961be1d reader runs outside core Lua 2003-08-27 17:57:52 -03:00
Roberto Ierusalimschy b114142799 new auxiliary function `luaH_setstr' 2003-08-26 09:04:13 -03:00
Roberto Ierusalimschy 4b2e71ddb6 ZIO passes Lua state to chunk reader 2003-08-25 17:00:50 -03:00
Roberto Ierusalimschy 9fcc485176 zio does not keep "source" name (nobody uses it) 2003-08-25 16:51:54 -03:00
Roberto Ierusalimschy 64066359dd bug: IBM AS400 (OS400) has sizeof(void *)==16, and a `%p' may generate
up to 60 characters in a `printf'. That causes a buffer overflow in
`tostring'..
2003-08-25 16:49:47 -03:00
Roberto Ierusalimschy 97af24ea32 newlines can be \n', \r', \r\n', or \n\r' 2003-08-21 11:16:43 -03:00
Roberto Ierusalimschy 433cb1d13a no more checks for non-default compilation options + luaU_dump has
new option to strip debug info
2003-08-15 10:48:53 -03:00
Roberto Ierusalimschy d66198719d several bugs for Lua 5.0 + new format for bug entries 2003-07-29 16:27:46 -03:00
Roberto Ierusalimschy 91bf77534c no need for a maximum number of parameters (maximum number of locals
take care of that).
2003-07-29 16:26:34 -03:00
Roberto Ierusalimschy a0a384a6b1 bug: userdata to be collected still counts into new GC threshold,
increasing memory consumption
2003-07-29 16:25:37 -03:00
Roberto Ierusalimschy e89945aaa1 syntax ...=var' changed to var=...' 2003-07-29 15:51:00 -03:00
Roberto Ierusalimschy d407d3fe0e details 2003-07-28 15:31:20 -03:00
Roberto Ierusalimschy 522407e23a we do not need a default panic (that does nothing anyway...) 2003-07-16 17:51:47 -03:00
Roberto Ierusalimschy fa26d294ae new way to control `pc' of running functions 2003-07-16 17:49:02 -03:00
Roberto Ierusalimschy 5a761e3a15 opcode number may be invalid 2003-07-10 08:59:06 -03:00
Roberto Ierusalimschy 265530478b more changes to reduce stack usage by the parser 2003-07-09 17:11:30 -03:00
Roberto Ierusalimschy 00180bb133 small changes to reduce stack usage by the parser 2003-07-09 12:36:38 -03:00
Roberto Ierusalimschy 66ed154c89 details 2003-07-09 09:08:43 -03:00
Roberto Ierusalimschy f52f357a55 correct handling when a thread turns on line hooks in another thread 2003-07-07 10:37:56 -03:00
Roberto Ierusalimschy 79fee99024 `debug' library can operate over other threads 2003-07-07 10:37:08 -03:00
Roberto Ierusalimschy a73ded2153 Move nothing when there is nothing to move 2003-07-07 10:34:25 -03:00
Roberto Ierusalimschy 0ec4c473df bug: file:close cannot be called without a file. 2003-07-07 10:32:52 -03:00
Roberto Ierusalimschy 9e05503ffa bug: C functions also may have stacks larger than current top 2003-07-07 10:32:19 -03:00
Roberto Ierusalimschy 17f695157c define a `lua_isthread' for completeness 2003-07-07 10:30:57 -03:00
Roberto Ierusalimschy b93f67f2ce detail 2003-06-10 09:36:26 -03:00
Roberto Ierusalimschy 60aa01d8f7 fully-weak tables are more efficient 2003-05-16 15:59:08 -03:00
Roberto Ierusalimschy ecf5730c0c (much) smarter way to clear weak tables 2003-05-16 15:58:39 -03:00
Roberto Ierusalimschy b10bfd4934 comments 2003-05-15 16:46:03 -03:00
Roberto Ierusalimschy 176cd7d1a3 `#!' is detected by loadfile, not by the lexer 2003-05-15 09:20:24 -03:00
Roberto Ierusalimschy 859c7f7ce0 LUA_SIGNATURE is public 2003-05-15 09:20:04 -03:00
Roberto Ierusalimschy 56c5e749cc no more compatibility code (`lua_pushupvalues') 2003-05-14 18:10:07 -03:00
Roberto Ierusalimschy 9ec9a012e7 details 2003-05-14 18:09:53 -03:00
Roberto Ierusalimschy dae99205cf no more compatibility code 2003-05-14 18:06:56 -03:00
Roberto Ierusalimschy 9eb0f25a29 no more compatibility code for 4.0 2003-05-14 18:02:39 -03:00
Roberto Ierusalimschy f93051155c ok to use #elif' and #if defined()' 2003-05-14 18:01:53 -03:00
Roberto Ierusalimschy 524ae9fc3d new function `setvbuf' 2003-05-14 16:03:43 -03:00
Roberto Ierusalimschy 0ddedaee92 new function `string.reverse' 2003-05-14 11:35:54 -03:00
Roberto Ierusalimschy 5cc448386a new syntax: `... [= name]' 2003-05-14 09:32:46 -03:00
Roberto Ierusalimschy c116dcb92b better information about instruction behavior (use of arguments) 2003-05-14 09:09:12 -03:00
Roberto Ierusalimschy 6d268b0b00 new semantics for "for" local variables 2003-05-13 17:15:59 -03:00
Roberto Ierusalimschy c767747191 new (internal) macros for error handling 2003-05-13 16:22:19 -03:00
Roberto Ierusalimschy f966404ed6 simpler implementation for valid/acceptable indices 2003-05-09 17:16:54 -03:00
Roberto Ierusalimschy ee07ad346d `getn' doesn't need this field (values cannot be nil) 2003-05-07 13:02:16 -03:00
Roberto Ierusalimschy fee9e473f2 inlining of `luaV_gettable' were too complex (dirty) 2003-05-05 15:39:57 -03:00
Roberto Ierusalimschy 82dfacbcf7 detail 2003-04-30 17:24:38 -03:00
Roberto Ierusalimschy 26097b6c4b uses integers as keys to standard i/o files 2003-04-30 17:15:55 -03:00
Roberto Ierusalimschy f1f8f0ca22 simpler way to check maximum gc threshold 2003-04-28 16:58:06 -03:00
Roberto Ierusalimschy bcc5f1406b test function for lua_setgcthreshold 2003-04-28 16:58:06 -03:00
Roberto Ierusalimschy b1b752fb2b comments 2003-04-28 16:57:50 -03:00
Roberto Ierusalimschy 572a69df78 Lua does not need all those different types... 2003-04-28 16:26:16 -03:00
Roberto Ierusalimschy 943c82b376 avoid unnecessary call to log2 on too large indices 2003-04-28 10:31:46 -03:00
Roberto Ierusalimschy 17149b7d43 avoid warnings (Instruction' may not fit into an int') 2003-04-28 10:31:06 -03:00
Roberto Ierusalimschy 01b303c87e simpler log2 implementation 2003-04-28 10:30:14 -03:00
Roberto Ierusalimschy 762c737037 last changes by lhf 2003-04-10 14:39:41 -03:00
Roberto Ierusalimschy de57dc2653 new scheme to control `loadlib' configuration (default for dlopen
implementation is not to include it)
2003-04-07 17:11:53 -03:00
Roberto Ierusalimschy d1df829f8d lua_getmetatable must accept any acceptable index 2003-04-07 11:36:08 -03:00
Roberto Ierusalimschy 2ad947fe03 new test options for luaL_getn/setn 2003-04-07 11:35:00 -03:00
Roberto Ierusalimschy f0cc013afa luaL_getn/setn must operate correctly over negative indices 2003-04-07 11:35:00 -03:00
Roberto Ierusalimschy 0d88545b82 warnings from several compilers (mainly typecasts when lua_Number is float) 2003-04-03 10:35:34 -03:00
Roberto Ierusalimschy f84c5a5fc6 avoid conflicts in (re)definition of `isatty' 2003-04-03 10:34:42 -03:00
Roberto Ierusalimschy 05d35d8f3c comments 2003-04-02 10:09:14 -03:00
Roberto Ierusalimschy 3a6230ef7c error-message format 2003-04-01 14:52:31 -03:00
Roberto Ierusalimschy a424a112b5 clearance of debuging code (left by mistake) 2003-03-31 10:00:25 -03:00
Roberto Ierusalimschy b858161fbc new hash method for lua_Number (double) (due to a performance problem) 2003-03-24 11:18:42 -03:00
Roberto Ierusalimschy 80bac182db do not mix --help' with --' 2003-03-24 09:40:01 -03:00
Roberto Ierusalimschy 30a411ab3c chars from zio are always unsigned 2003-03-24 09:39:34 -03:00
Roberto Ierusalimschy 5bb5a1831d details 2003-03-20 17:26:33 -03:00
Roberto Ierusalimschy b518d14071 bug: zio mixes a 255 as first char in a buffer with EOZ 2003-03-20 13:00:56 -03:00
Roberto Ierusalimschy 15dbb53461 towards 5.0 final 2003-03-19 18:27:30 -03:00
Roberto Ierusalimschy abc304f9da avoid name colision (for alllua.c) 2003-03-19 18:24:04 -03:00
Roberto Ierusalimschy 1a553f9199 better error messages 2003-03-19 18:16:12 -03:00
Roberto Ierusalimschy 0ca225d33a better error message 2003-03-19 18:15:18 -03:00
Roberto Ierusalimschy 70e2b7ab86 name changes to avoid name collision between macros and variables 2003-03-19 18:14:53 -03:00
Roberto Ierusalimschy 5a144e891a __globals' -> __fenv' 2003-03-19 18:14:34 -03:00
Roberto Ierusalimschy b12776f29c `luaL_getmetafield' was leaving extra value on the stack 2003-03-18 15:48:31 -03:00
Roberto Ierusalimschy ab9e062928 name changes to avoid name collision between macros and variables 2003-03-18 09:50:04 -03:00
Roberto Ierusalimschy 81cdbabf09 detail (change place of a prototype) 2003-03-18 09:31:39 -03:00
Roberto Ierusalimschy 40cfb0691e new auxiliary functions for `type' manipulation 2003-03-18 09:25:32 -03:00
Roberto Ierusalimschy 9b7af7e45b tests for Windows version 2003-03-18 09:25:01 -03:00
Roberto Ierusalimschy 2e66248f8a unused argument 2003-03-18 09:24:38 -03:00
Roberto Ierusalimschy 79db75101e detail 2003-03-18 09:24:26 -03:00
Roberto Ierusalimschy b0c40e2405 first version of `loadlib' 2003-03-17 10:04:58 -03:00
Roberto Ierusalimschy 4734e2de05 `loadlib' now an official library 2003-03-17 10:01:48 -03:00
Roberto Ierusalimschy 7ea180af6e detail 2003-03-14 16:08:11 -03:00
Roberto Ierusalimschy 05d567d52e io.input'/io.output' always return current file 2003-03-14 16:00:16 -03:00
Roberto Ierusalimschy d8a3a00d84 `string.find' also accepts out-of-range indices 2003-03-14 15:59:53 -03:00
Roberto Ierusalimschy c9ea94ec92 out-of-bound upvalues (in C) are acceptable indices 2003-03-14 15:59:21 -03:00
Roberto Ierusalimschy fa4b4c1100 loadstring/loadfile use global environment + setfenv(0) changes
global environment
2003-03-11 15:17:43 -03:00
Roberto Ierusalimschy 4039bf457d ^ operator is defined by global `__pow' 2003-03-11 09:30:37 -03:00
Roberto Ierusalimschy 034de1fe73 new names for functions that open C libraries 2003-03-11 09:24:34 -03:00
Roberto Ierusalimschy 430d6db928 LUA_PATH components may have multiple interrogation marks 2003-03-11 09:08:13 -03:00
Roberto Ierusalimschy 7c3857cded comments 2003-03-07 10:21:31 -03:00
Roberto Ierusalimschy 8ce6f0b418 avoid including system headers after program headers 2003-03-06 16:37:42 -03:00
Roberto Ierusalimschy 572bddc0b0 LUA_USETMPNAME -> USE_TMPNAME 2003-03-06 16:36:44 -03:00
Roberto Ierusalimschy 3684f67771 details (text of an error message) 2003-03-06 16:36:16 -03:00
Roberto Ierusalimschy 69dd9461e5 bug: GC metamethod calls could mess C/Lua stack syncronization 2003-02-28 16:45:15 -03:00
Roberto Ierusalimschy 6b6bc532a4 better error message for (deprecated) "%global" 2003-02-28 14:19:47 -03:00
Roberto Ierusalimschy ea16ee41a8 no more attempt to optimize GC when parsing new modules (too complex) 2003-02-28 12:42:08 -03:00
Roberto Ierusalimschy 60d11ec316 by default, gcc does not get tmpname 2003-02-27 09:39:05 -03:00
Roberto Ierusalimschy e1a424e8a3 avoid the identifier index' (clashes with BSD index' function) 2003-02-27 09:33:07 -03:00
Roberto Ierusalimschy 59ce42dbd5 detail 2003-02-27 09:32:30 -03:00
Roberto Ierusalimschy 92f6e0c1bf no-nonsense debug information about tail calls 2003-02-27 08:52:30 -03:00
Roberto Ierusalimschy 5cd99b82b7 set/getenvtable' -> set/getfenv' 2003-02-24 13:54:20 -03:00
Roberto Ierusalimschy 07e210e655 `require' returns value returned by package 2003-02-24 13:50:41 -03:00
Roberto Ierusalimschy feb724c122 ULONG_MAX>>10 may not fit into an int (old bug) 2003-02-21 16:00:14 -03:00
Roberto Ierusalimschy 67f9a2a98f details 2003-02-20 17:12:39 -03:00
Roberto Ierusalimschy c4f9c887fc expressions too complex for an ARM compiler... 2003-02-19 07:28:58 -03:00
Roberto Ierusalimschy 9866fb0ef1 set/getglobals' -> set/getenvtable' 2003-02-18 13:13:15 -03:00
Roberto Ierusalimschy 60c83ded30 small optimization for sizes of array constructors 2003-02-18 13:02:56 -03:00
Roberto Ierusalimschy 07948c3181 restore _REQUIREDNAME after requiring a file 2003-02-18 13:02:13 -03:00
Roberto Ierusalimschy dce9a49a08 final version 2003-02-18 13:01:57 -03:00
Roberto Ierusalimschy 15db58a2f5 create arg table with correct size 2003-02-13 14:08:47 -02:00
Roberto Ierusalimschy d6826dbc80 simpler way to count uses 2003-02-13 14:08:32 -02:00
Roberto Ierusalimschy e75a6ae9ee `defaultmeta' is always empty, but registry needs some space for
names and numbers (references)
2003-02-13 14:07:57 -02:00
Roberto Ierusalimschy 2866fb2dd0 reset _REQUIREDNAME after loading module 2003-02-13 14:07:37 -02:00
Roberto Ierusalimschy 4b6f436d67 unpack' uses getn' to get table size 2003-02-12 07:11:01 -02:00
Roberto Ierusalimschy 8f105d6b59 string.byte returns nil if index is out-of-range 2003-02-12 07:10:41 -02:00
Roberto Ierusalimschy 2fef8c772b auxiliary function to check userdata with types 2003-02-11 13:32:31 -02:00
Roberto Ierusalimschy 7285fa393b use C names for C types 2003-02-11 13:31:50 -02:00
Roberto Ierusalimschy 5085f09ce5 small optimizations 2003-02-11 13:24:52 -02:00
Roberto Ierusalimschy d674626392 compatibility with '%' syntax is optional 2003-02-11 08:49:53 -02:00
Roberto Ierusalimschy 7a40cdbda0 different variables for number of upvalues and size of upvalue array
(makes code clearer)
2003-02-11 08:46:24 -02:00
Roberto Ierusalimschy 3cdeacbbfb reference system also uses getn/setn (plus small corrections) 2003-02-11 07:44:38 -02:00
Roberto Ierusalimschy 6f207b15fb resist errors in finalizers during lua_close 2003-02-10 15:32:50 -02:00
Roberto Ierusalimschy 3184314bf3 warning 2003-02-10 15:31:13 -02:00
Roberto Ierusalimschy 7964f7cbbd more complete information for coroutine errors 2003-02-10 08:21:31 -02:00
Roberto Ierusalimschy 383a6e88f9 argv[0] may be NULL 2003-01-29 11:23:45 -02:00
Roberto Ierusalimschy 871166d7db test for panic function 2003-01-29 08:27:53 -02:00
Roberto Ierusalimschy 592cf2334e "panic" cannot happen in lua.c, with lua_cpcall +
argv[0] may be empty
2003-01-29 08:27:07 -02:00
Roberto Ierusalimschy 0175f8d5d1 dump/undump of upvalue names 2003-01-27 13:52:57 -02:00
Roberto Ierusalimschy e79bf02f33 correct semantics for comparison metamethods (they are only valid
when both operands have the same metamethod).
2003-01-27 13:12:52 -02:00
Roberto Ierusalimschy 41ed3c4771 getn/setn in C moved to lauxlib 2003-01-27 11:46:16 -02:00
Roberto Ierusalimschy 635b7c707d details 2003-01-27 11:00:43 -02:00
Roberto Ierusalimschy 83f0d6ef1a DEPRECATED (new manual uses an independent format instead of LaTeX) 2003-01-24 14:38:18 -02:00
Roberto Ierusalimschy 3088ebd95b last changes before leaving Latex 2003-01-24 07:14:54 -02:00
Roberto Ierusalimschy 797d964df9 detail 2003-01-23 09:34:18 -02:00
Roberto Ierusalimschy e44e579dc1 bug: luaD_protectedparser must protect its garbage collection too 2003-01-23 09:31:38 -02:00
Roberto Ierusalimschy a153cafd8d starting translation to new format (@comand{...}). 2003-01-22 14:29:38 -02:00
Roberto Ierusalimschy 3b5158f2a1 corrections from Asko Kauppi 2003-01-21 15:45:11 -02:00
Roberto Ierusalimschy 60a8b94fd0 corrections/suggestions by Ed Ferguson 2003-01-20 09:03:05 -02:00
Roberto Ierusalimschy c499442e5f compatibility macros must be available by default 2003-01-17 13:28:09 -02:00
Roberto Ierusalimschy 9a5bab82ff use the more modern _POSIX_C_SOURCE instead of older _POSIX_SOURCE 2003-01-17 13:27:28 -02:00
Roberto Ierusalimschy 32fd039bb5 `openlib' functions return new module 2002-12-20 08:26:33 -02:00
Roberto Ierusalimschy 75f73172c4 bug: `resume' was checking the wrong value for stack overflow 2002-12-20 07:55:56 -02:00
Roberto Ierusalimschy 754c630754 details 2002-12-19 11:21:08 -02:00
Roberto Ierusalimschy dd8edecae1 new functions to manipulate upvales (get/setupvalue) 2002-12-19 09:11:55 -02:00
Roberto Ierusalimschy 28021c5c66 better explanation (+ example) for coroutines 2002-12-11 11:43:15 -02:00
Roberto Ierusalimschy 73517e86b0 OP_TFORLOOP uses extra stack space 2002-12-11 10:34:22 -02:00
Roberto Ierusalimschy 9e8face8d8 must move call results in the last iteration, too 2002-12-11 10:34:22 -02:00
Roberto Ierusalimschy 64864f094b new options for debugging Lua (HARDSTACKTESTS & EXTERNMEMCHECK) 2002-12-06 15:20:45 -02:00
Roberto Ierusalimschy 9bd3fc1039 TFORLOOP makes a call that affects all values above it on the stack 2002-12-06 15:15:35 -02:00
Roberto Ierusalimschy cc4a22ebe2 bug: scope of generic for variables is not sound 2002-12-06 15:09:00 -02:00
Roberto Ierusalimschy acf62ddfbe "load*" creates chunk with same global table than caller 2002-12-06 15:05:15 -02:00
Roberto Ierusalimschy 04f95ce879 hook counts are integers now 2002-12-05 15:50:10 -02:00
Roberto Ierusalimschy 27c6b4d422 each .c file defines its own name 2002-12-04 15:38:31 -02:00
Roberto Ierusalimschy 0bb8eb5151 new function `lua_cpcall' 2002-12-04 15:29:32 -02:00
Roberto Ierusalimschy 38da8c0d7d new facilities to test memory overflow in main.c 2002-12-04 15:29:05 -02:00
Roberto Ierusalimschy 76de732745 avoid non-raw accesses to globals when variable may not exist 2002-12-04 13:38:25 -02:00
Roberto Ierusalimschy 90d7892007 new function `io.type' 2002-12-04 13:27:17 -02:00
Roberto Ierusalimschy 041cb96992 small bug: `write' must return three values in case of errors 2002-12-04 13:17:36 -02:00
Roberto Ierusalimschy c75c3cfd19 avoid names `str...' (may conflict with string.h) 2002-12-02 10:06:10 -02:00
Roberto Ierusalimschy 24471525d7 details 2002-12-02 10:06:10 -02:00
Roberto Ierusalimschy 1f55dbc699 details 2002-11-26 10:53:29 -02:00
Roberto Ierusalimschy c194a46bc5 detail 2002-11-26 06:59:48 -02:00
Roberto Ierusalimschy 8954bdc706 new `coroutine.status' function 2002-11-26 06:45:36 -02:00
Roberto Ierusalimschy 5a228bb1d8 new function `lua_version' 2002-11-25 15:50:14 -02:00
Roberto Ierusalimschy 5f698f8b6f simpler interface to hooks + use of `int' to count hooks 2002-11-25 15:47:13 -02:00
Roberto Ierusalimschy 9b1c586b2f renaming stringdump' -> string.dump' 2002-11-25 15:33:33 -02:00
Roberto Ierusalimschy d9340154ac `__tostring' for files + small bug (could do invalid read inside
a userdata when it was not a file)
2002-11-25 13:05:39 -02:00
Roberto Ierusalimschy e47baca75a warnings from Visual C++ 2002-11-25 10:38:47 -02:00
Roberto Ierusalimschy b8a680c114 resets hook count even in case of errors 2002-11-25 09:20:29 -02:00
Roberto Ierusalimschy 709b27b456 ULONG_MAX>>10 may not fit into an int 2002-11-25 09:16:48 -02:00
Roberto Ierusalimschy dbc5451bea comments 2002-11-22 16:01:46 -02:00
Roberto Ierusalimschy 2d2d45976c separated control over C recursion level 2002-11-22 15:16:52 -02:00
Roberto Ierusalimschy 0050d983fc make more clear "primitive" recursive definitions 2002-11-22 14:42:53 -02:00
Roberto Ierusalimschy 04b143ddf9 avoid C stack overflow during parsing 2002-11-22 14:35:20 -02:00
Roberto Ierusalimschy 007f229568 detail 2002-11-22 11:59:04 -02:00
Roberto Ierusalimschy 84488c5670 small bug: previous call may change `base' 2002-11-21 15:19:42 -02:00
Roberto Ierusalimschy 5142e630bf new macro `condhardstacktests' to control hard stack tests 2002-11-21 15:19:11 -02:00
Roberto Ierusalimschy 010bbd9d9c simpler definition for incr_top 2002-11-21 14:46:16 -02:00
Roberto Ierusalimschy be00cd2a6b easier way to keep `base' correct 2002-11-21 13:46:44 -02:00
Roberto Ierusalimschy 2e4e888de0 Lua functions must have a frame or a saved pc. 2002-11-21 13:46:20 -02:00
Roberto Ierusalimschy ddc144e4d2 keep L->ci->base in L->base for faster access 2002-11-21 13:16:04 -02:00
Roberto Ierusalimschy b48c6e7680 no problem keeping some dead meat while doing collection 2002-11-21 12:18:01 -02:00
Roberto Ierusalimschy aff97fffc4 C functions cannot increase its top without filling the stack 2002-11-21 12:17:15 -02:00
Roberto Ierusalimschy 1648674653 must check GC every time it can create new objects 2002-11-21 12:16:52 -02:00
Roberto Ierusalimschy d404f0c276 global_State must be deallocated (and so allocated) with NULL also
(otherwise it trys to decrement inside itself after its own free)
2002-11-21 12:14:42 -02:00
Roberto Ierusalimschy 48e42261ac details 2002-11-19 15:42:32 -02:00
Roberto Ierusalimschy be762f38bd better organization of "malloc responsabilities" 2002-11-19 12:12:13 -02:00
Roberto Ierusalimschy c8a79057f7 option -l does a require', instead of dofile' 2002-11-19 11:49:43 -02:00
Roberto Ierusalimschy 642af82e81 small bugs (state could keep its CI_HASFRAME attribute after returning) 2002-11-19 06:50:56 -02:00
Roberto Ierusalimschy 636c629e56 new assertions 2002-11-18 16:45:38 -02:00
Roberto Ierusalimschy 96ba5d0bc2 include file name in error messages 2002-11-18 14:53:19 -02:00
Roberto Ierusalimschy f0185f7628 support for tests of yield inside hooks + better support for tests
with valgrind and other memory checkers
2002-11-18 13:24:27 -02:00
Roberto Ierusalimschy 9bab2cf55d support for yield inside hooks 2002-11-18 13:24:11 -02:00
Roberto Ierusalimschy c4ae00a3d1 details 2002-11-18 13:23:43 -02:00
Roberto Ierusalimschy f4d3bc52f4 towards 5.0 beta 2002-11-18 12:39:34 -02:00
Roberto Ierusalimschy 18765d900e messages 2002-11-18 09:20:01 -02:00
Roberto Ierusalimschy 43013b39cc new representation for hooks (to allow asynchronous calls to sethook) 2002-11-18 09:01:55 -02:00
Roberto Ierusalimschy 94912d99fc details 2002-11-14 14:59:16 -02:00
Roberto Ierusalimschy b40c9f7a3c better code to signal write barriers 2002-11-14 14:16:21 -02:00
Roberto Ierusalimschy 41fd639cab documentation for write barriers 2002-11-14 14:15:53 -02:00
Roberto Ierusalimschy a845a46cc8 C function may leave garbage on the stack (besides return values) 2002-11-14 13:42:05 -02:00
Roberto Ierusalimschy 097edd3884 better names for auxiliar functions 2002-11-14 13:41:38 -02:00
Roberto Ierusalimschy 5c5d9b2703 back to `__mode' metafield to specify weakness 2002-11-14 10:01:35 -02:00
Roberto Ierusalimschy 43d1a6af12 detail 2002-11-14 09:51:23 -02:00
Roberto Ierusalimschy 3010eb0536 all objects with several children (tables, closures, stacks, prototypes)
go to `gray' queue
2002-11-13 09:49:19 -02:00
Roberto Ierusalimschy 2f91f95d94 better control over GCObjects 2002-11-13 09:32:26 -02:00
Roberto Ierusalimschy 42dd080a2e details 2002-11-12 12:34:18 -02:00
Roberto Ierusalimschy 9957f7d598 better way to open libraries 2002-11-11 11:28:06 -02:00
Roberto Ierusalimschy ac27b7a842 avoid traversing extra elements when cleaning weak tables 2002-11-11 09:52:43 -02:00
Roberto Ierusalimschy 81e142fc14 detail (`key' is always on stack) 2002-11-07 14:03:33 -02:00
Roberto Ierusalimschy 63633c5b5f better name for `lua_movethread' 2002-11-07 13:39:23 -02:00
Roberto Ierusalimschy dff9be4224 new macros to distinguish different types of object moves (for future GC
evolution).
2002-11-07 13:37:10 -02:00
Roberto Ierusalimschy 118347d8c3 new API for coroutines 2002-11-06 17:08:00 -02:00
Roberto Ierusalimschy 6820da5096 detail 2002-11-04 10:31:44 -02:00
Roberto Ierusalimschy c3eb4675b9 new module, ldump.c 2002-10-25 18:38:17 -03:00
Roberto Ierusalimschy 7e0f880bc5 C++ demands cast from void to specific types 2002-10-25 18:36:54 -03:00
Roberto Ierusalimschy 118e9cd843 new facility for dumping chunks 2002-10-25 18:31:28 -03:00
Roberto Ierusalimschy de00d0d0ad module for dumping chunks 2002-10-25 18:31:28 -03:00
Roberto Ierusalimschy 1713b64065 Writer type must be public (so, in lua.h) 2002-10-25 18:30:49 -03:00
Roberto Ierusalimschy 671dc6eec2 new version (from lhf) 2002-10-25 18:30:41 -03:00
Roberto Ierusalimschy e356a43dc0 C needs "union" (unlike C++) 2002-10-25 18:30:00 -03:00
Roberto Ierusalimschy f36038e42a assertion must be always valid (not only in debug mode) 2002-10-25 18:29:20 -03:00
Roberto Ierusalimschy 96e15b8501 threads now are real Lua objects, subject to garbage collection 2002-10-25 17:05:28 -03:00
Roberto Ierusalimschy 0fd91b1b08 optional limits for table.concat 2002-10-23 16:08:23 -03:00
Roberto Ierusalimschy a2b353e044 details 2002-10-23 16:08:13 -03:00
Roberto Ierusalimschy 92a2ef9dca field `__globals' protect global tables 2002-10-22 16:41:08 -03:00
Roberto Ierusalimschy 4fb9110a6e tests for compatibility functions lua_dostring/lua_dofile 2002-10-22 15:07:55 -03:00
Roberto Ierusalimschy 11886dc7b0 print error on stderr when _ALERT is not defined 2002-10-22 15:07:55 -03:00
Roberto Ierusalimschy 81bc5711a8 only one instance of registry and default metatable per global state 2002-10-22 14:58:14 -03:00
Roberto Ierusalimschy 6a77a6b73f avoid too much precision when printing numbers 2002-10-22 14:21:25 -03:00
Roberto Ierusalimschy 84e0b1bc97 small changes in type configuration facilities 2002-10-22 14:18:28 -03:00
Roberto Ierusalimschy 6823a2f57f better tokens for error messages 2002-10-22 13:45:52 -03:00
Roberto Ierusalimschy 313b2fe902 detail 2002-10-21 17:43:38 -03:00
Roberto Ierusalimschy 425e5813b0 free prototype in (more or less) the same order it is created by
`undump'
2002-10-21 17:41:46 -03:00
Roberto Ierusalimschy 6505503b49 do not pretend that file is closed when close fails 2002-10-21 17:41:24 -03:00
Roberto Ierusalimschy ec748fcb0a correct handling of opened files in presence of memory allocation
errors
2002-10-16 17:41:35 -03:00
Roberto Ierusalimschy c196348717 in case of memory allocation errors, sizecode and sizelineinfo can
be different
2002-10-16 17:40:58 -03:00
Roberto Ierusalimschy 669129a6d8 io.lines() iterate over the standard input file 2002-10-11 17:40:32 -03:00
Roberto Ierusalimschy 46b063ef59 `undump' also uses private buffer 2002-10-09 10:42:01 -03:00
Roberto Ierusalimschy e1d5153a33 details 2002-10-09 10:00:08 -03:00
Roberto Ierusalimschy b3d0682fb9 use of different buffers for scanner and concatenation 2002-10-08 15:46:08 -03:00
Roberto Ierusalimschy 02afc892d5 new ANSI C does not assure that realloc(p,0) == free(p) 2002-10-08 15:45:07 -03:00
Roberto Ierusalimschy fa2f1ec7ba to avoid `strerror', define itself to something else;
nil has a special, fixed reference
2002-10-04 11:31:40 -03:00
Roberto Ierusalimschy 829befcc41 small optimization for object comparison 2002-10-04 11:31:03 -03:00
Roberto Ierusalimschy d477e4ffd6 detail 2002-10-04 11:30:31 -03:00
Roberto Ierusalimschy ce09af1e25 easier to define api_check' using assert' 2002-09-20 14:01:24 -03:00
Roberto Ierusalimschy 98d0b79613 EXIT_SUCCESS may be different from 0 2002-09-20 10:32:56 -03:00
Roberto Ierusalimschy e8f35fc4ff unification of __index & __gettable (and __newindex & __settable) 2002-09-19 17:12:47 -03:00
Roberto Ierusalimschy 6fb0fd5063 avoid `reclearing' weak tables 2002-09-19 16:54:22 -03:00
Roberto Ierusalimschy 565e6d74e1 state's buffer is used only for chars 2002-09-19 10:03:53 -03:00
Roberto Ierusalimschy f6bc7884be new generators for reading a file line by line 2002-09-17 17:35:54 -03:00
Roberto Ierusalimschy 32a5d96dfc `setmetatable' cannot change protected objects 2002-09-16 16:49:45 -03:00
Roberto Ierusalimschy 8dae071f42 details 2002-09-16 16:18:01 -03:00
Roberto Ierusalimschy afe1305b1a avoid luaS_resize (which may need extra memory) during `main' activities 2002-09-05 16:57:40 -03:00
Roberto Ierusalimschy 728fa167d2 cannot raise memory error when realloc to smaller block 2002-09-05 16:57:08 -03:00
Roberto Ierusalimschy 1bdde38bd2 no more newlines at the end of error messages 2002-09-05 16:45:42 -03:00
Roberto Ierusalimschy b2bc3b44b6 no more reserved word "global" 2002-09-03 08:57:38 -03:00
Roberto Ierusalimschy 7c0ccdfd61 avoid the use of "enum" in the API, as they do not have a fixed representation 2002-09-02 17:00:41 -03:00
Roberto Ierusalimschy 4964e7c8a0 details 2002-09-02 16:54:49 -03:00
Roberto Ierusalimschy 2c670baf24 avoid the use of "obvious" names in header files to avoid conflicts 2002-08-30 17:00:59 -03:00
Roberto Ierusalimschy fdafd4f4a8 new structure for collectable objects, sharing a common header 2002-08-30 16:09:21 -03:00
Roberto Ierusalimschy beeff4ccaf GC metamethod stored in a weak metatable being collected together with
userdata may not be cleared properly
2002-08-30 16:08:30 -03:00
Roberto Ierusalimschy 12c4e48506 `frontier' patterns 2002-08-23 16:45:24 -03:00
Roberto Ierusalimschy c78aaa9a70 better line number for function definitions 2002-08-22 16:51:08 -03:00
Roberto Ierusalimschy 4d7a554921 style for switch statements 2002-08-21 16:39:31 -03:00
Roberto Ierusalimschy fbc23d0245 details 2002-08-21 15:56:33 -03:00
Roberto Ierusalimschy 81a8845e4f detail 2002-08-21 11:57:48 -03:00
Roberto Ierusalimschy 6c283b2f4f new simetric format for ABC instructions, to avoid exchanging operands
for `commutative' operators
2002-08-20 17:03:05 -03:00
Roberto Ierusalimschy 576bded513 details 2002-08-16 17:02:13 -03:00
Roberto Ierusalimschy ecc7769de2 names... 2002-08-16 17:00:28 -03:00
Roberto Ierusalimschy da19c436cc cleaning the stage for generational collection 2002-08-16 11:45:55 -03:00
Roberto Ierusalimschy 0039feb9da warning from Visual C 2002-08-16 11:45:18 -03:00
109 changed files with 50129 additions and 12876 deletions
Executable
+9
View File
@@ -0,0 +1,9 @@
make -s -j
cd testes/libs; make -s
cd .. # back to directory 'testes'
ulimit -S -s 2000
if { ../lua -W all.lua; } then
echo -e "\n\n final OK!!!!\n\n"
else
echo -e "\n\n >>>> BUG!!!!\n\n"
fi
-288
View File
@@ -1,288 +0,0 @@
** lua.stx / llex.c
Tue Dec 2 10:45:48 EDT 1997
>> BUG: "lastline" was not reset on function entry, so debug information
>> started only in the 2nd line of a function.
=================================================================
--- Version 3.1 alpha
** lua.c
Thu Jan 15 14:34:58 EDT 1998
>> must include "stdlib.h" (for "exit()").
** lbuiltin.c / lobject.h
Thu Jan 15 14:34:58 EDT 1998
>> MAX_WORD may be bigger than MAX_INT
(by lhf)
** llex.c
Mon Jan 19 18:17:18 EDT 1998
>> wrong line number (+1) in error report when file starts with "#..."
** lstrlib.c
Tue Jan 27 15:27:49 EDT 1998
>> formats like "%020d" were considered too big (3 digits); moreover,
>> some sistems limit printf to at most 500 chars, so we can limit sizes
>> to 2 digits (99).
** lapi.c
Tue Jan 27 17:12:36 EDT 1998
>> "lua_getstring" may create a new string, so should check GC
** lstring.c / ltable.c
Wed Jan 28 14:48:12 EDT 1998
>> tables can become full of "empty" slots, and keep growing without limits.
** lstrlib.c
Mon Mar 9 15:26:09 EST 1998
>> gsub('a', '(b?)%1*' ...) loops (because the capture is empty).
** lstrlib.c
Mon May 18 19:20:00 EST 1998
>> arguments for "format" 'x', 'X', 'o' and 'u' must be unsigned int.
=================================================================
--- Version 3.1
** liolib.c / lauxlib.c
Mon Sep 7 15:57:02 EST 1998
>> function "luaL_argerror" prints wrong argument number (from a user's point
of view) when functions have upvalues.
** lstrlib.c
Tue Nov 10 17:29:36 EDT 1998
>> gsub/strfind do not check whether captures are properly finished.
(by roberto/tomas)
** lbuiltin.c
Fri Dec 18 11:22:55 EDT 1998
>> "tonumber" goes crazy with negative numbers in other bases (not 10),
because "strtol" returns long, not unsigned long.
(by Visual C++)
** lstrlib.c
Mon Jan 4 10:41:40 EDT 1999
>> "format" does not check size of format item (such as "%00000...00000d").
** lapi.c
Wed Feb 3 14:40:21 EDT 1999
>> getlocal cannot return the local itself, since lua_isstring and
lua_isnumber can modify it.
** lstrlib.c
Thu Feb 4 17:08:50 EDT 1999
>> format "%s" may break limit of "sprintf" on some machines.
(by Marcelo Sales)
** lzio.c
Thu Mar 4 11:49:37 EST 1999
>> file stream cannot call fread after EOF.
(by lhf)
=================================================================
--- Version 3.2 (beta)
** lstrlib.c
Fri Apr 30 11:10:20 EST 1999
>> '$' at end of pattern was matching regular '$', too.
(by anna; since 2.5)
** lbuiltin.c
Fri May 21 17:15:11 EST 1999
>> foreach, foreachi, foreachvar points to function in stack when stack
can be reallocated.
(by tomas; since 3.2 beta)
** lparser.c
Wed Jun 16 10:32:46 EST 1999
>> cannot assign to unlimited variables, because it causes overflow in
the number of returns of a function.
(since 3.1)
=================================================================
--- Version 3.2
** lmathlib.c
Wed Aug 18 11:28:38 EST 1999
>> random(0) and random(x,0) are wrong (0 is read as no argument!).
(by Dave Bollinger; since 3.1)
** lparser.c
Thu Sep 2 10:07:20 EST 1999
>> in the (old) expression << ls->fs->f->consts[checkname(ls)] >>, checkname
could realloc f->consts.
(by Supratik Champati; since 3.2 beta)
** lobject.c / lbuiltin.c
Wed Sep 8 17:41:54 EST 1999
>> tonumber'e1' and tonumber(' ', x), for x!=10, gave 0 instead of nil.
(since 3.1)
** lstrlib.c
Thu Nov 11 14:36:30 EDT 1999
>> `strfind' does not handle \0 in plain search.
(by Jon Kleiser; since 3.1)
** lparser.c
Wed Dec 29 16:05:43 EDT 1999
>> return gives wrong line in debug information
(by lhf; since 3.2 [at least])
** ldo.c
Thu Dec 30 16:39:33 EDT 1999
>> cannot reopen stdin (for binary mode)
(by lhf & roberto; since 3.1)
** lapi.c
Thu Mar 2 09:41:53 EST 2000
>> lua_settable should check stack space (it could call a T.M.)
(by lhf & celes; since 3.2; it was already fixed by fixed stack)
** lparser.c
Mon Apr 3 09:59:06 EST 2000
>> '%' should be in expfollow
(by Edgar Toernig; since 3.1; it was already fixed)
** lbuiltin.c
Mon Apr 3 10:05:05 EST 2000
>> tostring() without arguments gives seg. fault.
(by Edgar Toernig; since 3.0)
=================================================================
--- Version 4.0 alpha
Tested with full test suites (as locked in Mon Apr 24 14:23:11 EST 2000)
in the following platforms:
* Linux - gcc, g++
* AIX - gcc
* Solaris - gcc, cc
* IRIX - cc, cc-purify
* Windows - Visual C++ (.c e .cpp, warning level=4)
** lstrlib.c
Tue May 2 15:27:58 EST 2000
>> `strfind' gets wrong subject length when there is an offset
(by Jon Kleiser; since 4.0a)
** lparser.c
Fri May 12 15:11:12 EST 2000
>> first element in a list constructor is not adjusted to one value
>> (e.g. «a = {gsub('a','a','')}»)
(by Tomas; since 4.0a)
** lparser.c
Wed May 24 14:50:16 EST 2000
>> record-constructor starting with an upvalue name gets an error
>> (e.g. «local a; function f() x = {a=1} end»)
(by Edgar Toernig; since 3.1)
** lparser.c
Tue Aug 29 15:56:05 EST 2000
>> error message for `for' uses `while'
(since 4.0a; already corrected)
** lgc.c
Tue Aug 29 15:57:41 EST 2000
>> gc tag method for nil could call line hook
(by ry; since ?)
=================================================================
--- Version 4.0 Beta
** liolib.c
Fri Sep 22 15:12:37 EST 2000
>> `read("*w")' should return nil at EOF
(by roberto; since 4.0b)
** lvm.c
Mon Sep 25 11:47:48 EST 2000
>> lua_gettable does not get key from stack top
(by Philip Yi; since 4.0b)
** lgc.c
Mon Sep 25 11:50:48 EST 2000
>> GC may crash when checking locked C closures
(by Philip Yi; since 4.0b)
** lapi.c
Wed Sep 27 09:50:19 EST 2000
>> lua_tag should return LUA_NOTAG for non-valid indices
(by Paul Hankin; since 4.0b)
** llex.h / llex.c / lparser.c
Wed Sep 27 13:39:45 EST 2000
>> parser overwrites semantic information when looking ahead
>> (e.g. «a = {print'foo'}»)
(by Edgar Toernig; since 4.0b, deriving from previous bug)
** liolib.c
Thu Oct 26 10:50:46 EDT 2000
>> in function `read_file', realloc() doesn't free the buffer if it can't
>> allocate new memory
(by Mauro Vezzosi; since 4.0b)
=================================================================
--- Version 4.0
** lparser.c
Wed Nov 29 09:51:44 EDT 2000
>> parser does not accept a `;' after a `return'
(by lhf; since 4.0b)
** liolib.c
Fri Dec 22 15:30:42 EDT 2000
>> when `read' fails it must return nil (and not no value)
(by cassino; since at least 3.1)
** lstring.c/lapi.c
Thu Feb 1 11:55:45 EDT 2001
>> lua_pushuserdata(L, NULL) is buggy
(by Edgar Toernig; since 4.0)
** ldo.c
Fri Feb 2 14:06:40 EDT 2001
>> «while 1 dostring[[print('hello\n')]] end» never reclaims memory
(by Andrew Paton; since 4.0b)
** lbaselib.c
Tue Feb 6 11:57:13 EDT 2001
>> ESC (which starts precompiled code) in C is \33, not \27
(by Edgar Toernig and lhf; since 4.0b)
** lparser.c
Tue Jul 10 16:59:18 EST 2001
>> error message for `%a' gave wrong line number
(by Leonardo Constantino; since 4.0)
** lbaselib.c
Fri Dec 21 15:21:05 EDT 2001
>> seg. fault when rawget/rawset get extra arguments
(by Eric Mauger; since 4.0b)
** lvm.c
Wed Jun 19 13:28:20 EST 2002
>> line hook gets wrong `ar'
(by Daniel C. Sinclair; since 4.0.b)
** ldo.c
Wed Jun 19 13:31:49 EST 2002
>> `protectedparser' may run GC, and then collect `filename'
>> (in function `parse_file')
(by Alex Bilyk; since 4.0)
+991 -345
View File
File diff suppressed because it is too large Load Diff
+34 -3
View File
@@ -1,5 +1,5 @@
/*
** $Id: lapi.h,v 1.20 2000/08/31 14:08:27 roberto Exp roberto $
** $Id: lapi.h $
** Auxiliary functions from Lua API
** See Copyright Notice in lua.h
*/
@@ -8,9 +8,40 @@
#define lapi_h
#include "lobject.h"
#include "llimits.h"
#include "lstate.h"
void luaA_pushobject (lua_State *L, const TObject *o);
/* Increments 'L->top', checking for stack overflows */
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
"stack overflow");}
/*
** If a call returns too many multiple returns, the callee may not have
** stack space to accommodate all results. In this case, this macro
** increases its stack space ('L->ci->top').
*/
#define adjustresults(L,nres) \
{ if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
/* Ensure the stack has at least 'n' elements */
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
"not enough elements in the stack")
/*
** To reduce the overhead of returning from C functions, the presence of
** to-be-closed variables in these functions is coded in the CallInfo's
** field 'nresults', in a way that functions with no to-be-closed variables
** with zero, one, or "all" wanted results have no overhead. Functions
** with other number of wanted results, as well as functions with
** variables to be closed, have an extra check.
*/
#define hastocloseCfunc(n) ((n) < LUA_MULTRET)
#define codeNresults(n) (-(n) - 3)
#endif
+852 -241
View File
File diff suppressed because it is too large Load Diff
+212 -66
View File
@@ -1,5 +1,5 @@
/*
** $Id: lauxlib.h,v 1.51 2002/07/01 19:23:58 roberto Exp roberto $
** $Id: lauxlib.h $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -15,49 +15,106 @@
#include "lua.h"
#ifndef LUALIB_API
#define LUALIB_API extern
#endif
/* global table */
#define LUA_GNAME "_G"
typedef struct luaL_Buffer luaL_Buffer;
typedef struct luaL_reg {
/* 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;
} luaL_Reg;
LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup);
LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname,
const luaL_reg *l, int nup);
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event);
LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname);
LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg);
LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg,
size_t *len);
LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg,
const char *def, size_t *len);
LUALIB_API lua_Number luaL_check_number (lua_State *L, int numArg);
LUALIB_API lua_Number luaL_opt_number (lua_State *L, int nArg, lua_Number def);
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg);
LUALIB_API void luaL_check_type (lua_State *L, int narg, int t);
LUALIB_API void luaL_check_any (lua_State *L, int narg);
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 void luaL_where (lua_State *L, int level);
LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...);
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 int (luaL_typeerror) (lua_State *L, int arg, const char *tname);
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 int luaL_findstring (const char *name,
const char *const list[]);
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 int luaL_ref (lua_State *L, int t);
LUALIB_API void luaL_unref (lua_State *L, int t, int ref);
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_loadfile (lua_State *L, const char *filename);
LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
const char *name);
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);
/* 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 void luaL_addgsub (luaL_Buffer *b, const char *s,
const char *p, const char *r);
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);
/*
** ===============================================================
@@ -65,14 +122,39 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
** ===============================================================
*/
#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \
luaL_argerror(L, numarg,extramsg)
#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL))
#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL))
#define luaL_check_int(L,n) ((int)luaL_check_number(L, n))
#define luaL_check_long(L,n) ((long)luaL_check_number(L, n))
#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d))
#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d))
#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_argexpected(L,cond,arg,tname) \
((void)((cond) || luaL_typeerror(L, (arg), (tname))))
#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)
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/*
@@ -81,48 +163,112 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
** =======================================================
*/
#ifndef LUAL_BUFFERSIZE
#define LUAL_BUFFERSIZE BUFSIZ
#endif
typedef struct luaL_Buffer {
char *p; /* current position in buffer */
int level;
struct luaL_Buffer {
char *b; /* buffer address */
size_t size; /* buffer size */
size_t n; /* number of characters in buffer */
lua_State *L;
char buffer[LUAL_BUFFERSIZE];
} luaL_Buffer;
union {
LUAI_MAXALIGN; /* ensure maximum alignment for buffer */
char b[LUAL_BUFFERSIZE]; /* initial buffer */
} init;
};
#define luaL_putchar(B,c) \
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
(*(B)->p++ = (char)(c)))
#define luaL_addsize(B,n) ((B)->p += (n))
#define luaL_bufflen(bf) ((bf)->n)
#define luaL_buffaddr(bf) ((bf)->b)
LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B);
LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B);
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);
#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))
#define luaL_buffsub(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)
/* }====================================================== */
/*
** Compatibility macros
** {======================================================
** File handles for IO library
** =======================================================
*/
#define luaL_checktype luaL_check_type
#define luaL_checkany luaL_check_any
/*
** 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;
/* }====================================================== */
/*
** {==================================================================
** "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
/* }============================================================ */
LUALIB_API int lua_dofile (lua_State *L, const char *filename);
LUALIB_API int lua_dostring (lua_State *L, const char *str);
LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
const char *name);
#endif
+367 -465
View File
@@ -1,9 +1,13 @@
/*
** $Id: lbaselib.c,v 1.96 2002/08/06 18:54:18 roberto Exp roberto $
** $Id: lbaselib.c $
** Basic library
** See Copyright Notice in lua.h
*/
#define lbaselib_c
#define LUA_LIB
#include "lprefix.h"
#include <ctype.h>
@@ -17,197 +21,235 @@
#include "lualib.h"
/*
** If your system does not support `stdout', you can just remove this function.
** If you need, you can define your own `print' function, following this
** model but changing `fputs' to put the strings at a proper place
** (a console window or a log file, for instance).
*/
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;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tostring(L, -1); /* get result */
if (s == NULL)
return luaL_error(L, "`tostring' must return a string to `print'");
if (i>1) fputs("\t", stdout);
fputs(s, stdout);
for (i = 1; i <= n; i++) { /* for each argument */
size_t l;
const char *s = luaL_tolstring(L, i, &l); /* convert it to string */
if (i > 1) /* not the first element? */
lua_writestring("\t", 1); /* add a tab before it */
lua_writestring(s, l); /* print it */
lua_pop(L, 1); /* pop result */
}
fputs("\n", stdout);
lua_writeline();
return 0;
}
/*
** Creates a warning with all given arguments.
** Check first for errors; otherwise an error may interrupt
** the composition of a warning, leaving it unfinished.
*/
static int luaB_warn (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
luaL_checkstring(L, 1); /* at least one argument */
for (i = 2; i <= n; i++)
luaL_checkstring(L, i); /* make sure all arguments are strings */
for (i = 1; i < n; i++) /* compose warning */
lua_warning(L, lua_tostring(L, i), 1);
lua_warning(L, lua_tostring(L, n), 0); /* close warning */
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 sign */
else if (*s == '+') s++;
if (!isalnum((unsigned char)*s)) /* no digit? */
return NULL;
do {
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
: (toupper((unsigned char)*s) - 'A') + 10;
if (digit >= base) return NULL; /* invalid numeral */
n = n * base + digit;
s++;
} while (isalnum((unsigned char)*s));
s += strspn(s, SPACECHARS); /* skip trailing spaces */
*pn = (lua_Integer)((neg) ? (0u - n) : n);
return s;
}
static int luaB_tonumber (lua_State *L) {
int base = luaL_opt_int(L, 2, 10);
if (base == 10) { /* standard conversion */
luaL_check_any(L, 1);
if (lua_isnumber(L, 1)) {
lua_pushnumber(L, lua_tonumber(L, 1));
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
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 */
luaL_checkany(L, 1); /* (but there must be some parameter) */
}
}
else {
const char *s1 = luaL_check_string(L, 1);
char *s2;
unsigned long n;
luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range");
n = strtoul(s1, &s2, base);
if (s1 != s2) { /* at least one valid digit? */
while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
if (*s2 == '\0') { /* no invalid trailing characters? */
lua_pushnumber(L, n);
return 1;
}
}
}
lua_pushnil(L); /* else not a number */
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); /* 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 */
luaL_pushfail(L); /* not a number */
return 1;
}
static int luaB_error (lua_State *L) {
int level = luaL_opt_int(L, 2, 1);
luaL_check_any(L, 1);
if (!lua_isstring(L, 1) || level == 0)
lua_pushvalue(L, 1); /* propagate error mesage without changes */
else { /* add extra information */
luaL_where(L, level);
int level = (int)luaL_optinteger(L, 2, 1);
lua_settop(L, 1);
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
luaL_where(L, level); /* add extra information */
lua_pushvalue(L, 1);
lua_pushliteral(L, "\n");
lua_concat(L, 3);
lua_concat(L, 2);
}
return lua_error(L);
}
static int luaB_getmode (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_pushstring(L, lua_getmode(L, 1));
return 1;
}
static int luaB_setmode (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_setmode(L, 1, luaL_check_string(L, 2));
lua_settop(L, 1);
return 1;
}
static int luaB_getmetatable (lua_State *L) {
luaL_check_any(L, 1);
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L);
return 1; /* no metatable */
}
else {
lua_pushliteral(L, "__metatable");
lua_rawget(L, -2);
if (lua_isnil(L, -1))
lua_pop(L, 1);
/* otherwise returns metatable.__metatable */
}
return 1;
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_check_type(L, 1, LUA_TTABLE);
luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
"nil or table expected");
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
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 void getfunc (lua_State *L) {
if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
else {
lua_Debug ar;
int level = luaL_opt_int(L, 1, 1);
luaL_arg_check(L, level >= 0, 1, "level must be non-negative");
if (lua_getstack(L, level, &ar) == 0)
luaL_argerror(L, 1, "invalid level");
lua_getinfo(L, "f", &ar);
}
}
static int luaB_getglobals (lua_State *L) {
getfunc(L);
lua_getglobals(L, -1);
return 1;
}
static int luaB_setglobals (lua_State *L) {
luaL_check_type(L, 2, LUA_TTABLE);
getfunc(L);
lua_pushvalue(L, 2);
if (lua_setglobals(L, -2) == 0)
luaL_error(L, "cannot change global table of given function");
return 0;
}
static int luaB_rawequal (lua_State *L) {
luaL_check_any(L, 1);
luaL_check_any(L, 2);
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_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
"table or string");
lua_pushinteger(L, lua_rawlen(L, 1));
return 1;
}
static int luaB_rawget (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_check_any(L, 2);
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_check_type(L, 1, LUA_TTABLE);
luaL_check_any(L, 2);
luaL_check_any(L, 3);
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_gcinfo (lua_State *L) {
lua_pushnumber(L, lua_getgccount(L));
lua_pushnumber(L, lua_getgcthreshold(L));
return 2;
static int pushmode (lua_State *L, int oldmode) {
lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational");
return 1;
}
static int luaB_collectgarbage (lua_State *L) {
lua_setgcthreshold(L, luaL_opt_int(L, 1, 0));
return 0;
static const char *const opts[] = {"stop", "restart", "collect",
"count", "step", "setpause", "setstepmul",
"isrunning", "generational", "incremental", NULL};
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
switch (o) {
case LUA_GCCOUNT: {
int k = lua_gc(L, o);
int b = lua_gc(L, LUA_GCCOUNTB);
lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024));
return 1;
}
case LUA_GCSTEP: {
int step = (int)luaL_optinteger(L, 2, 0);
int res = lua_gc(L, o, step);
lua_pushboolean(L, res);
return 1;
}
case LUA_GCSETPAUSE:
case LUA_GCSETSTEPMUL: {
int p = (int)luaL_optinteger(L, 2, 0);
int previous = lua_gc(L, o, p);
lua_pushinteger(L, previous);
return 1;
}
case LUA_GCISRUNNING: {
int res = lua_gc(L, o);
lua_pushboolean(L, res);
return 1;
}
case LUA_GCGEN: {
int minormul = (int)luaL_optinteger(L, 2, 0);
int majormul = (int)luaL_optinteger(L, 3, 0);
return pushmode(L, lua_gc(L, o, minormul, majormul));
}
case LUA_GCINC: {
int pause = (int)luaL_optinteger(L, 2, 0);
int stepmul = (int)luaL_optinteger(L, 3, 0);
int stepsize = (int)luaL_optinteger(L, 4, 0);
return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize));
}
default: {
int res = lua_gc(L, o);
lua_pushinteger(L, res);
return 1;
}
}
}
static int luaB_type (lua_State *L) {
luaL_check_any(L, 1);
lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
int t = lua_type(L, 1);
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
lua_pushstring(L, lua_typename(L, t));
return 1;
}
static int luaB_next (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
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;
@@ -219,407 +261,267 @@ static int luaB_next (lua_State *L) {
static int luaB_pairs (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
lua_getglobal(L, "next"); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
luaL_checkany(L, 1);
if (luaL_getmetafield(L, 1, "__pairs") == LUA_TNIL) { /* no metamethod? */
lua_pushcfunction(L, luaB_next); /* will return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnil(L); /* and initial value */
}
else {
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
lua_call(L, 1, 3); /* get 3 values from metamethod */
}
return 3;
}
/*
** Traversal function for 'ipairs'
*/
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;
}
/*
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
** (The given "table" may not be a table.)
*/
static int luaB_ipairs (lua_State *L) {
lua_Number i = lua_tonumber(L, 2);
luaL_check_type(L, 1, LUA_TTABLE);
if (i == 0 && lua_isnull(L, 2)) { /* `for' start? */
lua_getglobal(L, "ipairs"); /* return generator, */
lua_pushvalue(L, 1); /* state, */
lua_pushnumber(L, 0); /* and initial value */
return 3;
}
else { /* `for' step */
i++; /* next value */
lua_pushnumber(L, i);
lua_rawgeti(L, 1, (int)i);
return (lua_isnil(L, -1)) ? 0 : 2;
}
luaL_checkany(L, 1);
lua_pushcfunction(L, ipairsaux); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
}
static int passresults (lua_State *L, int status) {
if (status == 0) return 1;
else {
lua_pushnil(L);
lua_insert(L, -2);
return 2;
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) */
luaL_pushfail(L);
lua_insert(L, -2); /* put before error message */
return 2; /* return fail plus error message */
}
}
static int luaB_loadstring (lua_State *L) {
size_t l;
const char *s = luaL_check_lstr(L, 1, &l);
const char *chunkname = luaL_opt_string(L, 2, s);
return passresults(L, luaL_loadbuffer(L, s, l, chunkname));
}
static int luaB_loadfile (lua_State *L) {
const char *fname = luaL_opt_string(L, 1, NULL);
return passresults(L, luaL_loadfile(L, fname));
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);
}
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_opt_string(L, 1, NULL);
int status = luaL_loadfile(L, fname);
if (status != 0) lua_error(L);
lua_call(L, 0, LUA_MULTRET);
/*
** {======================================================
** 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_assert (lua_State *L) {
luaL_check_any(L, 1);
if (!lua_toboolean(L, 1))
return luaL_error(L, "%s", luaL_opt_string(L, 2, "assertion failed!"));
static int luaB_dofile (lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
lua_settop(L, 1);
return 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_unpack (lua_State *L) {
int n, i;
luaL_check_type(L, 1, LUA_TTABLE);
lua_pushliteral(L, "n");
lua_rawget(L, 1);
n = (lua_isnumber(L, -1)) ? (int)lua_tonumber(L, -1) : -1;
for (i=0; i<n || n==-1; i++) { /* push arg[1...n] */
luaL_check_stack(L, LUA_MINSTACK, "table too big to unpack");
lua_rawgeti(L, 1, i+1);
if (n == -1) { /* no explicit limit? */
if (lua_isnil(L, -1)) { /* stop at first `nil' element */
lua_pop(L, 1); /* remove `nil' */
break;
}
}
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' */
}
return i;
}
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_check_any(L, 1);
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
lua_pushboolean(L, (status == 0));
lua_insert(L, 1);
return lua_gettop(L); /* return status + all results */
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 <f, err, true, f, [args...]>; so, the function passes
** 2 to 'finishpcall' to skip the 2 first values when returning results.
*/
static int luaB_xpcall (lua_State *L) {
int status;
luaL_check_any(L, 2);
lua_settop(L, 2);
lua_insert(L, 1); /* put error function under function to be called */
status = lua_pcall(L, 0, LUA_MULTRET, 1);
lua_pushboolean(L, (status == 0));
lua_replace(L, 1);
return lua_gettop(L); /* return status + all results */
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) {
char buff[64];
luaL_checkany(L, 1);
if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
return 1; /* use its value */
switch (lua_type(L, 1)) {
case LUA_TNUMBER:
lua_pushstring(L, lua_tostring(L, 1));
return 1;
case LUA_TSTRING:
lua_pushvalue(L, 1);
return 1;
case LUA_TBOOLEAN:
lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
return 1;
case LUA_TTABLE:
sprintf(buff, "table: %p", lua_topointer(L, 1));
break;
case LUA_TFUNCTION:
sprintf(buff, "function: %p", lua_topointer(L, 1));
break;
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
break;
case LUA_TNIL:
lua_pushliteral(L, "nil");
return 1;
}
lua_pushstring(L, buff);
luaL_tolstring(L, 1, NULL);
return 1;
}
static int luaB_newproxy (lua_State *L) {
lua_settop(L, 1);
lua_newuserdata(L, 0); /* create proxy */
if (lua_toboolean(L, 1) == 0)
return 1; /* no metatable */
else if (lua_isboolean(L, 1)) {
lua_newtable(L); /* create a new metatable `m' ... */
lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
lua_pushboolean(L, 1);
lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */
}
else {
int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
if (lua_getmetatable(L, 1)) {
lua_rawget(L, lua_upvalueindex(1));
validproxy = lua_toboolean(L, -1);
lua_pop(L, 1); /* remove value */
}
luaL_arg_check(L, validproxy, 1, "boolean/proxy expected");
lua_getmetatable(L, 1); /* metatable is valid; get it */
}
lua_setmetatable(L, 2);
return 1;
}
/*
** {======================================================
** `require' function
** =======================================================
*/
/* name of global that holds table with loaded packages */
#define REQTAB "_LOADED"
/* name of global that holds the search path for packages */
#define LUA_PATH "LUA_PATH"
#ifndef LUA_PATH_SEP
#define LUA_PATH_SEP ';'
#endif
#ifndef LUA_PATH_DEFAULT
#define LUA_PATH_DEFAULT "?;?.lua"
#endif
static const char *getpath (lua_State *L) {
const char *path;
lua_getglobal(L, LUA_PATH); /* try global variable */
path = lua_tostring(L, -1);
lua_pop(L, 1);
if (path) return path;
path = getenv(LUA_PATH); /* else try environment variable */
if (path) return path;
return LUA_PATH_DEFAULT; /* else use default */
}
static const char *pushnextpath (lua_State *L, const char *path) {
const char *l;
if (*path == '\0') return NULL; /* no more pathes */
if (*path == LUA_PATH_SEP) path++; /* skip separator */
l = strchr(path, LUA_PATH_SEP); /* find next separator */
if (l == NULL) l = path+strlen(path);
lua_pushlstring(L, path, l - path); /* directory name */
return l;
}
static void pushcomposename (lua_State *L) {
const char *path = lua_tostring(L, -1);
const char *wild = strchr(path, '?');
if (wild == NULL) return; /* no wild char; path is the file name */
lua_pushlstring(L, path, wild - path);
lua_pushvalue(L, 1); /* package name */
lua_pushstring(L, wild + 1);
lua_concat(L, 3);
}
static int luaB_require (lua_State *L) {
const char *path;
int status = LUA_ERRFILE; /* not found (yet) */
luaL_check_string(L, 1);
lua_settop(L, 1);
lua_pushvalue(L, 1);
lua_setglobal(L, "_REQUIREDNAME");
lua_getglobal(L, REQTAB);
if (!lua_istable(L, 2)) return luaL_error(L, "`" REQTAB "' is not a table");
path = getpath(L);
lua_pushvalue(L, 1); /* check package's name in book-keeping table */
lua_rawget(L, 2);
if (!lua_isnil(L, -1)) /* is it there? */
return 0; /* package is already loaded */
else { /* must load it */
while (status == LUA_ERRFILE) {
lua_settop(L, 3); /* reset stack position */
if ((path = pushnextpath(L, path)) == NULL) break;
pushcomposename(L);
status = luaL_loadfile(L, lua_tostring(L, -1)); /* try to load it */
}
}
switch (status) {
case 0: {
lua_call(L, 0, 0); /* run loaded module */
lua_pushvalue(L, 1);
lua_pushboolean(L, 1);
lua_rawset(L, 2); /* mark it as loaded */
return 0;
}
case LUA_ERRFILE: { /* file not found */
return luaL_error(L, "could not load package `%s' from path `%s'",
lua_tostring(L, 1), getpath(L));
}
default: {
return luaL_error(L, "error loading package\n%s", lua_tostring(L, -1));
}
}
}
/* }====================================================== */
static const luaL_reg base_funcs[] = {
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
{"collectgarbage", luaB_collectgarbage},
{"dofile", luaB_dofile},
{"error", luaB_error},
{"getmetatable", luaB_getmetatable},
{"setmetatable", luaB_setmetatable},
{"getglobals", luaB_getglobals},
{"setglobals", luaB_setglobals},
{"getmode", luaB_getmode},
{"setmode", luaB_setmode},
{"next", luaB_next},
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
{"next", luaB_next},
{"pairs", luaB_pairs},
{"pcall", luaB_pcall},
{"print", luaB_print},
{"warn", luaB_warn},
{"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},
{"assert", luaB_assert},
{"unpack", luaB_unpack},
{"rawequal", luaB_rawequal},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
{"pcall", luaB_pcall},
{"xpcall", luaB_xpcall},
{"collectgarbage", luaB_collectgarbage},
{"gcinfo", luaB_gcinfo},
{"loadfile", luaB_loadfile},
{"dofile", luaB_dofile},
{"loadstring", luaB_loadstring},
{"require", luaB_require},
/* placeholders */
{LUA_GNAME, NULL},
{"_VERSION", NULL},
{NULL, NULL}
};
/*
** {======================================================
** Coroutine library
** =======================================================
*/
static int luaB_resume (lua_State *L) {
lua_State *co = (lua_State *)lua_unboxpointer(L, lua_upvalueindex(1));
int status;
lua_settop(L, 0);
status = lua_resume(L, co);
if (status != 0)
return lua_error(L);
return lua_gettop(L);
}
static int gc_coroutine (lua_State *L) {
lua_State *co = (lua_State *)lua_unboxpointer(L, 1);
lua_closethread(L, co);
return 0;
}
static int luaB_coroutine (lua_State *L) {
lua_State *NL;
int ref;
int i;
int n = lua_gettop(L);
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
"Lua function expected");
NL = lua_newthread(L);
if (NL == NULL) return luaL_error(L, "unable to create new thread");
/* move function and arguments from L to NL */
for (i=0; i<n; i++) {
ref = lua_ref(L, 1);
lua_getref(NL, ref);
lua_insert(NL, 1);
lua_unref(L, ref);
}
lua_cobegin(NL, n-1);
lua_boxpointer(L, NL);
lua_pushliteral(L, "Coroutine");
lua_rawget(L, LUA_REGISTRYINDEX);
lua_setmetatable(L, -2);
lua_pushcclosure(L, luaB_resume, 1);
LUAMOD_API int luaopen_base (lua_State *L) {
/* 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, LUA_GNAME);
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
return 1;
}
static int luaB_yield (lua_State *L) {
return lua_yield(L, lua_gettop(L));
}
static const luaL_reg co_funcs[] = {
{"create", luaB_coroutine},
{"yield", luaB_yield},
{NULL, NULL}
};
static void co_open (lua_State *L) {
luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0);
/* create metatable for coroutines */
lua_pushliteral(L, "Coroutine");
lua_newtable(L);
lua_pushliteral(L, "__gc");
lua_pushcfunction(L, gc_coroutine);
lua_rawset(L, -3);
lua_rawset(L, LUA_REGISTRYINDEX);
}
/* }====================================================== */
static void base_open (lua_State *L) {
lua_pushliteral(L, "_G");
lua_pushvalue(L, LUA_GLOBALSINDEX);
luaL_openlib(L, base_funcs, 0); /* open lib into global table */
lua_pushliteral(L, "_VERSION");
lua_pushliteral(L, LUA_VERSION);
lua_rawset(L, -3); /* set global _VERSION */
/* `newproxy' needs a weaktable as upvalue */
lua_pushliteral(L, "newproxy");
lua_newtable(L); /* new table `w' */
lua_setmode(L, -1, "k");
lua_pushcclosure(L, luaB_newproxy, 1);
lua_rawset(L, -3); /* set global `newproxy' */
lua_rawset(L, -1); /* set global _G */
}
LUALIB_API int lua_baselibopen (lua_State *L) {
base_open(L);
co_open(L);
lua_newtable(L);
lua_setglobal(L, REQTAB);
return 0;
}
+1480 -410
View File
File diff suppressed because it is too large Load Diff
+67 -36
View File
@@ -1,5 +1,5 @@
/*
** $Id: lcode.h,v 1.36 2002/05/13 13:07:48 roberto Exp roberto $
** $Id: lcode.h $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -21,53 +21,84 @@
/*
** grep "ORDER OPR" if you change these enums
** grep "ORDER OPR" if you change these enums (ORDER OP)
*/
typedef enum BinOpr {
OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW,
/* arithmetic operators */
OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
OPR_DIV, OPR_IDIV,
/* bitwise operators */
OPR_BAND, OPR_BOR, OPR_BXOR,
OPR_SHL, OPR_SHR,
/* string operator */
OPR_CONCAT,
OPR_NE, OPR_EQ,
OPR_LT, OPR_LE, OPR_GT, OPR_GE,
/* comparison operators */
OPR_EQ, OPR_LT, OPR_LE,
OPR_NE, OPR_GT, OPR_GE,
/* logical operators */
OPR_AND, OPR_OR,
OPR_NOBINOPR
} BinOpr;
#define binopistest(op) ((op) >= OPR_NE)
typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr;
/* true if operation is foldable (that is, it is arithmetic or bitwise) */
#define foldbinop(op) ((op) <= OPR_SHR)
#define getcode(fs,e) ((fs)->f->code[(e)->info])
#define luaK_codeABC(fs,o,a,b,c) luaK_codeABCk(fs,o,a,b,c,0)
#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)
int luaK_code (FuncState *fs, Instruction i, int line);
int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);
void luaK_fixline (FuncState *fs, int line);
void luaK_nil (FuncState *fs, int from, int n);
void luaK_reserveregs (FuncState *fs, int n);
int luaK_stringK (FuncState *fs, TString *s);
int luaK_numberK (FuncState *fs, lua_Number r);
void luaK_dischargevars (FuncState *fs, expdesc *e);
int luaK_exp2anyreg (FuncState *fs, expdesc *e);
void luaK_exp2nextreg (FuncState *fs, expdesc *e);
void luaK_exp2val (FuncState *fs, expdesc *e);
int luaK_exp2RK (FuncState *fs, expdesc *e);
void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
void luaK_goiftrue (FuncState *fs, expdesc *e);
void luaK_goiffalse (FuncState *fs, expdesc *e);
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults);
int luaK_jump (FuncState *fs);
void luaK_patchlist (FuncState *fs, int list, int target);
void luaK_patchtohere (FuncState *fs, int list);
void luaK_concat (FuncState *fs, int *l1, int l2);
int luaK_getlabel (FuncState *fs);
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);
void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
/* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
#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_code (FuncState *fs, Instruction i);
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
int B, int C, int k);
LUAI_FUNC int luaK_isKint (expdesc *e);
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
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 void luaK_int (FuncState *fs, int reg, 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_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_settablesize (FuncState *fs, int pc,
int ra, int asize, int hsize);
LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
LUAI_FUNC void luaK_finish (FuncState *fs);
LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
#endif
+206
View File
@@ -0,0 +1,206 @@
/*
** $Id: lcorolib.c $
** Coroutine Library
** See Copyright Notice in lua.h
*/
#define lcorolib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdlib.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static lua_State *getco (lua_State *L) {
lua_State *co = lua_tothread(L, 1);
luaL_argexpected(L, co, 1, "thread");
return co;
}
/*
** Resumes a coroutine. Returns the number of results for non-error
** cases or -1 for errors.
*/
static int auxresume (lua_State *L, lua_State *co, int narg) {
int status, nres;
if (!lua_checkstack(co, narg)) {
lua_pushliteral(L, "too many arguments to resume");
return -1; /* error flag */
}
lua_xmove(L, co, narg);
status = lua_resume(co, L, narg, &nres);
if (status == LUA_OK || status == LUA_YIELD) {
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) {
int stat = lua_status(co);
if (stat != LUA_OK && stat != LUA_YIELD)
lua_resetthread(co); /* close variables in case of errors */
if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
luaL_where(L, 1); /* add extra info, if available */
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));
}
#define COS_RUN 0
#define COS_DEAD 1
#define COS_YIELD 2
#define COS_NORM 3
static const char *const statname[] =
{"running", "dead", "suspended", "normal"};
static int auxstatus (lua_State *L, lua_State *co) {
if (L == co) return COS_RUN;
else {
switch (lua_status(co)) {
case LUA_YIELD:
return COS_YIELD;
case LUA_OK: {
lua_Debug ar;
if (lua_getstack(co, 0, &ar)) /* does it have frames? */
return COS_NORM; /* it is running */
else if (lua_gettop(co) == 0)
return COS_DEAD;
else
return COS_YIELD; /* initial state */
}
default: /* some error occurred */
return COS_DEAD;
}
}
}
static int luaB_costatus (lua_State *L) {
lua_State *co = getco(L);
lua_pushstring(L, statname[auxstatus(L, co)]);
return 1;
}
static int luaB_yieldable (lua_State *L) {
lua_State *co = lua_isnone(L, 1) ? L : getco(L);
lua_pushboolean(L, lua_isyieldable(co));
return 1;
}
static int luaB_corunning (lua_State *L) {
int ismain = lua_pushthread(L);
lua_pushboolean(L, ismain);
return 2;
}
static int luaB_close (lua_State *L) {
lua_State *co = getco(L);
int status = auxstatus(L, co);
switch (status) {
case COS_DEAD: case COS_YIELD: {
status = lua_resetthread(co);
if (status == LUA_OK) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushboolean(L, 0);
lua_xmove(co, L, 1); /* copy error message */
return 2;
}
}
default: /* normal or running coroutine */
return luaL_error(L, "cannot close a %s coroutine", statname[status]);
}
}
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},
{"close", luaB_close},
{NULL, NULL}
};
LUAMOD_API int luaopen_coroutine (lua_State *L) {
luaL_newlib(L, co_funcs);
return 1;
}
+64
View File
@@ -0,0 +1,64 @@
/*
** $Id: lctype.c $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#define lctype_c
#define LUA_CORE
#include "lprefix.h"
#include "lctype.h"
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#if defined (LUA_UCID) /* accept UniCode IDentifiers? */
/* consider all non-ascii codepoints to be alphabetic */
#define NONA 0x01
#else
#define NONA 0x00 /* default */
#endif
LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = {
0x00, /* EOZ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */
0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05,
0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */
0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 8. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* 9. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* a. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* b. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
0x00, 0x00, NONA, NONA, NONA, NONA, NONA, NONA, /* c. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* d. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA, /* e. */
NONA, NONA, NONA, NONA, NONA, NONA, NONA, NONA,
NONA, NONA, NONA, NONA, NONA, 0x00, 0x00, 0x00, /* f. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif /* } */
+95
View File
@@ -0,0 +1,95 @@
/*
** $Id: lctype.h $
** 'ctype' functions for Lua
** See Copyright Notice in lua.h
*/
#ifndef lctype_h
#define lctype_h
#include "lua.h"
/*
** WARNING: the functions defined here do not necessarily correspond
** to the similar functions in the standard C ctype.h. They are
** optimized for the specific needs of Lua
*/
#if !defined(LUA_USE_CTYPE)
#if 'A' == 65 && '0' == 48
/* ASCII case: can use its own tables; faster and fixed */
#define LUA_USE_CTYPE 0
#else
/* must use standard C ctype */
#define LUA_USE_CTYPE 1
#endif
#endif
#if !LUA_USE_CTYPE /* { */
#include <limits.h>
#include "llimits.h"
#define ALPHABIT 0
#define DIGITBIT 1
#define PRINTBIT 2
#define SPACEBIT 3
#define XDIGITBIT 4
#define MASK(B) (1 << (B))
/*
** add 1 to char to allow index -1 (EOZ)
*/
#define testprop(c,p) (luai_ctype_[(c)+1] & (p))
/*
** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_'
*/
#define lislalpha(c) testprop(c, MASK(ALPHABIT))
#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT)))
#define lisdigit(c) testprop(c, MASK(DIGITBIT))
#define lisspace(c) testprop(c, MASK(SPACEBIT))
#define lisprint(c) testprop(c, MASK(PRINTBIT))
#define lisxdigit(c) testprop(c, MASK(XDIGITBIT))
/*
** this 'ltolower' only works for alphabetic characters
*/
#define ltolower(c) ((c) | ('A' ^ 'a'))
/* two more entries for 0 and -1 (EOZ) */
LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
#else /* }{ */
/*
** use standard C ctypes
*/
#include <ctype.h>
#define lislalpha(c) (isalpha(c) || (c) == '_')
#define lislalnum(c) (isalnum(c) || (c) == '_')
#define lisdigit(c) (isdigit(c))
#define lisspace(c) (isspace(c))
#define lisprint(c) (isprint(c))
#define lisxdigit(c) (isxdigit(c))
#define ltolower(c) (tolower(c))
#endif /* } */
#endif
+401 -188
View File
@@ -1,9 +1,14 @@
/*
** $Id: ldblib.c,v 1.66 2002/08/06 18:01:50 roberto Exp roberto $
** $Id: ldblib.c $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
#define ldblib_c
#define LUA_LIB
#include "lprefix.h"
#include <stdio.h>
#include <stdlib.h>
@@ -15,127 +20,330 @@
#include "lualib.h"
/*
** The hook table at registry[HOOKKEY] maps threads to their current
** hook function.
*/
static const char *const HOOKKEY = "_HOOKKEY";
static void settabss (lua_State *L, const char *i, const char *v) {
lua_pushstring(L, i);
lua_pushstring(L, v);
lua_rawset(L, -3);
/*
** 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 void settabsi (lua_State *L, const char *i, int v) {
lua_pushstring(L, i);
lua_pushnumber(L, v);
lua_rawset(L, -3);
}
static int getinfo (lua_State *L) {
lua_Debug ar;
const char *options = luaL_opt_string(L, 2, "flnSu");
if (lua_isnumber(L, 1)) {
if (!lua_getstack(L, (int)(lua_tonumber(L, 1)), &ar)) {
lua_pushnil(L); /* level out of range */
return 1;
}
}
else if (lua_isfunction(L, 1)) {
lua_pushfstring(L, ">%s", options);
options = lua_tostring(L, -1);
lua_pushvalue(L, 1);
}
else
return luaL_argerror(L, 1, "function or level expected");
if (!lua_getinfo(L, options, &ar))
return luaL_argerror(L, 2, "invalid option");
lua_newtable(L);
for (; *options; options++) {
switch (*options) {
case 'S':
settabss(L, "source", ar.source);
settabss(L, "short_src", ar.short_src);
settabsi(L, "linedefined", ar.linedefined);
settabss(L, "what", ar.what);
break;
case 'l':
settabsi(L, "currentline", ar.currentline);
break;
case 'u':
settabsi(L, "nups", ar.nups);
break;
case 'n':
settabss(L, "name", ar.name);
settabss(L, "namewhat", ar.namewhat);
break;
case 'f':
lua_pushliteral(L, "func");
lua_pushvalue(L, -3);
lua_rawset(L, -3);
break;
}
}
return 1; /* return table */
}
static int getlocal (lua_State *L) {
lua_Debug ar;
const char *name;
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
return luaL_argerror(L, 1, "level out of range");
name = lua_getlocal(L, &ar, luaL_check_int(L, 2));
if (name) {
lua_pushstring(L, name);
lua_pushvalue(L, -2);
return 2;
}
else {
lua_pushnil(L);
return 1;
}
}
static int setlocal (lua_State *L) {
lua_Debug ar;
if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */
return luaL_argerror(L, 1, "level out of range");
luaL_check_any(L, 3);
lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2)));
static int db_getregistry (lua_State *L) {
lua_pushvalue(L, LUA_REGISTRYINDEX);
return 1;
}
static const char KEY_HOOK = 'h';
static void hookf (lua_State *L, lua_Debug *ar) {
static const char *const hooknames[] = {"call", "return", "line", "count"};
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_isfunction(L, -1)) {
lua_pushstring(L, hooknames[(int)ar->event]);
if (ar->currentline >= 0) lua_pushnumber(L, ar->currentline);
else lua_pushnil(L);
lua_assert(lua_getinfo(L, "lS", ar));
lua_call(L, 2, 0);
static int db_getmetatable (lua_State *L) {
luaL_checkany(L, 1);
if (!lua_getmetatable(L, 1)) {
lua_pushnil(L); /* no metatable */
}
else
lua_pop(L, 1); /* pop result from gettable */
return 1;
}
static unsigned long makemask (const char *smask, int count) {
unsigned long mask = 0;
static int db_setmetatable (lua_State *L) {
int t = lua_type(L, 2);
luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
lua_settop(L, 2);
lua_setmetatable(L, 1);
return 1; /* return 1st argument */
}
static int db_getuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 2, 1);
if (lua_type(L, 1) != LUA_TUSERDATA)
luaL_pushfail(L);
else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) {
lua_pushboolean(L, 1);
return 2;
}
return 1;
}
static int db_setuservalue (lua_State *L) {
int n = (int)luaL_optinteger(L, 3, 1);
luaL_checktype(L, 1, LUA_TUSERDATA);
luaL_checkany(L, 2);
lua_settop(L, 2);
if (!lua_setiuservalue(L, 1, n))
luaL_pushfail(L);
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, "flnSrtu");
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)) {
luaL_pushfail(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')) {
lua_pushlstring(L, ar.source, ar.srclen);
lua_setfield(L, -2, "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, 'r')) {
settabsi(L, "ftransfer", ar.ftransfer);
settabsi(L, "ntransfer", ar.ntransfer);
}
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);
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 */
lua_Debug ar;
const char *name;
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 {
luaL_pushfail(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_getfield(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;
return mask | LUA_MASKCOUNT(count);
if (count > 0) mask |= LUA_MASKCOUNT;
return mask;
}
static char *unmakemask (unsigned long mask, char *smask) {
/*
** 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';
@@ -145,120 +353,125 @@ static char *unmakemask (unsigned long mask, char *smask) {
}
static int sethook (lua_State *L) {
if (lua_isnoneornil(L, 1)) {
lua_settop(L, 1);
lua_sethook(L, NULL, 0); /* turn off hooks */
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_check_string(L, 2);
lua_Number count = luaL_opt_number(L, 3, 0);
luaL_check_type(L, 1, LUA_TFUNCTION);
luaL_arg_check(L, count <= LUA_MAXCOUNT, 2, "count too large (>= 2^24)");
lua_sethook(L, hookf, makemask(smask, count));
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);
}
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_pushvalue(L, 1);
lua_rawset(L, LUA_REGISTRYINDEX); /* set new hook */
if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) {
/* table just created; initialize it */
lua_pushstring(L, "k");
lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */
lua_pushvalue(L, -1);
lua_setmetatable(L, -2); /* metatable(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 gethook (lua_State *L) {
static int db_gethook (lua_State *L) {
int arg;
lua_State *L1 = getthread(L, &arg);
char buff[5];
unsigned long mask = lua_gethookmask(L);
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
lua_pushstring(L, unmakemask(mask, buff));
lua_pushnumber(L, lua_getmaskcount(mask));
int mask = lua_gethookmask(L1);
lua_Hook hook = lua_gethook(L1);
if (hook == NULL) { /* no hook? */
luaL_pushfail(L);
return 1;
}
else if (hook != hookf) /* external hook? */
lua_pushliteral(L, "external hook");
else { /* hook table must exist */
lua_getfield(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 debug (lua_State *L) {
static int db_debug (lua_State *L) {
for (;;) {
char buffer[250];
fputs("lua_debug> ", stderr);
lua_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
strcmp(buffer, "cont\n") == 0)
return 0;
lua_dostring(L, buffer);
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
lua_pcall(L, 0, 0, 0))
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
lua_settop(L, 0); /* remove eventual returns */
}
}
#define LEVELS1 12 /* size of the first part of the stack */
#define LEVELS2 10 /* size of the second part of the stack */
static int errorfb (lua_State *L) {
int level = 1; /* skip level 0 (it's this function) */
int firstpart = 1; /* still before eventual `...' */
lua_Debug ar;
if (lua_gettop(L) == 0)
lua_pushliteral(L, "");
else if (!lua_isstring(L, 1)) return 1; /* no string message */
lua_pushliteral(L, "stack traceback:\n");
while (lua_getstack(L, level++, &ar)) {
if (level > LEVELS1 && firstpart) {
/* no more than `LEVELS2' more levels? */
if (!lua_getstack(L, level+LEVELS2, &ar))
level--; /* keep going */
else {
lua_pushliteral(L, "\t...\n"); /* too many levels */
while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */
level++;
}
firstpart = 0;
continue;
}
lua_pushliteral(L, "\t");
lua_getinfo(L, "Snl", &ar);
lua_pushfstring(L, "%s:", ar.short_src);
if (ar.currentline > 0)
lua_pushfstring(L, "%d:", ar.currentline);
switch (*ar.namewhat) {
case 'g': /* global */
case 'l': /* local */
case 'f': /* field */
case 'm': /* method */
lua_pushfstring(L, " in function `%s'", ar.name);
break;
default: {
if (*ar.what == 'm') /* main? */
lua_pushfstring(L, " in main chunk");
else if (*ar.what == 'C') /* C function? */
lua_pushfstring(L, "%s", ar.short_src);
else
lua_pushfstring(L, " in function <%s:%d>",
ar.short_src, ar.linedefined);
}
}
lua_pushliteral(L, "\n");
lua_concat(L, lua_gettop(L));
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);
}
lua_concat(L, lua_gettop(L));
return 1;
}
static const luaL_reg dblib[] = {
{"getlocal", getlocal},
{"getinfo", getinfo},
{"gethook", gethook},
{"sethook", sethook},
{"setlocal", setlocal},
{"debug", debug},
{"traceback", errorfb},
static int db_setcstacklimit (lua_State *L) {
int limit = (int)luaL_checkinteger(L, 1);
int res = lua_setcstacklimit(L, limit);
if (res == 0)
lua_pushboolean(L, 0);
else
lua_pushinteger(L, res);
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},
{"setcstacklimit", db_setcstacklimit},
{NULL, NULL}
};
LUALIB_API int lua_dblibopen (lua_State *L) {
luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
lua_pushliteral(L, "_TRACEBACK");
lua_pushcfunction(L, errorfb);
lua_settable(L, LUA_GLOBALSINDEX);
return 0;
LUAMOD_API int luaopen_debug (lua_State *L) {
luaL_newlib(L, dblib);
return 1;
}
+637 -348
View File
File diff suppressed because it is too large Load Diff
+29 -15
View File
@@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 1.29 2002/08/08 20:08:41 roberto Exp roberto $
** $Id: ldebug.h $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@@ -11,23 +11,37 @@
#include "lstate.h"
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
#define resethookcount(L) (L->hookcount = L->basehookcount)
#define resethookcount(L) (L->hookcount = lua_getmaskcount(L->hookmask))
/*
** mark for entries in 'lineinfo' array that has absolute information in
** 'abslineinfo' array
*/
#define ABSLINEINFO (-0x80)
#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond))
#define allowhook(L) ((L->hookmask) & 1)
void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);
int luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2);
void luaG_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L);
int luaG_checkcode (const Proto *pt);
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos);
LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
const char *opname);
LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
const char *what);
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 int luaG_traceexec (lua_State *L, const Instruction *pc);
#endif
+651 -290
View File
File diff suppressed because it is too large Load Diff
+49 -26
View File
@@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 1.50 2002/08/06 15:32:22 roberto Exp roberto $
** $Id: ldo.h $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -14,39 +14,62 @@
/*
** macro to increment stack top.
** There must be always an empty slot at the L->stack.top
** 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 incr_top(L) \
{if (L->top >= L->stack_last) luaD_growstack(L, 1); L->top++;}
#define luaD_checkstackaux(L,n,pre,pos) \
if (L->stack_last - L->top <= (n)) \
{ pre; luaD_growstack(L, n, 1); 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 luaD_checkstack(L,n) \
if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TObject)) \
luaD_growstack(L, n)
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TObject *)((char *)L->stack + (n)))
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
#define restorestack(L,n) ((StkId)((char *)L->stack + (n)))
/* type of protected functions, to be ran by `runprotected' */
/* 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' */
/* macro to check stack size and GC */
#define checkstackGC(L,fsize) \
luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L))
/* type of protected functions, to be ran by 'runprotected' */
typedef void (*Pfunc) (lua_State *L, void *ud);
void luaD_resetprotection (lua_State *L);
int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
StkId luaD_precall (lua_State *L, StkId func);
void luaD_call (lua_State *L, StkId func, int nResults);
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc);
void luaD_poscall (lua_State *L, int wanted, StkId firstResult);
void luaD_reallocCI (lua_State *L, int newsize);
void luaD_reallocstack (lua_State *L, int newsize);
void luaD_growstack (lua_State *L, int n);
void luaD_throw (lua_State *L, int errcode);
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
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,
int fTransfer, int nTransfer);
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
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 void luaD_tryfuncTM (lua_State *L, StkId func);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
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
+226
View File
@@ -0,0 +1,226 @@
/*
** $Id: ldump.c $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define ldump_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "lobject.h"
#include "lstate.h"
#include "lundump.h"
typedef struct {
lua_State *L;
lua_Writer writer;
void *data;
int strip;
int status;
} DumpState;
/*
** All high-level dumps go through dumpVector; you can change it to
** change the endianness of the result
*/
#define dumpVector(D,v,n) dumpBlock(D,v,(n)*sizeof((v)[0]))
#define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char))
static void dumpBlock (DumpState *D, const void *b, size_t size) {
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(D,x) dumpVector(D,&x,1)
static void dumpByte (DumpState *D, int y) {
lu_byte x = (lu_byte)y;
dumpVar(D, x);
}
/* dumpInt Buff Size */
#define DIBS ((sizeof(size_t) * 8 / 7) + 1)
static void dumpSize (DumpState *D, size_t x) {
lu_byte buff[DIBS];
int n = 0;
do {
buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */
x >>= 7;
} while (x != 0);
buff[DIBS - 1] |= 0x80; /* mark last byte */
dumpVector(D, buff + DIBS - n, n);
}
static void dumpInt (DumpState *D, int x) {
dumpSize(D, x);
}
static void dumpNumber (DumpState *D, lua_Number x) {
dumpVar(D, x);
}
static void dumpInteger (DumpState *D, lua_Integer x) {
dumpVar(D, x);
}
static void dumpString (DumpState *D, const TString *s) {
if (s == NULL)
dumpSize(D, 0);
else {
size_t size = tsslen(s);
const char *str = getstr(s);
dumpSize(D, size + 1);
dumpVector(D, str, size);
}
}
static void dumpCode (DumpState *D, const Proto *f) {
dumpInt(D, f->sizecode);
dumpVector(D, f->code, f->sizecode);
}
static void dumpFunction(DumpState *D, const Proto *f, TString *psource);
static void dumpConstants (DumpState *D, const Proto *f) {
int i;
int n = f->sizek;
dumpInt(D, n);
for (i = 0; i < n; i++) {
const TValue *o = &f->k[i];
int tt = ttypetag(o);
dumpByte(D, tt);
switch (tt) {
case LUA_VNUMFLT:
dumpNumber(D, fltvalue(o));
break;
case LUA_VNUMINT:
dumpInteger(D, ivalue(o));
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
dumpString(D, tsvalue(o));
break;
default:
lua_assert(tt == LUA_VNIL || tt == LUA_VFALSE || tt == LUA_VTRUE);
}
}
}
static void dumpProtos (DumpState *D, const Proto *f) {
int i;
int n = f->sizep;
dumpInt(D, n);
for (i = 0; i < n; i++)
dumpFunction(D, f->p[i], f->source);
}
static void dumpUpvalues (DumpState *D, const Proto *f) {
int i, n = f->sizeupvalues;
dumpInt(D, n);
for (i = 0; i < n; i++) {
dumpByte(D, f->upvalues[i].instack);
dumpByte(D, f->upvalues[i].idx);
dumpByte(D, f->upvalues[i].kind);
}
}
static void dumpDebug (DumpState *D, const Proto *f) {
int i, n;
n = (D->strip) ? 0 : f->sizelineinfo;
dumpInt(D, n);
dumpVector(D, f->lineinfo, n);
n = (D->strip) ? 0 : f->sizeabslineinfo;
dumpInt(D, n);
for (i = 0; i < n; i++) {
dumpInt(D, f->abslineinfo[i].pc);
dumpInt(D, f->abslineinfo[i].line);
}
n = (D->strip) ? 0 : f->sizelocvars;
dumpInt(D, n);
for (i = 0; i < n; i++) {
dumpString(D, f->locvars[i].varname);
dumpInt(D, f->locvars[i].startpc);
dumpInt(D, f->locvars[i].endpc);
}
n = (D->strip) ? 0 : f->sizeupvalues;
dumpInt(D, n);
for (i = 0; i < n; i++)
dumpString(D, f->upvalues[i].name);
}
static void dumpFunction (DumpState *D, const Proto *f, TString *psource) {
if (D->strip || f->source == psource)
dumpString(D, NULL); /* no debug info or same source as its parent */
else
dumpString(D, f->source);
dumpInt(D, f->linedefined);
dumpInt(D, f->lastlinedefined);
dumpByte(D, f->numparams);
dumpByte(D, f->is_vararg);
dumpByte(D, f->maxstacksize);
dumpCode(D, f);
dumpConstants(D, f);
dumpUpvalues(D, f);
dumpProtos(D, f);
dumpDebug(D, f);
}
static void dumpHeader (DumpState *D) {
dumpLiteral(D, LUA_SIGNATURE);
dumpByte(D, LUAC_VERSION);
dumpByte(D, LUAC_FORMAT);
dumpLiteral(D, LUAC_DATA);
dumpByte(D, sizeof(Instruction));
dumpByte(D, sizeof(lua_Integer));
dumpByte(D, sizeof(lua_Number));
dumpInteger(D, LUAC_INT);
dumpNumber(D, LUAC_NUM);
}
/*
** 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(&D, f->sizeupvalues);
dumpFunction(&D, f, NULL);
return D.status;
}
+229 -63
View File
@@ -1,122 +1,288 @@
/*
** $Id: lfunc.c,v 1.56 2002/05/02 13:06:20 roberto Exp roberto $
** $Id: lfunc.c $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
#define lfunc_c
#define LUA_CORE
#include <stdlib.h>
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
cast(int, sizeof(TObject)*((n)-1)))
#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
cast(int, sizeof(TObject *)*((n)-1)))
Closure *luaF_newCclosure (lua_State *L, int nelems) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
c->c.isC = 1;
c->c.next = G(L)->rootcl;
G(L)->rootcl = c;
c->c.marked = 0;
c->c.nupvalues = cast(lu_byte, nelems);
CClosure *luaF_newCclosure (lua_State *L, int nupvals) {
GCObject *o = luaC_newobj(L, LUA_VCCL, sizeCclosure(nupvals));
CClosure *c = gco2ccl(o);
c->nupvalues = cast_byte(nupvals);
return c;
}
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt) {
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
c->l.isC = 0;
c->c.next = G(L)->rootcl;
G(L)->rootcl = c;
c->l.marked = 0;
c->l.g = *gt;
c->l.nupvalues = cast(lu_byte, nelems);
LClosure *luaF_newLclosure (lua_State *L, int nupvals) {
GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals));
LClosure *c = gco2lcl(o);
c->p = NULL;
c->nupvalues = cast_byte(nupvals);
while (nupvals--) c->upvals[nupvals] = NULL;
return c;
}
/*
** fill a closure with new closed upvalues
*/
void luaF_initupvals (lua_State *L, LClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) {
GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
UpVal *uv = gco2upv(o);
uv->v = &uv->u.value; /* make it closed */
setnilvalue(uv->v);
cl->upvals[i] = uv;
luaC_objbarrier(L, cl, o);
}
}
/*
** Create a new upvalue at the given level, and link it to the list of
** open upvalues of 'L' after entry 'prev'.
**/
static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) {
GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
UpVal *uv = gco2upv(o);
UpVal *next = *prev;
uv->v = s2v(level); /* current value lives in the stack */
uv->tbc = tbc;
uv->u.open.next = next; /* link it to list of open upvalues */
uv->u.open.previous = prev;
if (next)
next->u.open.previous = &uv->u.open.next;
*prev = uv;
if (!isintwups(L)) { /* thread not in list of threads with upvalues? */
L->twups = G(L)->twups; /* link it to the list */
G(L)->twups = L;
}
return uv;
}
/*
** Find and reuse, or create if it does not exist, an upvalue
** at the given level.
*/
UpVal *luaF_findupval (lua_State *L, StkId level) {
UpVal **pp = &L->openupval;
UpVal *p;
while ((p = *pp) != NULL && p->v >= level) {
if (p->v == level) return p;
pp = &p->next;
lua_assert(isintwups(L) || L->openupval == NULL);
while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */
lua_assert(!isdead(G(L), p));
if (uplevel(p) == level) /* corresponding upvalue? */
return p; /* return it */
pp = &p->u.open.next;
}
p = luaM_new(L, UpVal); /* not found: create a new one */
p->v = level; /* current value lives in the stack */
p->next = *pp; /* chain it in the proper position */
*pp = p;
return p;
/* not found: create a new upvalue after 'pp' */
return newupval(L, 0, level, pp);
}
void luaF_close (lua_State *L, StkId level) {
UpVal *p;
while ((p = L->openupval) != NULL && p->v >= level) {
setobj(&p->value, p->v); /* save current value */
p->v = &p->value; /* now current value lives here */
L->openupval = p->next; /* remove from `open' list */
p->next = G(L)->rootupval; /* chain in `closed' list */
G(L)->rootupval = p;
static void callclose (lua_State *L, void *ud) {
UNUSED(ud);
luaD_callnoyield(L, L->top - 3, 0);
}
/*
** Prepare closing method plus its arguments for object 'obj' with
** error message 'err'. (This function assumes EXTRA_STACK.)
*/
static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) {
StkId top = L->top;
const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
if (ttisnil(tm)) /* no metamethod? */
return 0; /* nothing to call */
setobj2s(L, top, tm); /* will call metamethod... */
setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */
setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */
L->top = top + 3; /* add function and arguments */
return 1;
}
/*
** Raise an error with message 'msg', inserting the name of the
** local variable at position 'level' in the stack.
*/
static void varerror (lua_State *L, StkId level, const char *msg) {
int idx = cast_int(level - L->ci->func);
const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
if (vname == NULL) vname = "?";
luaG_runerror(L, msg, vname);
}
/*
** Prepare and call a closing method. If status is OK, code is still
** inside the original protected call, and so any error will be handled
** there. Otherwise, a previous error already activated the original
** protected call, and so the call to the closing method must be
** protected here. (A status == CLOSEPROTECT behaves like a previous
** error, to also run the closing method in protected mode).
** If status is OK, the call to the closing method will be pushed
** at the top of the stack. Otherwise, values are pushed after
** the 'level' of the upvalue being closed, as everything after
** that won't be used again.
*/
static int callclosemth (lua_State *L, StkId level, int status) {
TValue *uv = s2v(level); /* value being closed */
if (likely(status == LUA_OK)) {
if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
callclose(L, NULL); /* call closing method */
else if (!l_isfalse(uv)) /* non-closable non-false value? */
varerror(L, level, "attempt to close non-closable variable '%s'");
}
else { /* must close the object in protected mode */
ptrdiff_t oldtop;
level++; /* space for error message */
oldtop = savestack(L, level + 1); /* top will be after that */
luaD_seterrorobj(L, status, level); /* set error message */
if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */
int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0);
if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */
status = newstatus; /* this will be the new error */
else {
if (newstatus != LUA_OK) /* suppressed error? */
luaE_warnerror(L, "__close metamethod");
/* leave original error (or nil) on top */
L->top = restorestack(L, oldtop);
}
}
/* else no metamethod; ignore this case and keep original error */
}
return status;
}
/*
** Try to create a to-be-closed upvalue
** (can raise a memory-allocation error)
*/
static void trynewtbcupval (lua_State *L, void *ud) {
newupval(L, 1, cast(StkId, ud), &L->openupval);
}
/*
** Create a to-be-closed upvalue. If there is a memory error
** when creating the upvalue, the closing method must be called here,
** as there is no upvalue to call it later.
*/
void luaF_newtbcupval (lua_State *L, StkId level) {
TValue *obj = s2v(level);
lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
if (!l_isfalse(obj)) { /* false doesn't need to be closed */
int status;
const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
if (ttisnil(tm)) /* no metamethod? */
varerror(L, level, "variable '%s' got a non-closable value");
status = luaD_rawrunprotected(L, trynewtbcupval, level);
if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */
lua_assert(status == LUA_ERRMEM);
luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
/* next call must succeed, as object is closable */
prepclosingmethod(L, s2v(level), s2v(level + 1));
callclose(L, NULL); /* call closing method */
luaD_throw(L, LUA_ERRMEM); /* throw memory error */
}
}
}
void luaF_unlinkupval (UpVal *uv) {
lua_assert(upisopen(uv));
*uv->u.open.previous = uv->u.open.next;
if (uv->u.open.next)
uv->u.open.next->u.open.previous = uv->u.open.previous;
}
int luaF_close (lua_State *L, StkId level, int status) {
UpVal *uv;
while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
TValue *slot = &uv->u.value; /* new position for value */
lua_assert(uplevel(uv) < L->top);
if (uv->tbc && status != NOCLOSINGMETH) {
/* must run closing method, which may change the stack */
ptrdiff_t levelrel = savestack(L, level);
status = callclosemth(L, uplevel(uv), status);
level = restorestack(L, levelrel);
}
luaF_unlinkupval(uv);
setobj(L, slot, uv->v); /* move value to upvalue slot */
uv->v = slot; /* now current value lives here */
if (!iswhite(uv))
gray2black(uv); /* closed upvalues cannot be gray */
luaC_barrier(L, uv, slot);
}
return status;
}
Proto *luaF_newproto (lua_State *L) {
Proto *f = luaM_new(L, Proto);
GCObject *o = luaC_newobj(L, LUA_VPROTO, sizeof(Proto));
Proto *f = gco2p(o);
f->k = NULL;
f->sizek = 0;
f->p = NULL;
f->sizep = 0;
f->code = NULL;
f->sizecode = 0;
f->nupvalues = 0;
f->lineinfo = NULL;
f->sizelineinfo = 0;
f->abslineinfo = NULL;
f->sizeabslineinfo = 0;
f->upvalues = NULL;
f->sizeupvalues = 0;
f->numparams = 0;
f->is_vararg = 0;
f->maxstacksize = 0;
f->marked = 0;
f->lineinfo = NULL;
f->sizelocvars = 0;
f->locvars = NULL;
f->lineDefined = 0;
f->sizelocvars = 0;
f->linedefined = 0;
f->lastlinedefined = 0;
f->source = NULL;
f->next = G(L)->rootproto; /* chain in list of protos */
G(L)->rootproto = f;
return f;
}
void luaF_freeproto (lua_State *L, Proto *f) {
luaM_freearray(L, f->code, f->sizecode, Instruction);
if (f->lineinfo)
luaM_freearray(L, f->lineinfo, f->sizecode, int);
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
luaM_freearray(L, f->k, f->sizek, TObject);
luaM_freearray(L, f->p, f->sizep, Proto *);
luaM_freelem(L, f);
}
void luaF_freeclosure (lua_State *L, Closure *c) {
int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
sizeLclosure(c->l.nupvalues);
luaM_free(L, c, size);
luaM_freearray(L, f->code, f->sizecode);
luaM_freearray(L, f->p, f->sizep);
luaM_freearray(L, f->k, f->sizek);
luaM_freearray(L, f->lineinfo, f->sizelineinfo);
luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo);
luaM_freearray(L, f->locvars, f->sizelocvars);
luaM_freearray(L, f->upvalues, f->sizeupvalues);
luaM_free(L, f);
}
/*
** Look for n-th local variable at line `line' in function `func'.
** Look for n-th local variable at line 'line' in function 'func'.
** Returns NULL if not found.
*/
const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
+53 -9
View File
@@ -1,5 +1,5 @@
/*
** $Id: lfunc.h,v 1.19 2001/11/29 20:22:22 roberto Exp roberto $
** $Id: lfunc.h $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -11,15 +11,59 @@
#include "lobject.h"
Proto *luaF_newproto (lua_State *L);
Closure *luaF_newCclosure (lua_State *L, int nelems);
Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt);
UpVal *luaF_findupval (lua_State *L, StkId level);
void luaF_close (lua_State *L, StkId level);
void luaF_freeproto (lua_State *L, Proto *f);
void luaF_freeclosure (lua_State *L, Closure *c);
#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \
cast_int(sizeof(TValue)) * (n))
const char *luaF_getlocalname (const Proto *func, int local_number, int pc);
#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \
cast_int(sizeof(TValue *)) * (n))
/* 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
#define upisopen(up) ((up)->v != &(up)->u.value)
#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v))
/*
** maximum number of misses before giving up the cache of closures
** in prototypes
*/
#define MAXMISS 10
/*
** Special "status" for 'luaF_close'
*/
/* close upvalues without running their closing methods */
#define NOCLOSINGMETH (-1)
/* close upvalues running all closing methods in protected mode */
#define CLOSEPROTECT (-2)
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nupvals);
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals);
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status);
LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
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
+1524 -402
View File
File diff suppressed because it is too large Load Diff
+169 -6
View File
@@ -1,5 +1,5 @@
/*
** $Id: lgc.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
** $Id: lgc.h $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -9,15 +9,178 @@
#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).
*/
#define luaC_checkGC(L) if (G(L)->nblocks >= G(L)->GCthreshold) \
luaC_collectgarbage(L)
/*
** Possible states of the Garbage Collector
*/
#define GCSpropagate 0
#define GCSenteratomic 1
#define GCSatomic 2
#define GCSswpallgc 3
#define GCSswpfinobj 4
#define GCSswptobefnz 5
#define GCSswpend 6
#define GCScallfin 7
#define GCSpause 8
void luaC_callallgcTM (lua_State *L);
void luaC_collect (lua_State *L, int all);
void luaC_collectgarbage (lua_State *L);
#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_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. First three bits are
** used for object "age" in generational mode. Last bit is free
** to be used by respective objects.
*/
#define WHITE0BIT 3 /* object is white (type 0) */
#define WHITE1BIT 4 /* object is white (type 1) */
#define BLACKBIT 5 /* object is black */
#define FINALIZEDBIT 6 /* object has been marked for finalization */
#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) & (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_byte((g)->currentwhite & WHITEBITS)
/* object age in generational mode */
#define G_NEW 0 /* created in current cycle */
#define G_SURVIVAL 1 /* created in previous cycle */
#define G_OLD0 2 /* marked old by frw. barrier in this cycle */
#define G_OLD1 3 /* first full cycle as old */
#define G_OLD 4 /* really old object (not to be visited) */
#define G_TOUCHED1 5 /* old object touched this cycle */
#define G_TOUCHED2 6 /* old object touched in previous cycle */
#define AGEBITS 7 /* all age bits (111) */
#define getage(o) ((o)->marked & AGEBITS)
#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a))
#define isold(o) (getage(o) > G_SURVIVAL)
#define changeage(o,f,t) \
check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t)))
/* Default Values for GC parameters */
#define LUAI_GENMAJORMUL 100
#define LUAI_GENMINORMUL 20
/* wait memory to double before starting new cycle */
#define LUAI_GCPAUSE 200
/*
** some gc parameters are stored divided by 4 to allow a maximum value
** up to 1023 in a 'lu_byte'.
*/
#define getgcparam(p) ((p) * 4)
#define setgcparam(p,v) ((p) = (v) / 4)
#define LUAI_GCMUL 100
/* how much to allocate before next GC step (log2) */
#define LUAI_GCSTEPSIZE 13 /* 8 KB */
/*
** Check whether the declared GC mode is generational. While in
** generational mode, the collector can go temporarily to incremental
** mode to improve performance. This is signaled by 'g->lastatomic != 0'.
*/
#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0)
/*
** 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) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
#define luaC_barrierback(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrierback_(L,p) : cast_void(0))
#define luaC_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : 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, GCObject *o);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);
#endif
+60 -3
View File
@@ -1,8 +1,65 @@
/*
** $Id: linit.c,v 1.5 2000/06/16 17:22:43 roberto Exp roberto $
** Initialization of libraries for lua.c
** $Id: linit.c $
** Initialization of libraries for lua.c and other clients
** See Copyright Notice in lua.h
*/
>>>>>>> This module is now obsolete, and is not part of Lua. <<<<<<<<<
#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, LUA_PRELOAD_TABLE);
** lua_pushcfunction(L, luaopen_modname);
** lua_setfield(L, -2, modname);
** lua_pop(L, 1); // remove PRELOAD table
*/
#include "lprefix.h"
#include <stddef.h>
#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[] = {
{LUA_GNAME, 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},
{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 */
}
}
+585 -401
View File
File diff suppressed because it is too large Load Diff
+112
View File
@@ -0,0 +1,112 @@
/*
** $Id: ljumptab.h $
** Jump Table for the Lua interpreter
** See Copyright Notice in lua.h
*/
#undef vmdispatch
#undef vmcase
#undef vmbreak
#define vmdispatch(x) goto *disptab[x];
#define vmcase(l) L_##l:
#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i));
static const void *const disptab[NUM_OPCODES] = {
#if 0
** you can update the following list with this command:
**
** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h
**
#endif
&&L_OP_MOVE,
&&L_OP_LOADI,
&&L_OP_LOADF,
&&L_OP_LOADK,
&&L_OP_LOADKX,
&&L_OP_LOADFALSE,
&&L_OP_LFALSESKIP,
&&L_OP_LOADTRUE,
&&L_OP_LOADNIL,
&&L_OP_GETUPVAL,
&&L_OP_SETUPVAL,
&&L_OP_GETTABUP,
&&L_OP_GETTABLE,
&&L_OP_GETI,
&&L_OP_GETFIELD,
&&L_OP_SETTABUP,
&&L_OP_SETTABLE,
&&L_OP_SETI,
&&L_OP_SETFIELD,
&&L_OP_NEWTABLE,
&&L_OP_SELF,
&&L_OP_ADDI,
&&L_OP_ADDK,
&&L_OP_SUBK,
&&L_OP_MULK,
&&L_OP_MODK,
&&L_OP_POWK,
&&L_OP_DIVK,
&&L_OP_IDIVK,
&&L_OP_BANDK,
&&L_OP_BORK,
&&L_OP_BXORK,
&&L_OP_SHRI,
&&L_OP_SHLI,
&&L_OP_ADD,
&&L_OP_SUB,
&&L_OP_MUL,
&&L_OP_MOD,
&&L_OP_POW,
&&L_OP_DIV,
&&L_OP_IDIV,
&&L_OP_BAND,
&&L_OP_BOR,
&&L_OP_BXOR,
&&L_OP_SHL,
&&L_OP_SHR,
&&L_OP_MMBIN,
&&L_OP_MMBINI,
&&L_OP_MMBINK,
&&L_OP_UNM,
&&L_OP_BNOT,
&&L_OP_NOT,
&&L_OP_LEN,
&&L_OP_CONCAT,
&&L_OP_CLOSE,
&&L_OP_TBC,
&&L_OP_JMP,
&&L_OP_EQ,
&&L_OP_LT,
&&L_OP_LE,
&&L_OP_EQK,
&&L_OP_EQI,
&&L_OP_LTI,
&&L_OP_LEI,
&&L_OP_GTI,
&&L_OP_GEI,
&&L_OP_TEST,
&&L_OP_TESTSET,
&&L_OP_CALL,
&&L_OP_TAILCALL,
&&L_OP_RETURN,
&&L_OP_RETURN0,
&&L_OP_RETURN1,
&&L_OP_FORLOOP,
&&L_OP_FORPREP,
&&L_OP_TFORPREP,
&&L_OP_TFORCALL,
&&L_OP_TFORLOOP,
&&L_OP_SETLIST,
&&L_OP_CLOSURE,
&&L_OP_VARARG,
&&L_OP_VARARGPREP,
&&L_OP_EXTRAARG
};
+480 -311
View File
@@ -1,132 +1,183 @@
/*
** $Id: llex.c,v 1.107 2002/07/08 18:14:36 roberto Exp roberto $
** $Id: llex.c $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
#define llex_c
#define LUA_CORE
#include <ctype.h>
#include "lprefix.h"
#include <locale.h>
#include <string.h>
#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 next(ls) (ls->current = zgetc(ls->z))
#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r')
/* ORDER RESERVED */
static const char *const token2string [] = {
static const char *const luaX_tokens [] = {
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "global", "if",
"end", "false", "for", "function", "goto", "if",
"in", "local", "nil", "not", "or", "repeat",
"return", "then", "true", "until", "while", "*name",
"..", "...", "==", ">=", "<=", "~=",
"*number", "*string", "<eof>"
"return", "then", "true", "until", "while",
"//", "..", "...", "==", ">=", "<=", "~=",
"<<", ">>", "::", "<eof>",
"<number>", "<integer>", "<name>", "<string>"
};
#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_newliteral(L, LUA_ENV); /* create env name */
luaC_fix(L, obj2gco(e)); /* never collect this name */
for (i=0; i<NUM_RESERVED; i++) {
TString *ts = luaS_new(L, token2string[i]);
lua_assert(strlen(token2string[i])+1 <= TOKEN_LEN);
ts->tsv.marked = cast(unsigned short, RESERVEDMARK+i); /* reserved word */
TString *ts = luaS_new(L, luaX_tokens[i]);
luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */
ts->extra = cast_byte(i+1); /* reserved word */
}
}
#define MAXSRC 80
void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) {
if (val > limit) {
msg = luaO_pushfstring(ls->L, "too many %s (limit=%d)", msg, limit);
luaX_syntaxerror(ls, msg);
}
}
static void luaX_error (LexState *ls, const char *s, const char *token) {
lua_State *L = ls->L;
char buff[MAXSRC];
luaO_chunkid(buff, getstr(ls->source), MAXSRC);
luaO_pushfstring(L, "%s:%d: %s near `%s'\n", buff, ls->linenumber, s, token);
luaD_throw(L, LUA_ERRSYNTAX);
}
void luaX_syntaxerror (LexState *ls, const char *msg) {
const char *lasttoken;
switch (ls->t.token) {
case TK_NAME:
lasttoken = luaO_pushfstring(ls->L, "%s", getstr(ls->t.seminfo.ts));
break;
case TK_STRING:
lasttoken = luaO_pushfstring(ls->L, "\"%s\"", getstr(ls->t.seminfo.ts));
break;
case TK_NUMBER:
lasttoken = luaO_pushfstring(ls->L, "%f", ls->t.seminfo.r);
break;
default:
lasttoken = luaX_token2str(ls, ls->t.token);
break;
}
luaX_error(ls, msg, lasttoken);
}
const char *luaX_token2str (LexState *ls, int token) {
if (token < FIRST_RESERVED) {
lua_assert(token == (char)token);
return luaO_pushfstring(ls->L, "%c", token);
if (token < FIRST_RESERVED) { /* single-byte symbols? */
lua_assert(token == cast_uchar(token));
if (lisprint(token))
return luaO_pushfstring(ls->L, "'%c'", token);
else /* control character */
return luaO_pushfstring(ls->L, "'<\\%d>'", token);
}
else
return token2string[token-FIRST_RESERVED];
}
static void luaX_lexerror (LexState *ls, const char *s, int token) {
if (token == TK_EOS)
luaX_error(ls, s, luaX_token2str(ls, token));
else
luaX_error(ls, s, cast(char *, G(ls->L)->Mbuffer));
}
static void inclinenumber (LexState *LS) {
next(LS); /* skip `\n' */
++LS->linenumber;
luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk");
}
void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
LS->L = L;
LS->lookahead.token = TK_EOS; /* no look-ahead token */
LS->z = z;
LS->fs = NULL;
LS->linenumber = 1;
LS->lastline = 1;
LS->source = source;
next(LS); /* read first char */
if (LS->current == '#') {
do { /* skip first line */
next(LS);
} while (LS->current != '\n' && LS->current != EOZ);
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) {
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, s2v(L->top - 1));
if (isempty(o)) { /* not in use yet? */
/* boolean value does not need GC barrier;
table is not a metatable, so it does not need to invalidate cache */
setbtvalue(o); /* t[string] = true */
luaC_checkGC(L);
}
else { /* string already present */
ts = keystrval(nodefromval(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->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_newliteral(L, LUA_ENV); /* get env name */
luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */
}
/*
** =======================================================
@@ -135,275 +186,393 @@ void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) {
*/
/* use Mbuffer to store names, literal strings and numbers */
#define EXTRABUFF 128
#define checkbuffer(L, len) \
if (((len)+10)*sizeof(char) > G(L)->Mbuffsize) \
luaO_openspace(L, (len)+EXTRABUFF, char)
#define save(L, c, l) (cast(char *, G(L)->Mbuffer)[l++] = cast(char, c))
#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS))
static int check_next1 (LexState *ls, int c) {
if (ls->current == c) {
next(ls);
return 1;
}
else return 0;
}
static size_t readname (LexState *LS) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
do {
checkbuffer(L, l);
save_and_next(L, LS, l);
} while (isalnum(LS->current) || LS->current == '_');
save(L, '\0', l);
return l-1;
/*
** 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;
}
/* LUA_NUMBER */
static void read_numeral (LexState *LS, int comma, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
if (comma) save(L, '.', l);
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
}
if (LS->current == '.') {
save_and_next(L, LS, l);
if (LS->current == '.') {
save_and_next(L, LS, l);
save(L, '\0', l);
luaX_lexerror(LS,
"ambiguous syntax (decimal point x string concatenation)",
TK_NUMBER);
}
}
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
}
if (LS->current == 'e' || LS->current == 'E') {
save_and_next(L, LS, l); /* read `E' */
if (LS->current == '+' || LS->current == '-')
save_and_next(L, LS, l); /* optional exponent sign */
while (isdigit(LS->current)) {
checkbuffer(L, l);
save_and_next(L, LS, l);
}
}
save(L, '\0', l);
if (!luaO_str2d(cast(char *, G(L)->Mbuffer), &seminfo->r))
luaX_lexerror(LS, "malformed number", TK_NUMBER);
}
static void read_long_string (LexState *LS, SemInfo *seminfo) {
lua_State *L = LS->L;
int cont = 0;
size_t l = 0;
checkbuffer(L, l);
save(L, '[', l); /* save first `[' */
save_and_next(L, LS, l); /* pass the second `[' */
if (LS->current == '\n') /* string starts with a newline? */
inclinenumber(LS); /* skip it */
/*
** This function is quite liberal in what it accepts, as 'luaO_str2num'
** will reject ill-formed numerals. Roughly, it accepts the following
** pattern:
**
** %d(%x|%.|([Ee][+-]?))* | 0[Xx](%x|%.|([Pp][+-]?))*
**
** The only tricky part is to accept [+-] only after a valid exponent
** mark, to avoid reading '3-4' or '0xe+1' as a single number.
**
** The caller might have already read an initial dot.
*/
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 (;;) {
checkbuffer(L, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
luaX_lexerror(LS, (seminfo) ? "unfinished long string" :
"unfinished long comment", TK_EOS);
break; /* to avoid warnings */
case '[':
save_and_next(L, LS, l);
if (LS->current == '[') {
cont++;
save_and_next(L, LS, l);
}
continue;
case ']':
save_and_next(L, LS, l);
if (LS->current == ']') {
if (cont == 0) goto endloop;
cont--;
save_and_next(L, LS, l);
}
continue;
case '\n':
save(L, '\n', l);
inclinenumber(LS);
if (!seminfo) l = 0; /* reset buffer to avoid wasting space */
continue;
default:
save_and_next(L, LS, l);
}
} endloop:
save_and_next(L, LS, l); /* skip the second `]' */
save(L, '\0', l);
if (seminfo)
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+2, l-5);
if (check_next2(ls, expo)) /* exponent mark? */
check_next2(ls, "-+"); /* optional exponent sign */
else if (lisxdigit(ls->current) || ls->current == '.') /* '%x|%.' */
save_and_next(ls);
else break;
}
if (lislalpha(ls->current)) /* is numeral touching a letter? */
save_and_next(ls); /* force an error */
save(ls, '\0');
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;
}
}
static void read_string (LexState *LS, int del, SemInfo *seminfo) {
lua_State *L = LS->L;
size_t l = 0;
checkbuffer(L, l);
save_and_next(L, LS, l);
while (LS->current != del) {
checkbuffer(L, l);
switch (LS->current) {
case EOZ:
save(L, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_EOS);
/*
** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
** If sequence is well formed, return its number of '='s + 2; otherwise,
** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
*/
static size_t skip_sep (LexState *ls) {
size_t 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 + 2
: (count == 0) ? 1
: 0;
}
static void read_long_string (LexState *ls, SemInfo *seminfo, size_t 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 '\n':
save(L, '\0', l);
luaX_lexerror(LS, "unfinished string", TK_STRING);
break; /* to avoid warnings */
case '\\':
next(LS); /* do not save the `\' */
switch (LS->current) {
case 'a': save(L, '\a', l); next(LS); break;
case 'b': save(L, '\b', l); next(LS); break;
case 'f': save(L, '\f', l); next(LS); break;
case 'n': save(L, '\n', l); next(LS); break;
case 'r': save(L, '\r', l); next(LS); break;
case 't': save(L, '\t', l); next(LS); break;
case 'v': save(L, '\v', l); next(LS); break;
case '\n': save(L, '\n', l); inclinenumber(LS); break;
case EOZ: break; /* will raise an error next loop */
default: {
if (!isdigit(LS->current))
save_and_next(L, LS, l); /* handles \\, \", \', and \? */
else { /* \xxx */
int c = 0;
int i = 0;
do {
c = 10*c + (LS->current-'0');
next(LS);
} while (++i<3 && isdigit(LS->current));
if (c > UCHAR_MAX) {
save(L, '\0', l);
luaX_lexerror(LS, "escape sequence too large", TK_STRING);
}
save(L, c, l);
}
}
}
case ']': {
if (skip_sep(ls) == sep) {
save_and_next(ls); /* skip 2nd ']' */
goto endloop;
}
break;
default:
save_and_next(L, LS, l);
}
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);
}
}
}
save_and_next(L, LS, l); /* skip delimiter */
save(L, '\0', l);
seminfo->ts = luaS_newlstr(L, cast(char *, G(L)->Mbuffer)+1, l-3);
} endloop:
if (seminfo)
seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep,
luaZ_bufflen(ls->buff) - 2 * sep);
}
int luaX_lex (LexState *LS, SemInfo *seminfo) {
for (;;) {
switch (LS->current) {
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);
}
}
case '\n': {
inclinenumber(LS);
continue;
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 (cast_void(save_and_next(ls)), lisxdigit(ls->current)) {
i++;
esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large");
r = (r << 4) + luaO_hexavalue(ls->current);
}
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;
}
case '-': {
next(LS);
if (LS->current != '-') return '-';
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 == '[' && (next(LS), LS->current == '['))
read_long_string(LS, NULL); /* long comment */
else /* short comment */
while (LS->current != '\n' && LS->current != EOZ)
next(LS);
continue;
next(ls);
if (ls->current == '[') { /* long comment? */
size_t sep = skip_sep(ls);
luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */
if (sep >= 2) {
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 '[': {
next(LS);
if (LS->current != '[') return '[';
else {
read_long_string(LS, seminfo);
case '[': { /* long string or simply '[' */
size_t sep = skip_sep(ls);
if (sep >= 2) {
read_long_string(ls, seminfo, sep);
return TK_STRING;
}
else if (sep == 0) /* '[=...' missing second bracket? */
lexerror(ls, "invalid long string delimiter", TK_STRING);
return '[';
}
case '=': {
next(LS);
if (LS->current != '=') return '=';
else { next(LS); return TK_EQ; }
next(ls);
if (check_next1(ls, '=')) return TK_EQ;
else return '=';
}
case '<': {
next(LS);
if (LS->current != '=') return '<';
else { next(LS); return TK_LE; }
next(ls);
if (check_next1(ls, '=')) return TK_LE;
else if (check_next1(ls, '<')) return TK_SHL;
else return '<';
}
case '>': {
next(LS);
if (LS->current != '=') return '>';
else { next(LS); return TK_GE; }
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 (LS->current != '=') return '~';
else { next(LS); return TK_NE; }
next(ls);
if (check_next1(ls, '=')) return TK_NE;
else return '~';
}
case '"':
case '\'': {
read_string(LS, LS->current, seminfo);
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 '.': {
next(LS);
if (LS->current == '.') {
next(LS);
if (LS->current == '.') {
next(LS);
return TK_DOTS; /* ... */
}
else return TK_CONCAT; /* .. */
}
else if (!isdigit(LS->current)) return '.';
else {
read_numeral(LS, 1, seminfo);
return TK_NUMBER;
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 (isspace(LS->current)) {
next(LS);
continue;
}
else if (isdigit(LS->current)) {
read_numeral(LS, 0, seminfo);
return TK_NUMBER;
}
else if (isalpha(LS->current) || LS->current == '_') {
/* identifier or reserved word */
size_t l = readname(LS);
TString *ts = luaS_newlstr(LS->L, cast(char *, G(LS->L)->Mbuffer), l);
if (ts->tsv.marked >= RESERVEDMARK) /* reserved word? */
return ts->tsv.marked-RESERVEDMARK+FIRST_RESERVED;
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;
return TK_NAME;
if (isreserved(ts)) /* reserved word? */
return ts->extra - 1 + FIRST_RESERVED;
else {
return TK_NAME;
}
}
else {
int c = LS->current;
if (iscntrl(c))
luaX_error(LS, "invalid control char",
luaO_pushfstring(LS->L, "char(%d)", c));
next(LS);
return c; /* single-char tokens (+ - / ...) */
else { /* single-char tokens (+ - / ...) */
int c = ls->current;
next(ls);
return c;
}
}
}
}
}
#undef next
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;
}
+29 -16
View File
@@ -1,5 +1,5 @@
/*
** $Id: llex.h,v 1.42 2002/02/08 22:42:41 roberto Exp roberto $
** $Id: llex.h $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -13,8 +13,10 @@
#define FIRST_RESERVED 257
/* maximum length of a reserved word */
#define TOKEN_LEN (sizeof("function")/sizeof(char))
#if !defined(LUA_ENV)
#define LUA_ENV "_ENV"
#endif
/*
@@ -25,19 +27,22 @@ 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_GLOBAL, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
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_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
TK_STRING, TK_EOS
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))
#define NUM_RESERVED (cast_int(TK_WHILE-FIRST_RESERVED + 1))
typedef union {
lua_Number r;
lua_Integer i;
TString *ts;
} SemInfo; /* semantics information */
@@ -48,25 +53,33 @@ typedef struct Token {
} 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' */
int lastline; /* line of last token 'consumed' */
Token t; /* current token */
Token lookahead; /* look ahead token */
struct FuncState *fs; /* `FuncState' is private to the parser */
struct FuncState *fs; /* current function (parser) */
struct lua_State *L;
struct zio *z; /* input stream */
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 */
} LexState;
void luaX_init (lua_State *L);
void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source);
int luaX_lex (LexState *LS, SemInfo *seminfo);
void luaX_checklimit (LexState *ls, int val, int limit, const char *msg);
void luaX_syntaxerror (LexState *ls, const char *s);
const char *luaX_token2str (LexState *ls, int token);
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
+293 -97
View File
@@ -1,6 +1,6 @@
/*
** $Id: llimits.h,v 1.44 2002/06/13 13:45:31 roberto Exp roberto $
** Limits, basic types, and some other `installation-dependent' definitions
** $Id: llimits.h $
** Limits, basic types, and some other 'installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -16,138 +16,334 @@
/*
** try to find number of bits in an integer
** '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.
*/
#ifndef BITS_INT
/* avoid overflows in comparison */
#if INT_MAX-20 < 32760
#define BITS_INT 16
#else
#if INT_MAX > 2147483640L
/* machine has at least 32 bits */
#define BITS_INT 32
#else
#error "you must define BITS_INT with number of bits in an integer"
#endif
#endif
#endif
/*
** the following types define integer types for values that may not
** fit in a `small int' (16 bits), but may waste space in a
** `large long' (64 bits). The current definitions should work in
** any machine, but may not be optimal.
*/
/* an unsigned integer to hold hash values */
typedef unsigned int lu_hash;
/* its signed equivalent */
typedef int ls_hash;
/* an unsigned integer big enough to count the total memory used by Lua; */
/* it should be at least as large as size_t */
#if defined(LUAI_MEM) /* { external definitions? */
typedef LUAI_UMEM lu_mem;
typedef LUAI_MEM l_mem;
#elif LUAI_IS32INT /* }{ */
typedef size_t lu_mem;
typedef ptrdiff_t l_mem;
#else /* 16-bit ints */ /* }{ */
typedef unsigned long lu_mem;
/* an integer big enough to count the number of strings in use */
typedef long ls_nstr;
/* an integer big enough to count the number of steps when calling a
** `count' hook */
typedef long ls_count;
typedef long l_mem;
#endif /* } */
/* chars used as small naturals (so that `char' is reserved for characteres) */
/* chars used as small naturals (so that 'char' is reserved for characters) */
typedef unsigned char lu_byte;
typedef signed char ls_byte;
#define MAX_SIZET ((size_t)(~(size_t)0)-2)
/* maximum value for size_t */
#define MAX_SIZET ((size_t)(~(size_t)0))
/* maximum size visible for Lua (must be representable in a lua_Integer) */
#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \
: (size_t)(LUA_MAXINTEGER))
#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */
#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
** floor of the log2 of the maximum signed value for integral type 't'.
** (That is, maximum 'n' such that '2^n' fits in the given signed type.)
*/
#define log2maxs(t) (sizeof(t) * 8 - 2)
/*
** test whether an unsigned value is a power of 2 (or zero)
*/
#define ispow2(x) (((x) & ((x) - 1)) == 0)
/* number of chars of a literal string without the ending \0 */
#define LL(x) (sizeof(x)/sizeof(char) - 1)
/*
** conversion of pointer to unsigned integer:
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
*/
#define IntPoint(p) ((lu_hash)(p))
#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX))
/* type to ensure maximum alignment */
#ifndef LUSER_ALIGNMENT_T
#define LUSER_ALIGNMENT_T double
/* 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) ((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
union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
/*
** assertion for checking API calls
*/
#if !defined(luai_apicheck)
#define luai_apicheck(l,e) ((void)l, lua_assert(e))
#endif
#define api_check(l,e,msg) luai_apicheck(l,(e) && msg)
#ifndef lua_assert
#define lua_assert(c) /* empty */
/* macro to avoid warnings about unused variables */
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x))
#endif
#ifndef check_exp
#define check_exp(c,e) (e)
#endif
#ifndef UNUSED
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
#endif
#ifndef cast
/* type casts (a macro highlights casts in the code) */
#define cast(t, exp) ((t)(exp))
#define cast_void(i) cast(void, (i))
#define cast_voidp(i) cast(void *, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
#define cast_uint(i) cast(unsigned int, (i))
#define cast_byte(i) cast(lu_byte, (i))
#define cast_uchar(i) cast(unsigned char, (i))
#define cast_char(i) cast(char, (i))
#define cast_charp(i) cast(char *, (i))
#define cast_sizet(i) cast(size_t, (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
/*
** macros to improve jump prediction (used mainly for error handling)
*/
#if !defined(likely)
#if defined(__GNUC__)
#define likely(x) (__builtin_expect(((x) != 0), 1))
#define unlikely(x) (__builtin_expect(((x) != 0), 0))
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
#endif
/*
** non-return type
*/
#if !defined(l_noret)
#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
#endif
/*
** type for virtual-machine instructions;
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
#if LUAI_IS32INT
typedef unsigned int l_uint32;
#else
typedef unsigned long l_uint32;
#endif
typedef l_uint32 Instruction;
/*
** Maximum length for short strings, that is, strings that are
** internalized. (Cannot be smaller than reserved words or tags for
** metamethods, as these strings must be internalized;
** #("function") = 8, #("__newindex") = 10.)
*/
#if !defined(LUAI_MAXSHORTLEN)
#define LUAI_MAXSHORTLEN 40
#endif
/*
** 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 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 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
/*
** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
** The luai_num* macros define the primitive operations over numbers.
*/
typedef unsigned long Instruction;
/* 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
/* maximum depth for calls */
#ifndef LUA_MAXCALLS
#define LUA_MAXCALLS 4096
/* float division */
#if !defined(luai_numdiv)
#define luai_numdiv(L,a,b) ((a)/(b))
#endif
/*
** modulo: defined as 'a - floor(a/b)*b'; the direct computation
** using this definition has several problems with rounding errors,
** so it is better to use 'fmod'. '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: non-integer result is equivalent to
** a non-zero remainder 'm'; negative result is equivalent to 'a' and
** 'b' with different signs, or 'm' and 'b' with different signs
** (as the result 'm' of 'fmod' has the same sign of 'a').
*/
#if !defined(luai_nummod)
#define luai_nummod(L,a,b,m) \
{ (void)L; (m) = l_mathop(fmod)(a,b); \
if (((m) > 0) ? (b) < 0 : ((m) < 0 && (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_numgt(a,b) ((a)>(b))
#define luai_numge(a,b) ((a)>=(b))
#define luai_numisnan(a) (!luai_numeq((a), (a)))
#endif
/* maximum size for the C stack */
#ifndef LUA_MAXCSTACK
#define LUA_MAXCSTACK 2048
/*
** macro to control inclusion of some hard tests on stack reallocation
*/
#if !defined(HARDSTACKTESTS)
#define condmovestack(L,pre,pos) ((void)0)
#else
/* realloc stack keeping its size */
#define condmovestack(L,pre,pos) \
{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_, 0); pos; }
#endif
/* maximum stack for a Lua function */
#define MAXSTACK 250
/* maximum number of variables declared in a function */
#ifndef MAXVARS
#define MAXVARS 200 /* arbitrary limit (<MAXSTACK) */
#if !defined(HARDMEMTESTS)
#define condchangemem(L,pre,pos) ((void)0)
#else
#define condchangemem(L,pre,pos) \
{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
#endif
/* maximum number of upvalues per function */
#ifndef MAXUPVALUES
#define MAXUPVALUES 32
#endif
/* maximum number of parameters in a function */
#ifndef MAXPARAMS
#define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */
#endif
/* minimum size for the string table (must be power of 2) */
#ifndef MINSTRTABSIZE
#define MINSTRTABSIZE 32
#endif
#endif
+629 -113
View File
@@ -1,12 +1,20 @@
/*
** $Id: lmathlib.c,v 1.50 2002/08/14 20:07:43 roberto Exp roberto $
** $Id: lmathlib.c $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
#define lmathlib_c
#define LUA_LIB
#include <stdlib.h>
#include "lprefix.h"
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "lua.h"
@@ -15,215 +23,723 @@
#undef PI
#define PI (3.14159265358979323846)
#define RADIANS_PER_DEGREE (PI/180.0)
/*
** If you want Lua to operate in degrees (instead of radians),
** define USE_DEGREES
*/
#ifdef USE_DEGREES
#define FROMRAD(a) ((a)/RADIANS_PER_DEGREE)
#define TORAD(a) ((a)*RADIANS_PER_DEGREE)
#else
#define FROMRAD(a) (a)
#define TORAD(a) (a)
#endif
#define PI (l_mathop(3.141592653589793238462643383279502884))
static int math_abs (lua_State *L) {
lua_pushnumber(L, fabs(luaL_check_number(L, 1)));
if (lua_isinteger(L, 1)) {
lua_Integer n = lua_tointeger(L, 1);
if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
lua_pushinteger(L, n);
}
else
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
}
static int math_sin (lua_State *L) {
lua_pushnumber(L, sin(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_cos (lua_State *L) {
lua_pushnumber(L, cos(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_tan (lua_State *L) {
lua_pushnumber(L, tan(TORAD(luaL_check_number(L, 1))));
lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1)));
return 1;
}
static int math_asin (lua_State *L) {
lua_pushnumber(L, FROMRAD(asin(luaL_check_number(L, 1))));
lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1)));
return 1;
}
static int math_acos (lua_State *L) {
lua_pushnumber(L, FROMRAD(acos(luaL_check_number(L, 1))));
lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1)));
return 1;
}
static int math_atan (lua_State *L) {
lua_pushnumber(L, FROMRAD(atan(luaL_check_number(L, 1))));
lua_Number y = luaL_checknumber(L, 1);
lua_Number x = luaL_optnumber(L, 2, 1);
lua_pushnumber(L, l_mathop(atan2)(y, x));
return 1;
}
static int math_atan2 (lua_State *L) {
lua_pushnumber(L, FROMRAD(atan2(luaL_check_number(L, 1), luaL_check_number(L, 2))));
static int math_toint (lua_State *L) {
int valid;
lua_Integer n = lua_tointegerx(L, 1, &valid);
if (valid)
lua_pushinteger(L, n);
else {
luaL_checkany(L, 1);
luaL_pushfail(L); /* value is not convertible to integer */
}
return 1;
}
static int math_ceil (lua_State *L) {
lua_pushnumber(L, ceil(luaL_check_number(L, 1)));
return 1;
static void pushnumint (lua_State *L, lua_Number d) {
lua_Integer n;
if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */
lua_pushinteger(L, n); /* result is integer */
else
lua_pushnumber(L, d); /* result is float */
}
static int math_floor (lua_State *L) {
lua_pushnumber(L, floor(luaL_check_number(L, 1)));
if (lua_isinteger(L, 1))
lua_settop(L, 1); /* integer is its own floor */
else {
lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1));
pushnumint(L, d);
}
return 1;
}
static int math_mod (lua_State *L) {
lua_pushnumber(L, fmod(luaL_check_number(L, 1), luaL_check_number(L, 2)));
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, sqrt(luaL_check_number(L, 1)));
lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1)));
return 1;
}
static int math_pow (lua_State *L) {
lua_pushnumber(L, pow(luaL_check_number(L, 1), luaL_check_number(L, 2)));
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_pushnumber(L, log(luaL_check_number(L, 1)));
return 1;
}
static int math_log10 (lua_State *L) {
lua_pushnumber(L, log10(luaL_check_number(L, 1)));
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 !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, exp(luaL_check_number(L, 1)));
lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1)));
return 1;
}
static int math_deg (lua_State *L) {
lua_pushnumber(L, luaL_check_number(L, 1)/RADIANS_PER_DEGREE);
lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI));
return 1;
}
static int math_rad (lua_State *L) {
lua_pushnumber(L, luaL_check_number(L, 1)*RADIANS_PER_DEGREE);
lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0)));
return 1;
}
static int math_frexp (lua_State *L) {
int e;
lua_pushnumber(L, frexp(luaL_check_number(L, 1), &e));
lua_pushnumber(L, e);
return 2;
}
static int math_ldexp (lua_State *L) {
lua_pushnumber(L, ldexp(luaL_check_number(L, 1), luaL_check_int(L, 2)));
return 1;
}
static int math_min (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmin = luaL_check_number(L, 1);
int imin = 1; /* index of current minimum value */
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_check_number(L, i);
if (d < dmin)
dmin = d;
luaL_argcheck(L, n >= 1, 1, "value expected");
for (i = 2; i <= n; i++) {
if (lua_compare(L, i, imin, LUA_OPLT))
imin = i;
}
lua_pushnumber(L, dmin);
lua_pushvalue(L, imin);
return 1;
}
static int math_max (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
lua_Number dmax = luaL_check_number(L, 1);
int imax = 1; /* index of current maximum value */
int i;
for (i=2; i<=n; i++) {
lua_Number d = luaL_check_number(L, i);
if (d > dmax)
dmax = d;
luaL_argcheck(L, n >= 1, 1, "value expected");
for (i = 2; i <= n; i++) {
if (lua_compare(L, imax, i, LUA_OPLT))
imax = i;
}
lua_pushnumber(L, dmax);
lua_pushvalue(L, imax);
return 1;
}
static int math_type (lua_State *L) {
if (lua_type(L, 1) == LUA_TNUMBER)
lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float");
else {
luaL_checkany(L, 1);
luaL_pushfail(L);
}
return 1;
}
/*
** {==================================================================
** Pseudo-Random Number Generator based on 'xoshiro256**'.
** ===================================================================
*/
/* number of binary digits in the mantissa of a float */
#define FIGS l_floatatt(MANT_DIG)
#if FIGS > 64
/* there are only 64 random bits; use them all */
#undef FIGS
#define FIGS 64
#endif
/*
** LUA_RAND32 forces the use of 32-bit integers in the implementation
** of the PRN generator (mainly for testing).
*/
#if !defined(LUA_RAND32) && !defined(Rand64)
/* try to find an integer type with at least 64 bits */
#if (ULONG_MAX >> 31 >> 31) >= 3
/* 'long' has at least 64 bits */
#define Rand64 unsigned long
#elif !defined(LUA_USE_C89) && defined(LLONG_MAX)
/* there is a 'long long' type (which must have at least 64 bits) */
#define Rand64 unsigned long long
#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3
/* 'lua_Integer' has at least 64 bits */
#define Rand64 lua_Unsigned
#endif
#endif
#if defined(Rand64) /* { */
/*
** Standard implementation, using 64-bit integers.
** If 'Rand64' has more than 64 bits, the extra bits do not interfere
** with the 64 initial bits, except in a right shift. Moreover, the
** final result has to discard the extra bits.
*/
/* avoid using extra bits when needed */
#define trim64(x) ((x) & 0xffffffffffffffffu)
/* rotate left 'x' by 'n' bits */
static Rand64 rotl (Rand64 x, int n) {
return (x << n) | (trim64(x) >> (64 - n));
}
static Rand64 nextrand (Rand64 *state) {
Rand64 state0 = state[0];
Rand64 state1 = state[1];
Rand64 state2 = state[2] ^ state0;
Rand64 state3 = state[3] ^ state1;
Rand64 res = rotl(state1 * 5, 7) * 9;
state[0] = state0 ^ state3;
state[1] = state1 ^ state2;
state[2] = state2 ^ (state1 << 17);
state[3] = rotl(state3, 45);
return res;
}
/* must take care to not shift stuff by more than 63 slots */
/*
** Convert bits from a random integer into a float in the
** interval [0,1), getting the higher FIG bits from the
** random unsigned integer and converting that to a float.
*/
/* must throw out the extra (64 - FIGS) bits */
#define shift64_FIG (64 - FIGS)
/* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */
#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
static lua_Number I2d (Rand64 x) {
return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG;
}
/* convert a 'Rand64' to a 'lua_Unsigned' */
#define I2UInt(x) ((lua_Unsigned)trim64(x))
/* convert a 'lua_Unsigned' to a 'Rand64' */
#define Int2I(x) ((Rand64)(x))
#else /* no 'Rand64' }{ */
/* get an integer with at least 32 bits */
#if LUAI_IS32INT
typedef unsigned int lu_int32;
#else
typedef unsigned long lu_int32;
#endif
/*
** Use two 32-bit integers to represent a 64-bit quantity.
*/
typedef struct Rand64 {
lu_int32 h; /* higher half */
lu_int32 l; /* lower half */
} Rand64;
/*
** If 'lu_int32' has more than 32 bits, the extra bits do not interfere
** with the 32 initial bits, except in a right shift and comparisons.
** Moreover, the final result has to discard the extra bits.
*/
/* avoid using extra bits when needed */
#define trim32(x) ((x) & 0xffffffffu)
/*
** basic operations on 'Rand64' values
*/
/* build a new Rand64 value */
static Rand64 packI (lu_int32 h, lu_int32 l) {
Rand64 result;
result.h = h;
result.l = l;
return result;
}
/* return i << n */
static Rand64 Ishl (Rand64 i, int n) {
lua_assert(n > 0 && n < 32);
return packI((i.h << n) | (trim32(i.l) >> (32 - n)), i.l << n);
}
/* i1 ^= i2 */
static void Ixor (Rand64 *i1, Rand64 i2) {
i1->h ^= i2.h;
i1->l ^= i2.l;
}
/* return i1 + i2 */
static Rand64 Iadd (Rand64 i1, Rand64 i2) {
Rand64 result = packI(i1.h + i2.h, i1.l + i2.l);
if (trim32(result.l) < trim32(i1.l)) /* carry? */
result.h++;
return result;
}
/* return i * 5 */
static Rand64 times5 (Rand64 i) {
return Iadd(Ishl(i, 2), i); /* i * 5 == (i << 2) + i */
}
/* return i * 9 */
static Rand64 times9 (Rand64 i) {
return Iadd(Ishl(i, 3), i); /* i * 9 == (i << 3) + i */
}
/* return 'i' rotated left 'n' bits */
static Rand64 rotl (Rand64 i, int n) {
lua_assert(n > 0 && n < 32);
return packI((i.h << n) | (trim32(i.l) >> (32 - n)),
(trim32(i.h) >> (32 - n)) | (i.l << n));
}
/* for offsets larger than 32, rotate right by 64 - offset */
static Rand64 rotl1 (Rand64 i, int n) {
lua_assert(n > 32 && n < 64);
n = 64 - n;
return packI((trim32(i.h) >> n) | (i.l << (32 - n)),
(i.h << (32 - n)) | (trim32(i.l) >> n));
}
/*
** implementation of 'xoshiro256**' algorithm on 'Rand64' values
*/
static Rand64 nextrand (Rand64 *state) {
Rand64 res = times9(rotl(times5(state[1]), 7));
Rand64 t = Ishl(state[1], 17);
Ixor(&state[2], state[0]);
Ixor(&state[3], state[1]);
Ixor(&state[1], state[2]);
Ixor(&state[0], state[3]);
Ixor(&state[2], t);
state[3] = rotl1(state[3], 45);
return res;
}
/*
** Converts a 'Rand64' into a float.
*/
/* an unsigned 1 with proper type */
#define UONE ((lu_int32)1)
#if FIGS <= 32
/* 2^(-FIGS) */
#define scaleFIG (l_mathop(0.5) / (UONE << (FIGS - 1)))
/*
** get up to 32 bits from higher half, shifting right to
** throw out the extra bits.
*/
static lua_Number I2d (Rand64 x) {
lua_Number h = (lua_Number)(trim32(x.h) >> (32 - FIGS));
return h * scaleFIG;
}
#else /* 32 < FIGS <= 64 */
/* must take care to not shift stuff by more than 31 slots */
/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
#define scaleFIG \
((lua_Number)1.0 / (UONE << 30) / 8.0 / (UONE << (FIGS - 33)))
/*
** use FIGS - 32 bits from lower half, throwing out the other
** (32 - (FIGS - 32)) = (64 - FIGS) bits
*/
#define shiftLOW (64 - FIGS)
/*
** higher 32 bits go after those (FIGS - 32) bits: shiftHI = 2^(FIGS - 32)
*/
#define shiftHI ((lua_Number)(UONE << (FIGS - 33)) * 2.0)
static lua_Number I2d (Rand64 x) {
lua_Number h = (lua_Number)trim32(x.h) * shiftHI;
lua_Number l = (lua_Number)(trim32(x.l) >> shiftLOW);
return (h + l) * scaleFIG;
}
#endif
/* convert a 'Rand64' to a 'lua_Unsigned' */
static lua_Unsigned I2UInt (Rand64 x) {
return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l);
}
/* convert a 'lua_Unsigned' to a 'Rand64' */
static Rand64 Int2I (lua_Unsigned n) {
return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n);
}
#endif /* } */
/*
** A state uses four 'Rand64' values.
*/
typedef struct {
Rand64 s[4];
} RanState;
/*
** Project the random integer 'ran' into the interval [0, n].
** Because 'ran' has 2^B possible values, the projection can only be
** uniform when the size of the interval is a power of 2 (exact
** division). Otherwise, to get a uniform projection into [0, n], we
** first compute 'lim', the smallest Mersenne number not smaller than
** 'n'. We then project 'ran' into the interval [0, lim]. If the result
** is inside [0, n], we are done. Otherwise, we try with another 'ran',
** until we have a result inside the interval.
*/
static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n,
RanState *state) {
if ((n & (n + 1)) == 0) /* is 'n + 1' a power of 2? */
return ran & n; /* no bias */
else {
lua_Unsigned lim = n;
/* compute the smallest (2^b - 1) not smaller than 'n' */
lim |= (lim >> 1);
lim |= (lim >> 2);
lim |= (lim >> 4);
lim |= (lim >> 8);
lim |= (lim >> 16);
#if (LUA_MAXUNSIGNED >> 31) >= 3
lim |= (lim >> 32); /* integer type has more than 32 bits */
#endif
lua_assert((lim & (lim + 1)) == 0 /* 'lim + 1' is a power of 2, */
&& lim >= n /* not smaller than 'n', */
&& (lim >> 1) < n); /* and it is the smallest one */
while ((ran &= lim) > n) /* project 'ran' into [0..lim] */
ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */
return ran;
}
}
static int math_random (lua_State *L) {
/* the `%' avoids the (rare) case of r==1, and is needed also because on
some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
lua_Integer low, up;
lua_Unsigned p;
RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
Rand64 rv = nextrand(state->s); /* next pseudo-random value */
switch (lua_gettop(L)) { /* check number of arguments */
case 0: { /* no arguments */
lua_pushnumber(L, r); /* Number between 0 and 1 */
break;
lua_pushnumber(L, I2d(rv)); /* float between 0 and 1 */
return 1;
}
case 1: { /* only upper limit */
int u = luaL_check_int(L, 1);
luaL_arg_check(L, 1<=u, 1, "interval is empty");
lua_pushnumber(L, (int)floor(r*u)+1); /* int between 1 and `u' */
low = 1;
up = luaL_checkinteger(L, 1);
if (up == 0) { /* single 0 as argument? */
lua_pushinteger(L, I2UInt(rv)); /* full random integer */
return 1;
}
break;
}
case 2: { /* lower and upper limits */
int l = luaL_check_int(L, 1);
int u = luaL_check_int(L, 2);
luaL_arg_check(L, l<=u, 2, "interval is empty");
lua_pushnumber(L, (int)floor(r*(u-l+1))+l); /* int between `l' and `u' */
low = luaL_checkinteger(L, 1);
up = luaL_checkinteger(L, 2);
break;
}
default: return luaL_error(L, "wrong number of arguments");
}
/* random integer in the interval [low, up] */
luaL_argcheck(L, low <= up, 1, "interval is empty");
/* project random integer into the interval [0, up - low] */
p = project(I2UInt(rv), (lua_Unsigned)up - (lua_Unsigned)low, state);
lua_pushinteger(L, p + (lua_Unsigned)low);
return 1;
}
static int math_randomseed (lua_State *L) {
srand(luaL_check_int(L, 1));
return 0;
static void setseed (lua_State *L, Rand64 *state,
lua_Unsigned n1, lua_Unsigned n2) {
int i;
state[0] = Int2I(n1);
state[1] = Int2I(0xff); /* avoid a zero state */
state[2] = Int2I(n2);
state[3] = Int2I(0);
for (i = 0; i < 16; i++)
nextrand(state); /* discard initial values to "spread" seed */
lua_pushinteger(L, n1);
lua_pushinteger(L, n2);
}
static const luaL_reg mathlib[] = {
/*
** Set a "random" seed. To get some randomness, use the current time
** and the address of 'L' (in case the machine does address space layout
** randomization).
*/
static void randseed (lua_State *L, RanState *state) {
lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
setseed(L, state->s, seed1, seed2);
}
static int math_randomseed (lua_State *L) {
RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
if (lua_isnone(L, 1)) {
randseed(L, state);
}
else {
lua_Integer n1 = luaL_checkinteger(L, 1);
lua_Integer n2 = luaL_optinteger(L, 2, 0);
setseed(L, state->s, n1, n2);
}
return 2; /* return seeds */
}
static const luaL_Reg randfuncs[] = {
{"random", math_random},
{"randomseed", math_randomseed},
{NULL, NULL}
};
/*
** Register the random functions and initialize their state.
*/
static void setrandfunc (lua_State *L) {
RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
randseed(L, state); /* initialize with a "random" seed */
lua_pop(L, 2); /* remove pushed seeds */
luaL_setfuncs(L, randfuncs, 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},
{"sin", math_sin},
{"cos", math_cos},
{"tan", math_tan},
{"asin", math_asin},
{"acos", math_acos},
{"asin", math_asin},
{"atan", math_atan},
{"atan2", math_atan2},
{"ceil", math_ceil},
{"cos", math_cos},
{"deg", math_deg},
{"exp", math_exp},
{"tointeger", math_toint},
{"floor", math_floor},
{"mod", math_mod},
{"fmod", math_fmod},
{"ult", math_ult},
{"log", math_log},
{"max", math_max},
{"min", math_min},
{"modf", math_modf},
{"rad", math_rad},
{"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},
{"sqrt", math_sqrt},
{"min", math_min},
{"max", math_max},
{"log", math_log},
{"log10", math_log10},
{"exp", math_exp},
{"deg", math_deg},
{"pow", math_pow},
{"rad", math_rad},
{"random", math_random},
{"randomseed", math_randomseed},
#endif
/* placeholders */
{"random", NULL},
{"randomseed", NULL},
{"pi", NULL},
{"huge", NULL},
{"maxinteger", NULL},
{"mininteger", NULL},
{NULL, NULL}
};
@@ -231,17 +747,17 @@ static const luaL_reg mathlib[] = {
/*
** Open math library
*/
LUALIB_API int lua_mathlibopen (lua_State *L) {
lua_pushliteral(L, LUA_MATHLIBNAME);
lua_newtable(L);
luaL_openlib(L, mathlib, 0);
lua_pushliteral(L, "pi");
LUAMOD_API int luaopen_math (lua_State *L) {
luaL_newlib(L, mathlib);
lua_pushnumber(L, PI);
lua_settable(L, -3);
lua_settable(L, LUA_GLOBALSINDEX);
lua_pushliteral(L, "__pow");
lua_pushcfunction(L, math_pow);
lua_settable(L, LUA_REGISTRYINDEX);
return 0;
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");
setrandfunc(L);
return 1;
}
+168 -45
View File
@@ -1,79 +1,202 @@
/*
** $Id: lmem.c,v 1.56 2002/06/11 16:23:47 roberto Exp roberto $
** $Id: lmem.c $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
#define lmem_c
#define LUA_CORE
#include <stdlib.h>
#include "lprefix.h"
#include <stddef.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#if defined(HARDMEMTESTS)
/*
** definition for realloc function. It must assure that
** l_realloc(block, x, 0) frees the block, and l_realloc(NULL, 0, x)
** allocates a new block (ANSI C assures that).
** (`os' is the old block size; some allocators may use that.)
** First allocation will fail whenever not building initial state
** and not shrinking a block. (This fail will trigger 'tryagain' and
** a full GC cycle at every allocation.)
*/
#ifndef l_realloc
#define l_realloc(b,os,s) realloc(b,s)
static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
if (ttisnil(&g->nilvalue) && ns > os)
return NULL; /* fail */
else /* normal allocation */
return (*g->frealloc)(g->ud, block, os, ns);
}
#else
#define firsttry(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns))
#endif
/*
** 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, p, x, 0) frees the block 'p' and returns NULL.
** Particularly, frealloc(ud, NULL, 0, 0) does nothing,
** which is equivalent to free(NULL) in ISO C.
**
** - frealloc(ud, NULL, x, s) creates a new block of size 's'
** (no matter 'x'). Returns NULL if it cannot create the new block.
**
** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from
** size 'x' to size 'y'. Returns NULL if it cannot reallocate the
** block to the new size.
*/
/*
** {==================================================================
** Functions to allocate/deallocate arrays for the Parser
** ===================================================================
*/
/*
** Minimum size for arrays during parsing, to avoid overhead of
** reallocating to size 1, then 2, and then 4. All these arrays
** will be reallocated to exact sizes or erased when parsing ends.
*/
#define MINSIZEARRAY 4
void *luaM_growaux (lua_State *L, void *block, int *size, int size_elems,
int limit, const char *errormsg) {
void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
int size_elems, int limit, const char *what) {
void *newblock;
int newsize = (*size)*2;
if (newsize < MINSIZEARRAY)
newsize = MINSIZEARRAY; /* minimum size */
else if (*size >= limit/2) { /* cannot double it? */
if (*size < limit - MINSIZEARRAY) /* try something smaller... */
newsize = limit; /* still have at least MINSIZEARRAY free places */
else luaG_runerror(L, errormsg);
int size = *psize;
if (nelems + 1 <= size) /* does one extra element still fit? */
return block; /* nothing to be done */
if (size >= limit / 2) { /* cannot double it? */
if (unlikely(size >= limit)) /* cannot grow even a little? */
luaG_runerror(L, "too many %s (limit is %d)", what, limit);
size = limit; /* still have at least one free place */
}
newblock = luaM_realloc(L, block,
cast(lu_mem, *size)*cast(lu_mem, size_elems),
cast(lu_mem, newsize)*cast(lu_mem, size_elems));
*size = newsize; /* update only when everything else is OK */
else {
size *= 2;
if (size < MINSIZEARRAY)
size = MINSIZEARRAY; /* minimum size */
}
lua_assert(nelems + 1 <= size && size <= limit);
/* 'limit' ensures that multiplication will not overflow */
newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems,
cast_sizet(size) * size_elems);
*psize = size; /* update only when everything else is OK */
return newblock;
}
/*
** generic allocation routine.
** In prototypes, the size of the array is also its number of
** elements (to save memory). So, if it cannot shrink an array
** to its number of elements, the only option is to raise an
** error.
*/
void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) {
if (size == 0) {
if (block != NULL) {
l_realloc(block, oldsize, size);
block = NULL;
}
}
else if (size >= MAX_SIZET)
luaG_runerror(L, "memory allocation error: block too big");
else {
block = l_realloc(block, oldsize, size);
if (block == NULL) {
if (L)
luaD_throw(L, LUA_ERRMEM);
else return NULL; /* error before creating state! */
}
}
if (L && G(L)) {
G(L)->nblocks -= oldsize;
G(L)->nblocks += size;
}
return block;
void *luaM_shrinkvector_ (lua_State *L, void *block, int *size,
int final_n, int size_elem) {
void *newblock;
size_t oldsize = cast_sizet((*size) * size_elem);
size_t newsize = cast_sizet(final_n * size_elem);
lua_assert(newsize <= oldsize);
newblock = luaM_saferealloc_(L, block, oldsize, newsize);
*size = final_n;
return newblock;
}
/* }================================================================== */
l_noret luaM_toobig (lua_State *L) {
luaG_runerror(L, "memory allocation error: block too big");
}
/*
** Free memory
*/
void luaM_free_ (lua_State *L, void *block, size_t osize) {
global_State *g = G(L);
lua_assert((osize == 0) == (block == NULL));
(*g->frealloc)(g->ud, block, osize, 0);
g->GCdebt -= osize;
}
/*
** In case of allocation fail, this function will call the GC to try
** to free some memory and then try the allocation again.
** (It should not be called when shrinking a block, because then the
** interpreter may be in the middle of a collection step.)
*/
static void *tryagain (lua_State *L, void *block,
size_t osize, size_t nsize) {
global_State *g = G(L);
if (ttisnil(&g->nilvalue)) { /* is state fully build? */
luaC_fullgc(L, 1); /* try to free some memory... */
return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
}
else return NULL; /* cannot free any memory without a full state */
}
/*
** Generic allocation routine.
** If allocation fails while shrinking a block, do not try again; the
** GC shrinks some blocks and it is not reentrant.
*/
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
void *newblock;
global_State *g = G(L);
lua_assert((osize == 0) == (block == NULL));
newblock = firsttry(g, block, osize, nsize);
if (unlikely(newblock == NULL && nsize > 0)) {
if (nsize > osize) /* not shrinking a block? */
newblock = tryagain(L, block, osize, nsize);
if (newblock == NULL) /* still no memory? */
return NULL; /* do not update 'GCdebt' */
}
lua_assert((nsize == 0) == (newblock == NULL));
g->GCdebt = (g->GCdebt + nsize) - osize;
return newblock;
}
void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
size_t nsize) {
void *newblock = luaM_realloc_(L, block, osize, nsize);
if (unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */
luaM_error(L);
return newblock;
}
void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
if (size == 0)
return NULL; /* that's all */
else {
global_State *g = G(L);
void *newblock = firsttry(g, NULL, tag, size);
if (unlikely(newblock == NULL)) {
newblock = tryagain(L, NULL, tag, size);
if (newblock == NULL)
luaM_error(L);
}
g->GCdebt += size;
return newblock;
}
}
+66 -17
View File
@@ -1,5 +1,5 @@
/*
** $Id: lmem.h,v 1.25 2001/11/28 20:13:13 roberto Exp roberto $
** $Id: lmem.h $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -13,32 +13,81 @@
#include "llimits.h"
#include "lua.h"
#define MEMERRMSG "not enough memory"
#define luaM_error(L) luaD_throw(L, LUA_ERRMEM)
void *luaM_realloc (lua_State *L, void *oldblock, lu_mem oldsize, lu_mem size);
/*
** This macro tests whether it is safe to multiply 'n' by the size of
** type 't' without overflows. Because 'e' is always constant, it avoids
** the runtime division MAX_SIZET/(e).
** (The macro is somewhat complex to avoid warnings: The 'sizeof'
** comparison avoids a runtime comparison when overflow cannot occur.
** The compiler should be able to optimize the real test by itself, but
** when it does it, it may give a warning about "comparison is always
** false due to limited range of data type"; the +1 tricks the compiler,
** avoiding this warning but also this optimization.)
*/
#define luaM_testsize(n,e) \
(sizeof(n) >= sizeof(size_t) && cast_sizet((n)) + 1 > MAX_SIZET/(e))
void *luaM_growaux (lua_State *L, void *block, int *size, int size_elem,
int limit, const char *errormsg);
#define luaM_checksize(L,n,e) \
(luaM_testsize(n,e) ? luaM_toobig(L) : cast_void(0))
#define luaM_free(L, b, s) luaM_realloc(L, (b), (s), 0)
#define luaM_freelem(L, b) luaM_realloc(L, (b), sizeof(*(b)), 0)
#define luaM_freearray(L, b, n, t) luaM_realloc(L, (b), \
cast(lu_mem, n)*cast(lu_mem, sizeof(t)), 0)
#define luaM_malloc(L, t) luaM_realloc(L, NULL, 0, (t))
#define luaM_new(L, t) cast(t *, luaM_malloc(L, sizeof(t)))
#define luaM_newvector(L, n,t) cast(t *, luaM_malloc(L, \
cast(lu_mem, n)*cast(lu_mem, sizeof(t))))
/*
** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that
** the result is not larger than 'n' and cannot overflow a 'size_t'
** when multiplied by the size of type 't'. (Assumes that 'n' is an
** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.)
*/
#define luaM_limitN(n,t) \
((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \
cast_uint((MAX_SIZET/sizeof(t))))
/*
** Arrays of chars do not need any test
*/
#define luaM_reallocvchar(L,b,on,n) \
cast_charp(luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s))
#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b)))
#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b)))
#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0))
#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0))
#define luaM_newvectorchecked(L,n,t) \
(luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t))
#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag)
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
if (((nelems)+1) > (size)) \
((v)=cast(t *, luaM_growaux(L,v,&(size),sizeof(t),limit,e)))
((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \
luaM_limitN(limit,t),e)))
#define luaM_reallocvector(L, v,oldn,n,t) \
((v)=cast(t *, luaM_realloc(L, v,cast(lu_mem, oldn)*cast(lu_mem, sizeof(t)), \
cast(lu_mem, n)*cast(lu_mem, sizeof(t)))))
(cast(t *, luaM_realloc_(L, v, cast_sizet(oldn) * sizeof(t), \
cast_sizet(n) * sizeof(t))))
#define luaM_shrinkvector(L,v,size,fs,t) \
((v)=cast(t *, luaM_shrinkvector_(L, v, &(size), fs, sizeof(t))))
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
/* not to be called directly */
LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
size_t size);
LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize,
size_t size);
LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize);
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems,
int *size, int size_elem, int limit,
const char *what);
LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem,
int final_n, int size_elem);
LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag);
#endif
+759
View File
@@ -0,0 +1,759 @@
/*
** $Id: loadlib.c $
** 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** LUA_IGMARK is a mark to ignore all before it when building the
** luaopen_ function name.
*/
#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 "_"
/*
** key for table in the registry that keeps handles
** for all loaded C libraries
*/
static const char *const CLIBS = "_CLIBS";
#define LIB_FAIL "open"
#define setprogdir(L) ((void)0)
/*
** Special type equivalent to '(void*)' for functions in gcc
** (to suppress warnings when converting function pointers)
*/
typedef void (*voidf)(void);
/*
** 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 <dlfcn.h>
/*
** 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 <windows.h>
/*
** 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); /* get exec. name */
if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL)
luaL_error(L, "unable to get ModuleFileName");
else {
*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)(voidf)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
/*
** 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 *dftmark;
const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX);
const char *path = getenv(nver); /* try versioned name */
if (path == NULL) /* no versioned environment variable? */
path = getenv(envname); /* try unversioned name */
if (path == NULL || noenv(L)) /* no environment variable? */
lua_pushstring(L, dft); /* use default */
else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL)
lua_pushstring(L, path); /* nothing to change */
else { /* path contains a ";;": insert default path in its place */
size_t len = strlen(path);
luaL_Buffer b;
luaL_buffinit(L, &b);
if (path < dftmark) { /* is there a prefix before ';;'? */
luaL_addlstring(&b, path, dftmark - path); /* add it */
luaL_addchar(&b, *LUA_PATH_SEP);
}
luaL_addstring(&b, dft); /* add default */
if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */
luaL_addchar(&b, *LUA_PATH_SEP);
luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark);
}
luaL_pushresult(&b);
}
setprogdir(L);
lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */
lua_pop(L, 1); /* pop versioned variable name ('nver') */
}
/* }================================================================== */
/*
** return registry.CLIBS[path]
*/
static void *checkclib (lua_State *L, const char *path) {
void *plib;
lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
lua_getfield(L, -1, path);
plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
lua_pop(L, 2); /* pop CLIBS table and 'plib' */
return plib;
}
/*
** 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_getfield(L, LUA_REGISTRYINDEX, CLIBS);
lua_pushlightuserdata(L, plib);
lua_pushvalue(L, -1);
lua_setfield(L, -3, path); /* CLIBS[path] = plib */
lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
lua_pop(L, 1); /* pop CLIBS table */
}
/*
** __gc tag method 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 */
luaL_pushfail(L);
lua_insert(L, -2);
lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init");
return 3; /* return fail, 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;
}
/*
** Get the next name in '*path' = 'name1;name2;name3;...', changing
** the ending ';' to '\0' to create a zero-terminated string. Return
** NULL when list ends.
*/
static const char *getnextfilename (char **path, char *end) {
char *sep;
char *name = *path;
if (name == end)
return NULL; /* no more names */
else if (*name == '\0') { /* from previous iteration? */
*name = *LUA_PATH_SEP; /* restore separator */
name++; /* skip it */
}
sep = strchr(name, *LUA_PATH_SEP); /* find next separator */
if (sep == NULL) /* separator not found? */
sep = end; /* name goes until the end */
*sep = '\0'; /* finish file name */
*path = sep; /* will start next search from here */
return name;
}
/*
** Given a path such as ";blabla.so;blublu.so", pushes the string
**
** no file 'blabla.so'
** no file 'blublu.so'
*/
static void pusherrornotfound (lua_State *L, const char *path) {
luaL_Buffer b;
luaL_buffinit(L, &b);
luaL_addstring(&b, "no file '");
luaL_addgsub(&b, path, LUA_PATH_SEP, "'\n\tno file '");
luaL_addstring(&b, "'");
luaL_pushresult(&b);
}
static const char *searchpath (lua_State *L, const char *name,
const char *path,
const char *sep,
const char *dirsep) {
luaL_Buffer buff;
char *pathname; /* path with name inserted */
char *endpathname; /* its end */
const char *filename;
/* separator is non-empty and appears in 'name'? */
if (*sep != '\0' && strchr(name, *sep) != NULL)
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
luaL_buffinit(L, &buff);
/* add path to the buffer, replacing marks ('?') with the file name */
luaL_addgsub(&buff, path, LUA_PATH_MARK, name);
luaL_addchar(&buff, '\0');
pathname = luaL_buffaddr(&buff); /* writable list of file names */
endpathname = pathname + luaL_bufflen(&buff) - 1;
while ((filename = getnextfilename(&pathname, endpathname)) != NULL) {
if (readable(filename)) /* does file exist and is readable? */
return lua_pushstring(L, filename); /* save and return name */
}
luaL_pushresult(&buff); /* push path to create error message */
pusherrornotfound(L, lua_tostring(L, -1)); /* 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 */
luaL_pushfail(L);
lua_insert(L, -2);
return 2; /* return fail + 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, "no 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, LUA_PRELOAD_TABLE);
if (lua_getfield(L, -1, name) == LUA_TNIL) { /* not found? */
lua_pushfstring(L, "no field package.preload['%s']", name);
return 1;
}
else {
lua_pushliteral(L, ":preload:");
return 2;
}
}
static void findloader (lua_State *L, const char *name) {
int i;
luaL_Buffer msg; /* to build error message */
/* 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");
luaL_buffinit(L, &msg);
/* iterate over available searchers to find a loader */
for (i = 1; ; i++) {
luaL_addstring(&msg, "\n\t"); /* error-message prefix */
if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */
lua_pop(L, 1); /* remove nil */
luaL_buffsub(&msg, 2); /* remove prefix */
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 { /* no error message */
lua_pop(L, 2); /* remove both returns */
luaL_buffsub(&msg, 2); /* remove prefix */
}
}
}
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, 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_rotate(L, -2, 1); /* function <-> loader data */
lua_pushvalue(L, 1); /* name is 1st argument to module loader */
lua_pushvalue(L, -3); /* loader data is 2nd argument */
/* stack: ...; loader data; loader function; mod. name; loader data */
lua_call(L, 2, 1); /* run loader to load module */
/* stack: ...; loader data; result from loader */
if (!lua_isnil(L, -1)) /* non-nil return? */
lua_setfield(L, 2, name); /* LOADED[name] = returned value */
else
lua_pop(L, 1); /* pop nil */
if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */
lua_pushboolean(L, 1); /* use true as result */
lua_copy(L, -1, -2); /* replace loader result */
lua_setfield(L, 2, name); /* LOADED[name] = true */
}
lua_rotate(L, -2, 1); /* loader data <-> module result */
return 2; /* return module result and loader data */
}
/* }====================================================== */
static const luaL_Reg pk_funcs[] = {
{"loadlib", ll_loadlib},
{"searchpath", ll_searchpath},
/* placeholders */
{"preload", NULL},
{"cpath", NULL},
{"path", NULL},
{"searchers", NULL},
{"loaded", NULL},
{NULL, NULL}
};
static const luaL_Reg ll_funcs[] = {
{"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 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);
}
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) {
luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* 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);
}
LUAMOD_API int luaopen_package (lua_State *L) {
createclibstable(L);
luaL_newlib(L, pk_funcs); /* create 'package' table */
createsearcherstable(L);
/* 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, LUA_LOADED_TABLE);
lua_setfield(L, -2, "loaded");
/* set field '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 */
}
+528 -140
View File
@@ -1,16 +1,26 @@
/*
** $Id: lobject.c,v 1.85 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: lobject.c $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
#include <ctype.h>
#define lobject_c
#define LUA_CORE
#include "lprefix.h"
#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lctype.h"
#include "ldebug.h"
#include "ldo.h"
#include "lmem.h"
#include "lobject.h"
@@ -19,134 +29,501 @@
#include "lvm.h"
/* function to convert a string to a lua_Number */
#ifndef lua_str2number
#define lua_str2number(s,p) strtod((s), (p))
/*
** Computes ceil(log2(x))
*/
int luaO_ceillog2 (unsigned int x) {
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_idiv(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: return luaV_modf(L, v1, v2);
default: lua_assert(0); return 0;
}
}
int luaO_rawarith (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 (tointegerns(p1, &i1) && tointegerns(p2, &i2)) {
setivalue(res, intarith(L, op, i1, i2));
return 1;
}
else return 0; /* fail */
}
case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */
lua_Number n1; lua_Number n2;
if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
setfltvalue(res, numarith(L, op, n1, n2));
return 1;
}
else return 0; /* fail */
}
default: { /* other operations */
lua_Number n1; lua_Number n2;
if (ttisinteger(p1) && ttisinteger(p2)) {
setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
return 1;
}
else if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
setfltvalue(res, numarith(L, op, n1, n2));
return 1;
}
else return 0; /* fail */
}
}
}
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
StkId res) {
if (!luaO_rawarith(L, op, p1, p2, s2v(res))) {
/* could not perform raw operation; try metamethod */
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;
}
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)
/* maximum number of significant digits to read (to avoid overflows
even with single floats) */
#define MAXSIGDIG 30
/*
** convert a 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 hasdot = 0; /* true after seen a dot */
*endptr = cast_charp(s); /* nothing is valid yet */
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
neg = isneg(&s); /* check sign */
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 == dot) {
if (hasdot) break; /* second dot? stop loop */
else hasdot = 1;
}
else if (lisxdigit(cast_uchar(*s))) {
if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */
nosigdig++;
else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */
r = (r * cast_num(16.0)) + luaO_hexavalue(*s);
else e++; /* too many digits; ignore, but still count for exponent */
if (hasdot) e--; /* decimal digit? correct exponent */
}
else break; /* neither a dot nor a digit */
}
if (nosigdig + sigdig == 0) /* no digits? */
return 0.0; /* invalid format */
*endptr = cast_charp(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 sign */
s++; /* skip 'p' */
neg1 = isneg(&s); /* sign */
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_charp(s); /* valid up to here */
}
if (neg) r = -r;
return l_mathop(ldexp)(r, e);
}
#endif
/* }====================================================== */
/* maximum length of a numeral */
#if !defined (L_MAXLENNUM)
#define L_MAXLENNUM 200
#endif
const TObject luaO_nilobject = {LUA_TNIL, {NULL}};
int luaO_log2 (unsigned int x) {
static const lu_byte log_8[255] = {
0,
1,1,
2,2,2,2,
3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,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,
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,
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
};
if (x >= 0x00010000) {
if (x >= 0x01000000) return log_8[((x>>24) & 0xff) - 1]+24;
else return log_8[((x>>16) & 0xff) - 1]+16;
}
else {
if (x >= 0x00000100) return log_8[((x>>8) & 0xff) - 1]+8;
else if (x) return log_8[(x & 0xff) - 1];
return -1; /* special `log' for 0 */
}
}
int luaO_rawequalObj (const TObject *t1, const TObject *t2) {
if (ttype(t1) != ttype(t2)) return 0;
switch (ttype(t1)) {
case LUA_TNUMBER:
return nvalue(t1) == nvalue(t2);
case LUA_TNIL:
return 1;
case LUA_TSTRING:
return tsvalue(t1) == tsvalue(t2);
case LUA_TBOOLEAN:
return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
case LUA_TLIGHTUSERDATA:
return pvalue(t1) == pvalue(t2);
case LUA_TUSERDATA:
return uvalue(t1) == uvalue(t2);
case LUA_TTABLE:
return hvalue(t1) == hvalue(t2);
case LUA_TFUNCTION:
return clvalue(t1) == clvalue(t2);
}
lua_assert(0);
return 0; /* to avoid warnings */
}
void *luaO_openspaceaux (lua_State *L, size_t n) {
if (n > G(L)->Mbuffsize) {
G(L)->Mbuffer = luaM_realloc(L, G(L)->Mbuffer, G(L)->Mbuffsize, n);
G(L)->Mbuffsize = n;
}
return G(L)->Mbuffer;
}
int luaO_str2d (const char *s, lua_Number *result) {
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
char *endptr;
lua_Number res = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* no conversion */
while (isspace((unsigned char)(*endptr))) endptr++;
if (*endptr != '\0') return 0; /* invalid trailing characters? */
*result = res;
return 1;
*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 a 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 conversion fails, it may mean number has a dot but
** locale accepts something else. In that case, the code copies 's'
** to a buffer (because 's' is read-only), changes the dot to the
** current locale radix mark, and tries to convert again.
*/
static const char *l_str2d (const char *s, lua_Number *result) {
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN");
int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
if (mode == 'n') /* reject 'inf' and 'nan' */
return NULL;
endptr = l_str2dloc(s, result, mode); /* try to convert */
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
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++) {
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 */
}
int luaO_utf8esc (char *buff, unsigned long x) {
int n = 1; /* number of bytes put in buffer (backwards) */
lua_assert(x <= 0x7FFFFFFFu);
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, adding it to a buffer
*/
static int tostringbuff (TValue *obj, char *buff) {
int len;
lua_assert(ttisnumber(obj));
if (ttisinteger(obj))
len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj));
else {
len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj));
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
buff[len++] = lua_getlocaledecpoint();
buff[len++] = '0'; /* adds '.0' to result */
}
}
return len;
}
/*
** Convert a number object to a Lua string, replacing the value at 'obj'
*/
void luaO_tostring (lua_State *L, TValue *obj) {
char buff[MAXNUMBER2STR];
int len = tostringbuff(obj, buff);
setsvalue(L, obj, luaS_newlstr(L, buff, len));
}
static void pushstr (lua_State *L, const char *str) {
setsvalue(L->top, luaS_new(L, str));
incr_top(L);
/*
** {==================================================================
** 'luaO_pushvfstring'
** ===================================================================
*/
/* size for buffer space used by 'luaO_pushvfstring' */
#define BUFVFS 400
/* buffer used by 'luaO_pushvfstring' */
typedef struct BuffFS {
lua_State *L;
int pushed; /* number of string pieces already on the stack */
int blen; /* length of partial string in 'space' */
char space[BUFVFS]; /* holds last part of the result */
} BuffFS;
/*
** Push given string to the stack, as part of the buffer. If the stack
** is almost full, join all partial strings in the stack into one.
*/
static void pushstr (BuffFS *buff, const char *str, size_t l) {
lua_State *L = buff->L;
setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
L->top++; /* may use one extra slot */
buff->pushed++;
if (buff->pushed > 1 && L->top + 1 >= L->stack_last) {
luaV_concat(L, buff->pushed); /* join all partial results into one */
buff->pushed = 1;
}
}
/* this function handles only `%d', `%c', %f, and `%s' formats */
/*
** empty the buffer space into the stack
*/
static void clearbuff (BuffFS *buff) {
pushstr(buff, buff->space, buff->blen); /* push buffer contents */
buff->blen = 0; /* space now is empty */
}
/*
** Get a space of size 'sz' in the buffer. If buffer has not enough
** space, empty it. 'sz' must fit in an empty buffer.
*/
static char *getbuff (BuffFS *buff, int sz) {
lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS);
if (sz > BUFVFS - buff->blen) /* not enough space? */
clearbuff(buff);
return buff->space + buff->blen;
}
#define addsize(b,sz) ((b)->blen += (sz))
/*
** Add 'str' to the buffer. If string is larger than the buffer space,
** push the string directly to the stack.
*/
static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
if (slen <= BUFVFS) { /* does string fit into buffer? */
char *bf = getbuff(buff, cast_int(slen));
memcpy(bf, str, slen); /* add string to buffer */
addsize(buff, cast_int(slen));
}
else { /* string larger than buffer */
clearbuff(buff); /* string comes after buffer's content */
pushstr(buff, str, slen); /* push string */
}
}
/*
** Add a number to the buffer.
*/
static void addnum2buff (BuffFS *buff, TValue *num) {
char *numbuff = getbuff(buff, MAXNUMBER2STR);
int len = tostringbuff(num, numbuff); /* format number into 'numbuff' */
addsize(buff, len);
}
/*
** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%'
conventional formats, plus Lua-specific '%I' and '%U'
*/
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
int n = 1;
pushstr(L, "");
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
setsvalue(L->top, luaS_newlstr(L, fmt, e-fmt));
incr_top(L);
switch (*(e+1)) {
case 's':
pushstr(L, va_arg(argp, char *));
break;
case 'c': {
char buff[2];
buff[0] = cast(char, va_arg(argp, int));
buff[1] = '\0';
pushstr(L, buff);
BuffFS buff; /* holds last part of the result */
const char *e; /* points to next '%' */
buff.pushed = buff.blen = 0;
buff.L = L;
while ((e = strchr(fmt, '%')) != NULL) {
addstr2buff(&buff, fmt, e - fmt); /* add 'fmt' up to '%' */
switch (*(e + 1)) { /* conversion specifier */
case 's': { /* zero-terminated string */
const char *s = va_arg(argp, char *);
if (s == NULL) s = "(null)";
addstr2buff(&buff, s, strlen(s));
break;
}
case 'd':
setnvalue(L->top, va_arg(argp, int));
incr_top(L);
case 'c': { /* an 'int' as a character */
char c = cast_uchar(va_arg(argp, int));
addstr2buff(&buff, &c, sizeof(char));
break;
case 'f':
setnvalue(L->top, va_arg(argp, lua_Number));
incr_top(L);
}
case 'd': { /* an 'int' */
TValue num;
setivalue(&num, va_arg(argp, int));
addnum2buff(&buff, &num);
break;
case '%':
pushstr(L, "%");
}
case 'I': { /* a 'lua_Integer' */
TValue num;
setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt)));
addnum2buff(&buff, &num);
break;
default: lua_assert(0);
}
case 'f': { /* a 'lua_Number' */
TValue num;
setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber)));
addnum2buff(&buff, &num);
break;
}
case 'p': { /* a pointer */
const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */
char *bf = getbuff(&buff, sz);
void *p = va_arg(argp, void *);
int len = lua_pointer2str(bf, sz, p);
addsize(&buff, len);
break;
}
case 'U': { /* a 'long' as a UTF-8 sequence */
char bf[UTF8BUFFSZ];
int len = luaO_utf8esc(bf, va_arg(argp, long));
addstr2buff(&buff, bf + UTF8BUFFSZ - len, len);
break;
}
case '%': {
addstr2buff(&buff, "%", 1);
break;
}
default: {
luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'",
*(e + 1));
}
}
n += 2;
fmt = e+2;
fmt = e + 2; /* skip '%' and the specifier */
}
pushstr(L, fmt);
luaV_concat(L, n+1, L->top - L->ci->base - 1);
L->top -= n;
return svalue(L->top - 1);
addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */
clearbuff(&buff); /* empty buffer into the stack */
if (buff.pushed > 1)
luaV_concat(L, buff.pushed); /* join all partial results */
return svalue(s2v(L->top - 1));
}
@@ -159,37 +536,48 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
return msg;
}
/* }================================================================== */
void luaO_chunkid (char *out, const char *source, int bufflen) {
if (*source == '=') {
strncpy(out, source+1, bufflen); /* remove first char */
out[bufflen-1] = '\0'; /* ensures null termination */
#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 srclen) {
size_t bufflen = LUA_IDSIZE; /* free space in buffer */
if (*source == '=') { /* 'literal' source */
if (srclen <= bufflen) /* small enough? */
memcpy(out, source + 1, srclen * sizeof(char));
else { /* truncate it */
addstr(out, source + 1, bufflen - 1);
*out = '\0';
}
}
else { /* out = "source", or "...source" */
if (*source == '@') {
int l;
source++; /* skip the `@' */
bufflen -= sizeof(" `...' ");
l = strlen(source);
strcpy(out, "");
if (l>bufflen) {
source += (l-bufflen); /* get last part of file name */
strcat(out, "...");
}
strcat(out, source);
else if (*source == '@') { /* file name */
if (srclen <= bufflen) /* small enough? */
memcpy(out, source + 1, srclen * sizeof(char));
else { /* add '...' before rest of name */
addstr(out, RETS, LL(RETS));
bufflen -= LL(RETS);
memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char));
}
else { /* out = [string "string"] */
int len = strcspn(source, "\n"); /* stop at first newline */
bufflen -= sizeof(" [string \"...\"] ");
if (len > bufflen) len = bufflen;
strcpy(out, "[string \"");
if (source[len] != '\0') { /* must truncate? */
strncat(out, source, len);
strcat(out, "...");
}
else
strcat(out, source);
strcat(out, "\"]");
}
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 (srclen < bufflen && nl == NULL) { /* small one-line source? */
addstr(out, source, srclen); /* keep it */
}
else {
if (nl != NULL) srclen = nl - source; /* stop at first newline */
if (srclen > bufflen) srclen = bufflen;
addstr(out, source, srclen);
addstr(out, RETS, LL(RETS));
}
memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
}
}
+684 -160
View File
@@ -1,153 +1,504 @@
/*
** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $
** $Id: lobject.h $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
#ifndef lobject_h
#define lobject_h
#include <stdarg.h>
#include "llimits.h"
#include "lua.h"
/* tags for values visible from Lua */
#define NUM_TAGS LUA_TFUNCTION
/*
** Extra types for collectable non-values
*/
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */
typedef union {
void *p;
union TString *ts;
union Udata *u;
union Closure *cl;
struct Table *h;
lua_Number n;
int b;
/*
** number of all possible types (including LUA_TNONE)
*/
#define LUA_TOTALTYPES (LUA_TPROTO + 2)
/*
** tags for Tagged Values have the following use of bits:
** bits 0-3: actual tag (a LUA_T* constant)
** bits 4-5: variant bits
** bit 6: whether value is collectable
*/
/* add variant bits to a type */
#define makevariant(t,v) ((t) | ((v) << 4))
/*
** Union of all Lua values
*/
typedef union Value {
struct GCObject *gc; /* collectable objects */
void *p; /* light userdata */
lua_CFunction f; /* light C functions */
lua_Integer i; /* integer numbers */
lua_Number n; /* float numbers */
} Value;
typedef struct lua_TObject {
int tt;
Value value;
} TObject;
/*
** Tagged Values. This is the basic representation of values in Lua:
** an actual value plus a tag with its type.
*/
#define TValuefields Value value_; lu_byte tt_
typedef struct TValue {
TValuefields;
} TValue;
#define val_(o) ((o)->value_)
#define valraw(o) (&val_(o))
/* raw type tag of a TValue */
#define rawtt(o) ((o)->tt_)
/* tag with no variants (bits 0-3) */
#define novariant(t) ((t) & 0x0F)
/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */
#define withvariant(t) ((t) & 0x3F)
#define ttypetag(o) withvariant(rawtt(o))
/* type of a TValue */
#define ttype(o) (novariant(rawtt(o)))
/* Macros to test type */
#define ttisnil(o) (ttype(o) == LUA_TNIL)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
#define ttistable(o) (ttype(o) == LUA_TTABLE)
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define checktag(o,t) (rawtt(o) == (t))
#define checktype(o,t) (ttype(o) == (t))
/* Macros to access values */
#define ttype(o) ((o)->tt)
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define tsvalue(o) check_exp(ttisstring(o), (o)->value.ts)
#define uvalue(o) check_exp(ttisuserdata(o), (o)->value.u)
#define clvalue(o) check_exp(ttisfunction(o), (o)->value.cl)
#define hvalue(o) check_exp(ttistable(o), (o)->value.h)
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
/* Macros for internal tests */
/* collectable object has the same tag as the original value */
#define righttt(obj) (ttypetag(obj) == gcvalue(obj)->tt)
/*
** Any value being manipulated by the program either is non
** collectable, or the collectable object has the right tag
** and it is not dead.
*/
#define checkliveness(L,obj) \
((void)L, lua_longassert(!iscollectable(obj) || \
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))))
/* Macros to set values */
#define setnvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); }
#define chgnvalue(obj,x) \
check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x))
#define setpvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); }
#define setbvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); }
#define setsvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TSTRING; i_o->value.ts=(x); }
#define setuvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; i_o->value.u=(x); }
#define setclvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; i_o->value.cl=(x); }
#define sethvalue(obj,x) \
{ TObject *i_o=(obj); i_o->tt=LUA_TTABLE; i_o->value.h=(x); }
#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
#define setobj(obj1,obj2) \
{ const TObject *o2=(obj2); TObject *o1=(obj1); \
o1->tt=o2->tt; o1->value = o2->value; }
#define setttype(obj, tt) (ttype(obj) = (tt))
/* set a value's tag */
#define settt_(o,t) ((o)->tt_=(t))
/* main macro to copy values (from 'obj1' to 'obj2') */
#define setobj(L,obj1,obj2) \
{ TValue *io1=(obj1); const TValue *io2=(obj2); \
io1->value_ = io2->value_; settt_(io1, io2->tt_); \
checkliveness(L,io1); lua_assert(!isnonstrictnil(io1)); }
typedef TObject *StkId; /* index to stack elements */
/*
** Different types of assignments, according to source and destination.
** (They are mostly equal now, but may be different in the future.)
*/
/* from stack to stack */
#define setobjs2s(L,o1,o2) setobj(L,s2v(o1),s2v(o2))
/* to stack (not from same stack) */
#define setobj2s(L,o1,o2) setobj(L,s2v(o1),o2)
/* from table to same table */
#define setobjt2t setobj
/* to new object */
#define setobj2n setobj
/* to table */
#define setobj2t setobj
/*
** String headers for string table
** Entries in the Lua stack
*/
typedef union TString {
union L_Umaxalign dummy; /* ensures maximum alignment for strings */
struct {
lu_hash hash;
size_t len;
int marked;
union TString *nexthash; /* chain for hash table */
} tsv;
typedef union StackValue {
TValue val;
} StackValue;
/* index to stack elements */
typedef StackValue *StkId;
/* convert a 'StackValue' to a 'TValue' */
#define s2v(o) (&(o)->val)
/*
** {==================================================================
** Nil
** ===================================================================
*/
/* Standard nil */
#define LUA_VNIL makevariant(LUA_TNIL, 0)
/* Empty slot (which might be different from a slot containing nil) */
#define LUA_VEMPTY makevariant(LUA_TNIL, 1)
/* Value returned for a key not found in a table (absent key) */
#define LUA_VABSTKEY makevariant(LUA_TNIL, 2)
/* macro to test for (any kind of) nil */
#define ttisnil(v) checktype((v), LUA_TNIL)
/* macro to test for a standard nil */
#define ttisstrictnil(o) checktag((o), LUA_VNIL)
#define setnilvalue(obj) settt_(obj, LUA_VNIL)
#define isabstkey(v) checktag((v), LUA_VABSTKEY)
/*
** macro to detect non-standard nils (used only in assertions)
*/
#define isnonstrictnil(v) (ttisnil(v) && !ttisstrictnil(v))
/*
** By default, entries with any kind of nil are considered empty.
** (In any definition, values associated with absent keys must also
** be accepted as empty.)
*/
#define isempty(v) ttisnil(v)
/* macro defining a value corresponding to an absent key */
#define ABSTKEYCONSTANT {NULL}, LUA_VABSTKEY
/* mark an entry as empty */
#define setempty(v) settt_(v, LUA_VEMPTY)
/* }================================================================== */
/*
** {==================================================================
** Booleans
** ===================================================================
*/
#define LUA_VFALSE makevariant(LUA_TBOOLEAN, 0)
#define LUA_VTRUE makevariant(LUA_TBOOLEAN, 1)
#define ttisboolean(o) checktype((o), LUA_TBOOLEAN)
#define ttisfalse(o) checktag((o), LUA_VFALSE)
#define ttistrue(o) checktag((o), LUA_VTRUE)
#define l_isfalse(o) (ttisfalse(o) || ttisnil(o))
#define setbfvalue(obj) settt_(obj, LUA_VFALSE)
#define setbtvalue(obj) settt_(obj, LUA_VTRUE)
/* }================================================================== */
/*
** {==================================================================
** Threads
** ===================================================================
*/
#define LUA_VTHREAD makevariant(LUA_TTHREAD, 0)
#define ttisthread(o) checktag((o), ctb(LUA_VTHREAD))
#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
#define setthvalue(L,obj,x) \
{ TValue *io = (obj); lua_State *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTHREAD)); \
checkliveness(L,io); }
#define setthvalue2s(L,o,t) setthvalue(L,s2v(o),t)
/* }================================================================== */
/*
** {==================================================================
** Collectable Objects
** ===================================================================
*/
/*
** Common Header for all collectable objects (in macro form, to be
** included in other objects)
*/
#define CommonHeader struct GCObject *next; lu_byte tt; lu_byte marked
/* Common type for all collectable objects */
typedef struct GCObject {
CommonHeader;
} GCObject;
/* Bit mark for collectable types */
#define BIT_ISCOLLECTABLE (1 << 6)
#define iscollectable(o) (rawtt(o) & BIT_ISCOLLECTABLE)
/* mark a tag as collectable */
#define ctb(t) ((t) | BIT_ISCOLLECTABLE)
#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc)
#define gcvalueraw(v) ((v).gc)
#define setgcovalue(L,obj,x) \
{ TValue *io = (obj); GCObject *i_g=(x); \
val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); }
/* }================================================================== */
/*
** {==================================================================
** Numbers
** ===================================================================
*/
/* Variant tags for numbers */
#define LUA_VNUMINT makevariant(LUA_TNUMBER, 0) /* integer numbers */
#define LUA_VNUMFLT makevariant(LUA_TNUMBER, 1) /* float numbers */
#define ttisnumber(o) checktype((o), LUA_TNUMBER)
#define ttisfloat(o) checktag((o), LUA_VNUMFLT)
#define ttisinteger(o) checktag((o), LUA_VNUMINT)
#define nvalue(o) check_exp(ttisnumber(o), \
(ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o)))
#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n)
#define ivalue(o) check_exp(ttisinteger(o), val_(o).i)
#define fltvalueraw(v) ((v).n)
#define ivalueraw(v) ((v).i)
#define setfltvalue(obj,x) \
{ TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_VNUMFLT); }
#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_VNUMINT); }
#define chgivalue(obj,x) \
{ TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); }
/* }================================================================== */
/*
** {==================================================================
** Strings
** ===================================================================
*/
/* Variant tags for strings */
#define LUA_VSHRSTR makevariant(LUA_TSTRING, 0) /* short strings */
#define LUA_VLNGSTR makevariant(LUA_TSTRING, 1) /* long strings */
#define ttisstring(o) checktype((o), LUA_TSTRING)
#define ttisshrstring(o) checktag((o), ctb(LUA_VSHRSTR))
#define ttislngstring(o) checktag((o), ctb(LUA_VLNGSTR))
#define tsvalueraw(v) (gco2ts((v).gc))
#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc))
#define setsvalue(L,obj,x) \
{ TValue *io = (obj); TString *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
checkliveness(L,io); }
/* set a string to the stack */
#define setsvalue2s(L,o,s) setsvalue(L,s2v(o),s)
/* set a string to a new object */
#define setsvalue2n setsvalue
/*
** Header for a string value.
*/
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
lu_byte shrlen; /* length for short strings */
unsigned int hash;
union {
size_t lnglen; /* length for long strings */
struct TString *hnext; /* linked list for hash table */
} u;
char contents[1];
} TString;
#define getstr(ts) cast(const char *, (ts) + 1)
/*
** Get the actual string (array of bytes) from a 'TString'.
*/
#define getstr(ts) ((ts)->contents)
/* 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_VSHRSTR ? (s)->shrlen : (s)->u.lnglen)
/* get string length from 'TValue *o' */
#define vslen(o) tsslen(tsvalue(o))
typedef union Udata {
union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
struct {
struct Table *metatable;
union Udata *next; /* chain for list of all udata */
size_t len; /* least 2 bits reserved for gc mark */
} uv;
} Udata;
/* }================================================================== */
/*
** Function Prototypes
** {==================================================================
** Userdata
** ===================================================================
*/
typedef struct Proto {
TObject *k; /* constants used by the function */
Instruction *code;
struct Proto **p; /* functions defined inside the function */
struct Proto *next;
int *lineinfo; /* map from opcodes to source lines */
struct LocVar *locvars; /* information about local variables */
TString *source;
int sizek; /* size of `k' */
int sizecode;
int sizep; /* size of `p' */
int sizelocvars;
int lineDefined;
lu_byte nupvalues;
lu_byte numparams;
lu_byte is_vararg;
lu_byte maxstacksize;
lu_byte marked;
} Proto;
/*
** Light userdata should be a variant of userdata, but for compatibility
** reasons they are also different types.
*/
#define LUA_VLIGHTUSERDATA makevariant(LUA_TLIGHTUSERDATA, 0)
#define LUA_VUSERDATA makevariant(LUA_TUSERDATA, 0)
#define ttislightuserdata(o) checktag((o), LUA_VLIGHTUSERDATA)
#define ttisfulluserdata(o) checktag((o), ctb(LUA_VUSERDATA))
#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p)
#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
#define pvalueraw(v) ((v).p)
#define setpvalue(obj,x) \
{ TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_VLIGHTUSERDATA); }
#define setuvalue(L,obj,x) \
{ TValue *io = (obj); Udata *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VUSERDATA)); \
checkliveness(L,io); }
/* Ensures that addresses after this type are always fully aligned. */
typedef union UValue {
TValue uv;
LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */
} UValue;
/*
** Header for userdata with user values;
** memory area follows the end of this structure.
*/
typedef struct Udata {
CommonHeader;
unsigned short nuvalue; /* number of user values */
size_t len; /* number of bytes */
struct Table *metatable;
GCObject *gclist;
UValue uv[1]; /* user values */
} Udata;
/*
** Header for userdata with no user values. These userdata do not need
** to be gray during GC, and therefore do not need a 'gclist' field.
** To simplify, the code always use 'Udata' for both kinds of userdata,
** making sure it never accesses 'gclist' on userdata with no user values.
** This structure here is used only to compute the correct size for
** this representation. (The 'bindata' field in its end ensures correct
** alignment for binary data following this header.)
*/
typedef struct Udata0 {
CommonHeader;
unsigned short nuvalue; /* number of user values */
size_t len; /* number of bytes */
struct Table *metatable;
union {LUAI_MAXALIGN;} bindata;
} Udata0;
/* compute the offset of the memory area of a userdata */
#define udatamemoffset(nuv) \
((nuv) == 0 ? offsetof(Udata0, bindata) \
: offsetof(Udata, uv) + (sizeof(UValue) * (nuv)))
/* get the address of the memory block inside 'Udata' */
#define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue))
/* compute the size of a userdata */
#define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb))
/* }================================================================== */
/*
** {==================================================================
** Prototypes
** ===================================================================
*/
#define LUA_VPROTO makevariant(LUA_TPROTO, 0)
/*
** 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 (register) */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
lu_byte kind; /* kind of corresponding variable */
} 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 */
@@ -155,40 +506,129 @@ typedef struct LocVar {
} LocVar;
/*
** Associates the absolute line source for a given instruction ('pc').
** The array 'lineinfo' gives, for each instruction, the difference in
** lines from the previous instruction. When that difference does not
** fit into a byte, Lua saves the absolute line for that instruction.
** (Lua also saves the absolute line periodically, to speed up the
** computation of a line number: we can use binary search in the
** absolute-line array, but we must traverse the 'lineinfo' array
** linearly to compute a line.)
*/
typedef struct AbsLineInfo {
int pc;
int line;
} AbsLineInfo;
/*
** Upvalues
** Function Prototypes
*/
typedef struct Proto {
CommonHeader;
lu_byte numparams; /* number of fixed (named) parameters */
lu_byte is_vararg;
lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
int sizecode;
int sizelineinfo;
int sizep; /* size of 'p' */
int sizelocvars;
int sizeabslineinfo; /* size of 'abslineinfo' */
int linedefined; /* debug information */
int lastlinedefined; /* debug information */
TValue *k; /* constants used by the function */
Instruction *code; /* opcodes */
struct Proto **p; /* functions defined inside the function */
Upvaldesc *upvalues; /* upvalue information */
ls_byte *lineinfo; /* information about source lines (debug information) */
AbsLineInfo *abslineinfo; /* idem */
LocVar *locvars; /* information about local variables (debug information) */
TString *source; /* used for debug information */
GCObject *gclist;
} Proto;
/* }================================================================== */
/*
** {==================================================================
** Closures
** ===================================================================
*/
#define LUA_VUPVAL makevariant(LUA_TUPVAL, 0)
/* Variant tags for functions */
#define LUA_VLCL makevariant(LUA_TFUNCTION, 0) /* Lua closure */
#define LUA_VLCF makevariant(LUA_TFUNCTION, 1) /* light C function */
#define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */
#define ttisfunction(o) checktype(o, LUA_TFUNCTION)
#define ttisclosure(o) ((rawtt(o) & 0x1F) == LUA_VLCL)
#define ttisLclosure(o) checktag((o), ctb(LUA_VLCL))
#define ttislcf(o) checktag((o), LUA_VLCF)
#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL))
#define isLfunction(o) ttisLclosure(o)
#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc))
#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
#define fvalue(o) check_exp(ttislcf(o), val_(o).f)
#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
#define fvalueraw(v) ((v).f)
#define setclLvalue(L,obj,x) \
{ TValue *io = (obj); LClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VLCL)); \
checkliveness(L,io); }
#define setclLvalue2s(L,o,cl) setclLvalue(L,s2v(o),cl)
#define setfvalue(obj,x) \
{ TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_VLCF); }
#define setclCvalue(L,obj,x) \
{ TValue *io = (obj); CClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \
checkliveness(L,io); }
/*
** Upvalues for Lua closures
*/
typedef struct UpVal {
TObject *v; /* points to stack or to its own value */
struct UpVal *next;
TObject value; /* the value (when closed) */
CommonHeader;
lu_byte tbc; /* true if it represents a to-be-closed variable */
TValue *v; /* points to stack or to its own value */
union {
struct { /* (when open) */
struct UpVal *next; /* linked list */
struct UpVal **previous;
} open;
TValue value; /* the value (when closed) */
} u;
} UpVal;
/*
** Closures
*/
#define ClosureHeader \
CommonHeader; lu_byte nupvalues; GCObject *gclist
typedef struct CClosure {
lu_byte isC; /* 0 for Lua functions, 1 for C functions */
lu_byte nupvalues;
lu_byte marked;
union Closure *next;
ClosureHeader;
lua_CFunction f;
TObject upvalue[1];
TValue upvalue[1]; /* list of upvalues */
} CClosure;
typedef struct LClosure {
lu_byte isC;
lu_byte nupvalues;
lu_byte marked;
union Closure *next; /* first four fields must be equal to CClosure!! */
ClosureHeader;
struct Proto *p;
TObject g; /* global table for this closure */
UpVal *upvals[1];
UpVal *upvals[1]; /* list of upvalues */
} LClosure;
@@ -198,66 +638,150 @@ typedef union Closure {
} Closure;
#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)
#define getproto(o) (clLvalue(o)->p)
/* }================================================================== */
/*
** {==================================================================
** Tables
** ===================================================================
*/
typedef struct Node {
TObject i_key;
TObject i_val;
struct Node *next; /* for chaining */
#define LUA_VTABLE makevariant(LUA_TTABLE, 0)
#define ttistable(o) checktag((o), ctb(LUA_VTABLE))
#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc))
#define sethvalue(L,obj,x) \
{ TValue *io = (obj); Table *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VTABLE)); \
checkliveness(L,io); }
#define sethvalue2s(L,o,h) sethvalue(L,s2v(o),h)
/*
** Nodes for Hash tables: A pack of two TValue's (key-value pairs)
** plus a 'next' field to link colliding entries. The distribution
** of the key's fields ('key_tt' and 'key_val') not forming a proper
** 'TValue' allows for a smaller size for 'Node' both in 4-byte
** and 8-byte alignments.
*/
typedef union Node {
struct NodeKey {
TValuefields; /* fields for value */
lu_byte key_tt; /* key type */
int next; /* for chaining */
Value key_val; /* key value */
} u;
TValue i_val; /* direct access to node's value as a proper 'TValue' */
} Node;
typedef struct Table {
struct Table *metatable;
TObject *array; /* array part */
Node *node;
Node *firstfree; /* this position is free; all positions after it are full */
struct Table *next;
struct Table *mark; /* marked tables (point to itself when not marked) */
int sizearray; /* size of `array' array */
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of `node' array */
lu_byte mode;
} Table;
/* copy a value into a key */
#define setnodekey(L,node,obj) \
{ Node *n_=(node); const TValue *io_=(obj); \
n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \
checkliveness(L,io_); }
/* bit masks for `mode' */
#define WEAKKEY 1
#define WEAKVALUE 2
/* copy a value from a key */
#define getnodekey(L,obj,node) \
{ TValue *io_=(obj); const Node *n_=(node); \
io_->value_ = n_->u.key_val; io_->tt_ = n_->u.key_tt; \
checkliveness(L,io_); }
/*
** `module' operation for hashing (size is always a power of 2)
** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
** real size of 'array'. Otherwise, the real size of 'array' is the
** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
** is zero); 'alimit' is then used as a hint for #t.
*/
#define BITRAS (1 << 7)
#define isrealasize(t) (!((t)->marked & BITRAS))
#define setrealasize(t) ((t)->marked &= cast_byte(~BITRAS))
#define setnorealasize(t) ((t)->marked |= BITRAS)
typedef struct Table {
CommonHeader;
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
lu_byte lsizenode; /* log2 of size of 'node' array */
unsigned int alimit; /* "limit" of 'array' array */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
struct Table *metatable;
GCObject *gclist;
} Table;
/*
** Macros to manipulate keys inserted in nodes
*/
#define keytt(node) ((node)->u.key_tt)
#define keyval(node) ((node)->u.key_val)
#define keyisnil(node) (keytt(node) == LUA_TNIL)
#define keyisinteger(node) (keytt(node) == LUA_VNUMINT)
#define keyival(node) (keyval(node).i)
#define keyisshrstr(node) (keytt(node) == ctb(LUA_VSHRSTR))
#define keystrval(node) (gco2ts(keyval(node).gc))
#define setnilkey(node) (keytt(node) = LUA_TNIL)
#define keyiscollectable(n) (keytt(n) & BIT_ISCOLLECTABLE)
#define gckey(n) (keyval(n).gc)
#define gckeyN(n) (keyiscollectable(n) ? gckey(n) : NULL)
/*
** Use a "nil table" to mark dead keys in a table. Those keys serve
** to keep space for removed entries, which may still be part of
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
** set, so these values are considered not collectable and are different
** from any valid value.
*/
#define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL)
/* }================================================================== */
/*
** 'module' operation for hashing (size is always a power of 2)
*/
#define lmod(s,size) \
check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))
(check_exp((size&(size-1))==0, (cast_int((s) & ((size)-1)))))
#define twoto(x) (1<<(x))
#define sizenode(t) (twoto((t)->lsizenode))
#define sizearray(t) ((t)->sizearray)
/* size of buffer for 'luaO_utf8esc' function */
#define UTF8BUFFSZ 8
extern const TObject luaO_nilobject;
int luaO_log2 (unsigned int x);
#define luaO_openspace(L,n,t) cast(t *, luaO_openspaceaux(L,(n)*sizeof(t)))
void *luaO_openspaceaux (lua_State *L, size_t n);
int luaO_rawequalObj (const TObject *t1, const TObject *t2);
int luaO_str2d (const char *s, lua_Number *result);
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp);
const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
void luaO_chunkid (char *out, const char *source, int len);
LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
LUAI_FUNC int luaO_ceillog2 (unsigned int x);
LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
const TValue *p2, TValue *res);
LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1,
const TValue *p2, StkId res);
LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
LUAI_FUNC int luaO_hexavalue (int c);
LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj);
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
#endif
+92 -92
View File
@@ -1,104 +1,104 @@
/*
** $Id: lopcodes.c,v 1.19 2002/05/13 13:09:00 roberto Exp roberto $
** extracted automatically from lopcodes.h by mkprint.lua
** DO NOT EDIT
** $Id: lopcodes.c $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
#define lopcodes_c
#define LUA_CORE
#include "lprefix.h"
#include "lua.h"
#include "lobject.h"
#include "lopcodes.h"
#ifdef LUA_OPNAMES
/* ORDER OP */
const char *const luaP_opnames[] = {
"MOVE",
"LOADK",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETGLOBAL",
"GETTABLE",
"SETGLOBAL",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"DIV",
"POW",
"UNM",
"NOT",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"GT",
"GE",
"TEST",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"TFORLOOP",
"TFORPREP",
"SETLIST",
"SETLISTO",
"CLOSE",
"CLOSURE"
};
#endif
#define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* T _ B C sA K mode opcode */
opmode(0,0,1,0, 1,0,iABC) /* OP_MOVE */
,opmode(0,0,0,0, 1,1,iABx) /* OP_LOADK */
,opmode(0,0,0,0, 1,0,iABC) /* OP_LOADBOOL */
,opmode(0,0,1,0, 1,0,iABC) /* OP_LOADNIL */
,opmode(0,0,0,0, 1,0,iABC) /* OP_GETUPVAL */
,opmode(0,0,0,0, 1,1,iABx) /* OP_GETGLOBAL */
,opmode(0,0,1,1, 1,0,iABC) /* OP_GETTABLE */
,opmode(0,0,0,0, 0,1,iABx) /* OP_SETGLOBAL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */
,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */
,opmode(0,0,0,0, 1,0,iABC) /* OP_NEWTABLE */
,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */
,opmode(0,0,1,1, 1,0,iABC) /* OP_ADD */
,opmode(0,0,1,1, 1,0,iABC) /* OP_SUB */
,opmode(0,0,1,1, 1,0,iABC) /* OP_MUL */
,opmode(0,0,1,1, 1,0,iABC) /* OP_DIV */
,opmode(0,0,1,1, 1,0,iABC) /* OP_POW */
,opmode(0,0,1,0, 1,0,iABC) /* OP_UNM */
,opmode(0,0,1,0, 1,0,iABC) /* OP_NOT */
,opmode(0,0,1,1, 1,0,iABC) /* OP_CONCAT */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_JMP */
,opmode(1,0,0,1, 0,0,iABC) /* OP_EQ */
,opmode(1,0,0,1, 0,0,iABC) /* OP_LT */
,opmode(1,0,0,1, 0,0,iABC) /* OP_LE */
,opmode(1,0,0,1, 0,0,iABC) /* OP_GT */
,opmode(1,0,0,1, 0,0,iABC) /* OP_GE */
,opmode(1,0,0,1, 1,0,iABC) /* OP_TEST */
,opmode(0,0,0,0, 0,0,iABC) /* OP_CALL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_TAILCALL */
,opmode(0,0,0,0, 0,0,iABC) /* OP_RETURN */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_FORLOOP */
,opmode(1,0,0,0, 0,0,iABC) /* OP_TFORLOOP */
,opmode(0,0,0,0, 0,0,iAsBx) /* OP_TFORPREP */
,opmode(0,0,0,0, 0,0,iABx) /* OP_SETLIST */
,opmode(0,0,0,0, 0,0,iABx) /* OP_SETLISTO */
,opmode(0,0,0,0, 0,0,iABC) /* OP_CLOSE */
,opmode(0,0,0,0, 1,0,iABx) /* OP_CLOSURE */
LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
/* MM OT IT T A mode opcode */
opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */
,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */
,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADFALSE */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_LFALSESKIP */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADTRUE */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */
,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */
,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/
,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/
,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */
,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */
,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */
,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */
,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */
,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */
,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */
,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */
,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
};
+288 -129
View File
@@ -1,5 +1,5 @@
/*
** $Id: lopcodes.h,v 1.99 2002/06/12 14:51:31 roberto Exp $
** $Id: lopcodes.h $
** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -11,223 +11,382 @@
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
`A' : 8 bits (25-32)
`B' : 8 bits (17-24)
`C' : 10 bits (7-16)
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
We assume that instructions are unsigned 32-bit integers.
All instructions have an opcode in the first 7 bits.
Instructions can have the following formats:
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
iABC C(8) | B(8) |k| A(8) | Op(7) |
iABx Bx(17) | A(8) | Op(7) |
iAsBx sBx (signed)(17) | A(8) | Op(7) |
iAx Ax(25) | Op(7) |
isJ sJ(25) | Op(7) |
A signed argument is represented in excess K: the represented value is
the written unsigned value minus K, where K is half the maximum for the
corresponding unsigned argument.
===========================================================================*/
enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */
enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
/*
** size and position of opcode arguments.
*/
#define SIZE_C 10
#define SIZE_C 8
#define SIZE_B 8
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_Bx (SIZE_C + SIZE_B + 1)
#define SIZE_A 8
#define SIZE_Ax (SIZE_Bx + SIZE_A)
#define SIZE_sJ (SIZE_Bx + SIZE_A)
#define SIZE_OP 6
#define SIZE_OP 7
#define POS_C SIZE_OP
#define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C
#define POS_A (POS_B + SIZE_B)
#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_k (POS_A + SIZE_A)
#define POS_B (POS_k + 1)
#define POS_C (POS_B + SIZE_B)
#define POS_Bx POS_k
#define POS_Ax POS_A
#define POS_sJ POS_A
/*
** limits for opcode arguments.
** we use (signed) int to manipulate most arguments,
** so they must fit in BITS_INT-1 bits (-1 for sign)
** we use (signed) 'int' to manipulate most arguments,
** so they must fit in ints.
*/
#if SIZE_Bx < BITS_INT-1
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
/* Check whether type 'int' has at least 'b' bits ('b' < 32) */
#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1)
#if L_INTHASBITS(SIZE_Bx)
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
#else
#define MAXARG_Bx MAX_INT
#define MAXARG_sBx MAX_INT
#define MAXARG_Bx MAX_INT
#endif
#define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1)
#define MAXARG_C ((1<<SIZE_C)-1)
#define OFFSET_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
/* creates a mask with `n' 1 bits at position `p' */
#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p)
#if L_INTHASBITS(SIZE_Ax)
#define MAXARG_Ax ((1<<SIZE_Ax)-1)
#else
#define MAXARG_Ax MAX_INT
#endif
/* creates a mask with `n' 0 bits at position `p' */
#if L_INTHASBITS(SIZE_sJ)
#define MAXARG_sJ ((1 << SIZE_sJ) - 1)
#else
#define MAXARG_sJ MAX_INT
#endif
#define OFFSET_sJ (MAXARG_sJ >> 1)
#define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1)
#define MAXARG_C ((1<<SIZE_C)-1)
#define OFFSET_sC (MAXARG_C >> 1)
#define int2sC(i) ((i) + OFFSET_sC)
#define sC2int(i) ((i) - OFFSET_sC)
/* creates a mask with 'n' 1 bits at position 'p' */
#define MASK1(n,p) ((~((~(Instruction)0)<<(n)))<<(p))
/* creates a mask with 'n' 0 bits at position 'p' */
#define MASK0(n,p) (~MASK1(n,p))
/*
** the following macros help to manipulate instructions
*/
#define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o)))
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
#define GETARG_A(i) (cast(int, (i)>>POS_A))
#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))
#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))
#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))
#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))
#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \
((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))
#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))
#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \
((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))
#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
#define checkopm(i,m) (getOpMode(GET_OPCODE(i)) == m)
#define CREATE_ABC(o,a,b,c) (cast(Instruction, o) \
#define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0)))
#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
((cast(Instruction, v)<<pos)&MASK1(size,pos))))
#define GETARG_A(i) getarg(i, POS_A, SIZE_A)
#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
#define GETARG_B(i) check_exp(checkopm(i, iABC), getarg(i, POS_B, SIZE_B))
#define GETARG_sB(i) sC2int(GETARG_B(i))
#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
#define GETARG_C(i) check_exp(checkopm(i, iABC), getarg(i, POS_C, SIZE_C))
#define GETARG_sC(i) sC2int(GETARG_C(i))
#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
#define TESTARG_k(i) check_exp(checkopm(i, iABC), (cast_int(((i) & (1u << POS_k)))))
#define GETARG_k(i) check_exp(checkopm(i, iABC), getarg(i, POS_k, 1))
#define SETARG_k(i,v) setarg(i, v, POS_k, 1)
#define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx))
#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
#define GETARG_Ax(i) check_exp(checkopm(i, iAx), getarg(i, POS_Ax, SIZE_Ax))
#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
#define GETARG_sBx(i) \
check_exp(checkopm(i, iAsBx), getarg(i, POS_Bx, SIZE_Bx) - OFFSET_sBx)
#define SETARG_sBx(i,b) SETARG_Bx((i),cast_uint((b)+OFFSET_sBx))
#define GETARG_sJ(i) \
check_exp(checkopm(i, isJ), getarg(i, POS_sJ, SIZE_sJ) - OFFSET_sJ)
#define SETARG_sJ(i,j) \
setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ)
#define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, b)<<POS_B) \
| (cast(Instruction, c)<<POS_C))
| (cast(Instruction, c)<<POS_C) \
| (cast(Instruction, k)<<POS_k))
#define CREATE_ABx(o,a,bc) (cast(Instruction, o) \
#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, bc)<<POS_Bx))
#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_Ax))
#define CREATE_sJ(o,j,k) ((cast(Instruction, o) << POS_OP) \
| (cast(Instruction, j) << POS_sJ) \
| (cast(Instruction, k) << POS_k))
#if !defined(MAXINDEXRK) /* (for debugging only) */
#define MAXINDEXRK MAXARG_B
#endif
/*
** invalid registers that fits in 8 bits
** invalid register that fits in 8 bits
*/
#define NO_REG MAXARG_A
#define NO_REG1 (NO_REG+1)
/*
** R(x) - register
** Kst(x) - constant (in constant table)
** R/K(x) == if x < MAXSTACK then R(x) else Kst(x-MAXSTACK)
** R[x] - register
** K[x] - constant (in constant table)
** RK(x) == if k(i) then K[x] else R[x]
*/
/*
** grep "ORDER OP" if you change these enums
*/
typedef enum {
/*----------------------------------------------------------------------
name args description
name args description
------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B) */
OP_LOADK,/* A Bx R(A) := Kst(Bx) */
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) PC++ */
OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_MOVE,/* A B R[A] := R[B] */
OP_LOADI,/* A sBx R[A] := sBx */
OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */
OP_LOADK,/* A Bx R[A] := K[Bx] */
OP_LOADKX,/* A R[A] := K[extra arg] */
OP_LOADFALSE,/* A R[A] := false */
OP_LFALSESKIP,/*A R[A] := false; pc++ */
OP_LOADTRUE,/* A R[A] := true */
OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
OP_SETUPVAL,/* A B UpValue[B] := R[A] */
OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */
OP_GETTABLE,/* A B C R(A) := R(B)[R/K(C)] */
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:string] */
OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */
OP_GETI,/* A B C R[A] := R[B][C] */
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:string] */
OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */
OP_SETTABUP,/* A B C UpValue[A][K[B]:string] := RK(C) */
OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */
OP_SETI,/* A B C R[A][B] := RK(C) */
OP_SETFIELD,/* A B C R[A][K[B]:string] := RK(C) */
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
OP_NEWTABLE,/* A B C k R[A] := {} */
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */
OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][RK(C):string] */
OP_ADD,/* A B C R(A) := R(B) + R/K(C) */
OP_SUB,/* A B C R(A) := R(B) - R/K(C) */
OP_MUL,/* A B C R(A) := R(B) * R/K(C) */
OP_DIV,/* A B C R(A) := R(B) / R/K(C) */
OP_POW,/* A B C R(A) := R(B) ^ R/K(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_NOT,/* A B R(A) := not R(B) */
OP_ADDI,/* A B sC R[A] := R[B] + sC */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
OP_ADDK,/* A B C R[A] := R[B] + K[C] */
OP_SUBK,/* A B C R[A] := R[B] - K[C] */
OP_MULK,/* A B C R[A] := R[B] * K[C] */
OP_MODK,/* A B C R[A] := R[B] % K[C] */
OP_POWK,/* A B C R[A] := R[B] ^ K[C] */
OP_DIVK,/* A B C R[A] := R[B] / K[C] */
OP_IDIVK,/* A B C R[A] := R[B] // K[C] */
OP_JMP,/* sBx PC += sBx */
OP_BANDK,/* A B C R[A] := R[B] & K[C]:integer */
OP_BORK,/* A B C R[A] := R[B] | K[C]:integer */
OP_BXORK,/* A B C R[A] := R[B] ~ K[C]:integer */
OP_EQ,/* A B C if ((R(A) == R/K(C)) ~= B) then pc++ */
OP_LT,/* A B C if ((R(A) < R/K(C)) ~= B) then pc++ */
OP_LE,/* A B C if ((R(A) <= R/K(C)) ~= B) then pc++ */
OP_GT,/* A B C if ((R(A) > R/K(C)) ~= B) then pc++ */
OP_GE,/* A B C if ((R(A) >= R/K(C)) ~= B) then pc++ */
OP_SHRI,/* A B sC R[A] := R[B] >> sC */
OP_SHLI,/* A B sC R[A] := sC << R[B] */
OP_TEST,/* A B C if (R(C) <=> B) then R(A) := R(C) else pc++ */
OP_ADD,/* A B C R[A] := R[B] + R[C] */
OP_SUB,/* A B C R[A] := R[B] - R[C] */
OP_MUL,/* A B C R[A] := R[B] * R[C] */
OP_MOD,/* A B C R[A] := R[B] % R[C] */
OP_POW,/* A B C R[A] := R[B] ^ R[C] */
OP_DIV,/* A B C R[A] := R[B] / R[C] */
OP_IDIV,/* A B C R[A] := R[B] // R[C] */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
OP_BAND,/* A B C R[A] := R[B] & R[C] */
OP_BOR,/* A B C R[A] := R[B] | R[C] */
OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */
OP_SHL,/* A B C R[A] := R[B] << R[C] */
OP_SHR,/* A B C R[A] := R[B] >> R[C] */
OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) <?= R(A+1) then PC+= sBx */
OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] */
OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */
OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
OP_TFORLOOP,/* A C R(A+2), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
if R(A+2) ~= nil then pc++ */
OP_TFORPREP,/* A sBx if type(R(A)) == table then R(A+1):=R(A), R(A):=next;
PC += sBx */
OP_UNM,/* A B R[A] := -R[B] */
OP_BNOT,/* A B R[A] := ~R[B] */
OP_NOT,/* A B R[A] := not R[B] */
OP_LEN,/* A B R[A] := length of R[B] */
OP_SETLIST,/* A Bx R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1 */
OP_SETLISTO,/* A Bx */
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
OP_CLOSE,/* A close all upvalues >= R[A] */
OP_TBC,/* A mark variable A "to be closed" */
OP_JMP,/* sJ pc += sJ */
OP_EQ,/* A B k if ((R[A] == R[B]) ~= k) then pc++ */
OP_LT,/* A B k if ((R[A] < R[B]) ~= k) then pc++ */
OP_LE,/* A B k if ((R[A] <= R[B]) ~= k) then pc++ */
OP_EQK,/* A B k if ((R[A] == K[B]) ~= k) then pc++ */
OP_EQI,/* A sB k if ((R[A] == sB) ~= k) then pc++ */
OP_LTI,/* A sB k if ((R[A] < sB) ~= k) then pc++ */
OP_LEI,/* A sB k if ((R[A] <= sB) ~= k) then pc++ */
OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */
OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */
OP_TEST,/* A k if (not R[A] == k) then pc++ */
OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] */
OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */
OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */
OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */
OP_RETURN0,/* return */
OP_RETURN1,/* A return R[A] */
OP_FORLOOP,/* A Bx update counters; if loop continues then pc-=Bx; */
OP_FORPREP,/* A Bx <check values and prepare counters>;
if not to run then pc+=Bx+1; */
OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
OP_VARARGPREP,/*A (adjust vararg parameters) */
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode;
#define NUM_OPCODES (cast(int, OP_CLOSURE+1))
#define NUM_OPCODES ((int)(OP_EXTRAARG) + 1)
/*===========================================================================
Notes:
(1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
(*) In OP_CALL, if (B == 0) then B = top - A. If (C == 0), then
'top' is set to last_result+1, so next open instruction (OP_CALL,
OP_RETURN*, OP_SETLIST) may use 'top'.
(2) In OP_RETURN, if (B == 0) then return up to `top'
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
(3) For comparisons, B specifies what conditions the test should accept.
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
(*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always
OP_EXTRAARG.
(*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then
real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the
bits of C).
(*) In OP_NEWTABLE, B is log2 of the hash size (which is always a
power of 2) plus 1, or zero for size zero. If not k, the array size
is C. Otherwise, the array size is EXTRAARG _ C.
(*) For comparisons, k specifies what condition the test should accept
(true or false).
(*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped
(the constant is the first operand).
(*) All 'skips' (pc++) assume that next instruction is a jump.
(*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the
function builds upvalues, which may need to be closed. C > 0 means
the function is vararg, so that its 'func' must be corrected before
returning; in this case, (C - 1) is its number of fixed parameters.
(*) In comparisons with an immediate operand, C signals whether the
original operand was a float. (It must be corrected in case of
metamethods.)
(4) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/
/*
** masks for instruction properties
*/
enum OpModeMask {
OpModeBreg = 2, /* B is a register */
OpModeCreg, /* C is a register/constant */
OpModesetA, /* instruction set register A */
OpModeK, /* Bx is a constant */
OpModeT /* operator is a test */
};
** masks for instruction properties. The format is:
** bits 0-2: op mode
** bit 3: instruction set register A
** bit 4: operator is a test (next instruction must be a jump)
** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0)
** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
** bit 7: instruction is an MM instruction (call a metamethod)
*/
extern const lu_byte luaP_opmodes[NUM_OPCODES];
LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3))
#define testOpMode(m, b) (luaP_opmodes[m] & (1 << (b)))
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7))
#define testAMode(m) (luaP_opmodes[m] & (1 << 3))
#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
/* "out top" (set top for next instruction) */
#define isOT(i) \
((testOTMode(GET_OPCODE(i)) && GETARG_C(i) == 0) || \
GET_OPCODE(i) == OP_TAILCALL)
#ifdef LUA_OPNAMES
extern const char *const luaP_opnames[]; /* opcode names */
#endif
/* "in top" (uses top from previous instruction) */
#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
#define opmode(mm,ot,it,t,a,m) \
(((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m))
/* number of list items to accumulate before a SETLIST instruction */
/* (must be a power of 2) */
#define LFIELDS_PER_FLUSH 32
#define LFIELDS_PER_FLUSH 50
#endif
+103
View File
@@ -0,0 +1,103 @@
/*
** $Id: lopnames.h $
** Opcode names
** See Copyright Notice in lua.h
*/
#if !defined(lopnames_h)
#define lopnames_h
#include <stddef.h>
/* ORDER OP */
static const char *const opnames[] = {
"MOVE",
"LOADI",
"LOADF",
"LOADK",
"LOADKX",
"LOADFALSE",
"LFALSESKIP",
"LOADTRUE",
"LOADNIL",
"GETUPVAL",
"SETUPVAL",
"GETTABUP",
"GETTABLE",
"GETI",
"GETFIELD",
"SETTABUP",
"SETTABLE",
"SETI",
"SETFIELD",
"NEWTABLE",
"SELF",
"ADDI",
"ADDK",
"SUBK",
"MULK",
"MODK",
"POWK",
"DIVK",
"IDIVK",
"BANDK",
"BORK",
"BXORK",
"SHRI",
"SHLI",
"ADD",
"SUB",
"MUL",
"MOD",
"POW",
"DIV",
"IDIV",
"BAND",
"BOR",
"BXOR",
"SHL",
"SHR",
"MMBIN",
"MMBINI",
"MMBINK",
"UNM",
"BNOT",
"NOT",
"LEN",
"CONCAT",
"CLOSE",
"TBC",
"JMP",
"EQ",
"LT",
"LE",
"EQK",
"EQI",
"LTI",
"LEI",
"GTI",
"GEI",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"RETURN0",
"RETURN1",
"FORLOOP",
"FORPREP",
"TFORPREP",
"TFORCALL",
"TFORLOOP",
"SETLIST",
"CLOSURE",
"VARARG",
"VARARGPREP",
"EXTRAARG",
NULL
};
#endif
+430
View File
@@ -0,0 +1,430 @@
/*
** $Id: loslib.c $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
#define loslib_c
#define LUA_LIB
#include "lprefix.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
/*
** {==================================================================
** List of valid conversion specifiers for the 'strftime' function;
** options are grouped by length; group of length 2 start with '||'.
** ===================================================================
*/
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
/* options for ANSI C 89 (only 1-char options) */
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
#endif
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for time-related stuff
** ===================================================================
*/
/*
** type to represent time_t in Lua
*/
#if !defined(LUA_NUMTIME) /* { */
#define l_timet lua_Integer
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
#define l_gettime(L,arg) luaL_checkinteger(L, arg)
#else /* }{ */
#define l_timet lua_Number
#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t))
#define l_gettime(L,arg) luaL_checknumber(L, arg)
#endif /* } */
#if !defined(l_gmtime) /* { */
/*
** By default, Lua uses gmtime/localtime, except when POSIX is available,
** where it uses gmtime_r/localtime_r
*/
#if defined(LUA_USE_POSIX) /* { */
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
#else /* }{ */
/* ISO C definitions */
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
#endif /* } */
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for 'tmpnam':
** By default, Lua uses tmpnam except when POSIX is available, where
** it uses mkstemp.
** ===================================================================
*/
#if !defined(lua_tmpnam) /* { */
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
#define LUA_TMPNAMBUFSIZE 32
#if !defined(LUA_TMPNAMTEMPLATE)
#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
#endif
#define lua_tmpnam(b,e) { \
strcpy(b, LUA_TMPNAMTEMPLATE); \
e = mkstemp(b); \
if (e != -1) close(e); \
e = (e == -1); }
#else /* }{ */
/* ISO C definitions */
#define LUA_TMPNAMBUFSIZE L_tmpnam
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif /* } */
#endif /* } */
/* }================================================================== */
static int os_execute (lua_State *L) {
const char *cmd = luaL_optstring(L, 1, NULL);
int stat;
errno = 0;
stat = system(cmd);
if (cmd != NULL)
return luaL_execresult(L, stat);
else {
lua_pushboolean(L, stat); /* true if there is a shell */
return 1;
}
}
static int os_remove (lua_State *L) {
const char *filename = luaL_checkstring(L, 1);
return luaL_fileresult(L, remove(filename) == 0, filename);
}
static int os_rename (lua_State *L) {
const char *fromname = luaL_checkstring(L, 1);
const char *toname = luaL_checkstring(L, 2);
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
}
static int os_tmpname (lua_State *L) {
char buff[LUA_TMPNAMBUFSIZE];
int err;
lua_tmpnam(buff, err);
if (err)
return luaL_error(L, "unable to generate a unique filename");
lua_pushstring(L, buff);
return 1;
}
static int os_getenv (lua_State *L) {
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
return 1;
}
static int os_clock (lua_State *L) {
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
return 1;
}
/*
** {======================================================
** Time/Date operations
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
** wday=%w+1, yday=%j, isdst=? }
** =======================================================
*/
/*
** About the overflow check: an overflow cannot occur when time
** is represented by a lua_Integer, because either lua_Integer is
** large enough to represent all int fields or it is not large enough
** to represent a time that cause a field to overflow. However, if
** times are represented as doubles and lua_Integer is int, then the
** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900
** to compute the year.
*/
static void setfield (lua_State *L, const char *key, int value, int delta) {
#if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX)
if (value > LUA_MAXINTEGER - delta)
luaL_error(L, "field '%s' is out-of-bound", key);
#endif
lua_pushinteger(L, (lua_Integer)value + delta);
lua_setfield(L, -2, key);
}
static void setboolfield (lua_State *L, const char *key, int value) {
if (value < 0) /* undefined? */
return; /* does not set field */
lua_pushboolean(L, value);
lua_setfield(L, -2, key);
}
/*
** Set all fields from structure 'tm' in the table on top of the stack
*/
static void setallfields (lua_State *L, struct tm *stm) {
setfield(L, "year", stm->tm_year, 1900);
setfield(L, "month", stm->tm_mon, 1);
setfield(L, "day", stm->tm_mday, 0);
setfield(L, "hour", stm->tm_hour, 0);
setfield(L, "min", stm->tm_min, 0);
setfield(L, "sec", stm->tm_sec, 0);
setfield(L, "yday", stm->tm_yday, 1);
setfield(L, "wday", stm->tm_wday, 1);
setboolfield(L, "isdst", stm->tm_isdst);
}
static int getboolfield (lua_State *L, const char *key) {
int res;
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
lua_pop(L, 1);
return res;
}
static int getfield (lua_State *L, const char *key, int d, int delta) {
int isnum;
int t = lua_getfield(L, -1, key); /* get field and its type */
lua_Integer res = lua_tointegerx(L, -1, &isnum);
if (!isnum) { /* field is not an integer? */
if (t != LUA_TNIL) /* some other value? */
return luaL_error(L, "field '%s' is not an integer", key);
else if (d < 0) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key);
res = d;
}
else {
/* unsigned avoids overflow when lua_Integer has 32 bits */
if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta
: (lua_Integer)INT_MIN + delta <= res))
return luaL_error(L, "field '%s' is out-of-bound", key);
res -= delta;
}
lua_pop(L, 1);
return (int)res;
}
static const char *checkoption (lua_State *L, const char *conv,
ptrdiff_t convlen, char *buff) {
const char *option = LUA_STRFTIMEOPTIONS;
int oplen = 1; /* length of options being checked */
for (; *option != '\0' && oplen <= convlen; option += oplen) {
if (*option == '|') /* next block? */
oplen++; /* will check options with next length (+1) */
else if (memcmp(conv, option, oplen) == 0) { /* match? */
memcpy(buff, conv, oplen); /* copy valid option to buffer */
buff[oplen] = '\0';
return conv + oplen; /* return next item */
}
}
luaL_argerror(L, 1,
lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
return conv; /* to avoid warnings */
}
static time_t l_checktime (lua_State *L, int arg) {
l_timet t = l_gettime(L, arg);
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
return (time_t)t;
}
/* maximum size for an individual 'strftime' item */
#define SIZETIMEFMT 250
static int os_date (lua_State *L) {
size_t slen;
const char *s = luaL_optlstring(L, 1, "%c", &slen);
time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
const char *se = s + slen; /* 's' end */
struct tm tmr, *stm;
if (*s == '!') { /* UTC? */
stm = l_gmtime(&t, &tmr);
s++; /* skip '!' */
}
else
stm = l_localtime(&t, &tmr);
if (stm == NULL) /* invalid date? */
return luaL_error(L,
"date result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */
setallfields(L, stm);
}
else {
char cc[4]; /* buffer for individual conversion specifiers */
luaL_Buffer b;
cc[0] = '%';
luaL_buffinit(L, &b);
while (s < se) {
if (*s != '%') /* not a conversion specifier? */
luaL_addchar(&b, *s++);
else {
size_t reslen;
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s++; /* skip '%' */
s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen);
}
}
luaL_pushresult(&b);
}
return 1;
}
static int os_time (lua_State *L) {
time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
else {
struct tm ts;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_mon = getfield(L, "month", -1, 1);
ts.tm_mday = getfield(L, "day", -1, 0);
ts.tm_hour = getfield(L, "hour", 12, 0);
ts.tm_min = getfield(L, "min", 0, 0);
ts.tm_sec = getfield(L, "sec", 0, 0);
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
setallfields(L, &ts); /* update fields with normalized values */
}
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
return luaL_error(L,
"time result cannot be represented in this installation");
l_pushtime(L, t);
return 1;
}
static int os_difftime (lua_State *L) {
time_t t1 = l_checktime(L, 1);
time_t t2 = l_checktime(L, 2);
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
return 1;
}
/* }====================================================== */
static int os_setlocale (lua_State *L) {
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
LC_NUMERIC, LC_TIME};
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
"numeric", "time", NULL};
const char *l = luaL_optstring(L, 1, NULL);
int op = luaL_checkoption(L, 2, "all", catnames);
lua_pushstring(L, setlocale(cat[op], l));
return 1;
}
static int os_exit (lua_State *L) {
int status;
if (lua_isboolean(L, 1))
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
else
status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
if (lua_toboolean(L, 2))
lua_close(L);
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
return 0;
}
static const luaL_Reg syslib[] = {
{"clock", os_clock},
{"date", os_date},
{"difftime", os_difftime},
{"execute", os_execute},
{"exit", os_exit},
{"getenv", os_getenv},
{"remove", os_remove},
{"rename", os_rename},
{"setlocale", os_setlocale},
{"time", os_time},
{"tmpname", os_tmpname},
{NULL, NULL}
};
/* }====================================================== */
LUAMOD_API int luaopen_os (lua_State *L) {
luaL_newlib(L, syslib);
return 1;
}
+1376 -689
View File
File diff suppressed because it is too large Load Diff
+131 -32
View File
@@ -1,5 +1,5 @@
/*
** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
** $Id: lparser.h $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -9,63 +9,162 @@
#include "llimits.h"
#include "lobject.h"
#include "ltable.h"
#include "lzio.h"
/*
** Expression descriptor
** Expression and variable descriptor.
** Code generation for variables and expressions can be delayed to allow
** optimizations; An 'expdesc' structure describes a potentially-delayed
** variable/expression. It has a description of its "main" value plus a
** list of conditional jumps that can also produce its value (generated
** by short-circuit operators 'and'/'or').
*/
/* kinds of variables/expressions */
typedef enum {
VVOID, /* no value */
VNIL,
VTRUE,
VFALSE,
VK, /* info = index of constant in `k' */
VLOCAL, /* info = local register */
VUPVAL, /* info = index of upvalue in `upvalues' */
VGLOBAL, /* info = index of table; aux = index of global name in `k' */
VINDEXED, /* info = table register; aux = index register (or `k') */
VJMP, /* info = instruction pc */
VRELOCABLE, /* info = instruction pc */
VNONRELOC, /* info = result register */
VCALL /* info = result register */
VVOID, /* when 'expdesc' describes the last expression a list,
this kind means an empty list (so, no expression) */
VNIL, /* constant nil */
VTRUE, /* constant true */
VFALSE, /* constant false */
VK, /* constant in 'k'; info = index of constant in 'k' */
VKFLT, /* floating constant; nval = numerical float value */
VKINT, /* integer constant; ival = numerical integer value */
VKSTR, /* string constant; strval = TString address;
(string is fixed by the lexer) */
VNONRELOC, /* expression has its value in a fixed register;
info = result register */
VLOCAL, /* local variable; var.sidx = stack index (local register);
var.vidx = relative index in 'actvar.arr' */
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */
VINDEXED, /* indexed variable;
ind.t = table register;
ind.idx = key's R index */
VINDEXUP, /* indexed upvalue;
ind.t = table upvalue;
ind.idx = key's K index */
VINDEXI, /* indexed variable with constant integer;
ind.t = table register;
ind.idx = key's value */
VINDEXSTR, /* indexed variable with literal string;
ind.t = table register;
ind.idx = key's K index */
VJMP, /* expression is a test/comparison;
info = pc of corresponding jump instruction */
VRELOC, /* expression can put result in any register;
info = instruction pc */
VCALL, /* expression is a function call; info = instruction pc */
VVARARG /* vararg expression; info = instruction pc */
} expkind;
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
typedef struct expdesc {
expkind k;
int info, aux;
int t; /* patch list of `exit when true' */
int f; /* patch list of `exit when false' */
union {
lua_Integer ival; /* for VKINT */
lua_Number nval; /* for VKFLT */
TString *strval; /* for VKSTR */
int info; /* for generic use */
struct { /* for indexed variables */
short idx; /* index (R or "long" K) */
lu_byte t; /* table (register or upvalue) */
} ind;
struct { /* for local variables */
lu_byte sidx; /* index in the stack */
unsigned short vidx; /* compiler index (in 'actvar.arr') */
} var;
} u;
int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */
} expdesc;
/* kinds of variables */
#define VDKREG 0 /* regular */
#define RDKCONST 1 /* constant */
#define RDKTOCLOSE 2 /* to-be-closed */
#define RDKCTC 3 /* compile-time constant */
/* description of an active local variable */
typedef union Vardesc {
struct {
TValuefields; /* constant value (if it is a compile-time constant) */
lu_byte kind;
lu_byte sidx; /* index of the variable in the stack */
short pidx; /* index of the variable in the Proto's 'locvars' array */
TString *name; /* variable name */
} vd;
TValue k; /* constant value (if any) */
} Vardesc;
/* description of pending goto statements and label statements */
typedef struct Labeldesc {
TString *name; /* label identifier */
int pc; /* position in code */
int line; /* line where it appeared */
lu_byte nactvar; /* number of active variables in that position */
lu_byte close; /* goto that escapes upvalues */
} Labeldesc;
/* list of labels or gotos */
typedef struct Labellist {
Labeldesc *arr; /* array */
int n; /* number of entries in use */
int size; /* array size */
} Labellist;
/* dynamic structures used by the parser */
typedef struct Dyndata {
struct { /* list of all active local variables */
Vardesc *arr;
int n;
int size;
} actvar;
Labellist gt; /* list of pending gotos */
Labellist label; /* list of active labels */
} Dyndata;
/* control of blocks */
struct BlockCnt; /* defined in lparser.c */
/* state needed to generate code for a given function */
typedef struct FuncState {
Proto *f; /* current function header */
Table *h; /* table to find (and reuse) elements in `k' */
struct FuncState *prev; /* enclosing function */
struct LexState *ls; /* lexical state */
struct lua_State *L; /* copy of the Lua state */
struct BlockCnt *bl; /* chain of current blocks */
int pc; /* next position to code (equivalent to `ncode') */
int lasttarget; /* `pc' of last `jump target' */
int jpc; /* list of pending jumps to `pc' */
int freereg; /* first free register */
int nk; /* number of elements in `k' */
int np; /* number of elements in `p' */
int nlocvars; /* number of elements in `locvars' */
int nactvar; /* number of active local variables */
expdesc upvalues[MAXUPVALUES]; /* upvalues */
int actvar[MAXVARS]; /* declared-variable stack */
int pc; /* next position to code (equivalent to 'ncode') */
int lasttarget; /* 'label' of last 'jump label' */
int previousline; /* last line that was saved in 'lineinfo' */
int nk; /* number of elements in 'k' */
int np; /* number of elements in 'p' */
int nabslineinfo; /* number of elements in 'abslineinfo' */
int firstlocal; /* index of first local var (in Dyndata array) */
int firstlabel; /* index of first label (in 'dyd->label->arr') */
short ndebugvars; /* number of elements in 'f->locvars' */
lu_byte nactvar; /* number of active local variables */
lu_byte nups; /* number of upvalues */
lu_byte freereg; /* first free register */
lu_byte iwthabs; /* instructions issued since last absolute line info */
lu_byte needclose; /* function needs to close upvalues when returning */
} FuncState;
Proto *luaY_parser (lua_State *L, ZIO *z);
LUAI_FUNC int luaY_nvarstack (FuncState *fs);
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Dyndata *dyd, const char *name, int firstchar);
#endif
+45
View File
@@ -0,0 +1,45 @@
/*
** $Id: lprefix.h $
** Definitions for Lua code that must come before any other header file
** See Copyright Notice in lua.h
*/
#ifndef lprefix_h
#define lprefix_h
/*
** Allows POSIX/XSI stuff
*/
#if !defined(LUA_USE_C89) /* { */
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#elif _XOPEN_SOURCE == 0
#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
#endif
/*
** Allows manipulation of large files in gcc and some other compilers
*/
#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#endif
#endif /* } */
/*
** Windows stuff
*/
#if defined(_WIN32) /* { */
#if !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
#endif
#endif /* } */
#endif
+403 -128
View File
@@ -1,12 +1,21 @@
/*
** $Id: lstate.c,v 1.102 2002/08/06 15:32:22 roberto Exp roberto $
** $Id: lstate.c $
** Global State
** See Copyright Notice in lua.h
*/
#define lstate_c
#define LUA_CORE
#include "lprefix.h"
#include <stddef.h>
#include <string.h>
#include "lua.h"
#include "lapi.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
@@ -20,173 +29,439 @@
static void close_state (lua_State *L);
/*
** you can change this function through the official API
** call `lua_setpanicf'
** thread state + extra space
*/
static int default_panic (lua_State *L) {
UNUSED(L);
return 0;
typedef struct LX {
lu_byte extra_[LUA_EXTRASPACE];
lua_State l;
} LX;
/*
** Main thread combines a thread state and the global state
*/
typedef struct LG {
LX l;
global_State g;
} LG;
#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
/*
** A macro to create a "random" seed when a state is created;
** the seed is used to randomize string hashes.
*/
#if !defined(luai_makeseed)
#include <time.h>
/*
** Compute an initial seed with some level of randomness.
** Rely on Address Space Layout Randomization (if present) and
** current time.
*/
#define addbuff(b,p,e) \
{ size_t t = cast_sizet(e); \
memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
static unsigned int luai_makeseed (lua_State *L) {
char buff[3 * sizeof(size_t)];
unsigned int h = cast_uint(time(NULL));
int p = 0;
addbuff(buff, p, L); /* heap variable */
addbuff(buff, p, &h); /* local variable */
addbuff(buff, p, &lua_newstate); /* public function */
lua_assert(p == sizeof(buff));
return luaS_hash(buff, p, h, 1);
}
#endif
/*
** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
** invariant (and avoiding underflows in 'totalbytes')
*/
void luaE_setdebt (global_State *g, l_mem debt) {
l_mem tb = gettotalbytes(g);
lua_assert(tb > 0);
if (debt < tb - MAX_LMEM)
debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */
g->totalbytes = tb - debt;
g->GCdebt = debt;
}
static void stack_init (lua_State *L, lua_State *OL) {
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L->top = L->stack;
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
L->ci = L->base_ci;
L->ci->state = CI_C; /* not a Lua function */
setnilvalue(L->top++); /* `function' entry for this `ci' */
L->ci->base = L->top;
L->ci->top = L->top + LUA_MINSTACK;
L->size_ci = BASIC_CI_SIZE;
L->end_ci = L->base_ci + L->size_ci;
LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
global_State *g = G(L);
int ccalls;
luaE_freeCI(L); /* release unused CIs */
ccalls = getCcalls(L);
if (limit >= 40000)
return 0; /* out of bounds */
limit += CSTACKERR;
if (L != g-> mainthread)
return 0; /* only main thread can change the C stack */
else if (ccalls <= CSTACKERR)
return 0; /* handling overflow */
else {
int diff = limit - g->Cstacklimit;
if (ccalls + diff <= CSTACKERR)
return 0; /* new limit would cause an overflow */
g->Cstacklimit = limit; /* set new limit */
L->nCcalls += diff; /* correct 'nCcalls' */
return limit - diff - CSTACKERR; /* success; return previous limit */
}
}
/*
** open parts that may cause memory-allocation errors
** Decrement count of "C calls" and check for overflows. In case of
** a stack overflow, check appropriate error ("regular" overflow or
** overflow while handling stack overflow). If 'nCcalls' is smaller
** than CSTACKERR but larger than CSTACKMARK, it means it has just
** entered the "overflow zone", so the function raises an overflow
** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is
** already handling an overflow) but larger than CSTACKERRMARK, does
** not report an error (to allow message handling to work). Otherwise,
** report a stack overflow while handling a stack overflow (probably
** caused by a repeating error in the message handling function).
*/
void luaE_enterCcall (lua_State *L) {
int ncalls = getCcalls(L);
L->nCcalls--;
if (ncalls <= CSTACKERR) { /* possible overflow? */
luaE_freeCI(L); /* release unused CIs */
ncalls = getCcalls(L); /* update call count */
if (ncalls <= CSTACKERR) { /* still overflow? */
if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */
luaD_throw(L, LUA_ERRERR); /* error while handling stack error */
else if (ncalls >= CSTACKMARK) {
/* not in error-handling zone; raise the error now */
L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */
luaG_runerror(L, "C stack overflow");
}
/* else stack is in the error-handling zone;
allow message handler to work */
}
}
}
CallInfo *luaE_extendCI (lua_State *L) {
CallInfo *ci;
lua_assert(L->ci->next == NULL);
luaE_enterCcall(L);
ci = luaM_new(L, CallInfo);
lua_assert(L->ci->next == NULL);
L->ci->next = ci;
ci->previous = L->ci;
ci->next = NULL;
ci->u.l.trap = 0;
L->nci++;
return ci;
}
/*
** free all CallInfo structures not in use by a thread
*/
void luaE_freeCI (lua_State *L) {
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
ci->next = NULL;
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
while ((ci = next) != NULL) {
next = ci->next;
luaM_free(L, ci);
L->nci--;
}
L->nCcalls -= L->nci; /* adjust result */
}
/*
** free half of the CallInfo structures not in use by a thread,
** keeping the first one.
*/
void luaE_shrinkCI (lua_State *L) {
CallInfo *ci = L->ci->next; /* first free CallInfo */
CallInfo *next;
if (ci == NULL)
return; /* no extra elements */
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
while ((next = ci->next) != NULL) { /* two extra elements? */
CallInfo *next2 = next->next; /* next's next */
ci->next = next2; /* remove next from the list */
L->nci--;
luaM_free(L, next); /* free next */
if (next2 == NULL)
break; /* no more elements */
else {
next2->previous = ci;
ci = next2; /* continue */
}
}
L->nCcalls -= L->nci; /* adjust result */
}
static void stack_init (lua_State *L1, lua_State *L) {
int i; CallInfo *ci;
/* initialize stack array */
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue);
L1->stacksize = BASIC_STACK_SIZE;
for (i = 0; i < BASIC_STACK_SIZE; i++)
setnilvalue(s2v(L1->stack + i)); /* erase new stack */
L1->top = L1->stack;
L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
/* initialize first ci */
ci = &L1->base_ci;
ci->next = ci->previous = NULL;
ci->callstatus = CIST_C;
ci->func = L1->top;
ci->u.c.k = NULL;
ci->nresults = 0;
setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */
L1->top++;
ci->top = L1->top + LUA_MINSTACK;
L1->ci = ci;
}
static void freestack (lua_State *L) {
if (L->stack == NULL)
return; /* stack not completely built yet */
L->ci = &L->base_ci; /* free the entire 'ci' list */
luaE_freeCI(L);
lua_assert(L->nci == 0);
luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
}
/*
** Create registry table and its predefined values
*/
static void init_registry (lua_State *L, global_State *g) {
TValue temp;
/* create registry */
Table *registry = luaH_new(L);
sethvalue(L, &g->l_registry, registry);
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
/* registry[LUA_RIDX_MAINTHREAD] = L */
setthvalue(L, &temp, L); /* temp = L */
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
/* registry[LUA_RIDX_GLOBALS] = table of globals */
sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
}
/*
** open parts of the state that may cause memory-allocation errors.
** ('g->nilvalue' being a nil value flags that the state was completely
** build.)
*/
static void f_luaopen (lua_State *L, void *ud) {
global_State *g = G(L);
UNUSED(ud);
/* create a new global state */
L->l_G = luaM_new(L, global_State);
G(L)->GCthreshold = 0; /* mark it as unfinished state */
G(L)->strt.size = 0;
G(L)->strt.nuse = 0;
G(L)->strt.hash = NULL;
G(L)->Mbuffer = NULL;
G(L)->Mbuffsize = 0;
G(L)->panic = &default_panic;
G(L)->rootproto = NULL;
G(L)->rootcl = NULL;
G(L)->roottable = NULL;
G(L)->rootupval = NULL;
G(L)->rootudata = NULL;
G(L)->tmudata = NULL;
setnilvalue(key(G(L)->dummynode));
setnilvalue(val(G(L)->dummynode));
G(L)->dummynode->next = NULL;
G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
stack_init(L, L); /* init stack */
/* create default meta table with a dummy table, and then close the loop */
sethvalue(defaultmeta(L), NULL);
sethvalue(defaultmeta(L), luaH_new(L, 0, 4));
hvalue(defaultmeta(L))->metatable = hvalue(defaultmeta(L));
sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
init_registry(L, g);
luaS_init(L);
luaT_init(L);
luaX_init(L);
luaS_fix(luaS_newliteral(L, MEMERRMSG));
G(L)->GCthreshold = 4*G(L)->nblocks;
g->gcrunning = 1; /* allow gc */
setnilvalue(&g->nilvalue);
luai_userstateopen(L);
}
static void preinit_state (lua_State *L) {
/*
** preinitialize a thread with consistent values without allocating
** any memory (to avoid errors)
*/
static void preinit_thread (lua_State *L, global_State *g) {
G(L) = g;
L->stack = NULL;
L->ci = NULL;
L->nci = 0;
L->stacksize = 0;
L->twups = L; /* thread has no upvalues */
L->errorJmp = NULL;
L->hook = NULL;
L->hookmask = 0;
setallowhook(L, 1);
L->basehookcount = 0;
L->allowhook = 1;
resethookcount(L);
L->openupval = NULL;
L->size_ci = 0;
L->base_ci = L->ci = NULL;
L->status = LUA_OK;
L->errfunc = 0;
setnilvalue(defaultmeta(L));
setnilvalue(gt(L));
setnilvalue(registry(L));
}
LUA_API lua_State *lua_newthread (lua_State *OL) {
lua_State *L;
lua_lock(OL);
L = luaM_new(OL, lua_State);
preinit_state(L);
L->l_G = OL->l_G;
OL->next->previous = L; /* insert L into linked list */
L->next = OL->next;
OL->next = L;
L->previous = OL;
stack_init(L, OL); /* init stack */
setobj(defaultmeta(L), defaultmeta(OL)); /* share default meta table */
setobj(gt(L), gt(OL)); /* share table of globals */
setobj(registry(L), registry(OL)); /* share registry */
lua_unlock(OL);
lua_userstateopen(L);
return L;
}
LUA_API lua_State *lua_open (void) {
lua_State *L;
L = luaM_new(NULL, lua_State);
if (L) { /* allocation OK? */
preinit_state(L);
L->l_G = NULL;
L->next = L->previous = L;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
/* memory allocation error: free partial state */
close_state(L);
L = NULL;
}
}
lua_userstateopen(L);
return L;
}
void luaE_closethread (lua_State *OL, lua_State *L) {
luaF_close(L, L->stack); /* close all upvalues for this thread */
lua_assert(L->openupval == NULL);
L->previous->next = L->next;
L->next->previous = L->previous;
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
luaM_freearray(OL, L->stack, L->stacksize, TObject);
luaM_freelem(OL, L);
}
static void close_state (lua_State *L) {
luaF_close(L, L->stack); /* close all upvalues for this thread */
if (G(L)) { /* close global state */
luaC_collect(L, 1); /* collect all elements */
lua_assert(G(L)->rootproto == NULL);
lua_assert(G(L)->rootudata == NULL);
lua_assert(G(L)->rootcl == NULL);
lua_assert(G(L)->rootupval == NULL);
lua_assert(G(L)->roottable == NULL);
luaS_freeall(L);
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
luaM_freelem(NULL, L->l_G);
}
luaE_closethread(NULL, L);
global_State *g = G(L);
luaF_close(L, L->stack, CLOSEPROTECT); /* close all upvalues */
luaC_freeallobjects(L); /* collect all objects */
if (ttisnil(&g->nilvalue)) /* closing a fully built state? */
luai_userstateclose(L);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
freestack(L);
lua_assert(gettotalbytes(g) == sizeof(LG));
(*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
}
LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
LUA_API lua_State *lua_newthread (lua_State *L) {
global_State *g = G(L);
lua_State *L1;
lua_lock(L);
if (L == thread) luaG_runerror(L, "cannot close only thread of a state");
luaE_closethread(L, thread);
luaC_checkGC(L);
/* create new thread */
L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
L1->marked = luaC_white(g);
L1->tt = LUA_VTHREAD;
/* link it on list 'allgc' */
L1->next = g->allgc;
g->allgc = obj2gco(L1);
/* anchor it on L stack */
setthvalue2s(L, L->top, L1);
api_incr_top(L);
preinit_thread(L1, g);
L1->nCcalls = getCcalls(L);
L1->hookmask = L->hookmask;
L1->basehookcount = L->basehookcount;
L1->hook = L->hook;
resethookcount(L1);
/* initialize L1 extra space */
memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
LUA_EXTRASPACE);
luai_userstatethread(L, L1);
stack_init(L1, L); /* init stack */
lua_unlock(L);
return L1;
}
void luaE_freethread (lua_State *L, lua_State *L1) {
LX *l = fromstate(L1);
luaF_close(L1, L1->stack, NOCLOSINGMETH); /* close all upvalues */
lua_assert(L1->openupval == NULL);
luai_userstatefree(L, L1);
freestack(L1);
luaM_free(L, l);
}
int lua_resetthread (lua_State *L) {
CallInfo *ci;
int status;
lua_lock(L);
L->ci = ci = &L->base_ci; /* unwind CallInfo list */
setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */
ci->func = L->stack;
ci->callstatus = CIST_C;
status = luaF_close(L, L->stack, CLOSEPROTECT);
if (status != CLOSEPROTECT) /* real errors? */
luaD_seterrorobj(L, status, L->stack + 1);
else {
status = LUA_OK;
L->top = L->stack + 1;
}
ci->top = L->top + LUA_MINSTACK;
L->status = status;
lua_unlock(L);
return status;
}
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
int i;
lua_State *L;
global_State *g;
LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
if (l == NULL) return NULL;
L = &l->l.l;
g = &l->g;
L->tt = LUA_VTHREAD;
g->currentwhite = bitmask(WHITE0BIT);
L->marked = luaC_white(g);
preinit_thread(L, g);
g->allgc = obj2gco(L); /* by now, only object is the main thread */
L->next = NULL;
g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR;
g->frealloc = f;
g->ud = ud;
g->warnf = NULL;
g->ud_warn = NULL;
g->mainthread = L;
g->seed = luai_makeseed(L);
g->gcrunning = 0; /* no GC while building state */
g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL;
setnilvalue(&g->l_registry);
g->panic = NULL;
g->gcstate = GCSpause;
g->gckind = KGC_INC;
g->gcemergency = 0;
g->finobj = g->tobefnz = g->fixedgc = NULL;
g->survival = g->old = g->reallyold = NULL;
g->finobjsur = g->finobjold = g->finobjrold = NULL;
g->sweepgc = NULL;
g->gray = g->grayagain = NULL;
g->weak = g->ephemeron = g->allweak = NULL;
g->twups = NULL;
g->totalbytes = sizeof(LG);
g->GCdebt = 0;
g->lastatomic = 0;
setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */
setgcparam(g->gcpause, LUAI_GCPAUSE);
setgcparam(g->gcstepmul, LUAI_GCMUL);
g->gcstepsize = LUAI_GCSTEPSIZE;
setgcparam(g->genmajormul, LUAI_GENMAJORMUL);
g->genminormul = LUAI_GENMINORMUL;
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
/* memory allocation error: free partial state */
close_state(L);
L = NULL;
}
return L;
}
LUA_API void lua_close (lua_State *L) {
L = G(L)->mainthread; /* only the main thread can be closed */
lua_lock(L);
luaC_callallgcTM(L); /* call GC tag methods for all udata */
lua_assert(G(L)->tmudata == NULL);
while (L->next != L) /* then, close all other threads */
luaE_closethread(L, L->next);
close_state(L);
}
void luaE_warning (lua_State *L, const char *msg, int tocont) {
lua_WarnFunction wf = G(L)->warnf;
if (wf != NULL)
wf(G(L)->ud_warn, msg, tocont);
}
/*
** Generate a warning from an error message
*/
void luaE_warnerror (lua_State *L, const char *where) {
TValue *errobj = s2v(L->top - 1); /* error object */
const char *msg = (ttisstring(errobj))
? svalue(errobj)
: "error object is not a string";
/* produce warning "error in %s (%s)" (where, msg) */
luaE_warning(L, "error in ", 1);
luaE_warning(L, where, 1);
luaE_warning(L, " (", 1);
luaE_warning(L, msg, 1);
luaE_warning(L, ")", 0);
}
+273 -81
View File
@@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 1.93 2002/08/07 19:22:39 roberto Exp roberto $
** $Id: lstate.h $
** Global State
** See Copyright Notice in lua.h
*/
@@ -11,162 +11,354 @@
#include "lobject.h"
#include "ltm.h"
#include "lzio.h"
/*
** macros for thread syncronization inside Lua core machine:
** all accesses to the global state and to global objects are syncronized.
** Because threads can read the stack of other threads
** (when running garbage collection),
** a thread must also syncronize any write-access to its own stack.
** Unsyncronized accesses are allowed only when reading its own stack,
** or when reading immutable fields from global objects
** (such as string values and udata values).
** Some notes about garbage-collected objects: All objects in Lua must
** be kept somehow accessible until being freed, so all objects always
** belong to one (and only one) of these lists, using field 'next' of
** the 'CommonHeader' for the link:
**
** 'allgc': all objects not marked for finalization;
** 'finobj': all objects marked for finalization;
** 'tobefnz': all objects ready to be finalized;
** 'fixedgc': all objects that are not to be collected (currently
** only small strings, such as reserved words).
**
** For the generational collector, some of these lists have marks for
** generations. Each mark points to the first element in the list for
** that particular generation; that generation goes until the next mark.
**
** 'allgc' -> 'survival': new objects;
** 'survival' -> 'old': objects that survived one collection;
** 'old' -> 'reallyold': objects that became old in last collection;
** 'reallyold' -> NULL: objects old for more than one cycle.
**
** 'finobj' -> 'finobjsur': new objects marked for finalization;
** 'finobjsur' -> 'finobjold': survived """";
** 'finobjold' -> 'finobjrold': just old """";
** 'finobjrold' -> NULL: really old """".
*/
#ifndef lua_lock
#define lua_lock(L) ((void) 0)
#endif
#ifndef lua_unlock
#define lua_unlock(L) ((void) 0)
#endif
/*
** macro to allow the inclusion of user information in Lua state
** Moreover, there is another set of lists that control gray objects.
** These lists are linked by fields 'gclist'. (All objects that
** can become gray have such a field. The field is not the same
** in all objects, but it always has this name.) Any gray object
** must belong to one of these lists, and all objects in these lists
** must be gray:
**
** 'gray': regular gray objects, still waiting to be visited.
** 'grayagain': objects that must be revisited at the atomic phase.
** That includes
** - black objects got in a write barrier;
** - all kinds of weak tables during propagation phase;
** - all threads.
** 'weak': tables with weak values to be cleared;
** 'ephemeron': ephemeron tables with white->white entries;
** 'allweak': tables with weak keys and/or weak values to be cleared.
*/
#ifndef LUA_USERSTATE
#define LUA_USERSTATE
#endif
#ifndef lua_userstateopen
#define lua_userstateopen(l)
#endif
/*
** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
** how many "C calls" it still can do in the C stack, to avoid C-stack
** overflow. This count is very rough approximation; it considers only
** recursive functions inside the interpreter, as non-recursive calls
** can be considered using a fixed (although unknown) amount of stack
** space.
**
** The count has two parts: the lower part is the count itself; the
** higher part counts the number of non-yieldable calls in the stack.
** (They are together so that we can change both with one instruction.)
**
** Because calls to external C functions can use an unknown amount
** of space (e.g., functions using an auxiliary buffer), calls
** to these functions add more than one to the count (see CSTACKCF).
**
** The proper count excludes the number of CallInfo structures allocated
** by Lua, as a kind of "potential" calls. So, when Lua calls a function
** (and "consumes" one CallInfo), it needs neither to decrement nor to
** check 'nCcalls', as its use of C stack is already accounted for.
*/
/* number of "C stack slots" used by an external C function */
#define CSTACKCF 10
/*
** The C-stack size is sliced in the following zones:
** - larger than CSTACKERR: normal stack;
** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow;
** - [CSTACKCF, CSTACKERRMARK]: error-handling zone;
** - below CSTACKERRMARK: buffer zone to signal overflow during overflow;
** (Because the counter can be decremented CSTACKCF at once, we need
** the so called "buffer zones", with at least that size, to properly
** detect a change from one zone to the next.)
*/
#define CSTACKERR (8 * CSTACKCF)
#define CSTACKMARK (CSTACKERR - (CSTACKCF + 2))
#define CSTACKERRMARK (CSTACKCF + 2)
/* initial limit for the C-stack of threads */
#define CSTACKTHREAD (2 * CSTACKERR)
/* true if this thread does not have non-yieldable calls in the stack */
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
/* real number of C calls */
#define getCcalls(L) ((L)->nCcalls & 0xffff)
/* Increment the number of non-yieldable calls */
#define incnny(L) ((L)->nCcalls += 0x10000)
/* Decrement the number of non-yieldable calls */
#define decnny(L) ((L)->nCcalls -= 0x10000)
/* Increment the number of non-yieldable calls and decrement nCcalls */
#define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF)
/* Decrement the number of non-yieldable calls and increment nCcalls */
#define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF)
struct lua_longjmp; /* defined in ldo.c */
/*
** array of `global' objects
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
** is thread safe
*/
#define NUMGLOBS 3
/* default meta table (both for tables and udata) */
#define defaultmeta(L) (L->globs)
/* table of globals */
#define gt(L) (L->globs + 1)
/* registry */
#define registry(L) (L->globs + 2)
#if !defined(l_signalT)
#include <signal.h>
#define l_signalT sig_atomic_t
#endif
/* extra stack space to handle TM calls and some other extras */
#define EXTRA_STACK 5
#define BASIC_CI_SIZE 8
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
/* kinds of Garbage Collection */
#define KGC_INC 0 /* incremental gc */
#define KGC_GEN 1 /* generational gc */
typedef struct stringtable {
TString **hash;
ls_nstr nuse; /* number of elements */
int nuse; /* number of elements */
int size;
} stringtable;
/*
** informations about a call
** Information about a call.
*/
typedef struct CallInfo {
StkId base; /* base for called function */
StkId func; /* function index in the stack */
StkId top; /* top for this function */
int state; /* bit fields; see below */
struct CallInfo *previous, *next; /* dynamic call link */
union {
struct { /* for Lua functions */
struct { /* only for Lua functions */
const Instruction *savedpc;
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
StkId *pb; /* points to `base' variable in `luaV_execute' */
volatile l_signalT trap;
int nextraargs; /* # of extra arguments in vararg functions */
} l;
struct { /* for C functions */
int yield_results;
struct { /* only for C functions */
lua_KFunction k; /* continuation in case of yields */
ptrdiff_t old_errfunc;
lua_KContext ctx; /* context info. in case of yields */
} c;
} u;
union {
int funcidx; /* called-function index */
int nyield; /* number of values yielded */
struct { /* info about transferred values (for call/return hooks) */
unsigned short ftransfer; /* offset of first value transferred */
unsigned short ntransfer; /* number of values transferred */
} transferinfo;
} u2;
short nresults; /* expected number of results from this function */
unsigned short callstatus;
} CallInfo;
/*
** bit fields for `CallInfo.state'
** Bits in CallInfo status
*/
#define CI_C 1 /* 1 if function is a C function */
/* 1 if (Lua) function has an active `luaV_execute' running it */
#define CI_HASFRAME 2
/* 1 if Lua function is calling another Lua function (and therefore its
`pc' is being used by the other, and therefore CI_SAVEDPC is 1 too) */
#define CI_CALLING 4
#define CI_SAVEDPC 8 /* 1 if `savedpc' is updated */
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
#define CIST_C (1<<1) /* call is running a C function */
#define CIST_HOOKED (1<<2) /* call is running a debug hook */
#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */
#define CIST_TAIL (1<<4) /* call was tail called */
#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */
#define CIST_FIN (1<<6) /* call is running a finalizer */
#define CIST_TRAN (1<<7) /* 'ci' has transfer information */
#if defined(LUA_COMPAT_LT_LE)
#define CIST_LEQ (1<<8) /* using __lt for __le */
#endif
/* active function is a Lua function */
#define isLua(ci) (!((ci)->callstatus & CIST_C))
#define ci_func(ci) (clvalue((ci)->base - 1))
/* call is running Lua code (not a hook) */
#define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED)))
/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v))
#define getoah(st) ((st) & CIST_OAH)
/*
** `global state', shared by all threads of this state
** 'global state', shared by all threads of this state
*/
typedef struct global_State {
lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to 'frealloc' */
l_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */
stringtable strt; /* hash table for strings */
Proto *rootproto; /* list of all prototypes */
Closure *rootcl; /* list of all closures */
Table *roottable; /* list of all tables */
UpVal *rootupval; /* list of closed up values */
Udata *rootudata; /* list of all userdata */
Udata *tmudata; /* list of userdata to be GC */
void *Mbuffer; /* global buffer */
size_t Mbuffsize; /* size of Mbuffer */
lu_mem GCthreshold;
lu_mem nblocks; /* number of `bytes' currently allocated */
TValue l_registry;
TValue nilvalue; /* a nil value */
unsigned int seed; /* randomized seed for hashes */
lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */
lu_byte genminormul; /* control for minor generational collections */
lu_byte genmajormul; /* control for major generational collections */
lu_byte gcrunning; /* true if GC is running */
lu_byte gcemergency; /* true if this is an emergency collection */
lu_byte gcpause; /* size of pause between successive GCs */
lu_byte gcstepmul; /* GC "speed" */
lu_byte gcstepsize; /* (log2 of) GC granularity */
GCObject *allgc; /* list of all collectable objects */
GCObject **sweepgc; /* current position of sweep in list */
GCObject *finobj; /* list of collectable objects with finalizers */
GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of tables with weak values */
GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
GCObject *allweak; /* list of all-weak tables */
GCObject *tobefnz; /* list of userdata to be GC */
GCObject *fixedgc; /* list of objects not to be collected */
/* fields for generational collector */
GCObject *survival; /* start of objects that survived one GC cycle */
GCObject *old; /* start of old objects */
GCObject *reallyold; /* old objects with more than one cycle */
GCObject *finobjsur; /* list of survival objects with finalizers */
GCObject *finobjold; /* list of old objects with finalizers */
GCObject *finobjrold; /* list of really old objects with finalizers */
struct lua_State *twups; /* list of threads with open upvalues */
lua_CFunction panic; /* to be called in unprotected errors */
Node dummynode[1]; /* common node array for all empty tables */
struct lua_State *mainthread;
TString *memerrmsg; /* message for memory-allocation errors */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
lua_WarnFunction warnf; /* warning function */
void *ud_warn; /* auxiliary data to 'warnf' */
unsigned int Cstacklimit; /* current limit for the C stack */
} global_State;
/*
** `per thread' state
** 'per thread' state
*/
struct lua_State {
LUA_USERSTATE
CommonHeader;
lu_byte status;
lu_byte allowhook;
unsigned short nci; /* number of items in 'ci' list */
StkId top; /* first free slot in the stack */
global_State *l_G;
CallInfo *ci; /* call info for current function */
const Instruction *oldpc; /* last pc traced */
StkId stack_last; /* last free slot in the stack */
StkId stack; /* stack base */
int stacksize;
CallInfo *end_ci; /* points after end of ci array*/
CallInfo *base_ci; /* array of CallInfo's */
int size_ci; /* size of array `base_ci' */
unsigned long hookmask;
ls_count hookcount;
lua_Hook hook;
UpVal *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_State *twups; /* list of threads with open upvalues */
struct lua_longjmp *errorJmp; /* current error recover point */
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
volatile lua_Hook hook;
ptrdiff_t errfunc; /* current error handling function (stack index) */
lua_State *next; /* circular double linked list of states */
lua_State *previous;
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
l_uint32 nCcalls; /* number of allowed nested C calls - 'nci' */
int stacksize;
int basehookcount;
int hookcount;
volatile l_signalT hookmask;
};
#define G(L) (L->l_G)
void luaE_closethread (lua_State *OL, lua_State *L);
/*
** Union of all collectable objects (only for conversions)
*/
union GCUnion {
GCObject gc; /* common header */
struct TString ts;
struct Udata u;
union Closure cl;
struct Table h;
struct Proto p;
struct lua_State th; /* thread */
struct UpVal upv;
};
#define cast_u(o) cast(union GCUnion *, (o))
/* macros to convert a GCObject into a specific value */
#define gco2ts(o) \
check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u))
#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l))
#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c))
#define gco2cl(o) \
check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
/*
** macro to convert a Lua object into a GCObject
** (The access to 'tt' tries to ensure that 'v' is actually a Lua object.)
*/
#define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc))
/* actual number of total bytes allocated */
#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt)
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
LUAI_FUNC void luaE_enterCcall (lua_State *L);
LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
#define luaE_exitCcall(L) ((L)->nCcalls++)
#endif
+248 -60
View File
@@ -1,97 +1,285 @@
/*
** $Id: lstring.c,v 1.73 2002/03/20 18:37:13 roberto Exp roberto $
** $Id: lstring.c $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
#define lstring_c
#define LUA_CORE
#include "lprefix.h"
#include <string.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
/*
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to
** compute its hash
*/
#if !defined(LUAI_HASHLIMIT)
#define LUAI_HASHLIMIT 5
#endif
void luaS_freeall (lua_State *L) {
lua_assert(G(L)->strt.nuse==0);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
/*
** Maximum size for string table.
*/
#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*))
/*
** equality for long strings
*/
int luaS_eqlngstr (TString *a, TString *b) {
size_t len = a->u.lnglen;
lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
return (a == b) || /* same instance or... */
((len == b->u.lnglen) && /* equal length and ... */
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}
void luaS_resize (lua_State *L, int newsize) {
TString **newhash = luaM_newvector(L, newsize, TString *);
stringtable *tb = &G(L)->strt;
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed,
size_t step) {
unsigned int h = seed ^ cast_uint(l);
for (; l >= step; l -= step)
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
return h;
}
unsigned int luaS_hashlongstr (TString *ts) {
lua_assert(ts->tt == LUA_VLNGSTR);
if (ts->extra == 0) { /* no hash? */
size_t len = ts->u.lnglen;
size_t step = (len >> LUAI_HASHLIMIT) + 1;
ts->hash = luaS_hash(getstr(ts), len, ts->hash, step);
ts->extra = 1; /* now it has its hash */
}
return ts->hash;
}
static void tablerehash (TString **vect, int osize, int nsize) {
int i;
for (i=0; i<newsize; i++) newhash[i] = NULL;
/* rehash */
for (i=0; i<tb->size; i++) {
TString *p = tb->hash[i];
while (p) { /* for each node in the list */
TString *next = p->tsv.nexthash; /* save next */
lu_hash h = p->tsv.hash;
int h1 = lmod(h, newsize); /* new position */
lua_assert(cast(int, h%newsize) == lmod(h, newsize));
p->tsv.nexthash = newhash[h1]; /* chain it in new position */
newhash[h1] = p;
p = next;
for (i = osize; i < nsize; i++) /* clear new elements */
vect[i] = NULL;
for (i = 0; i < osize; i++) { /* rehash old part of the array */
TString *p = vect[i];
vect[i] = NULL;
while (p) { /* for each string in the list */
TString *hnext = p->u.hnext; /* save next */
unsigned int h = lmod(p->hash, nsize); /* new position */
p->u.hnext = vect[h]; /* chain it into array */
vect[h] = p;
p = hnext;
}
}
luaM_freearray(L, tb->hash, tb->size, TString *);
tb->size = newsize;
tb->hash = newhash;
}
static TString *newlstr (lua_State *L, const char *str, size_t l, lu_hash h) {
TString *ts = cast(TString *, luaM_malloc(L, sizestring(l)));
stringtable *tb;
ts->tsv.nexthash = NULL;
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.marked = 0;
memcpy(ts+1, str, l*sizeof(char));
((char *)(ts+1))[l] = '\0'; /* ending 0 */
tb = &G(L)->strt;
h = lmod(h, tb->size);
ts->tsv.nexthash = tb->hash[h]; /* chain new entry */
tb->hash[h] = ts;
tb->nuse++;
if (tb->nuse > cast(ls_nstr, tb->size) && tb->size <= MAX_INT/2)
luaS_resize(L, tb->size*2); /* too crowded */
/*
** Resize the string table. If allocation fails, keep the current size.
** (This can degrade performance, but any non-zero size should work
** correctly.)
*/
void luaS_resize (lua_State *L, int nsize) {
stringtable *tb = &G(L)->strt;
int osize = tb->size;
TString **newvect;
if (nsize < osize) /* shrinking table? */
tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */
newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
if (unlikely(newvect == NULL)) { /* reallocation failed? */
if (nsize < osize) /* was it shrinking table? */
tablerehash(tb->hash, nsize, osize); /* restore to original size */
/* leave table as it was */
}
else { /* allocation succeeded */
tb->hash = newvect;
tb->size = nsize;
if (nsize > osize)
tablerehash(newvect, osize, nsize); /* rehash for new size */
}
}
/*
** Clear API string cache. (Entries cannot be empty, so fill them with
** a non-collectable string.)
*/
void luaS_clearcache (global_State *g) {
int i, j;
for (i = 0; i < STRCACHE_N; i++)
for (j = 0; j < STRCACHE_M; j++) {
if (iswhite(g->strcache[i][j])) /* will entry be collected? */
g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */
}
}
/*
** Initialize the string table and the string cache
*/
void luaS_init (lua_State *L) {
global_State *g = G(L);
int i, j;
stringtable *tb = &G(L)->strt;
tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */
tb->size = MINSTRTABSIZE;
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */
for (j = 0; j < STRCACHE_M; j++)
g->strcache[i][j] = g->memerrmsg;
}
/*
** creates a new string object
*/
static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
TString *ts;
GCObject *o;
size_t totalsize; /* total size of TString object */
totalsize = sizelstring(l);
o = luaC_newobj(L, tag, totalsize);
ts = gco2ts(o);
ts->hash = h;
ts->extra = 0;
getstr(ts)[l] = '\0'; /* ending 0 */
return ts;
}
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
TString *ts;
lu_hash h = (lu_hash)l; /* seed */
size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */
size_t l1;
for (l1=l; l1>=step; l1-=step) /* compute hash */
h = h ^ ((h<<5)+(h>>2)+(unsigned char)(str[l1-1]));
for (ts = G(L)->strt.hash[lmod(h, G(L)->strt.size)];
ts != NULL;
ts = ts->tsv.nexthash) {
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0))
return ts;
}
return newlstr(L, str, l, h); /* not found */
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
ts->u.lnglen = l;
return ts;
}
Udata *luaS_newudata (lua_State *L, size_t s) {
void luaS_remove (lua_State *L, TString *ts) {
stringtable *tb = &G(L)->strt;
TString **p = &tb->hash[lmod(ts->hash, tb->size)];
while (*p != ts) /* find previous element */
p = &(*p)->u.hnext;
*p = (*p)->u.hnext; /* remove element from its list */
tb->nuse--;
}
static void growstrtab (lua_State *L, stringtable *tb) {
if (unlikely(tb->nuse == MAX_INT)) { /* too many strings? */
luaC_fullgc(L, 1); /* try to free some... */
if (tb->nuse == MAX_INT) /* still too many? */
luaM_error(L); /* cannot even create a message... */
}
if (tb->size <= MAXSTRTB / 2) /* can grow string table? */
luaS_resize(L, tb->size * 2);
}
/*
** Checks whether short string exists and reuses it or creates a new one.
*/
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
TString *ts;
global_State *g = G(L);
stringtable *tb = &g->strt;
unsigned int h = luaS_hash(str, l, g->seed, 1);
TString **list = &tb->hash[lmod(h, tb->size)];
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
/* found! */
if (isdead(g, ts)) /* dead (but not collected yet)? */
changewhite(ts); /* resurrect it */
return ts;
}
}
/* else must create a new string */
if (tb->nuse >= tb->size) { /* need to grow string table? */
growstrtab(L, tb);
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
}
ts = createstrobj(L, l, LUA_VSHRSTR, h);
memcpy(getstr(ts), str, l * sizeof(char));
ts->shrlen = cast_byte(l);
ts->u.hnext = *list;
*list = ts;
tb->nuse++;
return ts;
}
/*
** new string (with explicit length)
*/
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
if (l <= LUAI_MAXSHORTLEN) /* short string? */
return internshrstr(L, str, l);
else {
TString *ts;
if (unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
luaM_toobig(L);
ts = luaS_createlngstrobj(L, l);
memcpy(getstr(ts), str, l * sizeof(char));
return ts;
}
}
/*
** Create or reuse a zero-terminated string, first checking in the
** cache (using the string address as a key). The cache can contain
** only zero-terminated strings, so it is safe to use 'strcmp' to
** check hits.
*/
TString *luaS_new (lua_State *L, const char *str) {
unsigned int i = point2uint(str) % STRCACHE_N; /* hash */
int j;
TString **p = G(L)->strcache[i];
for (j = 0; j < STRCACHE_M; j++) {
if (strcmp(str, getstr(p[j])) == 0) /* hit? */
return p[j]; /* that is it */
}
/* normal route */
for (j = STRCACHE_M - 1; j > 0; j--)
p[j] = p[j - 1]; /* move out last element */
/* new element is first in the list */
p[0] = luaS_newlstr(L, str, strlen(str));
return p[0];
}
Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
Udata *u;
s = (s+3) & (~(size_t)3); /* make sure size is multiple of 4 */
u = cast(Udata *, luaM_malloc(L, sizeudata(s)));
u->uv.len = s;
u->uv.metatable = hvalue(defaultmeta(L));
/* chain it on udata list */
u->uv.next = G(L)->rootudata;
G(L)->rootudata = u;
int i;
GCObject *o;
if (unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
luaM_toobig(L);
o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
u = gco2u(o);
u->len = s;
u->nuvalue = nuvalue;
u->metatable = NULL;
for (i = 0; i < nuvalue; i++)
setnilvalue(&u->uv[i].uv);
return u;
}
+35 -18
View File
@@ -1,5 +1,5 @@
/*
** $Id: lstring.h,v 1.35 2001/11/28 20:13:13 roberto Exp roberto $
** $Id: lstring.h $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -7,35 +7,52 @@
#ifndef lstring_h
#define lstring_h
#include "lgc.h"
#include "lobject.h"
#include "lstate.h"
/*
** Memory-allocation error message must be preallocated (it cannot
** be created after memory is exhausted)
*/
#define MEMERRMSG "not enough memory"
/*
** any TString with mark>=FIXMARK is never collected.
** Marks>=RESERVEDMARK are used to identify reserved words.
** Size of a TString: Size of the header plus space for the string
** itself (including final '\0').
*/
#define FIXMARK 2
#define RESERVEDMARK 3
#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
#define sizestring(l) (cast(lu_mem, sizeof(union TString))+ \
(cast(lu_mem, l)+1)*sizeof(char))
#define sizeudata(l) (cast(lu_mem, sizeof(union Udata))+(l))
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
(sizeof(s)/sizeof(char))-1))
#define luaS_fix(s) ((s)->tsv.marked = FIXMARK)
void luaS_resize (lua_State *L, int newsize);
Udata *luaS_newudata (lua_State *L, size_t s);
void luaS_freeall (lua_State *L);
TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
/*
** test whether a string is a reserved word
*/
#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0)
/*
** equality for short strings, which are always internalized
*/
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l,
unsigned int seed, size_t step);
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC void luaS_clearcache (global_State *g);
LUAI_FUNC void luaS_init (lua_State *L);
LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
#endif
+1417 -324
View File
File diff suppressed because it is too large Load Diff
+777 -342
View File
File diff suppressed because it is too large Load Diff
+40 -14
View File
@@ -1,5 +1,5 @@
/*
** $Id: ltable.h,v 1.41 2002/03/11 12:45:00 roberto Exp roberto $
** $Id: ltable.h $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -10,22 +10,48 @@
#include "lobject.h"
#define node(t,i) (&(t)->node[i])
#define key(n) (&(n)->i_key)
#define val(n) (&(n)->i_val)
#define gnode(t,i) (&(t)->node[i])
#define gval(n) (&(n)->i_val)
#define gnext(n) ((n)->u.next)
const TObject *luaH_getnum (Table *t, int key);
TObject *luaH_setnum (lua_State *L, Table *t, int key);
const TObject *luaH_getstr (Table *t, TString *key);
const TObject *luaH_get (Table *t, const TObject *key);
TObject *luaH_set (lua_State *L, Table *t, const TObject *key);
Table *luaH_new (lua_State *L, int narray, int lnhash);
void luaH_free (lua_State *L, Table *t);
int luaH_next (lua_State *L, Table *t, TObject *key);
#define invalidateTMcache(t) ((t)->flags = 0)
/* exported only for debugging */
Node *luaH_mainposition (const Table *t, const TObject *key);
/* true when 't' is using 'dummynode' as its hash part */
#define isdummy(t) ((t)->lastfree == NULL)
/* allocated size for hash nodes */
#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t))
/* returns the Node, given the value of a table entry */
#define nodefromval(v) cast(Node *, (v))
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
TValue *value);
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
LUAI_FUNC Table *luaH_new (lua_State *L);
LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
unsigned int nhsize);
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize);
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
LUAI_FUNC unsigned int luaH_realasize (const Table *t);
#if defined(LUA_DEBUG)
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
LUAI_FUNC int luaH_isdummy (const Table *t);
#endif
#endif
+349 -215
View File
@@ -1,11 +1,18 @@
/*
** $Id: ltablib.c,v 1.11 2002/08/06 17:06:56 roberto Exp roberto $
** $Id: ltablib.c $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
#define ltablib_c
#define LUA_LIB
#include "lprefix.h"
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include "lua.h"
@@ -13,282 +20,409 @@
#include "lualib.h"
/*
** Operations that an object must define to mimic a table
** (some functions only need some of them)
*/
#define TAB_R 1 /* read */
#define TAB_W 2 /* write */
#define TAB_L 4 /* length */
#define TAB_RW (TAB_R | TAB_W) /* read/write */
static int checkint (lua_State *L) {
int n = (int)lua_tonumber(L, -1);
if (n == 0 && !lua_isnumber(L, -1)) n = -1;
lua_pop(L, 1);
return n;
#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n))
static int checkfield (lua_State *L, const char *key, int n) {
lua_pushstring(L, key);
return (lua_rawget(L, -n) != LUA_TNIL);
}
static void aux_setn (lua_State *L, int t, int n) {
lua_pushliteral(L, "n");
lua_rawget(L, t);
if (checkint(L) >= 0) {
lua_pushliteral(L, "n"); /* use it */
lua_pushnumber(L, n);
lua_rawset(L, t);
}
else { /* use N */
lua_pushvalue(L, t);
lua_pushnumber(L, n);
lua_rawset(L, lua_upvalueindex(1)); /* N[t] = n */
}
}
static int aux_getn (lua_State *L, int t) {
int n;
luaL_check_type(L, t, LUA_TTABLE);
lua_pushliteral(L, "n"); /* try t.n */
lua_rawget(L, t);
if ((n = checkint(L)) >= 0) return n;
lua_pushvalue(L, t); /* try N[t] */
lua_rawget(L, lua_upvalueindex(1));
if ((n = checkint(L)) >= 0) return n;
else { /* must count elements */
n = 0;
for (;;) {
lua_rawgeti(L, t, ++n);
if (lua_isnil(L, -1)) break;
lua_pop(L, 1);
/*
** Check that 'arg' either is a table or can behave like one (that is,
** has a metatable with the required metamethods)
*/
static void checktab (lua_State *L, int arg, int what) {
if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */
int n = 1; /* number of elements to pop */
if (lua_getmetatable(L, arg) && /* must have metatable */
(!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
(!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
(!(what & TAB_L) || checkfield(L, "__len", ++n))) {
lua_pop(L, n); /* pop metatable and tested metamethods */
}
lua_pop(L, 1);
aux_setn(L, t, n - 1);
return n - 1;
else
luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
}
}
static int luaB_foreachi (lua_State *L) {
int i;
int n = aux_getn(L, 1);
luaL_check_type(L, 2, LUA_TFUNCTION);
for (i=1; i<=n; i++) {
lua_pushvalue(L, 2); /* function */
lua_pushnumber(L, i); /* 1st argument */
lua_rawgeti(L, 1, i); /* 2nd argument */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 1); /* remove nil result */
static int tinsert (lua_State *L) {
lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */
lua_Integer pos; /* where to insert new element */
switch (lua_gettop(L)) {
case 2: { /* called with only 2 arguments */
pos = e; /* insert new element at the end */
break;
}
case 3: {
lua_Integer i;
pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
/* check whether 'pos' is in [1, e] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u < (lua_Unsigned)e, 2,
"position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
lua_geti(L, 1, i - 1);
lua_seti(L, 1, i); /* t[i] = t[i - 1] */
}
break;
}
default: {
return luaL_error(L, "wrong number of arguments to 'insert'");
}
}
lua_seti(L, 1, pos); /* t[pos] = v */
return 0;
}
static int luaB_foreach (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
luaL_check_type(L, 2, LUA_TFUNCTION);
lua_pushnil(L); /* first key */
for (;;) {
if (lua_next(L, 1) == 0)
return 0;
lua_pushvalue(L, 2); /* function */
lua_pushvalue(L, -3); /* key */
lua_pushvalue(L, -3); /* value */
lua_call(L, 2, 1);
if (!lua_isnil(L, -1))
return 1;
lua_pop(L, 2); /* remove value and result */
}
}
static int luaB_getn (lua_State *L) {
lua_pushnumber(L, aux_getn(L, 1));
return 1;
}
static int luaB_setn (lua_State *L) {
luaL_check_type(L, 1, LUA_TTABLE);
aux_setn(L, 1, luaL_check_int(L, 2));
return 0;
}
static int luaB_tinsert (lua_State *L) {
int v = lua_gettop(L); /* number of arguments */
int n = aux_getn(L, 1) + 1;
int pos; /* where to insert new element */
if (v == 2) /* called with only 2 arguments */
pos = n; /* insert new element at the end */
else {
pos = luaL_check_int(L, 2); /* 2nd argument is the position */
if (pos > n) n = pos; /* `grow' array if necessary */
v = 3; /* function may be called with more than 3 args */
}
aux_setn(L, 1, n); /* new size */
while (--n >= pos) { /* move up elements */
lua_rawgeti(L, 1, n);
lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */
}
lua_pushvalue(L, v);
lua_rawseti(L, 1, pos); /* t[pos] = v */
return 0;
}
static int luaB_tremove (lua_State *L) {
int n = aux_getn(L, 1);
int pos = luaL_opt_int(L, 2, n);
if (n <= 0) return 0; /* table is `empty' */
aux_setn(L, 1, n-1); /* t.n = n-1 */
lua_rawgeti(L, 1, pos); /* result = t[pos] */
for ( ;pos<n; pos++) {
lua_rawgeti(L, 1, pos+1);
lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */
static int tremove (lua_State *L) {
lua_Integer size = aux_getn(L, 1, TAB_RW);
lua_Integer pos = luaL_optinteger(L, 2, size);
if (pos != size) /* validate 'pos' if given */
/* check whether 'pos' is in [1, size + 1] */
luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1,
"position out of bounds");
lua_geti(L, 1, pos); /* result = t[pos] */
for ( ; pos < size; pos++) {
lua_geti(L, 1, pos + 1);
lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
}
lua_pushnil(L);
lua_rawseti(L, 1, n); /* t[n] = nil */
lua_seti(L, 1, pos); /* remove entry t[pos] */
return 1;
}
static int str_concat (lua_State *L) {
luaL_Buffer b;
int n = aux_getn(L, 1);
size_t lsep;
const char *sep = luaL_opt_lstr(L, 2, "", &lsep);
int i;
luaL_buffinit(L, &b);
for (i=1; i<=n; i++) {
lua_rawgeti(L, 1, i);
luaL_arg_check(L, lua_isstring(L, -1), 1,
"table contains non-strings");
luaL_addvalue(&b);
if (i != n)
luaL_addlstring(&b, sep, lsep);
/*
** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
** possible, copy in increasing order, which is better for rehashing.
** "possible" means destination after original range, or smaller
** than origin, or copying to another table.
*/
static int tmove (lua_State *L) {
lua_Integer f = luaL_checkinteger(L, 2);
lua_Integer e = luaL_checkinteger(L, 3);
lua_Integer t = luaL_checkinteger(L, 4);
int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
checktab(L, 1, TAB_R);
checktab(L, tt, TAB_W);
if (e >= f) { /* otherwise, nothing to move */
lua_Integer n, i;
luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
"too many elements to move");
n = e - f + 1; /* number of elements to move */
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
"destination wrap around");
if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
for (i = 0; i < n; i++) {
lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i);
}
}
else {
for (i = n - 1; i >= 0; i--) {
lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i);
}
}
}
lua_pushvalue(L, tt); /* return destination table */
return 1;
}
static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
lua_geti(L, 1, i);
if (!lua_isstring(L, -1))
luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
luaL_typename(L, -1), i);
luaL_addvalue(b);
}
static int tconcat (lua_State *L) {
luaL_Buffer b;
lua_Integer last = aux_getn(L, 1, TAB_R);
size_t lsep;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
lua_Integer i = luaL_optinteger(L, 3, 1);
last = luaL_optinteger(L, 4, last);
luaL_buffinit(L, &b);
for (; i < last; i++) {
addfield(L, &b, i);
luaL_addlstring(&b, sep, lsep);
}
if (i == last) /* add last value (if interval was not empty) */
addfield(L, &b, i);
luaL_pushresult(&b);
return 1;
}
/*
** {======================================================
** Pack/unpack
** =======================================================
*/
static int tpack (lua_State *L) {
int i;
int n = lua_gettop(L); /* number of elements to pack */
lua_createtable(L, n, 1); /* create result table */
lua_insert(L, 1); /* put it at index 1 */
for (i = n; i >= 1; i--) /* assign elements */
lua_seti(L, 1, i);
lua_pushinteger(L, n);
lua_setfield(L, 1, "n"); /* t.n = number of elements */
return 1; /* return table */
}
static int tunpack (lua_State *L) {
lua_Unsigned n;
lua_Integer i = luaL_optinteger(L, 2, 1);
lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n)))
return luaL_error(L, "too many results to unpack");
for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */
lua_geti(L, 1, i);
}
lua_geti(L, 1, e); /* push last element */
return (int)n;
}
/* }====================================================== */
/*
** {======================================================
** Quicksort
** (based on `Algorithms in MODULA-3', Robert Sedgewick;
** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
** Addison-Wesley, 1993.)
** =======================================================
*/
static void set2 (lua_State *L, int i, int j) {
lua_rawseti(L, 1, i);
lua_rawseti(L, 1, j);
/* type for array indices */
typedef unsigned int IdxT;
/*
** Produce a "random" 'unsigned int' to randomize pivot choice. This
** macro is used only when 'sort' detects a big imbalance in the result
** of a partition. (If you don't want/need this "randomness", ~0 is a
** good choice.)
*/
#if !defined(l_randomizePivot) /* { */
#include <time.h>
/* size of 'e' measured in number of 'unsigned int's */
#define sof(e) (sizeof(e) / sizeof(unsigned int))
/*
** Use 'time' and 'clock' as sources of "randomness". Because we don't
** know the types 'clock_t' and 'time_t', we cannot cast them to
** anything without risking overflows. A safe way to use their values
** is to copy them to an array of a known type and use the array values.
*/
static unsigned int l_randomizePivot (void) {
clock_t c = clock();
time_t t = time(NULL);
unsigned int buff[sof(c) + sof(t)];
unsigned int i, rnd = 0;
memcpy(buff, &c, sof(c) * sizeof(unsigned int));
memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
for (i = 0; i < sof(buff); i++)
rnd += buff[i];
return rnd;
}
#endif /* } */
/* arrays larger than 'RANLIMIT' may use randomized pivots */
#define RANLIMIT 100u
static void set2 (lua_State *L, IdxT i, IdxT j) {
lua_seti(L, 1, i);
lua_seti(L, 1, j);
}
/*
** Return true iff value at stack index 'a' is less than the value at
** index 'b' (according to the order of the sort).
*/
static int sort_comp (lua_State *L, int a, int b) {
if (!lua_isnil(L, 2)) { /* function? */
if (lua_isnil(L, 2)) /* no function? */
return lua_compare(L, a, b, LUA_OPLT); /* a < b */
else { /* function */
int res;
lua_pushvalue(L, 2);
lua_pushvalue(L, 2); /* push function */
lua_pushvalue(L, a-1); /* -1 to compensate function */
lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
lua_call(L, 2, 1);
res = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
lua_call(L, 2, 1); /* call function */
res = lua_toboolean(L, -1); /* get result */
lua_pop(L, 1); /* pop result */
return res;
}
else /* a < b? */
return lua_lessthan(L, a, b);
}
static void auxsort (lua_State *L, int l, int u) {
while (l < u) { /* for tail recursion */
int i, j;
/* sort elements a[l], a[(l+u)/2] and a[u] */
lua_rawgeti(L, 1, l);
lua_rawgeti(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
set2(L, l, u); /* swap a[l] - a[u] */
/*
** Does the partition: Pivot P is at the top of the stack.
** precondition: a[lo] <= P == a[up-1] <= a[up],
** so it only needs to do the partition from lo + 1 to up - 2.
** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
** returns 'i'.
*/
static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
IdxT i = lo; /* will be incremented before first use */
IdxT j = up - 1; /* will be decremented before first use */
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */
for (;;) {
/* next loop: repeat ++i while a[i] < P */
while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */
luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[i] */
}
/* after the loop, a[i] >= P and a[lo .. i - 1] < P */
/* next loop: repeat --j while P < a[j] */
while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
if (j < i) /* j < i but a[j] > P ?? */
luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[j] */
}
/* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
if (j < i) { /* no elements out of place? */
/* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
lua_pop(L, 1); /* pop a[j] */
/* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
set2(L, up - 1, i);
return i;
}
/* otherwise, swap a[i] - a[j] to restore invariant and repeat */
set2(L, i, j);
}
}
/*
** Choose an element in the middle (2nd-3th quarters) of [lo,up]
** "randomized" by 'rnd'
*/
static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
IdxT r4 = (up - lo) / 4; /* range/4 */
IdxT p = rnd % (r4 * 2) + (lo + r4);
lua_assert(lo + r4 <= p && p <= up - r4);
return p;
}
/*
** Quicksort algorithm (recursive function)
*/
static void auxsort (lua_State *L, IdxT lo, IdxT up,
unsigned int rnd) {
while (lo < up) { /* loop for tail recursion */
IdxT p; /* Pivot index */
IdxT n; /* to be used later */
/* sort elements 'lo', 'p', and 'up' */
lua_geti(L, 1, lo);
lua_geti(L, 1, up);
if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */
set2(L, lo, up); /* swap a[lo] - a[up] */
else
lua_pop(L, 2);
if (u-l == 1) break; /* only 2 elements */
i = (l+u)/2;
lua_rawgeti(L, 1, i);
lua_rawgeti(L, 1, l);
if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
set2(L, i, l);
lua_pop(L, 2); /* remove both values */
if (up - lo == 1) /* only 2 elements? */
return; /* already sorted */
if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */
p = (lo + up)/2; /* middle element is a good pivot */
else /* for larger intervals, it is worth a random pivot */
p = choosePivot(lo, up, rnd);
lua_geti(L, 1, p);
lua_geti(L, 1, lo);
if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
set2(L, p, lo); /* swap a[p] - a[lo] */
else {
lua_pop(L, 1); /* remove a[l] */
lua_rawgeti(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
set2(L, i, u);
lua_pop(L, 1); /* remove a[lo] */
lua_geti(L, 1, up);
if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */
set2(L, p, up); /* swap a[up] - a[p] */
else
lua_pop(L, 2);
}
if (u-l == 2) break; /* only 3 elements */
lua_rawgeti(L, 1, i); /* Pivot */
lua_pushvalue(L, -1);
lua_rawgeti(L, 1, u-1);
set2(L, i, u-1);
/* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
i = l; j = u-1;
for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
/* repeat ++i until a[i] >= P */
while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i>u) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[i] */
}
/* repeat --j until a[j] <= P */
while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
if (j<l) luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[j] */
}
if (j<i) {
lua_pop(L, 3); /* pop pivot, a[i], a[j] */
break;
}
set2(L, i, j);
}
lua_rawgeti(L, 1, u-1);
lua_rawgeti(L, 1, i);
set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
/* a[l..i-1] <= a[i] == P <= a[i+1..u] */
/* adjust so that smaller half is in [j..i] and larger one in [l..u] */
if (i-l < u-i) {
j=l; i=i-1; l=i+2;
if (up - lo == 2) /* only 3 elements? */
return; /* already sorted */
lua_geti(L, 1, p); /* get middle element (Pivot) */
lua_pushvalue(L, -1); /* push Pivot */
lua_geti(L, 1, up - 1); /* push a[up - 1] */
set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */
p = partition(L, lo, up);
/* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
if (p - lo < up - p) { /* lower interval is smaller? */
auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */
n = p - lo; /* size of smaller interval */
lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */
}
else {
j=i+1; i=u; u=j-2;
auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */
n = up - p; /* size of smaller interval */
up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
}
auxsort(L, j, i); /* call recursively the smaller one */
} /* repeat the routine for the larger one */
if ((up - lo) / 128 > n) /* partition too imbalanced? */
rnd = l_randomizePivot(); /* try a new randomization */
} /* tail call auxsort(L, lo, up, rnd) */
}
static int luaB_sort (lua_State *L) {
int n = aux_getn(L, 1);
luaL_check_stack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_check_type(L, 2, LUA_TFUNCTION);
lua_settop(L, 2); /* make sure there is two arguments */
auxsort(L, 1, n);
static int sort (lua_State *L) {
lua_Integer n = aux_getn(L, 1, TAB_RW);
if (n > 1) { /* non-trivial interval? */
luaL_argcheck(L, n < INT_MAX, 1, "array too big");
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, 1, (IdxT)n, 0);
}
return 0;
}
/* }====================================================== */
static const luaL_reg tab_funcs[] = {
{"concat", str_concat},
{"foreach", luaB_foreach},
{"foreachi", luaB_foreachi},
{"getn", luaB_getn},
{"setn", luaB_setn},
{"sort", luaB_sort},
{"insert", luaB_tinsert},
{"remove", luaB_tremove},
static const luaL_Reg tab_funcs[] = {
{"concat", tconcat},
{"insert", tinsert},
{"pack", tpack},
{"unpack", tunpack},
{"remove", tremove},
{"move", tmove},
{"sort", sort},
{NULL, NULL}
};
LUALIB_API int lua_tablibopen (lua_State *L) {
lua_newtable(L); /* create N (table to store num. elements in tables) */
lua_setmode(L, -1, "k"); /* make it a weak table */
luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
return 0;
LUAMOD_API int luaopen_table (lua_State *L) {
luaL_newlib(L, tab_funcs);
return 1;
}
+1495 -340
View File
File diff suppressed because it is too large Load Diff
+97 -19
View File
@@ -1,5 +1,5 @@
/*
** $Id: ltests.h,v 1.14 2002/06/13 13:45:31 roberto Exp roberto $
** $Id: ltests.h $
** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -8,54 +8,132 @@
#define ltests_h
#include <stdio.h>
#include <stdlib.h>
/* test Lua with compatibility code */
#define LUA_COMPAT_MATHLIB
#define LUA_COMPAT_LT_LE
#define LUA_DEBUG
#define LUA_OPNAMES
/* turn on assertions */
#undef NDEBUG
#include <assert.h>
#define lua_assert(c) assert(c)
#define check_exp(c,e) (lua_assert(c), (e))
#define api_check(L, o) lua_assert(o)
/* compiled with -O0, Lua uses a lot of C stack space... */
#undef LUAI_MAXCSTACK
#define LUAI_MAXCSTACK 400
/* to avoid warnings, and to make sure value is really unused */
#define UNUSED(x) (x=0, (void)(x))
/* memory allocator control variables */
extern unsigned long memdebug_numblocks;
extern unsigned long memdebug_total;
extern unsigned long memdebug_maxmem;
extern unsigned long memdebug_memlimit;
/* test for sizes in 'l_sprintf' (make sure whole buffer is available) */
#undef l_sprintf
#if !defined(LUA_USE_C89)
#define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), snprintf(s,sz,f,i))
#else
#define l_sprintf(s,sz,f,i) (memset(s,0xAB,sz), sprintf(s,f,i))
#endif
#define l_realloc(b, os, s) debug_realloc(b, os, s)
/* get a chance to test code without jump tables */
#define LUA_USE_JUMPTABLE 0
void *debug_realloc (void *block, size_t oldsize, size_t size);
/* use 32-bit integers in random generator */
#define LUA_RAND32
/* memory-allocator control variables */
typedef struct Memcontrol {
unsigned long numblocks;
unsigned long total;
unsigned long maxmem;
unsigned long memlimit;
unsigned long countlimit;
unsigned long objcount[LUA_NUMTYPES];
} Memcontrol;
LUA_API Memcontrol l_memcontrol;
/*
** generic variable for debug tricks
*/
extern void *l_Trick;
/*
** Function to traverse and check all memory used by Lua
*/
int lua_checkmemory (lua_State *L);
/* test for lock/unlock */
extern int islocked;
#define LUA_USERSTATE int *lock;
#define lua_userstateopen(l) if (l != NULL) *cast(int **, l) = &islocked;
#define lua_lock(L) lua_assert((**cast(int **, L))++ == 0)
#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0)
struct L_EXTRA { int lock; int *plock; };
#undef LUA_EXTRASPACE
#define LUA_EXTRASPACE sizeof(struct L_EXTRA)
#define getlock(l) cast(struct L_EXTRA*, lua_getextraspace(l))
#define luai_userstateopen(l) \
(getlock(l)->lock = 0, getlock(l)->plock = &(getlock(l)->lock))
#define luai_userstateclose(l) \
lua_assert(getlock(l)->lock == 1 && getlock(l)->plock == &(getlock(l)->lock))
#define luai_userstatethread(l,l1) \
lua_assert(getlock(l1)->plock == getlock(l)->plock)
#define luai_userstatefree(l,l1) \
lua_assert(getlock(l)->plock == getlock(l1)->plock)
#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0)
#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0)
int luaB_opentests (lua_State *L);
#define lua_userinit(L) (luaB_opentests(L) + openstdlibs(L))
LUA_API int luaB_opentests (lua_State *L);
LUA_API void *debug_realloc (void *ud, void *block,
size_t osize, size_t nsize);
#if defined(lua_c)
#define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol)
#define luaL_openlibs(L) \
{ (luaL_openlibs)(L); \
luaL_requiref(L, "T", luaB_opentests, 1); \
lua_pop(L, 1); }
#endif
/* change some sizes to give some bugs a chance */
#define LUAL_BUFFERSIZE 27
#undef LUAL_BUFFERSIZE
#define LUAL_BUFFERSIZE 23
#define MINSTRTABSIZE 2
#define MAXIWTHABS 3
#define STRCACHE_N 23
#define STRCACHE_M 5
#undef LUAI_USER_ALIGNMENT_T
#define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; }
/* make stack-overflow tests run faster */
#undef LUAI_MAXSTACK
#define LUAI_MAXSTACK 50000
/* force Lua to use its own implementations */
#undef lua_strx2number
#undef lua_number2strx
#endif
+220 -19
View File
@@ -1,41 +1,54 @@
/*
** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $
** $Id: ltm.c $
** Tag methods
** See Copyright Notice in lua.h
*/
#define ltm_c
#define LUA_CORE
#include "lprefix.h"
#include <string.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lvm.h"
static const char udatatypename[] = "userdata";
const char *const luaT_typenames[] = {
"nil", "number", "string", "boolean", "table",
"function", "userdata", "userdata"
LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTYPES] = {
"no value",
"nil", "boolean", udatatypename, "number",
"string", "table", "function", udatatypename, "thread",
"upvalue", "proto" /* these last cases are used for tests only */
};
void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */
"__index", "__newindex",
"__gc", "__eq",
"__gettable", "__settable",
"__add", "__sub", "__mul", "__div",
"__pow", "__unm", "__lt", "__le",
"__concat", "__call"
"__gc", "__mode", "__len", "__eq",
"__add", "__sub", "__mul", "__mod", "__pow",
"__div", "__idiv",
"__band", "__bor", "__bxor", "__shl", "__shr",
"__unm", "__bnot", "__lt", "__le",
"__concat", "__call", "__close"
};
int i;
for (i=0; i<TM_N; i++) {
G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
luaS_fix(G(L)->tmname[i]); /* never collect these names */
luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */
}
}
@@ -44,26 +57,214 @@ void luaT_init (lua_State *L) {
** function to be used with macro "fasttm": optimized for absence of
** tag methods
*/
const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
const TObject *tm = luaH_getstr(events, ename);
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm = luaH_getshortstr(events, ename);
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= (1u<<event); /* cache this fact */
if (notm(tm)) { /* no tag method? */
events->flags |= cast_byte(1u<<event); /* cache this fact */
return NULL;
}
else return tm;
}
const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event) {
TString *ename = G(L)->tmname[event];
const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
Table *mt;
switch (ttype(o)) {
case LUA_TTABLE:
return luaH_getstr(hvalue(o)->metatable, ename);
mt = hvalue(o)->metatable;
break;
case LUA_TUSERDATA:
return luaH_getstr(uvalue(o)->uv.metatable, ename);
mt = uvalue(o)->metatable;
break;
default:
return &luaO_nilobject;
mt = G(L)->mt[ttype(o)];
}
return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue);
}
/*
** Return the name of the type of an object. For tables and userdata
** with metatable, use their '__name' metafield, if present.
*/
const char *luaT_objtypename (lua_State *L, const TValue *o) {
Table *mt;
if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
(ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
if (ttisstring(name)) /* is '__name' a string? */
return getstr(tsvalue(name)); /* use it as type name */
}
return ttypename(ttype(o)); /* else use standard type name */
}
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, const TValue *p3) {
StkId func = L->top;
setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
setobj2s(L, func + 1, p1); /* 1st argument */
setobj2s(L, func + 2, p2); /* 2nd argument */
setobj2s(L, func + 3, p3); /* 3rd argument */
L->top = func + 4;
/* metamethod may yield only when called from Lua code */
if (isLuacode(L->ci))
luaD_call(L, func, 0);
else
luaD_callnoyield(L, func, 0);
}
void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, StkId res) {
ptrdiff_t result = savestack(L, res);
StkId func = L->top;
setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
setobj2s(L, func + 1, p1); /* 1st argument */
setobj2s(L, func + 2, p2); /* 2nd argument */
L->top += 3;
/* metamethod may yield only when called from Lua code */
if (isLuacode(L->ci))
luaD_call(L, func, 1);
else
luaD_callnoyield(L, func, 1);
res = restorestack(L, result);
setobjs2s(L, res, --L->top); /* move result to its place */
}
static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event) {
const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
if (notm(tm))
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
if (notm(tm)) return 0;
luaT_callTMres(L, tm, p1, p2, res);
return 1;
}
void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event) {
if (!callbinTM(L, p1, p2, res, event)) {
switch (event) {
case TM_BAND: case TM_BOR: case TM_BXOR:
case TM_SHL: case TM_SHR: case TM_BNOT: {
if (ttisnumber(p1) && ttisnumber(p2))
luaG_tointerror(L, p1, p2);
else
luaG_opinterror(L, p1, p2, "perform bitwise operation on");
}
/* calls never return, but to avoid warnings: *//* FALLTHROUGH */
default:
luaG_opinterror(L, p1, p2, "perform arithmetic on");
}
}
}
void luaT_tryconcatTM (lua_State *L) {
StkId top = L->top;
if (!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT))
luaG_concaterror(L, s2v(top - 2), s2v(top - 1));
}
void luaT_trybinassocTM (lua_State *L, const TValue *p1, const TValue *p2,
int flip, StkId res, TMS event) {
if (flip)
luaT_trybinTM(L, p2, p1, res, event);
else
luaT_trybinTM(L, p1, p2, res, event);
}
void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
int flip, StkId res, TMS event) {
TValue aux;
setivalue(&aux, i2);
luaT_trybinassocTM(L, p1, &aux, flip, res, event);
}
/*
** Calls an order tag method.
** For lessequal, LUA_COMPAT_LT_LE keeps compatibility with old
** behavior: if there is no '__le', try '__lt', based on l <= r iff
** !(r < l) (assuming a total order). If the metamethod yields during
** this substitution, the continuation has to know about it (to negate
** the result of r<l); bit CIST_LEQ in the call status keeps that
** information.
*/
int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
TMS event) {
if (callbinTM(L, p1, p2, L->top, event)) /* try original event */
return !l_isfalse(s2v(L->top));
#if defined(LUA_COMPAT_LT_LE)
else if (event == TM_LE) {
/* try '!(p2 < p1)' for '(p1 <= p2)' */
L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */
if (callbinTM(L, p2, p1, L->top, TM_LT)) {
L->ci->callstatus ^= CIST_LEQ; /* clear mark */
return l_isfalse(s2v(L->top));
}
/* else error will remove this 'ci'; no need to clear mark */
}
#endif
luaG_ordererror(L, p1, p2); /* no metamethod found */
return 0; /* to avoid warnings */
}
int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
int flip, int isfloat, TMS event) {
TValue aux; const TValue *p2;
if (isfloat) {
setfltvalue(&aux, cast_num(v2));
}
else
setivalue(&aux, v2);
if (flip) { /* arguments were exchanged? */
p2 = p1; p1 = &aux; /* correct them */
}
else
p2 = &aux;
return luaT_callorderTM(L, p1, p2, event);
}
void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
const Proto *p) {
int i;
int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */
int nextra = actual - nfixparams; /* number of extra arguments */
ci->u.l.nextraargs = nextra;
checkstackGC(L, p->maxstacksize + 1);
/* copy function to the top of the stack */
setobjs2s(L, L->top++, ci->func);
/* move fixed parameters to the top of the stack */
for (i = 1; i <= nfixparams; i++) {
setobjs2s(L, L->top++, ci->func + i);
setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */
}
ci->func += actual + 1;
ci->top += actual + 1;
lua_assert(L->top <= ci->top && ci->top <= L->stack_last);
}
void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
int i;
int nextra = ci->u.l.nextraargs;
if (wanted < 0) {
wanted = nextra; /* get all extra arguments available */
checkstackp(L, nextra, where); /* ensure stack space */
L->top = where + nextra; /* next instruction will need top */
}
for (i = 0; i < wanted && i < nextra; i++)
setobjs2s(L, where + i, ci->func - nextra + i);
for (; i < wanted; i++) /* complete required results with nil */
setnilvalue(s2v(where + i));
}
+57 -13
View File
@@ -1,5 +1,5 @@
/*
** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $
** $Id: ltm.h $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -13,38 +13,82 @@
/*
* WARNING: if you change the order of this enumeration,
* grep "ORDER TM"
* grep "ORDER TM" and "ORDER OP"
*/
typedef enum {
TM_INDEX,
TM_NEWINDEX,
TM_GC,
TM_EQ, /* last tag method with `fast' access */
TM_GETTABLE,
TM_SETTABLE,
TM_MODE,
TM_LEN,
TM_EQ, /* last tag method with fast access */
TM_ADD,
TM_SUB,
TM_MUL,
TM_DIV,
TM_MOD,
TM_POW,
TM_DIV,
TM_IDIV,
TM_BAND,
TM_BOR,
TM_BXOR,
TM_SHL,
TM_SHR,
TM_UNM,
TM_BNOT,
TM_LT,
TM_LE,
TM_CONCAT,
TM_CALL,
TM_CLOSE,
TM_N /* number of elements in the enum */
} TMS;
#define fasttm(l,et,e) \
(((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, G(l)->tmname[e]))
/*
** Test whether there is no tagmethod.
** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
*/
#define notm(tm) ttisnil(tm)
const TObject *luaT_gettm (Table *events, TMS event, TString *ename);
const TObject *luaT_gettmbyobj (lua_State *L, const TObject *o, TMS event);
void luaT_init (lua_State *L);
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
#define fasttm(l,et,e) gfasttm(G(l), et, e)
#define ttypename(x) luaT_typenames_[(x) + 1]
LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTYPES];)
LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);
LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);
LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,
TMS event);
LUAI_FUNC void luaT_init (lua_State *L);
LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, const TValue *p3);
LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f,
const TValue *p1, const TValue *p2, StkId p3);
LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
StkId res, TMS event);
LUAI_FUNC void luaT_tryconcatTM (lua_State *L);
LUAI_FUNC void luaT_trybinassocTM (lua_State *L, const TValue *p1,
const TValue *p2, int inv, StkId res, TMS event);
LUAI_FUNC void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2,
int inv, StkId res, TMS event);
LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
const TValue *p2, TMS event);
LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
int inv, int isfloat, TMS event);
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
struct CallInfo *ci, const Proto *p);
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
StkId where, int wanted);
extern const char *const luaT_typenames[];
#endif
+530 -280
View File
@@ -1,385 +1,635 @@
/*
** $Id: lua.c,v 1.102 2002/08/12 17:23:12 roberto Exp roberto $
** $Id: lua.c $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
#define lua_c
#include "lprefix.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if !defined(LUA_PROGNAME)
#define LUA_PROGNAME "lua"
#endif
#if !defined(LUA_INIT_VAR)
#define LUA_INIT_VAR "LUA_INIT"
#endif
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
/*
** generic extra include file
** Hook set by signal function to stop the interpreter.
*/
#ifdef LUA_USERCONFIG
#include LUA_USERCONFIG
#endif
#ifdef _POSIX_SOURCE
#include <unistd.h>
#else
static int isatty (int x) { return x==0; } /* assume stdin is a tty */
#endif
#ifndef PROMPT
#define PROMPT "> "
#endif
#ifndef PROMPT2
#define PROMPT2 ">> "
#endif
#ifndef lua_userinit
#define lua_userinit(L) openstdlibs(L)
#endif
static lua_State *L = NULL;
static const char *progname;
static lua_Hook old_hook = NULL;
static unsigned long old_mask = 0;
static void lstop (lua_State *l, lua_Debug *ar) {
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
lua_sethook(l, old_hook, old_mask);
luaL_error(l, "interrupted!");
lua_sethook(L, NULL, 0, 0); /* reset hook */
luaL_error(L, "interrupted!");
}
/*
** Function to be called at a C signal. Because a C signal cannot
** just change a Lua state (as there is no proper synchronization),
** this function only sets a hook that, when called, will stop the
** interpreter.
*/
static void laction (int i) {
signal(i, SIG_DFL); /* if another SIGINT happens before lstop,
terminate process (default action) */
old_hook = lua_gethook(L);
old_mask = lua_gethookmask(L);
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT(1));
int flag = LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT;
signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
lua_sethook(globalL, lstop, flag, 1);
}
static void print_usage (void) {
fprintf(stderr,
"usage: %s [options] [prog [args]].\n"
static void print_usage (const char *badoption) {
lua_writestringerror("%s: ", progname);
if (badoption[1] == 'e' || badoption[1] == 'l')
lua_writestringerror("'%s' needs argument\n", badoption);
else
lua_writestringerror("unrecognized option '%s'\n", badoption);
lua_writestringerror(
"usage: %s [options] [script [args]]\n"
"Available options are:\n"
" - execute stdin as a file\n"
" -e stat execute string `stat'\n"
" -i enter interactive mode after executing `prog'\n"
" -l name execute file `name'\n"
" -v print version information\n"
" -- stop handling options\n" ,
" -e stat execute string 'stat'\n"
" -i enter interactive mode after executing 'script'\n"
" -l name require library 'name' into global 'name'\n"
" -v show version information\n"
" -E ignore environment variables\n"
" -W turn warnings on\n"
" -- stop handling options\n"
" - stop handling options and execute stdin\n"
,
progname);
}
/*
** Prints an error message, adding the program name in front of it
** (if present)
*/
static void l_message (const char *pname, const char *msg) {
size_t l = strlen(msg);
if (pname) fprintf(stderr, "%s: ", pname);
fprintf(stderr, "%s", msg);
if (l > 0 && msg[l-1] != '\n') /* does not end with newline? */
fprintf(stderr, "\n"); /* add a newline */
if (pname) lua_writestringerror("%s: ", pname);
lua_writestringerror("%s\n", msg);
}
static void report (int status) {
const char *msg;
if (status) {
msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error with no message)";
/*
** Check whether 'status' is not OK and, if so, prints the error
** message on the top of the stack. It assumes that the error object
** is a string, as it was either generated by Lua or by 'msghandler'.
*/
static int report (lua_State *L, int status) {
if (status != LUA_OK) {
const char *msg = lua_tostring(L, -1);
l_message(progname, msg);
lua_pop(L, 1);
lua_pop(L, 1); /* remove message */
}
}
static int lcall (int clear) {
int status;
int top = lua_gettop(L);
lua_getglobal(L, "_TRACEBACK"); /* get traceback function */
lua_insert(L, top); /* put it under chunk */
signal(SIGINT, laction);
status = lua_pcall(L, 0, LUA_MULTRET, -2);
signal(SIGINT, SIG_DFL);
lua_remove(L, top); /* remove traceback function */
if (status == 0 && clear)
lua_settop(L, top); /* remove eventual results */
return status;
}
static int l_panic (lua_State *l) {
(void)l;
l_message(progname, "unable to recover; exiting");
return 0;
/*
** Message handler used to run all chunks
*/
static int msghandler (lua_State *L) {
const char *msg = lua_tostring(L, 1);
if (msg == NULL) { /* is error object not a string? */
if (luaL_callmeta(L, 1, "__tostring") && /* does it have a metamethod */
lua_type(L, -1) == LUA_TSTRING) /* that produces a string? */
return 1; /* that is the message */
else
msg = lua_pushfstring(L, "(error object is a %s value)",
luaL_typename(L, 1));
}
luaL_traceback(L, L, msg, 1); /* append a standard traceback */
return 1; /* return the traceback */
}
/*
** Interface to 'lua_pcall', which sets appropriate message function
** and C-signal handler. Used to run all chunks.
*/
static int docall (lua_State *L, int narg, int nres) {
int status;
int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, msghandler); /* push message handler */
lua_insert(L, base); /* put it under function and args */
globalL = L; /* to be available to 'laction' */
signal(SIGINT, laction); /* set C-signal handler */
status = lua_pcall(L, narg, nres, base);
signal(SIGINT, SIG_DFL); /* reset C-signal handler */
lua_remove(L, base); /* remove message handler from the stack */
return status;
}
static void print_version (void) {
l_message(NULL, LUA_VERSION " " LUA_COPYRIGHT);
lua_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT));
lua_writeline();
}
static void getargs (char *argv[], int n) {
int i;
lua_newtable(L);
for (i=0; argv[i]; i++) {
lua_pushnumber(L, i - n);
/*
** Create the 'arg' table, which stores all arguments from the
** command line ('argv'). It should be aligned so that, at index 0,
** it has 'argv[script]', which is the script name. The arguments
** to the script (everything after 'script') go to positive indices;
** other arguments (before the script name) go to negative indices.
** If there is no script name, assume interpreter's name as base.
*/
static void createargtable (lua_State *L, char **argv, int argc, int script) {
int i, narg;
if (script == argc) script = 0; /* no script name? */
narg = argc - (script + 1); /* number of positive indices */
lua_createtable(L, narg, script + 1);
for (i = 0; i < argc; i++) {
lua_pushstring(L, argv[i]);
lua_rawset(L, -3);
lua_rawseti(L, -2, i - script);
}
/* arg.n = maximum index in table `arg' */
lua_pushliteral(L, "n");
lua_pushnumber(L, i-n-1);
lua_rawset(L, -3);
lua_setglobal(L, "arg");
}
static int docall (int status) {
if (status == 0) status = lcall(1);
report(status);
return status;
static int dochunk (lua_State *L, int status) {
if (status == LUA_OK) status = docall(L, 0, 0);
return report(L, status);
}
static int file_input (const char *name) {
return docall(luaL_loadfile(L, name));
static int dofile (lua_State *L, const char *name) {
return dochunk(L, luaL_loadfile(L, name));
}
static int dostring (const char *s, const char *name) {
return docall(luaL_loadbuffer(L, s, strlen(s), name));
static int dostring (lua_State *L, const char *s, const char *name) {
return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name));
}
/*
** this macro can be used by some `history' system to save lines
** read in manual input
** Calls 'require(name)' and stores the result in a global variable
** with the given name.
*/
#ifndef lua_saveline
#define lua_saveline(L,line) /* empty */
static int dolibrary (lua_State *L, const char *name) {
int status;
lua_getglobal(L, "require");
lua_pushstring(L, name);
status = docall(L, 1, 1); /* call 'require(name)' */
if (status == LUA_OK)
lua_setglobal(L, name); /* global[name] = require return */
return report(L, status);
}
/*
** Push on the stack the contents of table 'arg' from 1 to #arg
*/
static int pushargs (lua_State *L) {
int i, n;
if (lua_getglobal(L, "arg") != LUA_TTABLE)
luaL_error(L, "'arg' is not a table");
n = (int)luaL_len(L, -1);
luaL_checkstack(L, n + 3, "too many arguments to script");
for (i = 1; i <= n; i++)
lua_rawgeti(L, -i, i);
lua_remove(L, -i); /* remove table from the stack */
return n;
}
static int handle_script (lua_State *L, char **argv) {
int status;
const char *fname = argv[0];
if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
fname = NULL; /* stdin */
status = luaL_loadfile(L, fname);
if (status == LUA_OK) {
int n = pushargs(L); /* push arguments to script */
status = docall(L, n, LUA_MULTRET);
}
return report(L, status);
}
/* bits of various argument indicators in 'args' */
#define has_error 1 /* bad option */
#define has_i 2 /* -i */
#define has_v 4 /* -v */
#define has_e 8 /* -e */
#define has_E 16 /* -E */
/*
** Traverses all arguments from 'argv', returning a mask with those
** needed before running any Lua code (or an error code if it finds
** any invalid argument). 'first' returns the first not-handled argument
** (either the script name or a bad argument in case of error).
*/
static int collectargs (char **argv, int *first) {
int args = 0;
int i;
for (i = 1; argv[i] != NULL; i++) {
*first = i;
if (argv[i][0] != '-') /* not an option? */
return args; /* stop handling options */
switch (argv[i][1]) { /* else check option */
case '-': /* '--' */
if (argv[i][2] != '\0') /* extra characters after '--'? */
return has_error; /* invalid option */
*first = i + 1;
return args;
case '\0': /* '-' */
return args; /* script "name" is '-' */
case 'E':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
args |= has_E;
break;
case 'W':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
break;
case 'i':
args |= has_i; /* (-i implies -v) *//* FALLTHROUGH */
case 'v':
if (argv[i][2] != '\0') /* extra characters? */
return has_error; /* invalid option */
args |= has_v;
break;
case 'e':
args |= has_e; /* FALLTHROUGH */
case 'l': /* both options need an argument */
if (argv[i][2] == '\0') { /* no concatenated argument? */
i++; /* try next 'argv' */
if (argv[i] == NULL || argv[i][0] == '-')
return has_error; /* no next argument or it is another option */
}
break;
default: /* invalid option */
return has_error;
}
}
*first = i; /* no script name */
return args;
}
/*
** Processes options 'e' and 'l', which involve running Lua code, and
** 'W', which also affects the state.
** Returns 0 if some code raises an error.
*/
static int runargs (lua_State *L, char **argv, int n) {
int i;
for (i = 1; i < n; i++) {
int option = argv[i][1];
lua_assert(argv[i][0] == '-'); /* already checked */
switch (option) {
case 'e': case 'l': {
int status;
const char *extra = argv[i] + 2; /* both options need an argument */
if (*extra == '\0') extra = argv[++i];
lua_assert(extra != NULL);
status = (option == 'e')
? dostring(L, extra, "=(command line)")
: dolibrary(L, extra);
if (status != LUA_OK) return 0;
break;
}
case 'W':
lua_warning(L, "@on", 0); /* warnings on */
break;
}
}
return 1;
}
static int handle_luainit (lua_State *L) {
const char *name = "=" LUA_INITVARVERSION;
const char *init = getenv(name + 1);
if (init == NULL) {
name = "=" LUA_INIT_VAR;
init = getenv(name + 1); /* try alternative name */
}
if (init == NULL) return LUA_OK;
else if (init[0] == '@')
return dofile(L, init+1);
else
return dostring(L, init, name);
}
/*
** {==================================================================
** Read-Eval-Print Loop (REPL)
** ===================================================================
*/
#if !defined(LUA_PROMPT)
#define LUA_PROMPT "> "
#define LUA_PROMPT2 ">> "
#endif
#if !defined(LUA_MAXINPUT)
#define LUA_MAXINPUT 512
#endif
/*
** this macro defines a function to show the prompt and reads the
** next line for manual input
** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
** is, whether we're running lua interactively).
*/
#ifndef lua_readline
#define lua_readline(L,prompt) readline(L,prompt)
#if !defined(lua_stdin_is_tty) /* { */
/* maximum length of an input line */
#ifndef MAXINPUT
#define MAXINPUT 512
#endif
#if defined(LUA_USE_POSIX) /* { */
#include <unistd.h>
#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_USE_WINDOWS) /* }{ */
#include <io.h>
#include <windows.h>
#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else /* }{ */
/* ISO C definition */
#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif /* } */
#endif /* } */
static int readline (lua_State *l, const char *prompt) {
static char buffer[MAXINPUT];
if (prompt) {
fputs(prompt, stdout);
fflush(stdout);
}
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return 0; /* read fails */
else {
lua_pushstring(l, buffer);
return 1;
}
}
/*
** lua_readline defines how to show a prompt and then read a line from
** the standard input.
** lua_saveline defines how to "save" a read line in a "history".
** lua_freeline defines how to free a line read by lua_readline.
*/
#if !defined(lua_readline) /* { */
#endif
#if defined(LUA_USE_READLINE) /* { */
#include <readline/readline.h>
#include <readline/history.h>
#define lua_initreadline(L) ((void)L, rl_readline_name="lua")
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,line) ((void)L, add_history(line))
#define lua_freeline(L,b) ((void)L, free(b))
#else /* }{ */
#define lua_initreadline(L) ((void)L)
#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
#define lua_saveline(L,line) { (void)L; (void)line; }
#define lua_freeline(L,b) { (void)L; (void)b; }
#endif /* } */
#endif /* } */
static const char *get_prompt (int firstline) {
const char *p = NULL;
/*
** Returns the string to be used as a prompt by the interpreter.
*/
static const char *get_prompt (lua_State *L, int firstline) {
const char *p;
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1);
if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
lua_pop(L, 1); /* remove global */
if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2);
return p;
}
/* mark in error messages for incomplete statements */
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
static int incomplete (int status) {
if (status == LUA_ERRSYNTAX &&
strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
lua_pop(L, 1);
return 1;
/*
** Check whether 'status' signals a syntax error and the error
** message at the top of the stack ends with the above mark for
** incomplete statements.
*/
static int incomplete (lua_State *L, int status) {
if (status == LUA_ERRSYNTAX) {
size_t lmsg;
const char *msg = lua_tolstring(L, -1, &lmsg);
if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) {
lua_pop(L, 1);
return 1;
}
}
else
return 0;
return 0; /* else... */
}
static int load_string (void) {
int status;
lua_settop(L, 0);
if (lua_readline(L, get_prompt(1)) == 0) /* no input? */
return -1;
if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */
lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */
lua_remove(L, -2); /* remove original line */
/*
** Prompt the user, read a line, and push it into the Lua stack.
*/
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
int readstatus = lua_readline(L, b, prmt);
if (readstatus == 0)
return 0; /* no input (prompt will be popped by caller) */
lua_pop(L, 1); /* remove prompt */
l = strlen(b);
if (l > 0 && b[l-1] == '\n') /* line ends with newline? */
b[--l] = '\0'; /* remove it */
if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */
lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */
else
lua_pushlstring(L, b, l);
lua_freeline(L, b);
return 1;
}
/*
** Try to compile line on the stack as 'return <line>;'; on return, stack
** has either compiled chunk or original line (if compilation failed).
*/
static int addreturn (lua_State *L) {
const char *line = lua_tostring(L, -1); /* original line */
const char *retline = lua_pushfstring(L, "return %s;", line);
int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin");
if (status == LUA_OK) {
lua_remove(L, -2); /* remove modified line */
if (line[0] != '\0') /* non empty? */
lua_saveline(L, line); /* keep history */
}
for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
if (!incomplete(status)) break; /* cannot try to add lines? */
if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */
return -1;
lua_concat(L, lua_gettop(L)); /* join lines */
}
lua_saveline(L, lua_tostring(L, 1));
lua_remove(L, 1); /* remove line */
else
lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
return status;
}
static void manual_input (void) {
/*
** Read multiple lines until a complete Lua statement
*/
static int multiline (lua_State *L) {
for (;;) { /* repeat until gets a complete statement */
size_t len;
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
if (!incomplete(L, status) || !pushline(L, 0)) {
lua_saveline(L, line); /* keep history */
return status; /* cannot or should not try to add continuation line */
}
lua_pushliteral(L, "\n"); /* add newline... */
lua_insert(L, -2); /* ...between the two lines */
lua_concat(L, 3); /* join them */
}
}
/*
** Read a line and try to load (compile) it first as an expression (by
** adding "return " in front of it) and second as a statement. Return
** the final status of load/call with the resulting function (if any)
** in the top of the stack.
*/
static int loadline (lua_State *L) {
int status;
lua_settop(L, 0);
if (!pushline(L, 1))
return -1; /* no input */
if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */
status = multiline(L); /* try as command, maybe with continuation lines */
lua_remove(L, 1); /* remove line from the stack */
lua_assert(lua_gettop(L) == 1);
return status;
}
/*
** Prints (calling the Lua 'print' function) any values on the stack
*/
static void l_print (lua_State *L) {
int n = lua_gettop(L);
if (n > 0) { /* any result to be printed? */
luaL_checkstack(L, LUA_MINSTACK, "too many results to print");
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, n, 0, 0) != LUA_OK)
l_message(progname, lua_pushfstring(L, "error calling 'print' (%s)",
lua_tostring(L, -1)));
}
}
/*
** Do the REPL: repeatedly read (load) a line, evaluate (call) it, and
** print any results.
*/
static void doREPL (lua_State *L) {
int status;
const char *oldprogname = progname;
progname = NULL;
while ((status = load_string()) != -1) {
if (status == 0) status = lcall(0);
report(status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname, "error calling `print'");
}
progname = NULL; /* no 'progname' on errors in interactive mode */
lua_initreadline(L);
while ((status = loadline(L)) != -1) {
if (status == LUA_OK)
status = docall(L, 0, LUA_MULTRET);
if (status == LUA_OK) l_print(L);
else report(L, status);
}
lua_settop(L, 0); /* clear stack */
fputs("\n", stdout);
lua_writeline();
progname = oldprogname;
}
/* }================================================================== */
static int handle_argv (char *argv[], int *interactive) {
if (argv[1] == NULL) { /* no more arguments? */
if (isatty(0)) {
/*
** Main body of stand-alone interpreter (to be called in protected mode).
** Reads the options and handles them all.
*/
static int pmain (lua_State *L) {
int argc = (int)lua_tointeger(L, 1);
char **argv = (char **)lua_touserdata(L, 2);
int script;
int args = collectargs(argv, &script);
luaL_checkversion(L); /* check that interpreter has correct version */
if (argv[0] && argv[0][0]) progname = argv[0];
if (args == has_error) { /* bad arg? */
print_usage(argv[script]); /* 'script' has index of bad arg. */
return 0;
}
if (args & has_v) /* option '-v'? */
print_version();
if (args & has_E) { /* option '-E'? */
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
}
luaL_openlibs(L); /* open standard libraries */
createargtable(L, argv, argc, script); /* create table 'arg' */
lua_gc(L, LUA_GCGEN, 0, 0); /* GC in generational mode */
if (!(args & has_E)) { /* no option '-E'? */
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
return 0; /* error running LUA_INIT */
}
if (!runargs(L, argv, script)) /* execute arguments -e and -l */
return 0; /* something failed */
if (script < argc && /* execute main script (if there is one) */
handle_script(L, argv + script) != LUA_OK)
return 0;
if (args & has_i) /* -i option? */
doREPL(L); /* do read-eval-print loop */
else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */
if (lua_stdin_is_tty()) { /* running in interactive mode? */
print_version();
manual_input();
doREPL(L); /* do read-eval-print loop */
}
else
file_input(NULL); /* executes stdin as a file */
else dofile(L, NULL); /* executes stdin as a file */
}
else { /* other arguments; loop over them */
int i;
for (i = 1; argv[i] != NULL; i++) {
if (argv[i][0] != '-') break; /* not an option? */
switch (argv[i][1]) { /* option */
case '-': { /* `--' */
i++; /* skip this argument */
goto endloop; /* stop handling arguments */
}
case '\0': {
file_input(NULL); /* executes stdin as a file */
break;
}
case 'i': {
*interactive = 1;
break;
}
case 'v': {
print_version();
break;
}
case 'e': {
const char *chunk = argv[i] + 2;
if (*chunk == '\0') chunk = argv[++i];
if (chunk == NULL) {
print_usage();
return EXIT_FAILURE;
}
if (dostring(chunk, "=<command line>") != 0)
return EXIT_FAILURE;
break;
}
case 'l': {
const char *filename = argv[i] + 2;
if (*filename == '\0') filename = argv[++i];
if (filename == NULL) {
print_usage();
return EXIT_FAILURE;
}
if (file_input(filename))
return EXIT_FAILURE; /* stop if file fails */
break;
}
case 'c': {
l_message(progname, "option `-c' is deprecated");
break;
}
case 's': {
l_message(progname, "option `-s' is deprecated");
break;
}
default: {
print_usage();
return EXIT_FAILURE;
}
}
} endloop:
if (argv[i] != NULL) {
const char *filename = argv[i];
getargs(argv, i); /* collect remaining arguments */
lua_setglobal(L, "arg");
return file_input(filename); /* stop scanning arguments */
}
lua_pushboolean(L, 1); /* signal no errors */
return 1;
}
int main (int argc, char **argv) {
int status, result;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int openstdlibs (lua_State *l) {
int res = 0;
res += lua_baselibopen(l);
res += lua_tablibopen(l);
res += lua_iolibopen(l);
res += lua_strlibopen(l);
res += lua_mathlibopen(l);
res += lua_dblibopen(l);
/* add your libraries here */
return res;
}
static int handle_luainit (void) {
const char *init = getenv("LUA_INIT");
if (init == NULL) return 0; /* status OK */
else if (init[0] == '@')
return file_input(init+1);
else
return dostring(init, "=LUA_INIT");
}
int main (int argc, char *argv[]) {
int status;
int interactive = 0;
(void)argc; /* to avoid warnings */
progname = argv[0];
L = lua_open(); /* create state */
lua_atpanic(L, l_panic);
lua_pop(L, lua_userinit(L)); /* open libraries, discard any results */
status = handle_luainit();
if (status != 0) return status;
status = handle_argv(argv, &interactive);
if (status == 0 && interactive) manual_input();
lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
lua_pushinteger(L, argc); /* 1st argument */
lua_pushlightuserdata(L, argv); /* 2nd argument */
status = lua_pcall(L, 2, 1, 0); /* do the call */
result = lua_toboolean(L, -1); /* get result */
report(L, status);
lua_close(L);
return status;
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}
+337 -202
View File
@@ -1,8 +1,7 @@
/*
** $Id: lua.h,v 1.153 2002/08/06 18:54:18 roberto Exp roberto $
** Lua - An Extensible Extension Language
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
** http://www.lua.org mailto:info@lua.org
** $Id: lua.h $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
*/
@@ -10,297 +9,412 @@
#ifndef lua_h
#define lua_h
/* definition of `va_list' */
#include <stdarg.h>
/* definition of `size_t' */
#include <stddef.h>
#define LUA_VERSION "Lua 5.0 (alpha)"
#define LUA_COPYRIGHT "Copyright (C) 1994-2002 Tecgraf, PUC-Rio"
#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo"
#include "luaconf.h"
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "4"
#define LUA_VERSION_RELEASE "0"
/* option for multiple returns in `lua_pcall' and `lua_call' */
#define LUA_VERSION_NUM 504
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2020 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
/* mark for precompiled code ('<esc>Lua') */
#define LUA_SIGNATURE "\x1bLua"
/* option for multiple returns in 'lua_pcall' and 'lua_call' */
#define LUA_MULTRET (-1)
/*
** pseudo-indices
** Pseudo-indices
** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty
** space after that to help overflow detection)
*/
#define LUA_REGISTRYINDEX (-10000)
#define LUA_GLOBALSINDEX (-10001)
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000)
#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i))
/* error codes for `lua_load' and `lua_pcall' */
#define LUA_ERRRUN 1
#define LUA_ERRFILE 2
/* thread status */
#define LUA_OK 0
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
#define LUA_ERRTHROW 6
typedef struct lua_State lua_State;
typedef int (*lua_CFunction) (lua_State *L);
/*
** functions that read blocks when loading Lua chunk
*/
typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *size);
/*
** basic types
*/
#define LUA_TNONE (-1)
#define LUA_TNONE (-1)
#define LUA_TNIL 0
#define LUA_TBOOLEAN 1
#define LUA_TLIGHTUSERDATA 2
#define LUA_TNUMBER 3
#define LUA_TSTRING 4
#define LUA_TTABLE 5
#define LUA_TFUNCTION 6
#define LUA_TUSERDATA 7
#define LUA_TTHREAD 8
#define LUA_NUMTYPES 9
#define LUA_TNIL 0
#define LUA_TNUMBER 1
#define LUA_TSTRING 2
#define LUA_TBOOLEAN 3
#define LUA_TTABLE 4
#define LUA_TFUNCTION 5
#define LUA_TUSERDATA 6
#define LUA_TLIGHTUSERDATA 7
/* minimum Lua stack available to a C function */
#define LUA_MINSTACK 20
/* predefined values in the registry */
#define LUA_RIDX_MAINTHREAD 1
#define LUA_RIDX_GLOBALS 2
#define LUA_RIDX_LAST LUA_RIDX_GLOBALS
/* type of numbers in Lua */
typedef LUA_NUMBER lua_Number;
/* type for integer functions */
typedef LUA_INTEGER lua_Integer;
/* unsigned integer type */
typedef LUA_UNSIGNED lua_Unsigned;
/* type for continuation-function contexts */
typedef LUA_KCONTEXT lua_KContext;
/*
** Type for C functions registered with Lua
*/
typedef int (*lua_CFunction) (lua_State *L);
/*
** Type for continuation functions
*/
typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx);
/*
** Type for functions that read/write blocks when loading/dumping Lua chunks
*/
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud);
/*
** Type for memory-allocation functions
*/
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
/*
** Type for warning functions
*/
typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont);
/*
** generic extra include file
*/
#ifdef LUA_USER_H
#if defined(LUA_USER_H)
#include LUA_USER_H
#endif
/* type of Numbers in Lua */
#ifndef LUA_NUMBER
#define LUA_NUMBER double
#endif
typedef LUA_NUMBER lua_Number;
/* mark for all API functions */
#ifndef LUA_API
#define LUA_API extern
#endif
/*
** RCS ident string
*/
extern const char lua_ident[];
/*
** state manipulation
*/
LUA_API lua_State *lua_open (void);
LUA_API void lua_close (lua_State *L);
LUA_API lua_State *lua_newthread (lua_State *L);
LUA_API void lua_closethread (lua_State *L, lua_State *thread);
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API int (lua_resetthread) (lua_State *L);
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
LUA_API lua_Number (lua_version) (lua_State *L);
/*
** basic stack manipulation
*/
LUA_API int lua_gettop (lua_State *L);
LUA_API void lua_settop (lua_State *L, int index);
LUA_API void lua_pushvalue (lua_State *L, int index);
LUA_API void lua_remove (lua_State *L, int index);
LUA_API void lua_insert (lua_State *L, int index);
LUA_API void lua_replace (lua_State *L, int index);
LUA_API int lua_checkstack (lua_State *L, int size);
LUA_API int (lua_absindex) (lua_State *L, int idx);
LUA_API int (lua_gettop) (lua_State *L);
LUA_API void (lua_settop) (lua_State *L, int idx);
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
LUA_API void (lua_rotate) (lua_State *L, int idx, int n);
LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx);
LUA_API int (lua_checkstack) (lua_State *L, int n);
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
/*
** access functions (stack -> C)
*/
LUA_API int lua_isnumber (lua_State *L, int index);
LUA_API int lua_isstring (lua_State *L, int index);
LUA_API int lua_iscfunction (lua_State *L, int index);
LUA_API int lua_type (lua_State *L, int index);
LUA_API const char *lua_typename (lua_State *L, int type);
LUA_API int (lua_isnumber) (lua_State *L, int idx);
LUA_API int (lua_isstring) (lua_State *L, int idx);
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
LUA_API int (lua_isinteger) (lua_State *L, int idx);
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
LUA_API int (lua_type) (lua_State *L, int idx);
LUA_API const char *(lua_typename) (lua_State *L, int tp);
LUA_API int lua_equal (lua_State *L, int index1, int index2);
LUA_API int lua_rawequal (lua_State *L, int index1, int index2);
LUA_API int lua_lessthan (lua_State *L, int index1, int index2);
LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum);
LUA_API int (lua_toboolean) (lua_State *L, int idx);
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API lua_Unsigned (lua_rawlen) (lua_State *L, int idx);
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
LUA_API lua_Number lua_tonumber (lua_State *L, int index);
LUA_API int lua_toboolean (lua_State *L, int index);
LUA_API const char *lua_tostring (lua_State *L, int index);
LUA_API size_t lua_strlen (lua_State *L, int index);
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index);
LUA_API void *lua_touserdata (lua_State *L, int index);
LUA_API const void *lua_topointer (lua_State *L, int index);
/*
** Comparison and arithmetic functions
*/
#define LUA_OPADD 0 /* ORDER TM, ORDER OP */
#define LUA_OPSUB 1
#define LUA_OPMUL 2
#define LUA_OPMOD 3
#define LUA_OPPOW 4
#define LUA_OPDIV 5
#define LUA_OPIDIV 6
#define LUA_OPBAND 7
#define LUA_OPBOR 8
#define LUA_OPBXOR 9
#define LUA_OPSHL 10
#define LUA_OPSHR 11
#define LUA_OPUNM 12
#define LUA_OPBNOT 13
LUA_API void (lua_arith) (lua_State *L, int op);
#define LUA_OPEQ 0
#define LUA_OPLT 1
#define LUA_OPLE 2
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
/*
** push functions (C -> stack)
*/
LUA_API void lua_pushnil (lua_State *L);
LUA_API void lua_pushnumber (lua_State *L, lua_Number n);
LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len);
LUA_API void lua_pushstring (lua_State *L, const char *s);
LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
LUA_API void lua_pushboolean (lua_State *L, int b);
LUA_API void lua_pushlightuserdata (lua_State *L, void *p);
LUA_API void (lua_pushnil) (lua_State *L);
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);
/*
** get functions (Lua -> stack)
*/
LUA_API void lua_gettable (lua_State *L, int index);
LUA_API void lua_rawget (lua_State *L, int index);
LUA_API void lua_rawgeti (lua_State *L, int index, int n);
LUA_API void lua_newtable (lua_State *L);
LUA_API int lua_getmetatable (lua_State *L, int objindex);
LUA_API const char *lua_getmode (lua_State *L, int index);
LUA_API void lua_getglobals (lua_State *L, int index);
LUA_API int (lua_getglobal) (lua_State *L, const char *name);
LUA_API int (lua_gettable) (lua_State *L, int idx);
LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawget) (lua_State *L, int idx);
LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
/*
** set functions (stack -> Lua)
*/
LUA_API void lua_settable (lua_State *L, int index);
LUA_API void lua_rawset (lua_State *L, int index);
LUA_API void lua_rawseti (lua_State *L, int index, int n);
LUA_API void lua_setmode (lua_State *L, int index, const char *mode);
LUA_API int lua_setmetatable (lua_State *L, int objindex);
LUA_API int lua_setglobals (lua_State *L, int index);
LUA_API void (lua_setglobal) (lua_State *L, const char *name);
LUA_API void (lua_settable) (lua_State *L, int idx);
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawset) (lua_State *L, int idx);
LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n);
/*
** `load' and `call' functions (load and run Lua code)
** 'load' and 'call' functions (load and run Lua code)
*/
LUA_API void lua_call (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
const char *chunkname);
LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults,
lua_KContext ctx, lua_KFunction k);
#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
lua_KContext ctx, lua_KFunction k);
#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL)
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
const char *chunkname, const char *mode);
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
/*
** coroutine functions
*/
LUA_API void lua_cobegin (lua_State *L, int nargs);
LUA_API int lua_yield (lua_State *L, int nresults);
LUA_API int lua_resume (lua_State *L, lua_State *co);
LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
lua_KFunction k);
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg,
int *nres);
LUA_API int (lua_status) (lua_State *L);
LUA_API int (lua_isyieldable) (lua_State *L);
#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL)
/*
** Garbage-collection functions
** Warning-related functions
*/
LUA_API int lua_getgcthreshold (lua_State *L);
LUA_API int lua_getgccount (lua_State *L);
LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold);
LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud);
LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont);
/*
** garbage-collection function and options
*/
#define LUA_GCSTOP 0
#define LUA_GCRESTART 1
#define LUA_GCCOLLECT 2
#define LUA_GCCOUNT 3
#define LUA_GCCOUNTB 4
#define LUA_GCSTEP 5
#define LUA_GCSETPAUSE 6
#define LUA_GCSETSTEPMUL 7
#define LUA_GCISRUNNING 9
#define LUA_GCGEN 10
#define LUA_GCINC 11
LUA_API int (lua_gc) (lua_State *L, int what, ...);
/*
** miscellaneous functions
*/
LUA_API int lua_error (lua_State *L);
LUA_API int (lua_error) (lua_State *L);
LUA_API int lua_next (lua_State *L, int index);
LUA_API int (lua_next) (lua_State *L, int idx);
LUA_API void lua_concat (lua_State *L, int n);
LUA_API void (lua_concat) (lua_State *L, int n);
LUA_API void (lua_len) (lua_State *L, int idx);
LUA_API void *lua_newuserdata (lua_State *L, size_t size);
LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s);
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
LUA_API void (lua_toclose) (lua_State *L, int idx);
/*
** ===============================================================
/*
** {==============================================================
** some useful macros
** ===============================================================
*/
#define lua_boxpointer(L,u) \
(*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
#define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i)))
#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL)
#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL)
#define lua_pop(L,n) lua_settop(L, -(n)-1)
#define lua_register(L,n,f) \
(lua_pushstring(L, n), \
lua_pushcfunction(L, f), \
lua_settable(L, LUA_GLOBALSINDEX))
#define lua_newtable(L) lua_createtable(L, 0, 0)
#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0)
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE)
#define lua_isuserdata(L,n) (lua_type(L,n) >= LUA_TUSERDATA)
#define lua_islightuserdata(L,n) (lua_type(L,n) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L,n) == LUA_TBOOLEAN)
#define lua_isnone(L,n) (lua_type(L,n) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L,n) <= 0)
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
#define lua_pushliteral(L, s) \
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
#define lua_pushglobaltable(L) \
((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
#define lua_insert(L,idx) lua_rotate(L, (idx), 1)
#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
/* }============================================================== */
/*
** compatibility macros and functions
** {==============================================================
** compatibility macros
** ===============================================================
*/
#if defined(LUA_COMPAT_APIINTCASTS)
#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is))
#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL)
LUA_API int lua_pushupvalues (lua_State *L);
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
#define lua_setglobal(L,s) \
(lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX))
#define lua_getglobal(L,s) \
(lua_pushstring(L, s), lua_gettable(L, LUA_GLOBALSINDEX))
#define lua_isnull lua_isnone
/* compatibility with ref system */
/* pre-defined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, ref)
/*
** {======================================================================
** useful definitions for Lua kernel and libraries
** =======================================================================
*/
/* formats for Lua numbers */
#ifndef LUA_NUMBER_SCAN
#define LUA_NUMBER_SCAN "%lf"
#endif
#ifndef LUA_NUMBER_FMT
#define LUA_NUMBER_FMT "%.16g"
#endif
#define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1)
#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1)
#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1)
/* }====================================================================== */
#define LUA_NUMTAGS LUA_NUMTYPES
/* }============================================================== */
/*
** {======================================================================
@@ -308,55 +422,76 @@ LUA_API int lua_pushupvalues (lua_State *L);
** =======================================================================
*/
typedef enum lua_Hookevent {
LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKLINE, LUA_HOOKCOUNT
} lua_Hookevent;
/*
** Event codes
*/
#define LUA_HOOKCALL 0
#define LUA_HOOKRET 1
#define LUA_HOOKLINE 2
#define LUA_HOOKCOUNT 3
#define LUA_HOOKTAILCALL 4
#define LUA_MASKCALL (2 << LUA_HOOKCALL)
#define LUA_MASKRET (2 << LUA_HOOKRET)
#define LUA_MASKLINE (2 << LUA_HOOKLINE)
#define LUA_MASKCOUNT(count) ((unsigned long)(count) << 8)
#define lua_getmaskcount(mask) ((mask) >> 8)
#define LUA_MAXCOUNT ((1<<24) - 1)
/*
** Event masks
*/
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
#define LUA_MASKRET (1 << LUA_HOOKRET)
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
typedef struct lua_Debug lua_Debug; /* activation record */
/* Functions to be called by the debugger in specific events */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar);
LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar);
LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n);
LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n);
LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n);
LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask);
LUA_API lua_Hook lua_gethook (lua_State *L);
LUA_API unsigned long lua_gethookmask (lua_State *L);
LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n);
LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1,
int fidx2, int n2);
LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count);
LUA_API lua_Hook (lua_gethook) (lua_State *L);
LUA_API int (lua_gethookmask) (lua_State *L);
LUA_API int (lua_gethookcount) (lua_State *L);
#define LUA_IDSIZE 60
LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit);
struct lua_Debug {
lua_Hookevent event;
int event;
const char *name; /* (n) */
const char *namewhat; /* (n) `global', `local', `field', `method' */
const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */
const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */
const char *source; /* (S) */
size_t srclen; /* (S) */
int currentline; /* (l) */
int nups; /* (u) number of upvalues */
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) */
unsigned short ftransfer; /* (r) index of first value transferred */
unsigned short ntransfer; /* (r) number of transferred values */
char short_src[LUA_IDSIZE]; /* (S) */
/* private part */
int i_ci; /* active function */
struct CallInfo *i_ci; /* active function */
};
/* }====================================================================== */
/******************************************************************************
* Copyright (C) 2002 Tecgraf, PUC-Rio. All rights reserved.
* Copyright (C) 1994-2020 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
+776
View File
@@ -0,0 +1,776 @@
/*
** $Id: luaconf.h $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
#ifndef luaconf_h
#define luaconf_h
#include <limits.h>
#include <stddef.h>
/*
** ===================================================================
** General Configuration File for Lua
**
** Some definitions here can be changed externally, through the
** compiler (e.g., with '-D' options). Those are protected by
** '#if !defined' guards. However, several other definitions should
** be changed directly here, either because they affect the Lua
** ABI (by making the changes here, you ensure that all software
** connected to Lua, such as C libraries, will be compiled with the
** same configuration); or because they are seldom changed.
**
** Search for "@@" to find all configurable definitions.
** ===================================================================
*/
/*
** {====================================================================
** System Configuration: macros to adapt (if needed) Lua to some
** particular platform, for instance restricting it to C89.
** =====================================================================
*/
/*
@@ LUAI_MAXCSTACK defines the maximum depth for nested calls and
** also limits the maximum depth of other recursive algorithms in
** the implementation, such as syntactic analysis. A value too
** large may allow the interpreter to crash (C-stack overflow).
** The default value seems ok for regular machines, but may be
** too high for restricted hardware.
** The test file 'cstack.lua' may help finding a good limit.
** (It will crash with a limit too high.)
*/
#if !defined(LUAI_MAXCSTACK)
#define LUAI_MAXCSTACK 2000
#endif
/*
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
** Define it if you want Lua to avoid the use of a few C99 features
** or Windows-specific features on Windows.
*/
/* #define LUA_USE_C89 */
/*
** By default, Lua on Windows use (some) specific Windows features
*/
#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE)
#define LUA_USE_WINDOWS /* enable goodies for regular Windows */
#endif
#if defined(LUA_USE_WINDOWS)
#define LUA_DL_DLL /* enable support for DLL */
#define LUA_USE_C89 /* broadly, Windows is C89 */
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* MacOS does not need -ldl */
#endif
/*
@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
*/
#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)
/* }================================================================== */
/*
** {==================================================================
** Configuration for Number types.
** ===================================================================
*/
/*
@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
*/
/* #define LUA_32BITS */
/*
@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
** C89 ('long' and 'double'); Windows always has '__int64', so it does
** not need to use this case.
*/
#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
#define LUA_C89_NUMBERS
#endif
/*
@@ LUA_INT_TYPE defines the type for Lua integers.
@@ LUA_FLOAT_TYPE defines the type for Lua floats.
** Lua should work fine with any mix of these options supported
** by your C compiler. The usual configurations are 64-bit integers
** and 'double' (the default), 32-bit integers and 'float' (for
** restricted platforms), and 'long'/'double' (for C compilers not
** compliant with C99, which may not have support for 'long long').
*/
/* predefined options for LUA_INT_TYPE */
#define LUA_INT_INT 1
#define LUA_INT_LONG 2
#define LUA_INT_LONGLONG 3
/* predefined options for LUA_FLOAT_TYPE */
#define LUA_FLOAT_FLOAT 1
#define LUA_FLOAT_DOUBLE 2
#define LUA_FLOAT_LONGDOUBLE 3
#if defined(LUA_32BITS) /* { */
/*
** 32-bit integers and 'float'
*/
#if LUAI_IS32INT /* use 'int' if big enough */
#define LUA_INT_TYPE LUA_INT_INT
#else /* otherwise use 'long' */
#define LUA_INT_TYPE LUA_INT_LONG
#endif
#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
#elif defined(LUA_C89_NUMBERS) /* }{ */
/*
** largest types available for C89 ('long' and 'double')
*/
#define LUA_INT_TYPE LUA_INT_LONG
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#endif /* } */
/*
** default configuration for 64-bit Lua ('long long' and 'double')
*/
#if !defined(LUA_INT_TYPE)
#define LUA_INT_TYPE LUA_INT_LONGLONG
#endif
#if !defined(LUA_FLOAT_TYPE)
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#endif
/* }================================================================== */
/*
** {==================================================================
** Configuration for Paths.
** ===================================================================
*/
/*
** LUA_PATH_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.
*/
#define LUA_PATH_SEP ";"
#define LUA_PATH_MARK "?"
#define LUA_EXEC_DIR "!"
/*
@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for
** Lua libraries.
@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for
** C libraries.
** CHANGE them if your machine has a non-conventional directory
** hierarchy or if you want to install your libraries in
** non-conventional directories.
*/
#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#if defined(_WIN32) /* { */
/*
** In Windows, any exclamation mark ('!') in the path is replaced by the
** path of the directory of the executable file of the current process.
*/
#define LUA_LDIR "!\\lua\\"
#define LUA_CDIR "!\\"
#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
".\\?.lua;" ".\\?\\init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.dll;" \
LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
LUA_CDIR"loadall.dll;" ".\\?.dll"
#endif
#else /* }{ */
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/"
#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/"
#if !defined(LUA_PATH_DEFAULT)
#define LUA_PATH_DEFAULT \
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
"./?.lua;" "./?/init.lua"
#endif
#if !defined(LUA_CPATH_DEFAULT)
#define LUA_CPATH_DEFAULT \
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
#endif
#endif /* } */
/*
@@ LUA_DIRSEP is the directory separator (for submodules).
** CHANGE it if your machine does not use "/" as the directory separator
** and is not Windows. (On Windows Lua automatically uses "\".)
*/
#if !defined(LUA_DIRSEP)
#if defined(_WIN32)
#define LUA_DIRSEP "\\"
#else
#define LUA_DIRSEP "/"
#endif
#endif
/* }================================================================== */
/*
** {==================================================================
** Marks for exported symbols in the C code
** ===================================================================
*/
/*
@@ LUA_API is a mark for all core API functions.
@@ LUALIB_API is a mark for all auxiliary library functions.
@@ LUAMOD_API is a mark for all standard library opening functions.
** CHANGE them if you need to define those functions in some special way.
** For instance, if you want to create one Windows DLL with the core and
** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it).
*/
#if defined(LUA_BUILD_AS_DLL) /* { */
#if defined(LUA_CORE) || defined(LUA_LIB) /* { */
#define LUA_API __declspec(dllexport)
#else /* }{ */
#define LUA_API __declspec(dllimport)
#endif /* } */
#else /* }{ */
#define LUA_API extern
#endif /* } */
/*
** More often than not the libs go together with the core.
*/
#define LUALIB_API LUA_API
#define LUAMOD_API LUA_API
/*
@@ LUAI_FUNC is a mark for all extern functions that are not to be
** exported to outside modules.
@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
** none of which to be exported to outside modules (LUAI_DDEF for
** definitions and LUAI_DDEC for declarations).
** CHANGE them if you need to mark them in some special way. Elf/gcc
** (versions 3.2 and later) mark them as "hidden" to optimize access
** when Lua is compiled as a shared library. Not all elf targets support
** this attribute. Unfortunately, gcc does not offer a way to check
** whether the target offers that support, and those without support
** give a warning about it. To avoid these warnings, change to the
** default definition.
*/
#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \
defined(__ELF__) /* { */
#define LUAI_FUNC __attribute__((visibility("internal"))) extern
#else /* }{ */
#define LUAI_FUNC extern
#endif /* } */
#define LUAI_DDEC(dec) LUAI_FUNC dec
#define LUAI_DDEF /* empty */
/* }================================================================== */
/*
** {==================================================================
** Compatibility with previous versions
** ===================================================================
*/
/*
@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3.
** You can define it to get all options, or change specific options
** to fit your specific needs.
*/
#if defined(LUA_COMPAT_5_3) /* { */
/*
@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated
** functions in the mathematical library.
** (These functions were already officially removed in 5.3;
** nevertheless they are still available here.)
*/
#define LUA_COMPAT_MATHLIB
/*
@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for
** manipulating other integer types (lua_pushunsigned, lua_tounsigned,
** luaL_checkint, luaL_checklong, etc.)
** (These macros were also officially removed in 5.3, but they are still
** available here.)
*/
#define LUA_COMPAT_APIINTCASTS
/*
@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod
** using '__lt'.
*/
#define LUA_COMPAT_LT_LE
/*
@@ The following macros supply trivial compatibility for some
** changes in the API. The macros themselves document how to
** change your code to avoid using them.
** (Once more, these macros were officially removed in 5.3, but they are
** still available here.)
*/
#define lua_strlen(L,i) lua_rawlen(L, (i))
#define lua_objlen(L,i) lua_rawlen(L, (i))
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Configuration for Numbers.
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
** satisfy your needs.
** ===================================================================
*/
/*
@@ LUA_NUMBER is the floating-point type used by Lua.
@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
@@ over a floating number.
@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
** by prefixing it with one of FLT/DBL/LDBL.
@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats.
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
@@ l_floor takes the floor of a float.
@@ lua_str2number converts a decimal numeral to a number.
*/
/* The following definitions are good for most cases here */
#define l_floor(x) (l_mathop(floor)(x))
#define lua_number2str(s,sz,n) \
l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n))
/*
@@ lua_numbertointeger converts a float number with an integral value
** to an integer, or returns 0 if float is not within the range of
** a lua_Integer. (The range comparisons are tricky because of
** rounding. The tests here assume a two-complement representation,
** where MININTEGER always has an exact representation as a float;
** MAXINTEGER may not have one, and therefore its conversion to float
** may have an ill-defined value.)
*/
#define lua_numbertointeger(n,p) \
((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
(n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
(*(p) = (LUA_INTEGER)(n), 1))
/* now the variable definitions */
#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */
#define LUA_NUMBER float
#define l_floatatt(n) (FLT_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_FMT "%.7g"
#define l_mathop(op) op##f
#define lua_str2number(s,p) strtof((s), (p))
#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */
#define LUA_NUMBER long double
#define l_floatatt(n) (LDBL_##n)
#define LUAI_UACNUMBER long double
#define LUA_NUMBER_FRMLEN "L"
#define LUA_NUMBER_FMT "%.19Lg"
#define l_mathop(op) op##l
#define lua_str2number(s,p) strtold((s), (p))
#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */
#define LUA_NUMBER double
#define l_floatatt(n) (DBL_##n)
#define LUAI_UACNUMBER double
#define LUA_NUMBER_FRMLEN ""
#define LUA_NUMBER_FMT "%.14g"
#define l_mathop(op) op
#define lua_str2number(s,p) strtod((s), (p))
#else /* }{ */
#error "numeric float type not defined"
#endif /* } */
/*
@@ LUA_INTEGER is the integer type used by Lua.
**
@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
**
@@ LUAI_UACINT is the result of a 'default argument promotion'
@@ over a LUA_INTEGER.
@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
@@ LUA_INTEGER_FMT is the format for writing integers.
@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED.
@@ lua_integer2str converts an integer to a string.
*/
/* The following definitions are good for most cases here */
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
#define LUAI_UACINT LUA_INTEGER
#define lua_integer2str(s,sz,n) \
l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n))
/*
** use LUAI_UACINT here to avoid problems with promotions (which
** can turn a comparison between unsigneds into a signed comparison)
*/
#define LUA_UNSIGNED unsigned LUAI_UACINT
#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT)
/* now the variable definitions */
#if LUA_INT_TYPE == LUA_INT_INT /* { int */
#define LUA_INTEGER int
#define LUA_INTEGER_FRMLEN ""
#define LUA_MAXINTEGER INT_MAX
#define LUA_MININTEGER INT_MIN
#define LUA_MAXUNSIGNED UINT_MAX
#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */
#define LUA_INTEGER long
#define LUA_INTEGER_FRMLEN "l"
#define LUA_MAXINTEGER LONG_MAX
#define LUA_MININTEGER LONG_MIN
#define LUA_MAXUNSIGNED ULONG_MAX
#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */
/* use presence of macro LLONG_MAX as proxy for C99 compliance */
#if defined(LLONG_MAX) /* { */
/* use ISO C99 stuff */
#define LUA_INTEGER long long
#define LUA_INTEGER_FRMLEN "ll"
#define LUA_MAXINTEGER LLONG_MAX
#define LUA_MININTEGER LLONG_MIN
#define LUA_MAXUNSIGNED ULLONG_MAX
#elif defined(LUA_USE_WINDOWS) /* }{ */
/* in Windows, can use specific Windows types */
#define LUA_INTEGER __int64
#define LUA_INTEGER_FRMLEN "I64"
#define LUA_MAXINTEGER _I64_MAX
#define LUA_MININTEGER _I64_MIN
#define LUA_MAXUNSIGNED _UI64_MAX
#else /* }{ */
#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \
or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)"
#endif /* } */
#else /* }{ */
#error "numeric integer type not defined"
#endif /* } */
/* }================================================================== */
/*
** {==================================================================
** Dependencies with C99 and other C details
** ===================================================================
*/
/*
@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89.
** (All uses in Lua have only one format item.)
*/
#if !defined(LUA_USE_C89)
#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i)
#else
#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i))
#endif
/*
@@ lua_strx2number converts a hexadecimal numeral to a number.
** In C99, 'strtod' does that conversion. Otherwise, you can
** leave 'lua_strx2number' undefined and Lua will provide its own
** implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_strx2number(s,p) lua_str2number(s,p)
#endif
/*
@@ lua_pointer2str converts a pointer to a readable string in a
** non-specified way.
*/
#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p)
/*
@@ lua_number2strx converts a float to a hexadecimal numeral.
** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that.
** Otherwise, you can leave 'lua_number2strx' undefined and Lua will
** provide its own implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_number2strx(L,b,sz,f,n) \
((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n)))
#endif
/*
** 'strtof' and 'opf' variants for math functions are not valid in
** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the
** availability of these variants. ('math.h' is already included in
** all files that use these macros.)
*/
#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF))
#undef l_mathop /* variants not available */
#undef lua_str2number
#define l_mathop(op) (lua_Number)op /* no variant */
#define lua_str2number(s,p) ((lua_Number)strtod((s), (p)))
#endif
/*
@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation
** functions. It must be a numerical type; Lua will use 'intptr_t' if
** available, otherwise it will use 'ptrdiff_t' (the nearest thing to
** 'intptr_t' in C89)
*/
#define LUA_KCONTEXT ptrdiff_t
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
__STDC_VERSION__ >= 199901L
#include <stdint.h>
#if defined(INTPTR_MAX) /* even in C99 this type is optional */
#undef LUA_KCONTEXT
#define LUA_KCONTEXT intptr_t
#endif
#endif
/*
@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point).
** Change that if you do not want to use C locales. (Code using this
** macro must include the header 'locale.h'.)
*/
#if !defined(lua_getlocaledecpoint)
#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
#endif
/* }================================================================== */
/*
** {==================================================================
** Language Variations
** =====================================================================
*/
/*
@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some
** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from
** numbers to strings. Define LUA_NOCVTS2N to turn off automatic
** coercion from strings to numbers.
*/
/* #define LUA_NOCVTN2S */
/* #define LUA_NOCVTS2N */
/*
@@ LUA_USE_APICHECK turns on several consistency checks on the C API.
** Define it as a help when debugging C code.
*/
#if defined(LUA_USE_APICHECK)
#include <assert.h>
#define luai_apicheck(l,e) assert(e)
#endif
/* }================================================================== */
/*
** {==================================================================
** Macros that affect the API and must be stable (that is, must be the
** same when you compile Lua and when you compile code that links to
** Lua).
** =====================================================================
*/
/*
@@ LUAI_MAXSTACK limits the size of the Lua stack.
** CHANGE it if you need a different limit. This limit is arbitrary;
** its only purpose is to stop Lua from consuming unlimited stack
** space (and to reserve some numbers for pseudo-indices).
** (It must fit into max(size_t)/32.)
*/
#if LUAI_IS32INT
#define LUAI_MAXSTACK 1000000
#else
#define LUAI_MAXSTACK 15000
#endif
/*
@@ LUA_EXTRASPACE defines the size of a raw memory area associated with
** a Lua state with very fast access.
** CHANGE it if you need a different size.
*/
#define LUA_EXTRASPACE (sizeof(void *))
/*
@@ LUA_IDSIZE gives the maximum size for the description of the source
@@ of a function in debug information.
** CHANGE it if you want a different size.
*/
#define LUA_IDSIZE 60
/*
@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
*/
#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number)))
/*
@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
** maximum alignment for the other items in that union.
*/
#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l
/* }================================================================== */
/* =================================================================== */
/*
** Local configuration. You can use this space to add your redefinitions
** without modifying the main part of the file.
*/
#endif
+27 -13
View File
@@ -1,5 +1,5 @@
/*
** $Id: lualib.h,v 1.24 2002/06/18 17:42:52 roberto Exp roberto $
** $Id: lualib.h $
** Lua standard libraries
** See Copyright Notice in lua.h
*/
@@ -11,34 +11,48 @@
#include "lua.h"
#ifndef LUALIB_API
#define LUALIB_API extern
#endif
/* version suffix for environment variable names */
#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR
LUAMOD_API int (luaopen_base) (lua_State *L);
#define LUA_COLIBNAME "coroutine"
LUALIB_API int lua_baselibopen (lua_State *L);
LUAMOD_API int (luaopen_coroutine) (lua_State *L);
#define LUA_TABLIBNAME "table"
LUALIB_API int lua_tablibopen (lua_State *L);
LUAMOD_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUAMOD_API int (luaopen_io) (lua_State *L);
#define LUA_OSLIBNAME "os"
LUALIB_API int lua_iolibopen (lua_State *L);
LUAMOD_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUALIB_API int lua_strlibopen (lua_State *L);
LUAMOD_API int (luaopen_string) (lua_State *L);
#define LUA_UTF8LIBNAME "utf8"
LUAMOD_API int (luaopen_utf8) (lua_State *L);
#define LUA_MATHLIBNAME "math"
LUALIB_API int lua_mathlibopen (lua_State *L);
LUAMOD_API int (luaopen_math) (lua_State *L);
#define LUA_DBLIBNAME "debug"
LUALIB_API int lua_dblibopen (lua_State *L);
LUAMOD_API int (luaopen_debug) (lua_State *L);
#define LUA_LOADLIBNAME "package"
LUAMOD_API int (luaopen_package) (lua_State *L);
/* to help testing the libraries */
#ifndef lua_assert
#define lua_assert(c) /* empty */
/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);
#if !defined(lua_assert)
#define lua_assert(x) ((void)0)
#endif
#endif
+298 -249
View File
@@ -1,274 +1,323 @@
/*
** $Id: lundump.c,v 1.43 2002/08/07 00:36:03 lhf Exp $
** load pre-compiled Lua chunks
** $Id: lundump.c $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define lundump_c
#define LUA_CORE
#include "lprefix.h"
#include <limits.h>
#include <string.h>
#include "lua.h"
#include "ldebug.h"
#include "ldo.h"
#include "lfunc.h"
#include "lmem.h"
#include "lopcodes.h"
#include "lobject.h"
#include "lstring.h"
#include "lundump.h"
#include "lzio.h"
#define LoadByte (lu_byte) ezgetc
#if !defined(luai_verifycode)
#define luai_verifycode(L,f) /* empty */
#endif
typedef struct {
lua_State* L;
ZIO* Z;
int swap;
const char* name;
lua_State *L;
ZIO *Z;
const char *name;
} LoadState;
static void unexpectedEOZ (LoadState* S)
{
luaG_runerror(S->L,"unexpected end of file in %s",S->name);
static l_noret error (LoadState *S, const char *why) {
luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
luaD_throw(S->L, LUA_ERRSYNTAX);
}
static int ezgetc (LoadState* S)
{
int c=zgetc(S->Z);
if (c==EOZ) unexpectedEOZ(S);
return c;
}
static void ezread (LoadState* S, void* b, int n)
{
int r=luaZ_read(S->Z,b,n);
if (r!=0) unexpectedEOZ(S);
}
static void LoadBlock (LoadState* S, void* b, size_t size)
{
if (S->swap)
{
char *p=(char*) b+size-1;
int n=size;
while (n--) *p--=(char)ezgetc(S);
}
else
ezread(S,b,size);
}
static void LoadVector (LoadState* S, void* b, int m, size_t size)
{
if (S->swap)
{
char *q=(char*) b;
while (m--)
{
char *p=q+size-1;
int n=size;
while (n--) *p--=(char)ezgetc(S);
q+=size;
}
}
else
ezread(S,b,m*size);
}
static int LoadInt (LoadState* S)
{
int x;
LoadBlock(S,&x,sizeof(x));
if (x<0) luaG_runerror(S->L,"bad integer in %s",S->name);
return x;
}
static size_t LoadSize (LoadState* S)
{
size_t x;
LoadBlock(S,&x,sizeof(x));
return x;
}
static lua_Number LoadNumber (LoadState* S)
{
lua_Number x;
LoadBlock(S,&x,sizeof(x));
return x;
}
static TString* LoadString (LoadState* S)
{
size_t size=LoadSize(S);
if (size==0)
return NULL;
else
{
char* s=luaO_openspace(S->L,size,char);
ezread(S,s,size);
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
}
}
static void LoadCode (LoadState* S, Proto* f)
{
int size=LoadInt(S);
f->code=luaM_newvector(S->L,size,Instruction);
f->sizecode=size;
LoadVector(S,f->code,size,sizeof(*f->code));
}
static void LoadLocals (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->locvars=luaM_newvector(S->L,n,LocVar);
f->sizelocvars=n;
for (i=0; i<n; i++)
{
f->locvars[i].varname=LoadString(S);
f->locvars[i].startpc=LoadInt(S);
f->locvars[i].endpc=LoadInt(S);
}
}
static void LoadLines (LoadState* S, Proto* f)
{
int n;
n=LoadInt(S);
f->lineinfo=luaM_newvector(S->L,n,int);
LoadVector(S,f->lineinfo,n,sizeof(*f->lineinfo));
}
static Proto* LoadFunction (LoadState* S, TString* p);
static void LoadConstants (LoadState* S, Proto* f)
{
int i,n;
n=LoadInt(S);
f->k=luaM_newvector(S->L,n,TObject);
f->sizek=n;
for (i=0; i<n; i++)
{
TObject* o=&f->k[i];
int t=LoadByte(S);
switch (t)
{
case LUA_TNUMBER:
setnvalue(o,LoadNumber(S));
break;
case LUA_TSTRING:
setsvalue(o,LoadString(S));
break;
case LUA_TNIL:
setnilvalue(o);
break;
default:
luaG_runerror(S->L,"bad constant type (%d) in %s",t,S->name);
break;
}
}
n=LoadInt(S);
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);
}
static Proto* LoadFunction (LoadState* S, TString* p)
{
Proto* f=luaF_newproto(S->L);
f->source=LoadString(S); if (f->source==NULL) f->source=p;
f->lineDefined=LoadInt(S);
f->nupvalues=LoadByte(S);
f->numparams=LoadByte(S);
f->is_vararg=LoadByte(S);
f->maxstacksize=LoadByte(S);
LoadLocals(S,f);
LoadLines(S,f);
LoadConstants(S,f);
LoadCode(S,f);
#ifndef TRUST_BINARIES
if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name);
#endif
return f;
}
static void LoadSignature (LoadState* S)
{
const char* s=LUA_SIGNATURE;
while (*s!=0 && ezgetc(S)==*s)
++s;
if (*s!=0) luaG_runerror(S->L,"bad signature in %s",S->name);
}
static void TestSize (LoadState* S, int s, const char* what)
{
int r=LoadByte(S);
if (r!=s)
luaG_runerror(S->L,"virtual machine mismatch in %s: "
"size of %s is %d but read %d",S->name,what,s,r);
}
#define TESTSIZE(s,w) TestSize(S,s,w)
#define V(v) v/16,v%16
static void LoadHeader (LoadState* S)
{
int version;
lua_Number x=0,tx=TEST_NUMBER;
LoadSignature(S);
version=LoadByte(S);
if (version>VERSION)
luaG_runerror(S->L,"%s too new: "
"read version %d.%d; expected at most %d.%d",
S->name,V(version),V(VERSION));
if (version<VERSION0) /* check last major change */
luaG_runerror(S->L,"%s too old: "
"read version %d.%d; expected at least %d.%d",
S->name,V(version),V(VERSION0));
S->swap=(luaU_endianness()!=LoadByte(S)); /* need to swap bytes? */
TESTSIZE(sizeof(int),"int");
TESTSIZE(sizeof(size_t), "size_t");
TESTSIZE(sizeof(Instruction), "Instruction");
TESTSIZE(SIZE_OP, "OP");
TESTSIZE(SIZE_A, "A");
TESTSIZE(SIZE_B, "B");
TESTSIZE(SIZE_C, "C");
TESTSIZE(sizeof(lua_Number), "number");
x=LoadNumber(S);
if ((long)x!=(long)tx) /* disregard errors in last bits of fraction */
luaG_runerror(S->L,"unknown number format in %s: read %f; expected %f",
S->name,x,tx);
}
static Proto* LoadChunk (LoadState* S)
{
LoadHeader(S);
return LoadFunction(S,NULL);
}
/*
** load one chunk from a file or buffer
** All high-level loads go through loadVector; you can change it to
** adapt to the endianness of the input
*/
Proto* luaU_undump (lua_State* L, ZIO* Z)
{
LoadState S;
Proto* f;
const char* s=zname(Z);
if (*s=='@' || *s=='=')
S.name=s+1;
else if (*s==LUA_SIGNATURE[0])
S.name="binary string";
else
S.name=s;
S.L=L;
S.Z=Z;
f=LoadChunk(&S);
if (zgetc(Z)!=EOZ)
luaG_runerror(L,"%s apparently contains more than one chunk",S.name);
return f;
#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0]))
static void loadBlock (LoadState *S, void *b, size_t size) {
if (luaZ_read(S->Z, b, size) != 0)
error(S, "truncated chunk");
}
/*
** find byte order
*/
int luaU_endianness (void)
{
int x=1;
return *(char*)&x;
#define loadVar(S,x) loadVector(S,&x,1)
static lu_byte loadByte (LoadState *S) {
int b = zgetc(S->Z);
if (b == EOZ)
error(S, "truncated chunk");
return cast_byte(b);
}
static size_t loadUnsigned (LoadState *S, size_t limit) {
size_t x = 0;
int b;
limit >>= 7;
do {
b = loadByte(S);
if (x >= limit)
error(S, "integer overflow");
x = (x << 7) | (b & 0x7f);
} while ((b & 0x80) == 0);
return x;
}
static size_t loadSize (LoadState *S) {
return loadUnsigned(S, ~(size_t)0);
}
static int loadInt (LoadState *S) {
return cast_int(loadUnsigned(S, INT_MAX));
}
static lua_Number loadNumber (LoadState *S) {
lua_Number x;
loadVar(S, x);
return x;
}
static lua_Integer loadInteger (LoadState *S) {
lua_Integer x;
loadVar(S, x);
return x;
}
/*
** Load a nullable string into prototype 'p'.
*/
static TString *loadStringN (LoadState *S, Proto *p) {
lua_State *L = S->L;
TString *ts;
size_t size = loadSize(S);
if (size == 0) /* no string? */
return NULL;
else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
char buff[LUAI_MAXSHORTLEN];
loadVector(S, buff, size); /* load string into buffer */
ts = luaS_newlstr(L, buff, size); /* create string */
}
else { /* long string */
ts = luaS_createlngstrobj(L, size); /* create string */
loadVector(S, getstr(ts), size); /* load directly in final place */
}
luaC_objbarrier(L, p, ts);
return ts;
}
/*
** Load a non-nullable string into prototype 'p'.
*/
static TString *loadString (LoadState *S, Proto *p) {
TString *st = loadStringN(S, p);
if (st == NULL)
error(S, "bad format for constant string");
return st;
}
static void loadCode (LoadState *S, Proto *f) {
int n = loadInt(S);
f->code = luaM_newvectorchecked(S->L, n, Instruction);
f->sizecode = n;
loadVector(S, f->code, n);
}
static void loadFunction(LoadState *S, Proto *f, TString *psource);
static void loadConstants (LoadState *S, Proto *f) {
int i;
int n = loadInt(S);
f->k = luaM_newvectorchecked(S->L, n, TValue);
f->sizek = n;
for (i = 0; i < n; i++)
setnilvalue(&f->k[i]);
for (i = 0; i < n; i++) {
TValue *o = &f->k[i];
int t = loadByte(S);
switch (t) {
case LUA_VNIL:
setnilvalue(o);
break;
case LUA_VFALSE:
setbfvalue(o);
break;
case LUA_VTRUE:
setbtvalue(o);
break;
case LUA_VNUMFLT:
setfltvalue(o, loadNumber(S));
break;
case LUA_VNUMINT:
setivalue(o, loadInteger(S));
break;
case LUA_VSHRSTR:
case LUA_VLNGSTR:
setsvalue2n(S->L, o, loadString(S, f));
break;
default: lua_assert(0);
}
}
}
static void loadProtos (LoadState *S, Proto *f) {
int i;
int n = loadInt(S);
f->p = luaM_newvectorchecked(S->L, n, Proto *);
f->sizep = n;
for (i = 0; i < n; i++)
f->p[i] = NULL;
for (i = 0; i < n; i++) {
f->p[i] = luaF_newproto(S->L);
luaC_objbarrier(S->L, f, f->p[i]);
loadFunction(S, f->p[i], f->source);
}
}
static void loadUpvalues (LoadState *S, Proto *f) {
int i, n;
n = loadInt(S);
f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
f->sizeupvalues = n;
for (i = 0; i < n; i++) {
f->upvalues[i].name = NULL;
f->upvalues[i].instack = loadByte(S);
f->upvalues[i].idx = loadByte(S);
f->upvalues[i].kind = loadByte(S);
}
}
static void loadDebug (LoadState *S, Proto *f) {
int i, n;
n = loadInt(S);
f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
f->sizelineinfo = n;
loadVector(S, f->lineinfo, n);
n = loadInt(S);
f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
f->sizeabslineinfo = n;
for (i = 0; i < n; i++) {
f->abslineinfo[i].pc = loadInt(S);
f->abslineinfo[i].line = loadInt(S);
}
n = loadInt(S);
f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
f->sizelocvars = n;
for (i = 0; i < n; i++)
f->locvars[i].varname = NULL;
for (i = 0; i < n; i++) {
f->locvars[i].varname = loadStringN(S, f);
f->locvars[i].startpc = loadInt(S);
f->locvars[i].endpc = loadInt(S);
}
n = loadInt(S);
for (i = 0; i < n; i++)
f->upvalues[i].name = loadStringN(S, f);
}
static void loadFunction (LoadState *S, Proto *f, TString *psource) {
f->source = loadStringN(S, f);
if (f->source == NULL) /* no source in dump? */
f->source = psource; /* reuse parent's source */
f->linedefined = loadInt(S);
f->lastlinedefined = loadInt(S);
f->numparams = loadByte(S);
f->is_vararg = loadByte(S);
f->maxstacksize = loadByte(S);
loadCode(S, f);
loadConstants(S, f);
loadUpvalues(S, f);
loadProtos(S, f);
loadDebug(S, f);
}
static void checkliteral (LoadState *S, const char *s, const char *msg) {
char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
size_t len = strlen(s);
loadVector(S, buff, len);
if (memcmp(s, buff, len) != 0)
error(S, msg);
}
static void fchecksize (LoadState *S, size_t size, const char *tname) {
if (loadByte(S) != size)
error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
}
#define checksize(S,t) fchecksize(S,sizeof(t),#t)
static void checkHeader (LoadState *S) {
/* skip 1st char (already read and checked) */
checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
if (loadByte(S) != LUAC_VERSION)
error(S, "version mismatch");
if (loadByte(S) != LUAC_FORMAT)
error(S, "format mismatch");
checkliteral(S, LUAC_DATA, "corrupted chunk");
checksize(S, Instruction);
checksize(S, lua_Integer);
checksize(S, lua_Number);
if (loadInteger(S) != LUAC_INT)
error(S, "integer format mismatch");
if (loadNumber(S) != LUAC_NUM)
error(S, "float format mismatch");
}
/*
** Load precompiled chunk.
*/
LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
LoadState S;
LClosure *cl;
if (*name == '@' || *name == '=')
S.name = name + 1;
else if (*name == LUA_SIGNATURE[0])
S.name = "binary string";
else
S.name = name;
S.L = L;
S.Z = Z;
checkHeader(&S);
cl = luaF_newLclosure(L, loadByte(&S));
setclLvalue2s(L, L->top, cl);
luaD_inctop(L);
cl->p = luaF_newproto(L);
luaC_objbarrier(L, cl, cl->p);
loadFunction(&S, cl->p, NULL);
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
luai_verifycode(L, cl->p);
return cl;
}
+21 -21
View File
@@ -1,36 +1,36 @@
/*
** $Id: lundump.h,v 1.26 2002/08/07 00:36:03 lhf Exp $
** load pre-compiled Lua chunks
** $Id: lundump.h $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#ifndef lundump_h
#define lundump_h
#include "llimits.h"
#include "lobject.h"
#include "lzio.h"
typedef int (*Writer)(const void* p, size_t size, void* u);
/* data to catch conversion errors */
#define LUAC_DATA "\x19\x93\r\n\x1a\n"
#define LUAC_INT 0x5678
#define LUAC_NUM cast_num(370.5)
/*
** Encode major-minor version in one byte, one nibble for each
*/
#define MYINT(s) (s[0]-'0') /* assume one-digit numerals */
#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR))
#define LUAC_FORMAT 0 /* this is the official format */
/* load one chunk; from lundump.c */
Proto* luaU_undump (lua_State* L, ZIO* Z);
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
/* find byte order; from lundump.c */
int luaU_endianness (void);
/* dump one chunk; from dump.c */
void luaU_dump (const Proto* Main, Writer w, void* data);
/* print one chunk; from print.c */
void luaU_print (const Proto* Main);
/* definitions for headers of binary files */
#define LUA_SIGNATURE "\033Lua" /* binary files start with <esc>Lua */
#define VERSION 0x50 /* last format change was in 5.0 */
#define VERSION0 0x50 /* last major change was in 5.0 */
/* a multiple of PI for testing native format */
/* multiplying by 1E8 gives non-trivial integer values */
#define TEST_NUMBER 3.14159265358979323846E8
/* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
void* data, int strip);
#endif
+289
View File
@@ -0,0 +1,289 @@
/*
** $Id: lutf8lib.c $
** Standard library for UTF-8 manipulation
** See Copyright Notice in lua.h
*/
#define lutf8lib_c
#define LUA_LIB
#include "lprefix.h"
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#define MAXUNICODE 0x10FFFFu
#define MAXUTF 0x7FFFFFFFu
/*
** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits.
*/
#if (UINT_MAX >> 30) >= 1
typedef unsigned int utfint;
#else
typedef unsigned long utfint;
#endif
#define iscont(p) ((*(p) & 0xC0) == 0x80)
/* from strlib */
/* translate a relative string position: negative means back from end */
static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
if (pos >= 0) return pos;
else if (0u - (size_t)pos > len) return 0;
else return (lua_Integer)len + pos + 1;
}
/*
** Decode one UTF-8 sequence, returning NULL if byte sequence is
** invalid. The array 'limits' stores the minimum value for each
** sequence length, to check for overlong representations. Its first
** entry forces an error for non-ascii bytes with no continuation
** bytes (count == 0).
*/
static const char *utf8_decode (const char *s, utfint *val, int strict) {
static const utfint limits[] =
{~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u};
unsigned int c = (unsigned char)s[0];
utfint res = 0; /* final result */
if (c < 0x80) /* ascii? */
res = c;
else {
int count = 0; /* to count number of continuation bytes */
for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
unsigned int cc = (unsigned char)s[++count]; /* read next byte */
if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
return NULL; /* invalid byte sequence */
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
}
res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */
if (count > 5 || res > MAXUTF || res < limits[count])
return NULL; /* invalid byte sequence */
s += count; /* skip continuation bytes read */
}
if (strict) {
/* check for invalid code points; too large or surrogates */
if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu))
return NULL;
}
if (val) *val = res;
return s + 1; /* +1 to include first byte */
}
/*
** utf8len(s [, i [, j [, lax]]]) --> number of characters that
** start in the range [i,j], or nil + current position if 's' is not
** well formed in that interval
*/
static int utflen (lua_State *L) {
lua_Integer n = 0; /* counter for the number of characters */
size_t len; /* string length in bytes */
const char *s = luaL_checklstring(L, 1, &len);
lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
int lax = lua_toboolean(L, 4);
luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
"initial position out of bounds");
luaL_argcheck(L, --posj < (lua_Integer)len, 3,
"final position out of bounds");
while (posi <= posj) {
const char *s1 = utf8_decode(s + posi, NULL, !lax);
if (s1 == NULL) { /* conversion error? */
luaL_pushfail(L); /* return fail ... */
lua_pushinteger(L, posi + 1); /* ... and current position */
return 2;
}
posi = s1 - s;
n++;
}
lua_pushinteger(L, n);
return 1;
}
/*
** codepoint(s, [i, [j [, lax]]]) -> returns codepoints for all
** characters that start in the range [i,j]
*/
static int codepoint (lua_State *L) {
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
int lax = lua_toboolean(L, 4);
int n;
const char *se;
luaL_argcheck(L, posi >= 1, 2, "out of bounds");
luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of bounds");
if (posi > pose) return 0; /* empty interval; return no values */
if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */
return luaL_error(L, "string slice too long");
n = (int)(pose - posi) + 1; /* upper bound for number of returns */
luaL_checkstack(L, n, "string slice too long");
n = 0; /* count the number of returns */
se = s + pose; /* string end */
for (s += posi - 1; s < se;) {
utfint code;
s = utf8_decode(s, &code, !lax);
if (s == NULL)
return luaL_error(L, "invalid UTF-8 code");
lua_pushinteger(L, code);
n++;
}
return n;
}
static void pushutfchar (lua_State *L, int arg) {
lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg);
luaL_argcheck(L, code <= MAXUTF, arg, "value out of range");
lua_pushfstring(L, "%U", (long)code);
}
/*
** utfchar(n1, n2, ...) -> char(n1)..char(n2)...
*/
static int utfchar (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
if (n == 1) /* optimize common case of single char */
pushutfchar(L, 1);
else {
int i;
luaL_Buffer b;
luaL_buffinit(L, &b);
for (i = 1; i <= n; i++) {
pushutfchar(L, i);
luaL_addvalue(&b);
}
luaL_pushresult(&b);
}
return 1;
}
/*
** offset(s, n, [i]) -> index where n-th character counting from
** position 'i' starts; 0 means character at 'i'.
*/
static int byteoffset (lua_State *L) {
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
lua_Integer n = luaL_checkinteger(L, 2);
lua_Integer posi = (n >= 0) ? 1 : len + 1;
posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
"position out of bounds");
if (n == 0) {
/* find beginning of current byte sequence */
while (posi > 0 && iscont(s + posi)) posi--;
}
else {
if (iscont(s + posi))
return luaL_error(L, "initial position is a continuation byte");
if (n < 0) {
while (n < 0 && posi > 0) { /* move back */
do { /* find beginning of previous character */
posi--;
} while (posi > 0 && iscont(s + posi));
n++;
}
}
else {
n--; /* do not move for 1st character */
while (n > 0 && posi < (lua_Integer)len) {
do { /* find beginning of next character */
posi++;
} while (iscont(s + posi)); /* (cannot pass final '\0') */
n--;
}
}
}
if (n == 0) /* did it find given character? */
lua_pushinteger(L, posi + 1);
else /* no such character */
luaL_pushfail(L);
return 1;
}
static int iter_aux (lua_State *L, int strict) {
size_t len;
const char *s = luaL_checklstring(L, 1, &len);
lua_Integer n = lua_tointeger(L, 2) - 1;
if (n < 0) /* first iteration? */
n = 0; /* start from here */
else if (n < (lua_Integer)len) {
n++; /* skip current byte */
while (iscont(s + n)) n++; /* and its continuations */
}
if (n >= (lua_Integer)len)
return 0; /* no more codepoints */
else {
utfint code;
const char *next = utf8_decode(s + n, &code, strict);
if (next == NULL)
return luaL_error(L, "invalid UTF-8 code");
lua_pushinteger(L, n + 1);
lua_pushinteger(L, code);
return 2;
}
}
static int iter_auxstrict (lua_State *L) {
return iter_aux(L, 1);
}
static int iter_auxlax (lua_State *L) {
return iter_aux(L, 0);
}
static int iter_codes (lua_State *L) {
int lax = lua_toboolean(L, 2);
luaL_checkstring(L, 1);
lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict);
lua_pushvalue(L, 1);
lua_pushinteger(L, 0);
return 3;
}
/* pattern to match a single UTF-8 character */
#define UTF8PATT "[\0-\x7F\xC2-\xFD][\x80-\xBF]*"
static const luaL_Reg funcs[] = {
{"offset", byteoffset},
{"codepoint", codepoint},
{"char", utfchar},
{"len", utflen},
{"codes", iter_codes},
/* placeholders */
{"charpattern", NULL},
{NULL, NULL}
};
LUAMOD_API int luaopen_utf8 (lua_State *L) {
luaL_newlib(L, funcs);
lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
lua_setfield(L, -2, "charpattern");
return 1;
}
+1674 -599
View File
File diff suppressed because it is too large Load Diff
+116 -17
View File
@@ -1,5 +1,5 @@
/*
** $Id: lvm.h,v 1.45 2002/08/05 17:36:24 roberto Exp roberto $
** $Id: lvm.h $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -13,23 +13,122 @@
#include "ltm.h"
#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
(((o) = luaV_tonumber(o,n)) != NULL))
#define equalobj(L,o1,o2) \
(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
#if !defined(LUA_NOCVTN2S)
#define cvt2str(o) ttisnumber(o)
#else
#define cvt2str(o) 0 /* no conversion from numbers to strings */
#endif
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
const TObject *luaV_tonumber (const TObject *obj, TObject *n);
int luaV_tostring (lua_State *L, TObject *obj);
const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
int loop);
void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val);
StkId luaV_execute (lua_State *L);
void luaV_concat (lua_State *L, int total, int last);
#if !defined(LUA_NOCVTS2N)
#define cvt2num(o) ttisstring(o)
#else
#define cvt2num(o) 0 /* no conversion from strings to numbers */
#endif
/*
** You can define LUA_FLOORN2I if you want to convert floats to integers
** by flooring them (instead of raising an error if they are not
** integral values)
*/
#if !defined(LUA_FLOORN2I)
#define LUA_FLOORN2I F2Ieq
#endif
/*
** Rounding modes for float->integer coercion
*/
typedef enum {
F2Ieq, /* no rounding; accepts only integral values */
F2Ifloor, /* takes the floor of the number */
F2Iceil /* takes the ceil of the number */
} F2Imod;
/* convert an object to a float (including string coercion) */
#define tonumber(o,n) \
(ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
/* convert an object to a float (without string coercion) */
#define tonumberns(o,n) \
(ttisfloat(o) ? ((n) = fltvalue(o), 1) : \
(ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0))
/* convert an object to an integer (including string coercion) */
#define tointeger(o,i) \
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
/* convert an object to an integer (without string coercion) */
#define tointegerns(o,i) \
(ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointegerns(o,i,LUA_FLOORN2I))
#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
/*
** fast track for 'gettable': if 't' is a table and 't[k]' is present,
** return 1 with 'slot' pointing to 't[k]' (position of final result).
** Otherwise, return 0 (meaning it will have to check metamethod)
** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL
** (otherwise). 'f' is the raw get function to use.
*/
#define luaV_fastget(L,t,k,slot,f) \
(!ttistable(t) \
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
: (slot = f(hvalue(t), k), /* else, do raw access */ \
!isempty(slot))) /* result not empty? */
/*
** Special case of 'luaV_fastget' for integers, inlining the fast case
** of 'luaH_getint'.
*/
#define luaV_fastgeti(L,t,k,slot) \
(!ttistable(t) \
? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \
: (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
!isempty(slot))) /* result not empty? */
/*
** Finish a fast set operation (when fast get succeeds). In that case,
** 'slot' points to the place to put the value.
*/
#define luaV_finishfastset(L,t,slot,v) \
{ setobj2t(L, cast(TValue *,slot), v); \
luaC_barrierback(L, gcvalue(t), v); }
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode);
LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p,
F2Imod mode);
LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode);
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *slot);
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
TValue *val, const TValue *slot);
LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci);
LUAI_FUNC void luaV_concat (lua_State *L, int total);
LUAI_FUNC lua_Integer luaV_idiv (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
LUAI_FUNC lua_Number luaV_modf (lua_State *L, lua_Number x, lua_Number y);
LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
#endif
+25 -25
View File
@@ -1,44 +1,44 @@
/*
** $Id: lzio.c,v 1.20 2002/08/05 18:45:02 roberto Exp roberto $
** a generic input stream interface
** $Id: lzio.c $
** Buffered streams
** See Copyright Notice in lua.h
*/
#define lzio_c
#define LUA_CORE
#include "lprefix.h"
#include <string.h>
#include "lua.h"
#include "llimits.h"
#include "lmem.h"
#include "lstate.h"
#include "lzio.h"
int luaZ_fill (ZIO *z) {
size_t size;
const char *buff = z->reader(NULL, z->data, &size);
if (buff == NULL || size == 0) return EOZ;
z->n = size - 1;
lua_State *L = z->L;
const char *buff;
lua_unlock(L);
buff = z->reader(L, z->data, &size);
lua_lock(L);
if (buff == NULL || size == 0)
return EOZ;
z->n = size - 1; /* discount char being returned */
z->p = buff;
return *(z->p++);
return cast_uchar(*(z->p++));
}
int luaZ_lookahead (ZIO *z) {
if (z->n == 0) {
int c = luaZ_fill(z);
if (c == EOZ) return c;
z->n++;
z->p--;
}
return *z->p;
}
void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
z->L = L;
z->reader = reader;
z->data = data;
z->name = name;
z->n = 0;
z->p = NULL;
}
@@ -48,12 +48,12 @@ void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name) {
size_t luaZ_read (ZIO *z, void *b, size_t n) {
while (n) {
size_t m;
if (z->n == 0) {
if (luaZ_fill(z) == EOZ)
return n; /* return number of missing bytes */
if (z->n == 0) { /* no bytes in buffer? */
if (luaZ_fill(z) == EOZ) /* try to read more */
return n; /* no more input; return number of missing bytes */
else {
++z->n; /* filbuf removed first byte; put back it */
--z->p;
z->n++; /* luaZ_fill consumed first byte; put it back */
z->p--;
}
}
m = (n <= z->n) ? n : z->n; /* min. between n and z->n */
+38 -14
View File
@@ -1,5 +1,5 @@
/*
** $Id: lzio.h,v 1.12 2002/06/06 12:40:22 roberto Exp roberto $
** $Id: lzio.h $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -10,33 +10,57 @@
#include "lua.h"
#include "lmem.h"
#define EOZ (-1) /* end of stream */
typedef struct zio ZIO;
typedef struct Zio ZIO;
#define zgetc(z) (((z)->n--)>0 ? \
cast(int, cast(unsigned char, *(z)->p++)) : \
luaZ_fill(z))
#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z))
#define zname(z) ((z)->name)
void luaZ_init (ZIO *z, lua_Chunkreader reader, void *data, const char *name);
size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */
int luaZ_lookahead (ZIO *z);
typedef struct Mbuffer {
char *buffer;
size_t n;
size_t buffsize;
} Mbuffer;
#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)
#define luaZ_buffer(buff) ((buff)->buffer)
#define luaZ_sizebuffer(buff) ((buff)->buffsize)
#define luaZ_bufflen(buff) ((buff)->n)
#define luaZ_buffremove(buff,i) ((buff)->n -= (i))
#define luaZ_resetbuffer(buff) ((buff)->n = 0)
#define luaZ_resizebuffer(L, buff, size) \
((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \
(buff)->buffsize, size), \
(buff)->buffsize = size)
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data);
LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */
/* --------- Private Part ------------------ */
struct zio {
struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Chunkreader reader;
void* data; /* additional data */
const char *name;
lua_Reader reader; /* reader function */
void *data; /* additional data */
lua_State *L; /* Lua state (for reader) */
};
int luaZ_fill (ZIO *z);
LUAI_FUNC int luaZ_fill (ZIO *z);
#endif
+185 -139
View File
@@ -1,160 +1,206 @@
#
## $Id: makefile,v 1.35 2002/03/18 18:18:35 roberto Exp roberto $
## Makefile
## See Copyright Notice in lua.h
#
# Developer's makefile for building Lua
# see luaconf.h for further customization
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
#CONFIGURATION
# define (undefine) POPEN if your system (does not) support piped I/O
#
# define (undefine) _POSIX_SOURCE if your system is (not) POSIX compliant
#
# define LUA_NUM_TYPE if you need numbers to be different from double
# (for instance, -DLUA_NUM_TYPE=float)
# you may need to adapat the code, too.
# DEBUG = -g -DLUA_USER_H='"ltests.h"'
OPTIMIZE = -O2 \
-D'lua_number2int(i,d)=__asm__("fldl %1\nfistpl %0":"=m"(i):"m"(d))' \
-fomit-frame-pointer
CONFIG = -D_POSIX_SOURCE -DPOPEN $(DEBUG) $(OPTIMIZE)
# Compilation parameters
CC = gcc
CWARNS = -Wall -pedantic \
-Waggregate-return \
-Wcast-align \
-Wmissing-prototypes \
-Wstrict-prototypes \
-Wnested-externs \
-Wpointer-arith \
# Warnings valid for both C and C++
CWARNSCPP= \
-fmax-errors=5 \
-Wextra \
-Wshadow \
-Wsign-compare \
-Wundef \
-Wwrite-strings \
# -Wtraditional \
# -Wcast-qual
-Wredundant-decls \
-Wdisabled-optimization \
-Wdouble-promotion \
-Wlogical-op \
-Wno-aggressive-loop-optimizations \
# the next warnings might be useful sometimes,
# but usually they generate too much noise
# -Werror \
# -pedantic # warns if we use jump tables \
# -Wconversion \
# -Wsign-conversion \
# -Wstrict-overflow=2 \
# -Wformat=2 \
# -Wcast-qual \
CFLAGS = $(CONFIG) $(CWARNS) -ansi
# The next warnings are neither valid nor needed for C++
CWARNSC= -Wdeclaration-after-statement \
-Wmissing-prototypes \
-Wnested-externs \
-Wstrict-prototypes \
-Wc++-compat \
-Wold-style-definition \
# To make early versions
CO_OPTIONS =
CWARNS= $(CWARNSCPP) $(CWARNSC)
AR = ar
ARFLAGS = rvl
# -DEXTERNMEMCHECK -DHARDSTACKTESTS -DHARDMEMTESTS -DTRACEMEM='"tempmem"'
# -DMAXINDEXRK=1 -DLUA_COMPAT_5_3
# -g -DLUA_USER_H='"ltests.h"'
# -pg -malign-double
# -DLUA_USE_CTYPE -DLUA_USE_APICHECK
# ('-ftrapv' for runtime checks of integer overflows)
# -fsanitize=undefined -ftrapv -fno-inline
# TESTS= -DLUA_USER_H='"ltests.h"' -O0 -g
# Aplication modules
LUAOBJS = \
lstate.o \
lapi.o \
lmem.o \
lstring.o \
ltable.o \
ltm.o \
lvm.o \
ldo.o \
lobject.o \
lfunc.o \
lgc.o \
lcode.o \
lparser.o \
llex.o \
lopcodes.o \
lundump.o \
lzio.o \
ldebug.o \
ltests.o
LIBOBJS = \
lauxlib.o \
lbaselib.o \
ltablib.o \
lmathlib.o \
liolib.o \
lstrlib.o \
ldblib.o
LOCAL = $(TESTS) $(CWARNS)
lua : lua.o liblua.a liblualib.a
$(CC) $(CFLAGS) -o $@ lua.o -L. -llua -llualib -lm
liblua.a : $(LUAOBJS)
$(AR) $(ARFLAGS) $@ $?
ranlib $@
liblualib.a : $(LIBOBJS)
$(AR) $(ARFLAGS) $@ $?
ranlib $@
liblua.so.1.0 : lua.o
ld -o liblua.so.1.0 $(LUAOBJS)
# enable Linux goodies
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_USE_READLINE
MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS= -ldl -lreadline
clear :
rcsclean
rm -f *.o *.a
CC= gcc
CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
AR= ar rc
RANLIB= ranlib
RM= rm -f
%.h : RCS/%.h,v
co $(CO_OPTIONS) $@
%.c : RCS/%.c,v
co $(CO_OPTIONS) $@
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
lapi.o: lapi.c lua.h lapi.h lobject.h llimits.h ldebug.h lstate.h \
ltm.h ldo.h lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h lundump.h \
LIBS = -lm
CORE_T= 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 ltests.o
AUX_O= lauxlib.o
LIB_O= lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o \
lutf8lib.o loadlib.o lcorolib.o linit.o
LUA_T= lua
LUA_O= lua.o
# LUAC_T= luac
# LUAC_O= luac.o print.o
ALL_T= $(CORE_T) $(LUA_T) $(LUAC_T)
ALL_O= $(CORE_O) $(LUA_O) $(LUAC_O) $(AUX_O) $(LIB_O)
ALL_A= $(CORE_T)
all: $(ALL_T)
touch all
o: $(ALL_O)
a: $(ALL_A)
$(CORE_T): $(CORE_O) $(AUX_O) $(LIB_O)
$(AR) $@ $?
$(RANLIB) $@
$(LUA_T): $(LUA_O) $(CORE_T)
$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(CORE_T) $(LIBS) $(MYLIBS) $(DL)
$(LUAC_T): $(LUAC_O) $(CORE_T)
$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(CORE_T) $(LIBS) $(MYLIBS)
llex.o:
$(CC) $(CFLAGS) -Os -c llex.c
lparser.o:
$(CC) $(CFLAGS) -Os -c lparser.c
lcode.o:
$(CC) $(CFLAGS) -Os -c lcode.c
clean:
$(RM) $(ALL_T) $(ALL_O)
depend:
@$(CC) $(CFLAGS) -MM *.c
echo:
@echo "CC = $(CC)"
@echo "CFLAGS = $(CFLAGS)"
@echo "AR = $(AR)"
@echo "RANLIB = $(RANLIB)"
@echo "RM = $(RM)"
@echo "MYCFLAGS = $(MYCFLAGS)"
@echo "MYLDFLAGS = $(MYLDFLAGS)"
@echo "MYLIBS = $(MYLIBS)"
@echo "DL = $(DL)"
$(ALL_O): makefile ltests.h
# DO NOT EDIT
# automatically made with 'gcc -MM l*.c'
lapi.o: lapi.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h \
ltable.h lundump.h lvm.h
lauxlib.o: lauxlib.c lprefix.h lua.h luaconf.h lauxlib.h
lbaselib.o: lbaselib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lcode.o: lcode.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lgc.h lstring.h ltable.h lvm.h
lcorolib.o: lcorolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lctype.o: lctype.c lprefix.h lctype.h lua.h luaconf.h llimits.h
ldblib.o: ldblib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ldebug.o: ldebug.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h \
ldebug.h ldo.h lfunc.h lstring.h lgc.h ltable.h lvm.h
ldo.o: ldo.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h \
lparser.h lstring.h ltable.h lundump.h lvm.h
ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h
linit.o: linit.c lprefix.h lua.h luaconf.h lualib.h lauxlib.h
liolib.o: liolib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
llex.o: llex.c lprefix.h lua.h luaconf.h lctype.h llimits.h ldebug.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h llex.h lparser.h \
lstring.h ltable.h
lmathlib.o: lmathlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lmem.o: lmem.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h
loadlib.o: loadlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lobject.o: lobject.c lprefix.h lua.h luaconf.h lctype.h llimits.h \
ldebug.h lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h \
lvm.h
lauxlib.o: lauxlib.c lua.h lauxlib.h
lbaselib.o: lbaselib.c lua.h lauxlib.h lualib.h
lcode.o: lcode.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h lmem.h
ldblib.o: ldblib.c lua.h lauxlib.h lualib.h
ldebug.o: ldebug.c lua.h lapi.h lobject.h llimits.h lcode.h llex.h \
lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h ldo.h \
lfunc.h lstring.h lvm.h
ldo.o: ldo.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lmem.h lopcodes.h lparser.h ltable.h lstring.h \
lundump.h lvm.h
lfunc.o: lfunc.c lua.h lfunc.h lobject.h llimits.h lmem.h lstate.h \
ltm.h
lgc.o: lgc.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lmem.h lstring.h ltable.h
liolib.o: liolib.c lua.h lauxlib.h lualib.h
llex.o: llex.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h lzio.h \
llex.h lparser.h ltable.h lstring.h
lmathlib.o: lmathlib.c lua.h lauxlib.h lualib.h
lmem.o: lmem.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lmem.h
lobject.o: lobject.c lua.h ldo.h lobject.h llimits.h lstate.h ltm.h \
lzio.h lmem.h lstring.h lvm.h
lopcodes.o: lopcodes.c lua.h lobject.h llimits.h lopcodes.h
lparser.o: lparser.c lua.h lcode.h llex.h lobject.h llimits.h lzio.h \
lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h lfunc.h lmem.h \
lstring.h
lstate.o: lstate.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
ldo.h lzio.h lfunc.h lgc.h llex.h lmem.h lstring.h ltable.h
lstring.o: lstring.c lua.h lmem.h llimits.h lobject.h lstate.h ltm.h \
lstring.h
lstrlib.o: lstrlib.c lua.h lauxlib.h lualib.h
ltable.o: ltable.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
ldo.h lzio.h lmem.h ltable.h
ltablib.o: ltablib.c lua.h lauxlib.h lualib.h
ltests.o: ltests.c lua.h lapi.h lobject.h llimits.h lauxlib.h lcode.h \
llex.h lzio.h lopcodes.h lparser.h ltable.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lmem.h lstring.h lualib.h
ltm.o: ltm.c lua.h lobject.h llimits.h lstate.h ltm.h lstring.h \
ltable.h
lua.o: lua.c lua.h lauxlib.h lualib.h
lundump.o: lundump.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h \
lfunc.h lmem.h lopcodes.h lstring.h lundump.h lzio.h
lvm.o: lvm.c lua.h ldebug.h lstate.h lobject.h llimits.h ltm.h ldo.h \
lzio.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h
lzio.o: lzio.c lua.h llimits.h lzio.h
lopcodes.o: lopcodes.c lprefix.h lopcodes.h llimits.h lua.h luaconf.h
loslib.o: loslib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.h \
llimits.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h \
ldo.h lfunc.h lstring.h lgc.h ltable.h
lstate.o: lstate.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h \
lstring.h ltable.h
lstring.o: lstring.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h
lstrlib.o: lstrlib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltable.o: ltable.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h
ltablib.o: ltablib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
ltests.o: ltests.c lprefix.h lua.h luaconf.h lapi.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h lauxlib.h lcode.h llex.h lopcodes.h \
lparser.h lctype.h ldebug.h ldo.h lfunc.h lopnames.h lstring.h lgc.h \
ltable.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 lgc.h lstring.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h lstate.h \
lobject.h llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h \
lundump.h
lutf8lib.o: lutf8lib.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h ljumptab.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
lobject.h ltm.h lzio.h
# (end of Makefile)
-4298
View File
File diff suppressed because it is too large Load Diff
Executable
+519
View File
@@ -0,0 +1,519 @@
#!/usr/bin/env lua5.3
-- special marks:
-- \1 - paragraph (empty line)
-- \4 - remove spaces around it
-- \3 - ref (followed by label|)
---------------------------------------------------------------
header = [[
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Lua 5.4 Reference Manual</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" href="lua.css">
<link rel="stylesheet" href="manual.css">
</head>
<body bgcolor="#FFFFFF">
<hr>
<h1>
<a href="http://www.lua.org/home.html"><img src="logo.gif" alt="[Lua logo]" border="0"></a>
Lua 5.4 Reference Manual
</h1>
by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
<p>
<small>
<a href="http://www.lua.org/copyright.html">Copyright</a>
&copy; 2020 Lua.org, PUC-Rio. All rights reserved.
</small>
<hr>
<!-- ====================================================================== -->
<p>
]]
footer = "\n\n</body></html>\n\n"
local seefmt = '(see %s)'
if arg[1] == 'port' then
seefmt = '(ver %s)'
header = string.gsub(header, "by (.-)\n",
"%1\n<p>Tradu&ccedil;&atilde;o: S&eacute;rgio Queiroz de Medeiros", 1)
header = string.gsub(header, "Lua (%d+.%d+) Reference Manual",
"Manual de Refer&ecirc;ncia de Lua %1")
header = string.gsub(header, "All rights reserved",
"Todos os direitos reservados")
end
---------------------------------------------------------------
local function compose (f,g)
assert(f and g)
return function (s) return g(f(s)) end
end
local function concat (f, g)
assert(f and g)
return function (s) return f(s) .. g(s) end
end
local Tag = {}
setmetatable(Tag, {
__index = function (t, tag)
local v = function (n, att)
local e = ""
if type(att) == "table" then
for k,v in pairs(att) do e = string.format('%s %s="%s"', e, k, v) end
end
if n then
return string.format("<%s%s>%s</%s>", tag, e, n, tag)
else
return string.format("<%s%s>", tag, e)
end
end
t[tag] = v
return v
end
})
---------------------------------------------------------------
local labels = {}
local function anchor (text, label, link, textlink)
if labels[label] then
error("label " .. label .. " already defined")
end
labels[label] = {text = textlink, link = link}
return Tag.a(text, {name=link})
end
local function makeref (label)
assert(not string.find(label, "|"))
return string.format("\3%s\3", label)
end
local function ref (label)
local l = labels[label]
if not l then
io.stderr:write("label ", label, " undefined\n")
return "@@@@@@@"
else
return Tag.a(l.text, {href="#"..l.link})
end
end
---------------------------------------------------------------
local function nopara (t)
t = string.gsub(t, "\1", "\n\n")
t = string.gsub(t, "<p>%s*</p>", "")
return t
end
local function fixpara (t)
t = string.gsub(t, "\1", "\n</p>\n\n<p>\n")
t = string.gsub(t, "<p>%s*</p>", "")
return t
end
local function antipara (t)
return "</p>\n" .. t .. "<p>"
end
Tag.pre = compose(Tag.pre, antipara)
Tag.ul = compose(Tag.ul, antipara)
---------------------------------------------------------------
local Gfoots = 0
local footnotes = {}
local line = Tag.hr(nil)
local function dischargefoots ()
if #footnotes == 0 then return "" end
local fn = table.concat(footnotes)
footnotes = {}
return line .. Tag.h3"footnotes:" .. fn .. line
end
local Glists = 0
local listings = {}
local function dischargelist ()
if #listings == 0 then return "" end
local l = listings
listings = {}
return line .. table.concat(l, line..line) .. line
end
---------------------------------------------------------------
local counters = {
h1 = {val = 1},
h2 = {father = "h1", val = 1},
h3 = {father = "h2", val = 1},
listing = {father = "h1", val = 1},
}
local function inccounter (count)
counters[count].val = counters[count].val + 1
for c, v in pairs(counters) do
if v.father == count then v.val = 1 end
end
end
local function getcounter (count)
local c = counters[count]
if c.father then
return getcounter(c.father) .. "." .. c.val
else
return c.val .. ""
end
end
---------------------------------------------------------------
local function fixed (x)
return function () return x end
end
local function id (x) return x end
local function prepos (x, y)
assert(x and y)
return function (s) return string.format("%s%s%s", x, s, y) end
end
local rw = Tag.b
local function LuaName (name)
return Tag.code(name)
end
local function getparam (s)
local i, e = string.find(s, "^[^%s@|]+|")
if not i then return nil, s
else return string.sub(s, i, e - 1), string.sub(s, e + 1)
end
end
local function gettitle (h)
local title, p = assert(string.match(h, "<title>(.-)</title>()"))
return title, string.sub(h, p)
end
local function getparamtitle (what, h, nonum)
local label, title, c, count
label, h = getparam(h)
title, h = gettitle(h)
if not nonum then
count = getcounter(what)
inccounter(what)
c = string.format("%s &ndash; ", count)
else
c = ""
end
label = label or count
if label then
title = anchor(title, label, count, "&sect;"..count)
end
title = string.format("%s%s", c, title)
return title, h
end
local function section (what, nonum)
return function (h)
local title
title, h = getparamtitle(what, h, nonum)
local fn = what == "h1" and dischargefoots() or ""
h = fixpara(Tag.p(h))
return "</p>\n" .. Tag[what](title) .. h .. fn ..
dischargelist() .. "<p>"
end
end
local function verbatim (s)
s = nopara(s)
s = string.gsub(s, "\n", "\n ")
s = string.gsub(s, "\n%s*$", "\n")
return Tag.pre(s)
end
local function verb (s)
return Tag.code(s)
end
local function lua2link (e)
return string.find(e, "luaL?_") and e or "pdf-"..e
end
local verbfixed = verb
local Tex = {
ANSI = function (func)
return "ISO&nbsp;C function " .. Tag.code(func)
end,
At = fixed"@",
B = Tag.b,
bigskip = fixed"",
bignum = id,
C = fixed"",
Ci = prepos("<!-- ", " -->"),
CId = function (func)
return "C&nbsp;function " .. Tag.code(func)
end,
chapter = section"h1",
Char = compose(verbfixed, prepos("'", "'")),
Cdots = fixed"&middot;&middot;&middot;",
Close = fixed"}",
col = Tag.td,
defid = function (name)
local l = lua2link(name)
local c = Tag.code(name)
return anchor(c, l, l, c)
end,
def = Tag.em,
description = compose(nopara, Tag.ul),
Em = fixed("\4" .. "&mdash;" .. "\4"),
emph = Tag.em,
emphx = Tag.em, -- emphasis plus index (if there was an index)
En = fixed("&ndash;"),
format = fixed"",
["false"] = fixed(Tag.b"false"),
id = Tag.code,
idx = Tag.code,
index = fixed"",
Lidx = fixed"", -- Tag.code,
ldots = fixed"...",
x = id,
itemize = compose(nopara, Tag.ul),
leq = fixed"&le;",
Lid = function (s)
return makeref(lua2link(s))
end,
M = Tag.em,
N = function (s) return (string.gsub(s, " ", "&nbsp;")) end,
NE = id, -- tag"foreignphrase",
num = id,
["nil"] = fixed(Tag.b"nil"),
fail = fixed(Tag.b"fail"),
Open = fixed"{",
part = section("h1", true),
Pat = compose(verbfixed, prepos("'", "'")),
preface = section("h1", true),
psect = section("h2", true),
Q = prepos('"', '"'),
refchp = makeref,
refcode = makeref,
refsec = makeref,
pi = fixed"&pi;",
rep = Tag.em, -- compose(prepos("&lt;", "&gt;"), Tag.em),
Rw = rw,
rw = rw,
sb = Tag.sub,
sp = Tag.sup,
St = compose(verbfixed, prepos('"', '"')),
sect1 = section"h1",
sect2 = section"h2",
sect3 = section"h3",
sect4 = section("h4", true),
simplesect = id,
Tab2 = function (s) return Tag.table(s, {border=1}) end,
row = Tag.tr,
title = Tag.title,
todo = Tag.todo,
["true"] = fixed(Tag.b"true"),
T = verb,
item = function (s)
local t, p = string.match(s, "^([^\n|]+)|()")
if t then
s = string.sub(s, p)
s = Tag.b(t..": ") .. s
end
return Tag.li(fixpara(s))
end,
verbatim = verbatim,
manual = id,
-- for the manual
link =function (s)
local l, t = getparam(s)
assert(l)
return string.format("%s (%s)", t, makeref(l))
end,
see = function (s) return string.format(seefmt, makeref(s)) end,
See = makeref,
seeC = function (s)
return string.format(seefmt, makeref(s))
end,
seeF = function (s)
return string.format(seefmt, makeref(lua2link(s)))
end,
APIEntry = function (e)
local h, name
h, e = string.match(e, "^%s*(.-)%s*|(.*)$")
name = string.match(h, "(luaL?_[%w_]+)%)? +%(") or
string.match(h, "luaL?_[%w_]+")
local a = anchor(Tag.code(name), name, name, Tag.code(name))
local apiicmd, ne = string.match(e, "^(.-</span>)(.*)")
--io.stderr:write(e)
if not apiicmd then
return antipara(Tag.hr() .. Tag.h3(a)) .. Tag.pre(h) .. e
else
return antipara(Tag.hr() .. Tag.h3(a)) .. apiicmd .. Tag.pre(h) .. ne
end
end,
LibEntry = function (e)
local h, name
h, e = string.match(e, "^(.-)|(.*)$")
name = string.gsub(h, " (.+", "")
local l = lua2link(name)
local a = anchor(Tag.code(h), l, l, Tag.code(name))
return Tag.hr() .. Tag.h3(a) .. e
end,
Produc = compose(nopara, Tag.pre),
producname = prepos("\t", " ::= "),
Or = fixed" | ",
VerBar = fixed"&#124;", -- vertical bar
OrNL = fixed" | \4",
bnfNter = prepos("", ""),
bnfopt = prepos("[", "]"),
bnfrep = prepos("{", "}"),
bnfter = compose(Tag.b, prepos("&lsquo;", "&rsquo;")),
producbody = function (s)
s = string.gsub(s, "%s+", " ")
s = string.gsub(s, "\4", "\n\t\t")
return s
end,
apii = function (s)
local pop,push,err = string.match(s, "^(.-),(.-),(.*)$")
if pop ~= "?" and string.find(pop, "%W") then
pop = "(" .. pop .. ")"
end
if push ~= "?" and string.find(push, "%W") then
push = "(" .. push .. ")"
end
err = (err == "-") and "&ndash;" or Tag.em(err)
return Tag.span(
string.format("[-%s, +%s, %s]", pop, push, err),
{class="apii"}
)
end,
}
local others = prepos("?? "," ??")
local function trata (t)
t = string.gsub(t, "@(%w+)(%b{})", function (w, f)
f = trata(string.sub(f, 2, -2))
if type(Tex[w]) ~= "function" then
io.stderr:write(w .. "\n")
return others(f)
else
return Tex[w](f, w)
end
end)
return t
end
---------------------------------------------------------------------
---------------------------------------------------------------------
-- read whole book
t = io.read"*a"
t = string.gsub(t, "[<>&\128-\255]",
{["<"] = "&lt;",
[">"] = "&gt;",
["&"] = "&amp;",
["\170"] = "&ordf;",
["\186"] = "&ordm;",
["\192"] = "&Agrave;",
["\193"] = "&Aacute;",
["\194"] = "&Acirc;",
["\195"] = "&Atilde;",
["\199"] = "&Ccedil;",
["\201"] = "&Eacute;",
["\202"] = "&Ecirc;",
["\205"] = "&Iacute;",
["\211"] = "&Oacute;",
["\212"] = "&Ocirc;",
["\218"] = "&Uacute;",
["\224"] = "&agrave;",
["\225"] = "&aacute;",
["\226"] = "&acirc;",
["\227"] = "&atilde;",
["\231"] = "&ccedil;",
["\233"] = "&eacute;",
["\234"] = "&ecirc;",
["\237"] = "&iacute;",
["\243"] = "&oacute;",
["\244"] = "&ocirc;",
["\245"] = "&otilde;",
["\250"] = "&uacute;",
["\252"] = "&uuml;"
})
t = string.gsub(t, "\n\n+", "\1")
-- complete macros with no arguments
t = string.gsub(t, "(@%w+)([^{%w])", "%1{}%2")
t = trata(t)
-- correct references
t = string.gsub(t, "\3(.-)\3", ref)
-- remove extra space (??)
t = string.gsub(t, "%s*\4%s*", "")
t = nopara(t)
-- HTML 3.2 does not need </p> (but complains when it is in wrong places :)
t = string.gsub(t, "</p>", "")
io.write(header, t, footer)
+9319
View File
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
/*
* one.c -- Lua core, libraries, and interpreter in a single file
*/
/* default is to build the full interpreter */
#ifndef MAKE_LIB
#ifndef MAKE_LUAC
#ifndef MAKE_LUA
#define MAKE_LUA
#endif
#endif
#endif
/* choose suitable platform-specific features */
/* some of these may need extra libraries such as -ldl -lreadline -lncurses */
#if 0
#define LUA_USE_LINUX
#define LUA_USE_MACOSX
#define LUA_USE_POSIX
#define LUA_ANSI
#endif
/* no need to change anything below this line ----------------------------- */
#include "lprefix.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* setup for luaconf.h */
#define LUA_CORE
#define LUA_LIB
#define ltable_c
#define lvm_c
#include "luaconf.h"
/* do not export internal symbols */
#undef LUAI_FUNC
#undef LUAI_DDEC
#undef LUAI_DDEF
#define LUAI_FUNC static
#define LUAI_DDEC(def) /* empty */
#define LUAI_DDEF static
/* core -- used by all */
#include "lzio.c"
#include "lctype.c"
#include "lopcodes.c"
#include "lmem.c"
#include "lundump.c"
#include "ldump.c"
#include "lstate.c"
#include "lgc.c"
#include "llex.c"
#include "lcode.c"
#include "lparser.c"
#include "ldebug.c"
#include "lfunc.c"
#include "lobject.c"
#include "ltm.c"
#include "lstring.c"
#include "ltable.c"
#include "ldo.c"
#include "lvm.c"
#include "lapi.c"
/* auxiliary library -- used by all */
#include "lauxlib.c"
/* standard library -- not used by luac */
#ifndef MAKE_LUAC
#include "lbaselib.c"
#include "lcorolib.c"
#include "ldblib.c"
#include "liolib.c"
#include "lmathlib.c"
#include "loadlib.c"
#include "loslib.c"
#include "lstrlib.c"
#include "ltablib.c"
#include "lutf8lib.c"
#include "linit.c"
#endif
/* lua */
#ifdef MAKE_LUA
#include "lua.c"
#endif
/* luac */
#ifdef MAKE_LUAC
#include "luac.c"
#endif
+321
View File
@@ -0,0 +1,321 @@
#!../lua
-- $Id: testes/all.lua $
-- See Copyright Notice at the end of this file
local version = "Lua 5.4"
if _VERSION ~= version then
io.stderr:write("This test suite is for ", version,
", not for ", _VERSION, "\nExiting tests")
return
end
_G.ARG = arg -- save arg for other tests
-- next variables control the execution of some tests
-- true means no test (so an undefined variable does not skip a test)
-- defaults are for Linux; test everything.
-- Make true to avoid long or memory consuming tests
_soft = rawget(_G, "_soft") or false
-- Make true to avoid non-portable tests
_port = rawget(_G, "_port") or false
-- Make true to avoid messages about tests not performed
_nomsg = rawget(_G, "_nomsg") or false
local usertests = rawget(_G, "_U")
if usertests then
-- tests for sissies ;) Avoid problems
_soft = true
_port = true
_nomsg = true
end
-- tests should require debug when needed
debug = nil
if usertests then
T = nil -- no "internal" tests for user tests
else
T = rawget(_G, "T") -- avoid problems with 'strict' module
end
--[=[
example of a long [comment],
[[spanning several [lines]]]
]=]
print("\n\tStarting Tests")
do
-- set random seed
local random_x, random_y = math.randomseed()
print(string.format("random seeds: %d, %d", random_x, random_y))
end
print("current path:\n****" .. package.path .. "****\n")
local initclock = os.clock()
local lastclock = initclock
local walltime = os.time()
local collectgarbage = collectgarbage
do -- (
-- track messages for tests not performed
local msgs = {}
function Message (m)
if not _nomsg then
print(m)
msgs[#msgs+1] = string.sub(m, 3, -3)
end
end
assert(os.setlocale"C")
local T,print,format,write,assert,type,unpack,floor =
T,print,string.format,io.write,assert,type,table.unpack,math.floor
-- use K for 1000 and M for 1000000 (not 2^10 -- 2^20)
local function F (m)
local function round (m)
m = m + 0.04999
return format("%.1f", m) -- keep one decimal digit
end
if m < 1000 then return m
else
m = m / 1000
if m < 1000 then return round(m).."K"
else
return round(m/1000).."M"
end
end
end
local Cstacklevel
local showmem
if not T then
local max = 0
showmem = function ()
local m = collectgarbage("count") * 1024
max = (m > max) and m or max
print(format(" ---- total memory: %s, max memory: %s ----\n",
F(m), F(max)))
end
Cstacklevel = function () return 0 end -- no info about stack level
else
showmem = function ()
T.checkmemory()
local total, numblocks, maxmem = T.totalmem()
local count = collectgarbage("count")
print(format(
"\n ---- total memory: %s (%.0fK), max use: %s, blocks: %d\n",
F(total), count, F(maxmem), numblocks))
print(format("\t(strings: %d, tables: %d, functions: %d, "..
"\n\tudata: %d, threads: %d)",
T.totalmem"string", T.totalmem"table", T.totalmem"function",
T.totalmem"userdata", T.totalmem"thread"))
end
Cstacklevel = function ()
local _, _, ncalls, nci = T.stacklevel()
return ncalls + nci -- number of free slots in the C stack
end
end
local Cstack = Cstacklevel()
--
-- redefine dofile to run files through dump/undump
--
local function report (n) print("\n***** FILE '"..n.."'*****") end
local olddofile = dofile
local dofile = function (n, strip)
showmem()
local c = os.clock()
print(string.format("time: %g (+%g)", c - initclock, c - lastclock))
lastclock = c
report(n)
local f = assert(loadfile(n))
local b = string.dump(f, strip)
f = assert(load(b))
return f()
end
dofile('main.lua')
do
local next, setmetatable, stderr = next, setmetatable, io.stderr
-- track collections
local mt = {}
-- each time a table is collected, remark it for finalization
-- on next cycle
mt.__gc = function (o)
stderr:write'.' -- mark progress
local n = setmetatable(o, mt) -- remark it
end
local n = setmetatable({}, mt) -- create object
end
report"gc.lua"
local f = assert(loadfile('gc.lua'))
f()
dofile('db.lua')
assert(dofile('calls.lua') == deep and deep)
olddofile('strings.lua')
olddofile('literals.lua')
dofile('tpack.lua')
assert(dofile('attrib.lua') == 27)
dofile('gengc.lua')
assert(dofile('locals.lua') == 5)
dofile('constructs.lua')
dofile('code.lua', true)
if not _G._soft then
report('big.lua')
local f = coroutine.wrap(assert(loadfile('big.lua')))
assert(f() == 'b')
assert(f() == 'a')
end
dofile('cstack.lua')
dofile('nextvar.lua')
dofile('pm.lua')
dofile('utf8.lua')
dofile('api.lua')
assert(dofile('events.lua') == 12)
dofile('vararg.lua')
dofile('closure.lua')
dofile('coroutine.lua')
dofile('goto.lua', true)
dofile('errors.lua')
dofile('math.lua')
dofile('sort.lua', true)
dofile('bitwise.lua')
assert(dofile('verybig.lua', true) == 10); collectgarbage()
dofile('files.lua')
if #msgs > 0 then
local m = table.concat(msgs, "\n ")
warn("#tests not performed:\n ", m, "\n")
end
print("(there should be two warnings now)")
warn("@on")
warn("#This is ", "an expected", " warning")
warn("@off")
warn("******** THIS WARNING SHOULD NOT APPEAR **********")
warn("******** THIS WARNING ALSO SHOULD NOT APPEAR **********")
warn("@on")
warn("#This is", " another one")
-- no test module should define 'debug'
assert(debug == nil)
local debug = require "debug"
print(string.format("%d-bit integers, %d-bit floats",
string.packsize("j") * 8, string.packsize("n") * 8))
debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
-- to survive outside block
_G.showmem = showmem
assert(Cstack == Cstacklevel(),
"should be at the same C-stack level it was when started the tests")
end --)
local _G, showmem, print, format, clock, time, difftime,
assert, open, warn =
_G, showmem, print, string.format, os.clock, os.time, os.difftime,
assert, io.open, warn
-- file with time of last performed test
local fname = T and "time-debug.txt" or "time.txt"
local lasttime
if not usertests then
-- open file with time of last performed test
local f = io.open(fname)
if f then
lasttime = assert(tonumber(f:read'a'))
f:close();
else -- no such file; assume it is recording time for first time
lasttime = nil
end
end
-- erase (almost) all globals
print('cleaning all!!!!')
for n in pairs(_G) do
if not ({___Glob = 1, tostring = 1})[n] then
_G[n] = undef
end
end
collectgarbage()
collectgarbage()
collectgarbage()
collectgarbage()
collectgarbage()
collectgarbage();showmem()
local clocktime = clock() - initclock
walltime = difftime(time(), walltime)
print(format("\n\ntotal time: %.2fs (wall time: %gs)\n", clocktime, walltime))
if not usertests then
lasttime = lasttime or clocktime -- if no last time, ignore difference
-- check whether current test time differs more than 5% from last time
local diff = (clocktime - lasttime) / lasttime
local tolerance = 0.05 -- 5%
if (diff >= tolerance or diff <= -tolerance) then
warn(format("#time difference from previous test: %+.1f%%",
diff * 100))
end
assert(open(fname, "w")):write(clocktime):close()
end
print("final OK !!!")
--[[
*****************************************************************************
* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "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.
*****************************************************************************
]]
+1462
View File
File diff suppressed because it is too large Load Diff
+515
View File
@@ -0,0 +1,515 @@
-- $Id: testes/attrib.lua $
-- See Copyright Notice in file all.lua
print "testing require"
assert(require"string" == string)
assert(require"math" == math)
assert(require"table" == table)
assert(require"io" == io)
assert(require"os" == os)
assert(require"coroutine" == coroutine)
assert(type(package.path) == "string")
assert(type(package.cpath) == "string")
assert(type(package.loaded) == "table")
assert(type(package.preload) == "table")
assert(type(package.config) == "string")
print("package config: "..string.gsub(package.config, "\n", "|"))
do
-- create a path with 'max' templates,
-- each with 1-10 repetitions of '?'
local max = _soft and 100 or 2000
local t = {}
for i = 1,max do t[i] = string.rep("?", i%10 + 1) end
t[#t + 1] = ";" -- empty template
local path = table.concat(t, ";")
-- use that path in a search
local s, err = package.searchpath("xuxu", path)
-- search fails; check that message has an occurrence of
-- '??????????' with ? replaced by xuxu and at least 'max' lines
assert(not s and
string.find(err, string.rep("xuxu", 10)) and
#string.gsub(err, "[^\n]", "") >= max)
-- path with one very long template
local path = string.rep("?", max)
local s, err = package.searchpath("xuxu", path)
assert(not s and string.find(err, string.rep('xuxu', max)))
end
do
local oldpath = package.path
package.path = {}
local s, err = pcall(require, "no-such-file")
assert(not s and string.find(err, "package.path"))
package.path = oldpath
end
do print"testing 'require' message"
local oldpath = package.path
local oldcpath = package.cpath
package.path = "?.lua;?/?"
package.cpath = "?.so;?/init"
local st, msg = pcall(require, 'XXX')
local expected = [[module 'XXX' not found:
no field package.preload['XXX']
no file 'XXX.lua'
no file 'XXX/XXX'
no file 'XXX.so'
no file 'XXX/init']]
assert(msg == expected)
package.path = oldpath
package.cpath = oldcpath
end
print('+')
-- The next tests for 'require' assume some specific directories and
-- libraries.
if not _port then --[
local dirsep = string.match(package.config, "^([^\n]+)\n")
-- auxiliary directory with C modules and temporary files
local DIR = "libs" .. dirsep
-- prepend DIR to a name and correct directory separators
local function D (x)
x = string.gsub(x, "/", dirsep)
return DIR .. x
end
-- prepend DIR and pospend proper C lib. extension to a name
local function DC (x)
local ext = (dirsep == '\\') and ".dll" or ".so"
return D(x .. ext)
end
local function createfiles (files, preextras, posextras)
for n,c in pairs(files) do
io.output(D(n))
io.write(string.format(preextras, n))
io.write(c)
io.write(string.format(posextras, n))
io.close(io.output())
end
end
function removefiles (files)
for n in pairs(files) do
os.remove(D(n))
end
end
local files = {
["names.lua"] = "do return {...} end\n",
["err.lua"] = "B = 15; a = a + 1;",
["synerr.lua"] = "B =",
["A.lua"] = "",
["B.lua"] = "assert(...=='B');require 'A'",
["A.lc"] = "",
["A"] = "",
["L"] = "",
["XXxX"] = "",
["C.lua"] = "package.loaded[...] = 25; require'C'",
}
AA = nil
local extras = [[
NAME = '%s'
REQUIRED = ...
return AA]]
createfiles(files, "", extras)
-- testing explicit "dir" separator in 'searchpath'
assert(package.searchpath("C.lua", D"?", "", "") == D"C.lua")
assert(package.searchpath("C.lua", D"?", ".", ".") == D"C.lua")
assert(package.searchpath("--x-", D"?", "-", "X") == D"XXxX")
assert(package.searchpath("---xX", D"?", "---", "XX") == D"XXxX")
assert(package.searchpath(D"C.lua", "?", dirsep) == D"C.lua")
assert(package.searchpath(".\\C.lua", D"?", "\\") == D"./C.lua")
local oldpath = package.path
package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
local try = function (p, n, r, ext)
NAME = nil
local rr, x = require(p)
assert(NAME == n)
assert(REQUIRED == p)
assert(rr == r)
assert(ext == x)
end
a = require"names"
assert(a[1] == "names" and a[2] == D"names.lua")
_G.a = nil
local st, msg = pcall(require, "err")
assert(not st and string.find(msg, "arithmetic") and B == 15)
st, msg = pcall(require, "synerr")
assert(not st and string.find(msg, "error loading module"))
assert(package.searchpath("C", package.path) == D"C.lua")
assert(require"C" == 25)
assert(require"C" == 25)
AA = nil
try('B', 'B.lua', true, "libs/B.lua")
assert(package.loaded.B)
assert(require"B" == true)
assert(package.loaded.A)
assert(require"C" == 25)
package.loaded.A = nil
try('B', nil, true, nil) -- should not reload package
try('A', 'A.lua', true, "libs/A.lua")
package.loaded.A = nil
os.remove(D'A.lua')
AA = {}
try('A', 'A.lc', AA, "libs/A.lc") -- now must find second option
assert(package.searchpath("A", package.path) == D"A.lc")
assert(require("A") == AA)
AA = false
try('K', 'L', false, "libs/L") -- default option
try('K', 'L', false, "libs/L") -- default option (should reload it)
assert(rawget(_G, "_REQUIREDNAME") == nil)
AA = "x"
try("X", "XXxX", AA, "libs/XXxX")
removefiles(files)
-- testing require of sub-packages
local _G = _G
package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
files = {
["P1/init.lua"] = "AA = 10",
["P1/xuxu.lua"] = "AA = 20",
}
createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n")
AA = 0
local m, ext = assert(require"P1")
assert(ext == "libs/P1/init.lua")
assert(AA == 0 and m.AA == 10)
assert(require"P1" == m)
assert(require"P1" == m)
assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua")
m.xuxu, ext = assert(require"P1.xuxu")
assert(AA == 0 and m.xuxu.AA == 20)
assert(ext == "libs/P1/xuxu.lua")
assert(require"P1.xuxu" == m.xuxu)
assert(require"P1.xuxu" == m.xuxu)
assert(require"P1" == m and m.AA == 10)
removefiles(files)
package.path = ""
assert(not pcall(require, "file_does_not_exist"))
package.path = "??\0?"
assert(not pcall(require, "file_does_not_exist1"))
package.path = oldpath
-- check 'require' error message
local fname = "file_does_not_exist2"
local m, err = pcall(require, fname)
for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
t = string.gsub(t, "?", fname)
assert(string.find(err, t, 1, true))
end
do -- testing 'package.searchers' not being a table
local searchers = package.searchers
package.searchers = 3
local st, msg = pcall(require, 'a')
assert(not st and string.find(msg, "must be a table"))
package.searchers = searchers
end
local function import(...)
local f = {...}
return function (m)
for i=1, #f do m[f[i]] = _G[f[i]] end
end
end
-- cannot change environment of a C function
assert(not pcall(module, 'XUXU'))
-- testing require of C libraries
local p = "" -- On Mac OS X, redefine this to "_"
-- check whether loadlib works in this system
local st, err, when = package.loadlib(DC"lib1", "*")
if not st then
local f, err, when = package.loadlib("donotexist", p.."xuxu")
assert(not f and type(err) == "string" and when == "absent")
;(Message or print)('\n >>> cannot load dynamic library <<<\n')
print(err, when)
else
-- tests for loadlib
local f = assert(package.loadlib(DC"lib1", p.."onefunction"))
local a, b = f(15, 25)
assert(a == 25 and b == 15)
f = assert(package.loadlib(DC"lib1", p.."anotherfunc"))
assert(f(10, 20) == "10%20\n")
-- check error messages
local f, err, when = package.loadlib(DC"lib1", p.."xuxu")
assert(not f and type(err) == "string" and when == "init")
f, err, when = package.loadlib("donotexist", p.."xuxu")
assert(not f and type(err) == "string" and when == "open")
-- symbols from 'lib1' must be visible to other libraries
f = assert(package.loadlib(DC"lib11", p.."luaopen_lib11"))
assert(f() == "exported")
-- test C modules with prefixes in names
package.cpath = DC"?"
local lib2, ext = require"lib2-v2"
assert(string.find(ext, "libs/lib2-v2", 1, true))
-- check correct access to global environment and correct
-- parameters
assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2")
assert(lib2.id("x") == true) -- a different "id" implementation
-- test C submodules
local fs, ext = require"lib1.sub"
assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1")
assert(string.find(ext, "libs/lib1", 1, true))
assert(fs.id(45) == 45)
end
_ENV = _G
-- testing preload
do
local p = package
package = {}
p.preload.pl = function (...)
local _ENV = {...}
function xuxu (x) return x+20 end
return _ENV
end
local pl, ext = require"pl"
assert(require"pl" == pl)
assert(pl.xuxu(10) == 30)
assert(pl[1] == "pl" and pl[2] == ":preload:" and ext == ":preload:")
package = p
assert(type(package.path) == "string")
end
print('+')
end --]
print("testing assignments, logical operators, and constructors")
local res, res2 = 27
a, b = 1, 2+3
assert(a==1 and b==5)
a={}
function f() return 10, 11, 12 end
a.x, b, a[1] = 1, 2, f()
assert(a.x==1 and b==2 and a[1]==10)
a[f()], b, a[f()+3] = f(), a, 'x'
assert(a[10] == 10 and b == a and a[13] == 'x')
do
local f = function (n) local x = {}; for i=1,n do x[i]=i end;
return table.unpack(x) end;
local a,b,c
a,b = 0, f(1)
assert(a == 0 and b == 1)
A,b = 0, f(1)
assert(A == 0 and b == 1)
a,b,c = 0,5,f(4)
assert(a==0 and b==5 and c==1)
a,b,c = 0,5,f(0)
assert(a==0 and b==5 and c==nil)
end
a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
assert(not a and b and c and d==6)
d = 20
a, b, c, d = f()
assert(a==10 and b==11 and c==12 and d==nil)
a,b = f(), 1, 2, 3, f()
assert(a==10 and b==1)
assert(a<b == false and a>b == true)
assert((10 and 2) == 2)
assert((10 or 2) == 10)
assert((10 or assert(nil)) == 10)
assert(not (nil and assert(nil)))
assert((nil or "alo") == "alo")
assert((nil and 10) == nil)
assert((false and 10) == false)
assert((true or 10) == true)
assert((false or 10) == 10)
assert(false ~= nil)
assert(nil ~= false)
assert(not nil == true)
assert(not not nil == false)
assert(not not 1 == true)
assert(not not a == true)
assert(not not (6 or nil) == true)
assert(not not (nil and 56) == false)
assert(not not (nil and true) == false)
assert(not 10 == false)
assert(not {} == false)
assert(not 0.5 == false)
assert(not "x" == false)
assert({} ~= {})
print('+')
a = {}
a[true] = 20
a[false] = 10
assert(a[1<2] == 20 and a[1>2] == 10)
function f(a) return a end
local a = {}
for i=3000,-3000,-1 do a[i + 0.0] = i; end
a[10e30] = "alo"; a[true] = 10; a[false] = 20
assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
for i=3000,-3000,-1 do assert(a[i] == i); end
a[print] = assert
a[f] = print
a[a] = a
assert(a[a][a][a][a][print] == assert)
a[print](a[a[f]] == a[print])
assert(not pcall(function () local a = {}; a[nil] = 10 end))
assert(not pcall(function () local a = {[nil] = 10} end))
assert(a[nil] == undef)
a = nil
a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
a, a.x, a.y = a, a[-3]
assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
a[1].alo(a[2]==10 and b==10 and c==print)
a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 = 10
local function foo ()
return a.aVeryLongName012345678901234567890123456789012345678901234567890123456789
end
assert(foo() == 10 and
a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 ==
10)
-- test of large float/integer indices
-- compute maximum integer where all bits fit in a float
local maxint = math.maxinteger
-- trim (if needed) to fit in a float
while maxint ~= (maxint + 0.0) or (maxint - 1) ~= (maxint - 1.0) do
maxint = maxint // 2
end
maxintF = maxint + 0.0 -- float version
assert(maxintF == maxint and math.type(maxintF) == "float" and
maxintF >= 2.0^14)
-- floats and integers must index the same places
a[maxintF] = 10; a[maxintF - 1.0] = 11;
a[-maxintF] = 12; a[-maxintF + 1.0] = 13;
assert(a[maxint] == 10 and a[maxint - 1] == 11 and
a[-maxint] == 12 and a[-maxint + 1] == 13)
a[maxint] = 20
a[-maxint] = 22
assert(a[maxintF] == 20 and a[maxintF - 1.0] == 11 and
a[-maxintF] == 22 and a[-maxintF + 1.0] == 13)
a = nil
-- test conflicts in multiple assignment
do
local a,i,j,b
a = {'a', 'b'}; i=1; j=2; b=a
i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
b[3] == 1)
a = {}
local function foo () -- assigining to upvalues
b, a.x, a = a, 10, 20
end
foo()
assert(a == 20 and b.x == 10)
end
-- repeat test with upvalues
do
local a,i,j,b
a = {'a', 'b'}; i=1; j=2; b=a
local function foo ()
i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
end
foo()
assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
b[3] == 1)
local t = {}
(function (a) t[a], a = 10, 20 end)(1);
assert(t[1] == 10)
end
-- bug in 5.2 beta
local function foo ()
local a
return function ()
local b
a, b = 3, 14 -- local and upvalue have same index
return a, b
end
end
local a, b = foo()()
assert(a == 3 and b == 14)
print('OK')
return res
+82
View File
@@ -0,0 +1,82 @@
-- $Id: testes/big.lua $
-- See Copyright Notice in file all.lua
if _soft then
return 'a'
end
print "testing large tables"
local debug = require"debug"
local lim = 2^18 + 1000
local prog = { "local y = {0" }
for i = 1, lim do prog[#prog + 1] = i end
prog[#prog + 1] = "}\n"
prog[#prog + 1] = "X = y\n"
prog[#prog + 1] = ("assert(X[%d] == %d)"):format(lim - 1, lim - 2)
prog[#prog + 1] = "return 0"
prog = table.concat(prog, ";")
local env = {string = string, assert = assert}
local f = assert(load(prog, nil, nil, env))
f()
assert(env.X[lim] == lim - 1 and env.X[lim + 1] == lim)
for k in pairs(env) do env[k] = undef end
-- yields during accesses larger than K (in RK)
setmetatable(env, {
__index = function (t, n) coroutine.yield('g'); return _G[n] end,
__newindex = function (t, n, v) coroutine.yield('s'); _G[n] = v end,
})
X = nil
co = coroutine.wrap(f)
assert(co() == 's')
assert(co() == 'g')
assert(co() == 'g')
assert(co() == 0)
assert(X[lim] == lim - 1 and X[lim + 1] == lim)
-- errors in accesses larger than K (in RK)
getmetatable(env).__index = function () end
getmetatable(env).__newindex = function () end
local e, m = pcall(f)
assert(not e and m:find("global 'X'"))
-- errors in metamethods
getmetatable(env).__newindex = function () error("hi") end
local e, m = xpcall(f, debug.traceback)
assert(not e and m:find("'newindex'"))
f, X = nil
coroutine.yield'b'
if 2^32 == 0 then -- (small integers) {
print "testing string length overflow"
local repstrings = 192 -- number of strings to be concatenated
local ssize = math.ceil(2.0^32 / repstrings) + 1 -- size of each string
assert(repstrings * ssize > 2.0^32) -- it should be larger than maximum size
local longs = string.rep("\0", ssize) -- create one long string
-- create function to concatenate 'repstrings' copies of its argument
local rep = assert(load(
"local a = ...; return " .. string.rep("a", repstrings, "..")))
local a, b = pcall(rep, longs) -- call that function
-- it should fail without creating string (result would be too large)
assert(not a and string.find(b, "overflow"))
end -- }
print'OK'
return 'a'
+346
View File
@@ -0,0 +1,346 @@
-- $Id: testes/bitwise.lua $
-- See Copyright Notice in file all.lua
print("testing bitwise operations")
require "bwcoercion"
local numbits = string.packsize('j') * 8
assert(~0 == -1)
assert((1 << (numbits - 1)) == math.mininteger)
-- basic tests for bitwise operators;
-- use variables to avoid constant folding
local a, b, c, d
a = 0xFFFFFFFFFFFFFFFF
assert(a == -1 and a & -1 == a and a & 35 == 35)
a = 0xF0F0F0F0F0F0F0F0
assert(a | -1 == -1)
assert(a ~ a == 0 and a ~ 0 == a and a ~ ~a == -1)
assert(a >> 4 == ~a)
a = 0xF0; b = 0xCC; c = 0xAA; d = 0xFD
assert(a | b ~ c & d == 0xF4)
a = 0xF0.0; b = 0xCC.0; c = "0xAA.0"; d = "0xFD.0"
assert(a | b ~ c & d == 0xF4)
a = 0xF0000000; b = 0xCC000000;
c = 0xAA000000; d = 0xFD000000
assert(a | b ~ c & d == 0xF4000000)
assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
a = a << 32
b = b << 32
c = c << 32
d = d << 32
assert(a | b ~ c & d == 0xF4000000 << 32)
assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
assert(-1 >> 1 == (1 << (numbits - 1)) - 1 and 1 << 31 == 0x80000000)
assert(-1 >> (numbits - 1) == 1)
assert(-1 >> numbits == 0 and
-1 >> -numbits == 0 and
-1 << numbits == 0 and
-1 << -numbits == 0)
assert((2^30 - 1) << 2^30 == 0)
assert((2^30 - 1) >> 2^30 == 0)
assert(1 >> -3 == 1 << 3 and 1000 >> 5 == 1000 << -5)
-- coercion from strings to integers
assert("0xffffffffffffffff" | 0 == -1)
assert("0xfffffffffffffffe" & "-1" == -2)
assert(" \t-0xfffffffffffffffe\n\t" & "-1" == 2)
assert(" \n -45 \t " >> " -2 " == -45 * 4)
assert("1234.0" << "5.0" == 1234 * 32)
assert("0xffff.0" ~ "0xAAAA" == 0x5555)
assert(~"0x0.000p4" == -1)
assert(("7" .. 3) << 1 == 146)
assert(0xffffffff >> (1 .. "9") == 0x1fff)
assert(10 | (1 .. "9") == 27)
do
local st, msg = pcall(function () return 4 & "a" end)
assert(string.find(msg, "'band'"))
local st, msg = pcall(function () return ~"a" end)
assert(string.find(msg, "'bnot'"))
end
-- out of range number
assert(not pcall(function () return "0xffffffffffffffff.0" | 0 end))
-- embedded zeros
assert(not pcall(function () return "0xffffffffffffffff\0" | 0 end))
print'+'
package.preload.bit32 = function () --{
-- no built-in 'bit32' library: implement it using bitwise operators
local bit = {}
function bit.bnot (a)
return ~a & 0xFFFFFFFF
end
--
-- in all vararg functions, avoid creating 'arg' table when there are
-- only 2 (or less) parameters, as 2 parameters is the common case
--
function bit.band (x, y, z, ...)
if not z then
return ((x or -1) & (y or -1)) & 0xFFFFFFFF
else
local arg = {...}
local res = x & y & z
for i = 1, #arg do res = res & arg[i] end
return res & 0xFFFFFFFF
end
end
function bit.bor (x, y, z, ...)
if not z then
return ((x or 0) | (y or 0)) & 0xFFFFFFFF
else
local arg = {...}
local res = x | y | z
for i = 1, #arg do res = res | arg[i] end
return res & 0xFFFFFFFF
end
end
function bit.bxor (x, y, z, ...)
if not z then
return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF
else
local arg = {...}
local res = x ~ y ~ z
for i = 1, #arg do res = res ~ arg[i] end
return res & 0xFFFFFFFF
end
end
function bit.btest (...)
return bit.band(...) ~= 0
end
function bit.lshift (a, b)
return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF
end
function bit.rshift (a, b)
return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF
end
function bit.arshift (a, b)
a = a & 0xFFFFFFFF
if b <= 0 or (a & 0x80000000) == 0 then
return (a >> b) & 0xFFFFFFFF
else
return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF
end
end
function bit.lrotate (a ,b)
b = b & 31
a = a & 0xFFFFFFFF
a = (a << b) | (a >> (32 - b))
return a & 0xFFFFFFFF
end
function bit.rrotate (a, b)
return bit.lrotate(a, -b)
end
local function checkfield (f, w)
w = w or 1
assert(f >= 0, "field cannot be negative")
assert(w > 0, "width must be positive")
assert(f + w <= 32, "trying to access non-existent bits")
return f, ~(-1 << w)
end
function bit.extract (a, f, w)
local f, mask = checkfield(f, w)
return (a >> f) & mask
end
function bit.replace (a, v, f, w)
local f, mask = checkfield(f, w)
v = v & mask
a = (a & ~(mask << f)) | (v << f)
return a & 0xFFFFFFFF
end
return bit
end --}
print("testing bitwise library")
local bit32 = require'bit32'
assert(bit32.band() == bit32.bnot(0))
assert(bit32.btest() == true)
assert(bit32.bor() == 0)
assert(bit32.bxor() == 0)
assert(bit32.band() == bit32.band(0xffffffff))
assert(bit32.band(1,2) == 0)
-- out-of-range numbers
assert(bit32.band(-1) == 0xffffffff)
assert(bit32.band((1 << 33) - 1) == 0xffffffff)
assert(bit32.band(-(1 << 33) - 1) == 0xffffffff)
assert(bit32.band((1 << 33) + 1) == 1)
assert(bit32.band(-(1 << 33) + 1) == 1)
assert(bit32.band(-(1 << 40)) == 0)
assert(bit32.band(1 << 40) == 0)
assert(bit32.band(-(1 << 40) - 2) == 0xfffffffe)
assert(bit32.band((1 << 40) - 4) == 0xfffffffc)
assert(bit32.lrotate(0, -1) == 0)
assert(bit32.lrotate(0, 7) == 0)
assert(bit32.lrotate(0x12345678, 0) == 0x12345678)
assert(bit32.lrotate(0x12345678, 32) == 0x12345678)
assert(bit32.lrotate(0x12345678, 4) == 0x23456781)
assert(bit32.rrotate(0x12345678, -4) == 0x23456781)
assert(bit32.lrotate(0x12345678, -8) == 0x78123456)
assert(bit32.rrotate(0x12345678, 8) == 0x78123456)
assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa)
assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa)
for i = -50, 50 do
assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32))
end
assert(bit32.lshift(0x12345678, 4) == 0x23456780)
assert(bit32.lshift(0x12345678, 8) == 0x34567800)
assert(bit32.lshift(0x12345678, -4) == 0x01234567)
assert(bit32.lshift(0x12345678, -8) == 0x00123456)
assert(bit32.lshift(0x12345678, 32) == 0)
assert(bit32.lshift(0x12345678, -32) == 0)
assert(bit32.rshift(0x12345678, 4) == 0x01234567)
assert(bit32.rshift(0x12345678, 8) == 0x00123456)
assert(bit32.rshift(0x12345678, 32) == 0)
assert(bit32.rshift(0x12345678, -32) == 0)
assert(bit32.arshift(0x12345678, 0) == 0x12345678)
assert(bit32.arshift(0x12345678, 1) == 0x12345678 // 2)
assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2)
assert(bit32.arshift(-1, 1) == 0xffffffff)
assert(bit32.arshift(-1, 24) == 0xffffffff)
assert(bit32.arshift(-1, 32) == 0xffffffff)
assert(bit32.arshift(-1, -1) == bit32.band(-1 * 2, 0xffffffff))
assert(0x12345678 << 4 == 0x123456780)
assert(0x12345678 << 8 == 0x1234567800)
assert(0x12345678 << -4 == 0x01234567)
assert(0x12345678 << -8 == 0x00123456)
assert(0x12345678 << 32 == 0x1234567800000000)
assert(0x12345678 << -32 == 0)
assert(0x12345678 >> 4 == 0x01234567)
assert(0x12345678 >> 8 == 0x00123456)
assert(0x12345678 >> 32 == 0)
assert(0x12345678 >> -32 == 0x1234567800000000)
print("+")
-- some special cases
local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555,
0xffffffff, 0x7fffffff}
for _, b in pairs(c) do
assert(bit32.band(b) == b)
assert(bit32.band(b, b) == b)
assert(bit32.band(b, b, b, b) == b)
assert(bit32.btest(b, b) == (b ~= 0))
assert(bit32.band(b, b, b) == b)
assert(bit32.band(b, b, b, ~b) == 0)
assert(bit32.btest(b, b, b) == (b ~= 0))
assert(bit32.band(b, bit32.bnot(b)) == 0)
assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0))
assert(bit32.bor(b) == b)
assert(bit32.bor(b, b) == b)
assert(bit32.bor(b, b, b) == b)
assert(bit32.bor(b, b, 0, ~b) == 0xffffffff)
assert(bit32.bxor(b) == b)
assert(bit32.bxor(b, b) == 0)
assert(bit32.bxor(b, b, b) == b)
assert(bit32.bxor(b, b, b, b) == 0)
assert(bit32.bxor(b, 0) == b)
assert(bit32.bnot(b) ~= b)
assert(bit32.bnot(bit32.bnot(b)) == b)
assert(bit32.bnot(b) == (1 << 32) - 1 - b)
assert(bit32.lrotate(b, 32) == b)
assert(bit32.rrotate(b, 32) == b)
assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf)))
assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf)))
end
-- for this test, use at most 24 bits (mantissa of a single float)
c = {0, 1, 2, 3, 10, 0x800000, 0xaaaaaa, 0x555555, 0xffffff, 0x7fffff}
for _, b in pairs(c) do
for i = -40, 40 do
local x = bit32.lshift(b, i)
local y = math.floor(math.fmod(b * 2.0^i, 2.0^32))
assert(math.fmod(x - y, 2.0^32) == 0)
end
end
assert(not pcall(bit32.band, {}))
assert(not pcall(bit32.bnot, "a"))
assert(not pcall(bit32.lshift, 45))
assert(not pcall(bit32.lshift, 45, print))
assert(not pcall(bit32.rshift, 45, print))
print("+")
-- testing extract/replace
assert(bit32.extract(0x12345678, 0, 4) == 8)
assert(bit32.extract(0x12345678, 4, 4) == 7)
assert(bit32.extract(0xa0001111, 28, 4) == 0xa)
assert(bit32.extract(0xa0001111, 31, 1) == 1)
assert(bit32.extract(0x50000111, 31, 1) == 0)
assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679)
assert(not pcall(bit32.extract, 0, -1))
assert(not pcall(bit32.extract, 0, 32))
assert(not pcall(bit32.extract, 0, 0, 33))
assert(not pcall(bit32.extract, 0, 31, 2))
assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678)
assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321)
assert(bit32.replace(0, 1, 2) == 2^2)
assert(bit32.replace(0, -1, 4) == 2^4)
assert(bit32.replace(-1, 0, 31) == (1 << 31) - 1)
assert(bit32.replace(-1, 0, 1, 2) == (1 << 32) - 7)
-- testing conversion of floats
assert(bit32.bor(3.0) == 3)
assert(bit32.bor(-4.0) == 0xfffffffc)
-- large floats and large-enough integers?
if 2.0^50 < 2.0^50 + 1.0 and 2.0^50 < (-1 >> 1) then
assert(bit32.bor(2.0^32 - 5.0) == 0xfffffffb)
assert(bit32.bor(-2.0^32 - 6.0) == 0xfffffffa)
assert(bit32.bor(2.0^48 - 5.0) == 0xfffffffb)
assert(bit32.bor(-2.0^48 - 6.0) == 0xfffffffa)
end
print'OK'
+78
View File
@@ -0,0 +1,78 @@
local tonumber, tointeger = tonumber, math.tointeger
local type, getmetatable, rawget, error = type, getmetatable, rawget, error
local strsub = string.sub
local print = print
_ENV = nil
-- Try to convert a value to an integer, without assuming any coercion.
local function toint (x)
x = tonumber(x) -- handle numerical strings
if not x then
return false -- not coercible to a number
end
return tointeger(x)
end
-- If operation fails, maybe second operand has a metamethod that should
-- have been called if not for this string metamethod, so try to
-- call it.
local function trymt (x, y, mtname)
if type(y) ~= "string" then -- avoid recalling original metamethod
local mt = getmetatable(y)
local mm = mt and rawget(mt, mtname)
if mm then
return mm(x, y)
end
end
-- if any test fails, there is no other metamethod to be called
error("attempt to '" .. strsub(mtname, 3) ..
"' a " .. type(x) .. " with a " .. type(y), 4)
end
local function checkargs (x, y, mtname)
local xi = toint(x)
local yi = toint(y)
if xi and yi then
return xi, yi
else
return trymt(x, y, mtname), nil
end
end
local smt = getmetatable("")
smt.__band = function (x, y)
local x, y = checkargs(x, y, "__band")
return y and x & y or x
end
smt.__bor = function (x, y)
local x, y = checkargs(x, y, "__bor")
return y and x | y or x
end
smt.__bxor = function (x, y)
local x, y = checkargs(x, y, "__bxor")
return y and x ~ y or x
end
smt.__shl = function (x, y)
local x, y = checkargs(x, y, "__shl")
return y and x << y or x
end
smt.__shr = function (x, y)
local x, y = checkargs(x, y, "__shr")
return y and x >> y or x
end
smt.__bnot = function (x)
local x, y = checkargs(x, x, "__bnot")
return y and ~x or x
end
+458
View File
@@ -0,0 +1,458 @@
-- $Id: testes/calls.lua $
-- See Copyright Notice in file all.lua
print("testing functions and calls")
local debug = require "debug"
-- get the opportunity to test 'type' too ;)
assert(type(1<2) == 'boolean')
assert(type(true) == 'boolean' and type(false) == 'boolean')
assert(type(nil) == 'nil'
and type(-3) == 'number'
and type'x' == 'string'
and type{} == 'table'
and type(type) == 'function')
assert(type(assert) == type(print))
function f (x) return a:x (x) end
assert(type(f) == 'function')
assert(not pcall(type))
-- testing local-function recursion
fact = false
do
local res = 1
local function fact (n)
if n==0 then return res
else return n*fact(n-1)
end
end
assert(fact(5) == 120)
end
assert(fact == false)
-- testing declarations
a = {i = 10}
self = 20
function a:x (x) return x+self.i end
function a.y (x) return x+self end
assert(a:x(1)+10 == a.y(1))
a.t = {i=-100}
a["t"].x = function (self, a,b) return self.i+a+b end
assert(a.t:x(2,3) == -95)
do
local a = {x=0}
function a:add (x) self.x, a.y = self.x+x, 20; return self end
assert(a:add(10):add(20):add(30).x == 60 and a.y == 20)
end
local a = {b={c={}}}
function a.b.c.f1 (x) return x+1 end
function a.b.c:f2 (x,y) self[x] = y end
assert(a.b.c.f1(4) == 5)
a.b.c:f2('k', 12); assert(a.b.c.k == 12)
print('+')
t = nil -- 'declare' t
function f(a,b,c) local d = 'a'; t={a,b,c,d} end
f( -- this line change must be valid
1,2)
assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a')
f(1,2, -- this one too
3,4)
assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
function fat(x)
if x <= 1 then return 1
else return x*load("return fat(" .. x-1 .. ")", "")()
end
end
assert(load "load 'assert(fat(6)==720)' () ")()
a = load('return fat(5), 3')
a,b = a()
assert(a == 120 and b == 3)
print('+')
function err_on_n (n)
if n==0 then error(); exit(1);
else err_on_n (n-1); exit(1);
end
end
do
function dummy (n)
if n > 0 then
assert(not pcall(err_on_n, n))
dummy(n-1)
end
end
end
dummy(10)
function deep (n)
if n>0 then deep(n-1) end
end
deep(10)
deep(180)
print"testing tail calls"
function deep (n) if n>0 then return deep(n-1) else return 101 end end
assert(deep(30000) == 101)
a = {}
function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end
assert(a:deep(30000) == 101)
do -- tail calls x varargs
local function foo (x, ...) local a = {...}; return x, a[1], a[2] end
local function foo1 (x) return foo(10, x, x + 1) end
local a, b, c = foo1(-2)
assert(a == 10 and b == -2 and c == -1)
-- tail calls x metamethods
local t = setmetatable({}, {__call = foo})
local function foo2 (x) return t(10, x) end
a, b, c = foo2(100)
assert(a == t and b == 10 and c == 100)
a, b = (function () return foo() end)()
assert(a == nil and b == nil)
local X, Y, A
local function foo (x, y, ...) X = x; Y = y; A = {...} end
local function foo1 (...) return foo(...) end
local a, b, c = foo1()
assert(X == nil and Y == nil and #A == 0)
a, b, c = foo1(10)
assert(X == 10 and Y == nil and #A == 0)
a, b, c = foo1(10, 20)
assert(X == 10 and Y == 20 and #A == 0)
a, b, c = foo1(10, 20, 30)
assert(X == 10 and Y == 20 and #A == 1 and A[1] == 30)
end
do -- tail calls x chain of __call
local n = 10000 -- depth
local function foo ()
if n == 0 then return 1023
else n = n - 1; return foo()
end
end
-- build a chain of __call metamethods ending in function 'foo'
for i = 1, 100 do
foo = setmetatable({}, {__call = foo})
end
-- call the first one as a tail call in a new coroutine
-- (to ensure stack is not preallocated)
assert(coroutine.wrap(function() return foo() end)() == 1023)
end
print('+')
do -- testing chains of '__call'
local N = 20
local u = table.pack
for i = 1, N do
u = setmetatable({i}, {__call = u})
end
local Res = u("a", "b", "c")
assert(Res.n == N + 3)
for i = 1, N do
assert(Res[i][1] == i)
end
assert(Res[N + 1] == "a" and Res[N + 2] == "b" and Res[N + 3] == "c")
end
a = nil
(function (x) a=x end)(23)
assert(a == 23 and (function (x) return x*2 end)(20) == 40)
-- testing closures
-- fixed-point operator
Z = function (le)
local function a (f)
return le(function (x) return f(f)(x) end)
end
return a(a)
end
-- non-recursive factorial
F = function (f)
return function (n)
if n == 0 then return 1
else return n*f(n-1) end
end
end
fat = Z(F)
assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4))
local function g (z)
local function f (a,b,c,d)
return function (x,y) return a+b+c+d+a+x+y+z end
end
return f(z,z+1,z+2,z+3)
end
f = g(10)
assert(f(9, 16) == 10+11+12+13+10+9+16+10)
Z, F, f = nil
print('+')
-- testing multiple returns
function unlpack (t, i)
i = i or 1
if (i <= #t) then
return t[i], unlpack(t, i+1)
end
end
function equaltab (t1, t2)
assert(#t1 == #t2)
for i = 1, #t1 do
assert(t1[i] == t2[i])
end
end
local pack = function (...) return (table.pack(...)) end
function f() return 1,2,30,4 end
function ret2 (a,b) return a,b end
local a,b,c,d = unlpack{1,2,3}
assert(a==1 and b==2 and c==3 and d==nil)
a = {1,2,3,4,false,10,'alo',false,assert}
equaltab(pack(unlpack(a)), a)
equaltab(pack(unlpack(a), -1), {1,-1})
a,b,c,d = ret2(f()), ret2(f())
assert(a==1 and b==1 and c==2 and d==nil)
a,b,c,d = unlpack(pack(ret2(f()), ret2(f())))
assert(a==1 and b==1 and c==2 and d==nil)
a,b,c,d = unlpack(pack(ret2(f()), (ret2(f()))))
assert(a==1 and b==1 and c==nil and d==nil)
a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}}
assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b")
-- testing calls with 'incorrect' arguments
rawget({}, "x", 1)
rawset({}, "x", 1, 2)
assert(math.sin(1,2) == math.sin(1))
table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
-- test for generic load
local x = "-- a comment\0\0\0\n x = 10 + \n23; \
local a = function () x = 'hi' end; \
return '\0'"
function read1 (x)
local i = 0
return function ()
collectgarbage()
i=i+1
return string.sub(x, i, i)
end
end
function cannotload (msg, a,b)
assert(not a and string.find(b, msg))
end
a = assert(load(read1(x), "modname", "t", _G))
assert(a() == "\0" and _G.x == 33)
assert(debug.getinfo(a).source == "modname")
-- cannot read text in binary mode
cannotload("attempt to load a text chunk", load(read1(x), "modname", "b", {}))
cannotload("attempt to load a text chunk", load(x, "modname", "b"))
a = assert(load(function () return nil end))
a() -- empty chunk
assert(not load(function () return true end))
-- small bug
local t = {nil, "return ", "3"}
f, msg = load(function () return table.remove(t, 1) end)
assert(f() == nil) -- should read the empty chunk
-- another small bug (in 5.2.1)
f = load(string.dump(function () return 1 end), nil, "b", {})
assert(type(f) == "function" and f() == 1)
x = string.dump(load("x = 1; return x"))
a = assert(load(read1(x), nil, "b"))
assert(a() == 1 and _G.x == 1)
cannotload("attempt to load a binary chunk", load(read1(x), nil, "t"))
cannotload("attempt to load a binary chunk", load(x, nil, "t"))
assert(not pcall(string.dump, print)) -- no dump of C functions
cannotload("unexpected symbol", load(read1("*a = 123")))
cannotload("unexpected symbol", load("*a = 123"))
cannotload("hhi", load(function () error("hhi") end))
-- any value is valid for _ENV
assert(load("return _ENV", nil, nil, 123)() == 123)
-- load when _ENV is not first upvalue
local x; XX = 123
local function h ()
local y=x -- use 'x', so that it becomes 1st upvalue
return XX -- global name
end
local d = string.dump(h)
x = load(d, "", "b")
assert(debug.getupvalue(x, 2) == '_ENV')
debug.setupvalue(x, 2, _G)
assert(x() == 123)
assert(assert(load("return XX + ...", nil, nil, {XX = 13}))(4) == 17)
-- test generic load with nested functions
x = [[
return function (x)
return function (y)
return function (z)
return x+y+z
end
end
end
]]
a = assert(load(read1(x)))
assert(a()(2)(3)(10) == 15)
-- test for dump/undump with upvalues
local a, b = 20, 30
x = load(string.dump(function (x)
if x == "set" then a = 10+b; b = b+1 else
return a
end
end), "", "b", nil)
assert(x() == nil)
assert(debug.setupvalue(x, 1, "hi") == "a")
assert(x() == "hi")
assert(debug.setupvalue(x, 2, 13) == "b")
assert(not debug.setupvalue(x, 3, 10)) -- only 2 upvalues
x("set")
assert(x() == 23)
x("set")
assert(x() == 24)
-- test for dump/undump with many upvalues
do
local nup = 200 -- maximum number of local variables
local prog = {"local a1"}
for i = 2, nup do prog[#prog + 1] = ", a" .. i end
prog[#prog + 1] = " = 1"
for i = 2, nup do prog[#prog + 1] = ", " .. i end
local sum = 1
prog[#prog + 1] = "; return function () return a1"
for i = 2, nup do prog[#prog + 1] = " + a" .. i; sum = sum + i end
prog[#prog + 1] = " end"
prog = table.concat(prog)
local f = assert(load(prog))()
assert(f() == sum)
f = load(string.dump(f)) -- main chunk now has many upvalues
local a = 10
local h = function () return a end
for i = 1, nup do
debug.upvaluejoin(f, i, h, 1)
end
assert(f() == 10 * nup)
end
-- test for long method names
do
local t = {x = 1}
function t:_012345678901234567890123456789012345678901234567890123456789 ()
return self.x
end
assert(t:_012345678901234567890123456789012345678901234567890123456789() == 1)
end
-- test for bug in parameter adjustment
assert((function () return nil end)(4) == nil)
assert((function () local a; return a end)(4) == nil)
assert((function (a) return a end)() == nil)
print("testing binary chunks")
do
local header = string.pack("c4BBc6BBBj",
"\27Lua", -- signature
0x54, -- version 5.4 (0x54)
0, -- format
"\x19\x93\r\n\x1a\n", -- data
4, -- size of instruction
string.packsize("j"), -- sizeof(lua integer)
string.packsize("n"), -- sizeof(lua number)
0x5678 -- LUAC_INT
-- LUAC_NUM may not have a unique binary representation (padding...)
)
local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end)
assert(string.sub(c, 1, #header) == header)
-- corrupted header
for i = 1, #header do
local s = string.sub(c, 1, i - 1) ..
string.char(string.byte(string.sub(c, i, i)) + 1) ..
string.sub(c, i + 1, -1)
assert(#s == #c)
assert(not load(s))
end
-- loading truncated binary chunks
for i = 1, #c - 1 do
local st, msg = load(string.sub(c, 1, i))
assert(not st and string.find(msg, "truncated"))
end
assert(assert(load(c))() == 10)
end
print('OK')
return deep
+270
View File
@@ -0,0 +1,270 @@
-- $Id: testes/closure.lua $
-- See Copyright Notice in file all.lua
print "testing closures"
local A,B = 0,{g=10}
function f(x)
local a = {}
for i=1,1000 do
local y = 0
do
a[i] = function () B.g = B.g+1; y = y+x; return y+A end
end
end
local dummy = function () return a[A] end
collectgarbage()
A = 1; assert(dummy() == a[1]); A = 0;
assert(a[1]() == x)
assert(a[3]() == x)
collectgarbage()
assert(B.g == 12)
return a
end
local a = f(10)
-- force a GC in this level
local x = {[1] = {}} -- to detect a GC
setmetatable(x, {__mode = 'kv'})
while x[1] do -- repeat until GC
local a = A..A..A..A -- create garbage
A = A+1
end
assert(a[1]() == 20+A)
assert(a[1]() == 30+A)
assert(a[2]() == 10+A)
collectgarbage()
assert(a[2]() == 20+A)
assert(a[2]() == 30+A)
assert(a[3]() == 20+A)
assert(a[8]() == 10+A)
assert(getmetatable(x).__mode == 'kv')
assert(B.g == 19)
-- testing equality
a = {}
for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end
assert(a[3] ~= a[4] and a[4] ~= a[5])
do
local a = function (x) return math.sin(_ENV[x]) end
local function f()
return a
end
assert(f() == f())
end
-- testing closures with 'for' control variable
a = {}
for i=1,10 do
a[i] = {set = function(x) i=x end, get = function () return i end}
if i == 3 then break end
end
assert(a[4] == undef)
a[1].set(10)
assert(a[2].get() == 2)
a[2].set('a')
assert(a[3].get() == 3)
assert(a[2].get() == 'a')
a = {}
local t = {"a", "b"}
for i = 1, #t do
local k = t[i]
a[i] = {set = function(x, y) i=x; k=y end,
get = function () return i, k end}
if i == 2 then break end
end
a[1].set(10, 20)
local r,s = a[2].get()
assert(r == 2 and s == 'b')
r,s = a[1].get()
assert(r == 10 and s == 20)
a[2].set('a', 'b')
r,s = a[2].get()
assert(r == "a" and s == "b")
-- testing closures with 'for' control variable x break
for i=1,3 do
f = function () return i end
break
end
assert(f() == 1)
for k = 1, #t do
local v = t[k]
f = function () return k, v end
break
end
assert(({f()})[1] == 1)
assert(({f()})[2] == "a")
-- testing closure x break x return x errors
local b
function f(x)
local first = 1
while 1 do
if x == 3 and not first then return end
local a = 'xuxu'
b = function (op, y)
if op == 'set' then
a = x+y
else
return a
end
end
if x == 1 then do break end
elseif x == 2 then return
else if x ~= 3 then error() end
end
first = nil
end
end
for i=1,3 do
f(i)
assert(b('get') == 'xuxu')
b('set', 10); assert(b('get') == 10+i)
b = nil
end
pcall(f, 4);
assert(b('get') == 'xuxu')
b('set', 10); assert(b('get') == 14)
local w
-- testing multi-level closure
function f(x)
return function (y)
return function (z) return w+x+y+z end
end
end
y = f(10)
w = 1.345
assert(y(20)(30) == 60+w)
-- testing closures x break
do
local X, Y
local a = math.sin(0)
while a do
local b = 10
X = function () return b end -- closure with upvalue
if a then break end
end
do
local b = 20
Y = function () return b end -- closure with upvalue
end
-- upvalues must be different
assert(X() == 10 and Y() == 20)
end
-- testing closures x repeat-until
local a = {}
local i = 1
repeat
local x = i
a[i] = function () i = x+1; return x end
until i > 10 or a[i]() ~= x
assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
-- testing closures created in 'then' and 'else' parts of 'if's
a = {}
for i = 1, 10 do
if i % 3 == 0 then
local y = 0
a[i] = function (x) local t = y; y = x; return t end
elseif i % 3 == 1 then
goto L1
error'not here'
::L1::
local y = 1
a[i] = function (x) local t = y; y = x; return t end
elseif i % 3 == 2 then
local t
goto l4
::l4a:: a[i] = t; goto l4b
error("should never be here!")
::l4::
local y = 2
t = function (x) local t = y; y = x; return t end
goto l4a
error("should never be here!")
::l4b::
end
end
for i = 1, 10 do
assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
end
print'+'
-- test for correctly closing upvalues in tail calls of vararg functions
local function t ()
local function c(a,b) assert(a=="test" and b=="OK") end
local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
local x = 1
return v(function() return x end)
end
t()
-- test for debug manipulation of upvalues
local debug = require'debug'
do
local a , b, c = 3, 5, 7
foo1 = function () return a+b end;
foo2 = function () return b+a end;
do
local a = 10
foo3 = function () return a+b end;
end
end
assert(debug.upvalueid(foo1, 1))
assert(debug.upvalueid(foo1, 2))
assert(not pcall(debug.upvalueid, foo1, 3))
assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
assert(debug.upvalueid(foo3, 1))
assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
assert(foo1() == 3 + 5 and foo2() == 5 + 3)
debug.upvaluejoin(foo1, 2, foo2, 2)
assert(foo1() == 3 + 3 and foo2() == 5 + 3)
assert(foo3() == 10 + 5)
debug.upvaluejoin(foo3, 2, foo2, 1)
assert(foo3() == 10 + 5)
debug.upvaluejoin(foo3, 2, foo2, 2)
assert(foo3() == 10 + 3)
assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
print'OK'
+443
View File
@@ -0,0 +1,443 @@
-- $Id: testes/code.lua $
-- See Copyright Notice in file all.lua
if T==nil then
(Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
return
end
print "testing code generation and optimizations"
-- to test constant propagation
local k0aux <const> = 0
local k0 <const> = k0aux
local k1 <const> = 1
local k3 <const> = 3
local k6 <const> = k3 + (k3 << k0)
local kFF0 <const> = 0xFF0
local k3_78 <const> = 3.78
local x, k3_78_4 <const> = 10, k3_78 / 4
assert(x == 10)
local kx <const> = "x"
local kTrue <const> = true
local kFalse <const> = false
local kNil <const> = nil
-- this code gave an error for the code checker
do
local function f (a)
for k,v,w in a do end
end
end
-- testing reuse in constant table
local function checkKlist (func, list)
local k = T.listk(func)
assert(#k == #list)
for i = 1, #k do
assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i]))
end
end
local function foo ()
local a
a = k3;
a = 0; a = 0.0; a = -7 + 7
a = k3_78/4; a = k3_78_4
a = -k3_78/4; a = k3_78/4; a = -3.78/4
a = -3.79/4; a = 0.0; a = -0;
a = k3; a = 3.0; a = 3; a = 3.0
end
checkKlist(foo, {3.78/4, -3.78/4, -3.79/4})
-- testing opcodes
-- check that 'f' opcodes match '...'
function check (f, ...)
local arg = {...}
local c = T.listcode(f)
for i=1, #arg do
local opcode = string.match(c[i], "%u%w+")
-- print(arg[i], opcode)
assert(arg[i] == opcode)
end
assert(c[#arg+2] == undef)
end
-- check that 'f' opcodes match '...' and that 'f(p) == r'.
function checkR (f, p, r, ...)
local r1 = f(p)
assert(r == r1 and math.type(r) == math.type(r1))
check(f, ...)
end
-- check that 'a' and 'b' has the same opcodes
function checkequal (a, b)
a = T.listcode(a)
b = T.listcode(b)
assert(#a == #b)
for i = 1, #a do
a[i] = string.gsub(a[i], '%b()', '') -- remove line number
b[i] = string.gsub(b[i], '%b()', '') -- remove line number
assert(a[i] == b[i])
end
end
-- some basic instructions
check(function () -- function does not create upvalues
(function () end){f()}
end, 'CLOSURE', 'NEWTABLE', 'EXTRAARG', 'GETTABUP', 'CALL',
'SETLIST', 'CALL', 'RETURN0')
check(function (x) -- function creates upvalues
(function () return x end){f()}
end, 'CLOSURE', 'NEWTABLE', 'EXTRAARG', 'GETTABUP', 'CALL',
'SETLIST', 'CALL', 'RETURN')
-- sequence of LOADNILs
check(function ()
local kNil <const> = nil
local a,b,c
local d; local e;
local f,g,h;
d = nil; d=nil; b=nil; a=kNil; c=nil;
end, 'LOADNIL', 'RETURN0')
check(function ()
local a,b,c,d = 1,1,1,1
d=nil;c=nil;b=nil;a=nil
end, 'LOADI', 'LOADI', 'LOADI', 'LOADI', 'LOADNIL', 'RETURN0')
do
local a,b,c,d = 1,1,1,1
d=nil;c=nil;b=nil;a=nil
assert(a == nil and b == nil and c == nil and d == nil)
end
-- single return
check (function (a,b,c) return a end, 'RETURN1')
-- infinite loops
check(function () while kTrue do local a = -1 end end,
'LOADI', 'JMP', 'RETURN0')
check(function () while 1 do local a = -1 end end,
'LOADI', 'JMP', 'RETURN0')
check(function () repeat local x = 1 until true end,
'LOADI', 'RETURN0')
-- concat optimization
check(function (a,b,c,d) return a..b..c..d end,
'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN1')
-- not
check(function () return not not nil end, 'LOADFALSE', 'RETURN1')
check(function () return not not kFalse end, 'LOADFALSE', 'RETURN1')
check(function () return not not true end, 'LOADTRUE', 'RETURN1')
check(function () return not not k3 end, 'LOADTRUE', 'RETURN1')
-- direct access to locals
check(function ()
local a,b,c,d
a = b*a
c.x, a[b] = -((a + d/b - a[b]) ^ a.x), b
end,
'LOADNIL',
'MUL', 'MMBIN',
'DIV', 'MMBIN', 'ADD', 'MMBIN', 'GETTABLE', 'SUB', 'MMBIN',
'GETFIELD', 'POW', 'MMBIN', 'UNM', 'SETTABLE', 'SETFIELD', 'RETURN0')
-- direct access to constants
check(function ()
local a,b
local c = kNil
a[kx] = 3.2
a.x = b
a[b] = 'x'
end,
'LOADNIL', 'SETFIELD', 'SETFIELD', 'SETTABLE', 'RETURN0')
-- "get/set table" with numeric indices
check(function (a)
local k255 <const> = 255
a[1] = a[100]
a[k255] = a[256]
a[256] = 5
end,
'GETI', 'SETI',
'LOADI', 'GETTABLE', 'SETI',
'LOADI', 'SETTABLE', 'RETURN0')
check(function ()
local a,b
a = a - a
b = a/a
b = 5-4
end,
'LOADNIL', 'SUB', 'MMBIN', 'DIV', 'MMBIN', 'LOADI', 'RETURN0')
check(function ()
local a,b
a[kTrue] = false
end,
'LOADNIL', 'LOADTRUE', 'SETTABLE', 'RETURN0')
-- equalities
checkR(function (a) if a == 1 then return 2 end end, 1, 2,
'EQI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if -4.0 == a then return 2 end end, -4, 2,
'EQI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if a == "hi" then return 2 end end, 10, nil,
'EQK', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if a == 10000 then return 2 end end, 1, nil,
'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large
checkR(function (a) if -10000 == a then return 2 end end, -10000, 2,
'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large
-- comparisons
checkR(function (a) if -10 <= a then return 2 end end, -10, 2,
'GEI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if 128.0 > a then return 2 end end, 129, nil,
'LTI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if -127.0 < a then return 2 end end, -127, nil,
'GTI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if 10 < a then return 2 end end, 11, 2,
'GTI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if 129 < a then return 2 end end, 130, 2,
'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if a >= 23.0 then return 2 end end, 25, 2,
'GEI', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if a >= 23.1 then return 2 end end, 0, nil,
'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1')
checkR(function (a) if a > 2300.0 then return 2 end end, 0, nil,
'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1')
-- constant folding
local function checkK (func, val)
check(func, 'LOADK', 'RETURN1')
checkKlist(func, {val})
assert(func() == val)
end
local function checkI (func, val)
check(func, 'LOADI', 'RETURN1')
checkKlist(func, {})
assert(func() == val)
end
local function checkF (func, val)
check(func, 'LOADF', 'RETURN1')
checkKlist(func, {})
assert(func() == val)
end
checkF(function () return 0.0 end, 0.0)
checkI(function () return k0 end, 0)
checkI(function () return -k0//1 end, 0)
checkK(function () return 3^-1 end, 1/3)
checkK(function () return (1 + 1)^(50 + 50) end, 2^100)
checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0)
checkF(function () return (-k3^0 + 5) // 3.0 end, 1.0)
checkI(function () return -k3 % 5 end, 2)
checkF(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0)
checkF(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0)
checkI(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4)
checkI(function () return ~(~kFF0 | kFF0) end, 0)
checkI(function () return ~~-1024.0 end, -1024)
checkI(function () return ((100 << k6) << -4) >> 2 end, 100)
-- borders around MAXARG_sBx ((((1 << 17) - 1) >> 1) == 65535)
local a = 17; local sbx = ((1 << a) - 1) >> 1 -- avoid folding
local border <const> = 65535
checkI(function () return border end, sbx)
checkI(function () return -border end, -sbx)
checkI(function () return border + 1 end, sbx + 1)
checkK(function () return border + 2 end, sbx + 2)
checkK(function () return -(border + 1) end, -(sbx + 1))
local border <const> = 65535.0
checkF(function () return border end, sbx + 0.0)
checkF(function () return -border end, -sbx + 0.0)
checkF(function () return border + 1 end, (sbx + 1.0))
checkK(function () return border + 2 end, (sbx + 2.0))
checkK(function () return -(border + 1) end, -(sbx + 1.0))
-- immediate operands
checkR(function (x) return x + k1 end, 10, 11, 'ADDI', 'MMBINI', 'RETURN1')
checkR(function (x) return x - 127 end, 10, -117, 'ADDI', 'MMBINI', 'RETURN1')
checkR(function (x) return 128 + x end, 0.0, 128.0,
'ADDI', 'MMBINI', 'RETURN1')
checkR(function (x) return x * -127 end, -1.0, 127.0,
'MULK', 'MMBINK', 'RETURN1')
checkR(function (x) return 20 * x end, 2, 40, 'MULK', 'MMBINK', 'RETURN1')
checkR(function (x) return x ^ -2 end, 2, 0.25, 'POWK', 'MMBINK', 'RETURN1')
checkR(function (x) return x / 40 end, 40, 1.0, 'DIVK', 'MMBINK', 'RETURN1')
checkR(function (x) return x // 1 end, 10.0, 10.0,
'IDIVK', 'MMBINK', 'RETURN1')
checkR(function (x) return x % (100 - 10) end, 91, 1,
'MODK', 'MMBINK', 'RETURN1')
checkR(function (x) return k1 << x end, 3, 8, 'SHLI', 'MMBINI', 'RETURN1')
checkR(function (x) return x << 127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
checkR(function (x) return x << -127 end, 10, 0, 'SHRI', 'MMBINI', 'RETURN1')
checkR(function (x) return x >> 128 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
checkR(function (x) return x >> -127 end, 8, 0, 'SHRI', 'MMBINI', 'RETURN1')
checkR(function (x) return x & 1 end, 9, 1, 'BANDK', 'MMBINK', 'RETURN1')
checkR(function (x) return 10 | x end, 1, 11, 'BORK', 'MMBINK', 'RETURN1')
checkR(function (x) return -10 ~ x end, -1, 9, 'BXORK', 'MMBINK', 'RETURN1')
-- K operands in arithmetic operations
checkR(function (x) return x + 0.0 end, 1, 1.0, 'ADDK', 'MMBINK', 'RETURN1')
-- check(function (x) return 128 + x end, 'ADDK', 'MMBINK', 'RETURN1')
checkR(function (x) return x * -10000 end, 2, -20000,
'MULK', 'MMBINK', 'RETURN1')
-- check(function (x) return 20 * x end, 'MULK', 'MMBINK', 'RETURN1')
checkR(function (x) return x ^ 0.5 end, 4, 2.0, 'POWK', 'MMBINK', 'RETURN1')
checkR(function (x) return x / 2.0 end, 4, 2.0, 'DIVK', 'MMBINK', 'RETURN1')
checkR(function (x) return x // 10000 end, 10000, 1,
'IDIVK', 'MMBINK', 'RETURN1')
checkR(function (x) return x % (100.0 - 10) end, 91, 1.0,
'MODK', 'MMBINK', 'RETURN1')
-- no foldings (and immediate operands)
check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1')
check(function () return k3/0 end, 'LOADI', 'DIVK', 'MMBINK', 'RETURN1')
check(function () return 0%0 end, 'LOADI', 'MODK', 'MMBINK', 'RETURN1')
check(function () return -4//0 end, 'LOADI', 'IDIVK', 'MMBINK', 'RETURN1')
check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'MMBIN', 'RETURN1')
check(function (x) return x << 128 end, 'LOADI', 'SHL', 'MMBIN', 'RETURN1')
check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'MMBIN', 'RETURN1')
-- basic 'for' loops
check(function () for i = -10, 10.5 do end end,
'LOADI', 'LOADK', 'LOADI', 'FORPREP', 'FORLOOP', 'RETURN0')
check(function () for i = 0xfffffff, 10.0, 1 do end end,
'LOADK', 'LOADF', 'LOADI', 'FORPREP', 'FORLOOP', 'RETURN0')
-- bug in constant folding for 5.1
check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN1')
check(function ()
local a,b,c
b[c], a = c, b
b[a], a = c, b
a, b = c, a
a = a
end,
'LOADNIL',
'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
'MOVE', 'MOVE', 'MOVE',
-- no code for a = a
'RETURN0')
-- x == nil , x ~= nil
-- checkequal(function (b) if (a==nil) then a=1 end; if a~=nil then a=1 end end,
-- function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
-- check(function () if a==nil then a='a' end end,
-- 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
do -- tests for table access in upvalues
local t
check(function () t[kx] = t.y end, 'GETTABUP', 'SETTABUP')
check(function (a) t[a()] = t[a()] end,
'MOVE', 'CALL', 'GETUPVAL', 'MOVE', 'CALL',
'GETUPVAL', 'GETTABLE', 'SETTABLE')
end
-- de morgan
checkequal(function () local a; if not (a or b) then b=a end end,
function () local a; if (not a and not b) then b=a end end)
checkequal(function (l) local a; return 0 <= a and a <= l end,
function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
-- if-break optimizations
check(function (a, b)
while a do
if b then break else a = a + 1 end
end
end,
'TEST', 'JMP', 'TEST', 'JMP', 'ADDI', 'MMBINI', 'JMP', 'RETURN0')
checkequal(
function (a) while a < 10 do a = a + 1 end end,
function (a)
::loop::
if not (a < 10) then goto exit end
a = a + 1
goto loop
::exit::
end
)
checkequal(
function (a) repeat local x = a + 1; a = x until a > 0 end,
function (a)
::loop:: do
local x = a + 1
a = x
end
if not (a > 0) then goto loop end
end
)
checkequal(function () return 6 or true or nil end,
function () return k6 or kTrue or kNil end)
checkequal(function () return 6 and true or nil end,
function () return k6 and kTrue or kNil end)
do -- string constants
local k0 <const> = "00000000000000000000000000000000000000000000000000"
local function f1 ()
local k <const> = k0
return function ()
return function () return k end
end
end
local f2 = f1()
local f3 = f2()
assert(f3() == k0)
checkK(f3, k0)
-- string is not needed by other functions
assert(T.listk(f1)[1] == nil)
assert(T.listk(f2)[1] == nil)
end
print 'OK'
+377
View File
@@ -0,0 +1,377 @@
-- $Id: testes/constructs.lua $
-- See Copyright Notice in file all.lua
;;print "testing syntax";;
local debug = require "debug"
local function checkload (s, msg)
assert(string.find(select(2, load(s)), msg))
end
-- testing semicollons
do ;;; end
; do ; a = 3; assert(a == 3) end;
;
-- invalid operations should not raise errors when not executed
if false then a = 3 // 0; a = 0 % 0 end
-- testing priorities
assert(2^3^2 == 2^(3^2));
assert(2^3*4 == (2^3)*4);
assert(2.0^-2 == 1/4 and -2^- -2 == - - -4);
assert(not nil and 2 and not(2>3 or 3<2));
assert(-3-1-5 == 0+0-9);
assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0);
assert(-3%5 == 2 and -3+5 == 2)
assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33");
assert(not(2+1 > 3*1) and "a".."b" > "a");
assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4)
assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4)
assert(0xF0 & 0x0F + 1 == 0x10)
assert(3^4//2^3//5 == 2)
assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3))
assert(not ((true or false) and nil))
assert( true or false and nil)
-- old bug
assert((((1 or false) and true) or false) == true)
assert((((nil and true) or false) and true) == false)
local a,b = 1,nil;
assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
x,y=1,2;
assert((x>y) and x or y == 2);
x,y=2,1;
assert((x>y) and x or y == 2);
assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
do -- testing operators with diffent kinds of constants
-- operands to consider:
-- * fit in register
-- * constant doesn't fit in register
-- * floats with integral values
local operand = {3, 100, 5.0, -10, -5.0, 10000, -10000}
local operator = {"+", "-", "*", "/", "//", "%", "^",
"&", "|", "^", "<<", ">>",
"==", "~=", "<", ">", "<=", ">=",}
for _, op in ipairs(operator) do
local f = assert(load(string.format([[return function (x,y)
return x %s y
end]], op)))();
for _, o1 in ipairs(operand) do
for _, o2 in ipairs(operand) do
local gab = f(o1, o2)
_ENV.XX = o1
code = string.format("return XX %s %s", op, o2)
res = assert(load(code))()
assert(res == gab)
_ENV.XX = o2
local code = string.format("return (%s) %s XX", o1, op)
local res = assert(load(code))()
assert(res == gab)
code = string.format("return (%s) %s %s", o1, op, o2)
res = assert(load(code))()
assert(res == gab)
end
end
end
end
-- silly loops
repeat until 1; repeat until true;
while false do end; while nil do end;
do -- test old bug (first name could not be an `upvalue')
local a; function f(x) x={a=1}; x={x=1}; x={G=1} end
end
function f (i)
if type(i) ~= 'number' then return i,'jojo'; end;
if i > 0 then return i, f(i-1); end;
end
x = {f(3), f(5), f(10);};
assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
assert(x[nil] == nil)
x = {f'alo', f'xixi', nil};
assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
x = {f'alo'..'xixi'};
assert(x[1] == 'aloxixi')
x = {f{}}
assert(x[2] == 'jojo' and type(x[1]) == 'table')
local f = function (i)
if i < 10 then return 'a';
elseif i < 20 then return 'b';
elseif i < 30 then return 'c';
end;
end
assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
for i=1,1000 do break; end;
n=100;
i=3;
t = {};
a=nil
while not a do
a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
end
assert(a == n*(n+1)/2 and i==3);
assert(t[1] and t[n] and not t[0] and not t[n+1])
function f(b)
local x = 1;
repeat
local a;
if b==1 then local b=1; x=10; break
elseif b==2 then x=20; break;
elseif b==3 then x=30;
else local a,b,c,d=math.sin(1); x=x+1;
end
until x>=12;
return x;
end;
assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
local f = function (i)
if i < 10 then return 'a'
elseif i < 20 then return 'b'
elseif i < 30 then return 'c'
else return 8
end
end
assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
local a, b = nil, 23
x = {f(100)*2+3 or a, a or b+2}
assert(x[1] == 19 and x[2] == 25)
x = {f=2+3 or a, a = b+2}
assert(x.f == 5 and x.a == 25)
a={y=1}
x = {a.y}
assert(x[1] == 1)
function f(i)
while 1 do
if i>0 then i=i-1;
else return; end;
end;
end;
function g(i)
while 1 do
if i>0 then i=i-1
else return end
end
end
f(10); g(10);
do
function f () return 1,2,3; end
local a, b, c = f();
assert(a==1 and b==2 and c==3)
a, b, c = (f());
assert(a==1 and b==nil and c==nil)
end
local a,b = 3 and f();
assert(a==1 and b==nil)
function g() f(); return; end;
assert(g() == nil)
function g() return nil or f() end
a,b = g()
assert(a==1 and b==nil)
print'+';
do -- testing constants
local prog <const> = [[local x <XXX> = 10]]
checkload(prog, "unknown attribute 'XXX'")
checkload([[local xxx <const> = 20; xxx = 10]],
":1: attempt to assign to const variable 'xxx'")
checkload([[
local xx;
local xxx <const> = 20;
local yyy;
local function foo ()
local abc = xx + yyy + xxx;
return function () return function () xxx = yyy end end
end
]], ":6: attempt to assign to const variable 'xxx'")
checkload([[
local x <close> = nil
x = io.open()
]], ":2: attempt to assign to const variable 'x'")
end
f = [[
return function ( a , b , c , d , e )
local x = a >= b or c or ( d and e ) or nil
return x
end , { a = 1 , b = 2 >= 1 , } or { 1 };
]]
f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes
f,a = load(f)();
assert(a.a == 1 and a.b)
function g (a,b,c,d,e)
if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
end
function h (a,b,c,d,e)
while (a>=b or c or (d and e) or nil) do return 1; end;
return 0;
end;
assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
assert(f(1,2,'a')
~= -- force SETLINE before nil
nil, "")
assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
h(1,2,nil,1,'x') == 1)
assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
h(1,2,nil,nil,'x') == 0)
assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
h(1,2,nil,1,nil) == 0)
assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
x = 2<3 and not 3; assert(x==false)
x = 2<1 or (2>1 and 'a'); assert(x=='a')
do
local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2
assert(a==2)
end
function F(a)
assert(debug.getinfo(1, "n").name == 'F')
return a,2,3
end
a,b = F(1)~=nil; assert(a == true and b == nil);
a,b = F(nil)==nil; assert(a == true and b == nil)
----------------------------------------------------------------
------------------------------------------------------------------
-- sometimes will be 0, sometimes will not...
_ENV.GLOB1 = math.random(0, 1)
-- basic expressions with their respective values
local basiccases = {
{"nil", nil},
{"false", false},
{"true", true},
{"10", 10},
{"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1},
}
local prog
if _ENV.GLOB1 == 0 then
basiccases[2][1] = "F" -- constant false
prog = [[
local F <const> = false
if %s then IX = true end
return %s
]]
else
basiccases[4][1] = "k10" -- constant 10
prog = [[
local k10 <const> = 10
if %s then IX = true end
return %s
]]
end
print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')')
-- operators with their respective values
local binops <const> = {
{" and ", function (a,b) if not a then return a else return b end end},
{" or ", function (a,b) if a then return a else return b end end},
}
local cases <const> = {}
-- creates all combinations of '(cases[i] op cases[n-i])' plus
-- 'not(cases[i] op cases[n-i])' (syntax + value)
local function createcases (n)
local res = {}
for i = 1, n - 1 do
for _, v1 in ipairs(cases[i]) do
for _, v2 in ipairs(cases[n - i]) do
for _, op in ipairs(binops) do
local t = {
"(" .. v1[1] .. op[1] .. v2[1] .. ")",
op[2](v1[2], v2[2])
}
res[#res + 1] = t
res[#res + 1] = {"not" .. t[1], not t[2]}
end
end
end
end
return res
end
-- do not do too many combinations for soft tests
local level = _soft and 3 or 4
cases[1] = basiccases
for i = 2, level do cases[i] = createcases(i) end
print("+")
local i = 0
for n = 1, level do
for _, v in pairs(cases[n]) do
local s = v[1]
local p = load(string.format(prog, s, s), "")
IX = false
assert(p() == v[2] and IX == not not v[2])
i = i + 1
if i % 60000 == 0 then print('+') end
end
end
------------------------------------------------------------------
-- testing some syntax errors (chosen through 'gcov')
checkload("for x do", "expected")
checkload("x:call", "expected")
print'OK'
+1015
View File
File diff suppressed because it is too large Load Diff
+160
View File
@@ -0,0 +1,160 @@
-- $Id: testes/cstack.lua $
-- See Copyright Notice in file all.lua
local debug = require "debug"
print"testing C-stack overflow detection"
print"If this test crashes, see its file ('cstack.lua')"
-- Segmentation faults in these tests probably result from a C-stack
-- overflow. To avoid these errors, you can use the function
-- 'debug.setcstacklimit' to set a smaller limit for the use of
-- C stack by Lua. After finding a reliable limit, you might want
-- to recompile Lua with this limit as the value for
-- the constant 'LUAI_MAXCCALLS', which defines the default limit.
-- (The default limit is printed by this test.)
-- Alternatively, you can ensure a larger stack for the program.
-- For Linux, a limit up to 30_000 seems Ok. Windows cannot go much
-- higher than 2_000.
-- get and print original limit
local origlimit <const> = debug.setcstacklimit(400)
print("default stack limit: " .. origlimit)
-- Do the tests using the original limit. Or else you may want to change
-- 'currentlimit' to lower values to avoid a seg. fault or to higher
-- values to check whether they are reliable.
local currentlimit <const> = origlimit
debug.setcstacklimit(currentlimit)
print("current stack limit: " .. currentlimit)
local function checkerror (msg, f, ...)
local s, err = pcall(f, ...)
assert(not s and string.find(err, msg))
end
-- auxiliary function to keep 'count' on the screen even if the program
-- crashes.
local count
local back = string.rep("\b", 8)
local function progress ()
count = count + 1
local n = string.format("%-8d", count)
io.stderr:write(back, n) -- erase previous value and write new one
end
do print("testing simple recursion:")
count = 0
local function foo ()
progress()
foo() -- do recursive calls until a stack error (or crash)
end
checkerror("stack overflow", foo)
print("\tfinal count: ", count)
end
do print("testing stack overflow in message handling")
count = 0
local function loop (x, y, z)
progress()
return 1 + loop(x, y, z)
end
local res, msg = xpcall(loop, loop)
assert(msg == "error in error handling")
print("\tfinal count: ", count)
end
-- bug since 2.5 (C-stack overflow in recursion inside pattern matching)
do print("testing recursion inside pattern matching")
local function f (size)
local s = string.rep("a", size)
local p = string.rep(".?", size)
return string.match(s, p)
end
local m = f(80)
assert(#m == 80)
checkerror("too complex", f, 200000)
end
do print("testing stack-overflow in recursive 'gsub'")
count = 0
local function foo ()
progress()
string.gsub("a", ".", foo)
end
checkerror("stack overflow", foo)
print("\tfinal count: ", count)
print("testing stack-overflow in recursive 'gsub' with metatables")
count = 0
local t = setmetatable({}, {__index = foo})
foo = function ()
count = count + 1
progress(count)
string.gsub("a", ".", t)
end
checkerror("stack overflow", foo)
print("\tfinal count: ", count)
end
do print("testing changes in C-stack limit")
-- Just an alternative limit, different from the current one
-- (smaller to avoid stack overflows)
local alterlimit <const> = currentlimit * 8 // 10
assert(not debug.setcstacklimit(0)) -- limit too small
assert(not debug.setcstacklimit(50000)) -- limit too large
local co = coroutine.wrap (function ()
return debug.setcstacklimit(alterlimit)
end)
assert(not co()) -- cannot change C stack inside coroutine
local n
local function foo () n = n + 1; foo () end
local function check ()
n = 0
pcall(foo)
return n
end
-- set limit to 'alterlimit'
assert(debug.setcstacklimit(alterlimit) == currentlimit)
local limalter <const> = check()
-- set a very low limit (given that there are already several active
-- calls to arrive here)
local lowlimit <const> = 38
assert(debug.setcstacklimit(lowlimit) == alterlimit)
-- usable limit is much lower, due to active calls
local actuallow = check()
assert(actuallow < lowlimit - 30)
-- now, add 'lowlimit' extra slots, which should all be available
assert(debug.setcstacklimit(lowlimit + lowlimit) == lowlimit)
local lim2 <const> = check()
assert(lim2 == actuallow + lowlimit)
-- 'setcstacklimit' works inside protected calls. (The new stack
-- limit is kept when 'pcall' returns.)
assert(pcall(function ()
assert(debug.setcstacklimit(alterlimit) == lowlimit * 2)
assert(check() <= limalter)
end))
assert(check() == limalter)
-- restore original limit
assert(debug.setcstacklimit(origlimit) == alterlimit)
end
print'OK'
+963
View File
@@ -0,0 +1,963 @@
-- $Id: testes/db.lua $
-- See Copyright Notice in file all.lua
-- testing debug library
local debug = require "debug"
local function dostring(s) return assert(load(s))() end
print"testing debug library and debug information"
do
local a=1
end
assert(not debug.gethook())
local testline = 19 -- line where 'test' is defined
function test (s, l, p) -- this must be line 19
collectgarbage() -- avoid gc during trace
local function f (event, line)
assert(event == 'line')
local l = table.remove(l, 1)
if p then print(l, line) end
assert(l == line, "wrong trace!!")
end
debug.sethook(f,"l"); load(s)(); debug.sethook()
assert(#l == 0)
end
do
assert(not pcall(debug.getinfo, print, "X")) -- invalid option
assert(not debug.getinfo(1000)) -- out of range level
assert(not debug.getinfo(-1)) -- out of range level
local a = debug.getinfo(print)
assert(a.what == "C" and a.short_src == "[C]")
a = debug.getinfo(print, "L")
assert(a.activelines == nil)
local b = debug.getinfo(test, "SfL")
assert(b.name == nil and b.what == "Lua" and b.linedefined == testline and
b.lastlinedefined == b.linedefined + 10 and
b.func == test and not string.find(b.short_src, "%["))
assert(b.activelines[b.linedefined + 1] and
b.activelines[b.lastlinedefined])
assert(not b.activelines[b.linedefined] and
not b.activelines[b.lastlinedefined + 1])
end
-- test file and string names truncation
a = "function f () end"
local function dostring (s, x) return load(s, x)() end
dostring(a)
assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
dostring(a..string.format("; %s=1", string.rep('p', 400)))
assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
dostring("\n"..a)
assert(debug.getinfo(f).short_src == '[string "..."]')
dostring(a, "")
assert(debug.getinfo(f).short_src == '[string ""]')
dostring(a, "@xuxu")
assert(debug.getinfo(f).short_src == "xuxu")
dostring(a, "@"..string.rep('p', 1000)..'t')
assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
dostring(a, "=xuxu")
assert(debug.getinfo(f).short_src == "xuxu")
dostring(a, string.format("=%s", string.rep('x', 500)))
assert(string.find(debug.getinfo(f).short_src, "^x*$"))
dostring(a, "=")
assert(debug.getinfo(f).short_src == "")
a = nil; f = nil;
repeat
local g = {x = function ()
local a = debug.getinfo(2)
assert(a.name == 'f' and a.namewhat == 'local')
a = debug.getinfo(1)
assert(a.name == 'x' and a.namewhat == 'field')
return 'xixi'
end}
local f = function () return 1+1 and (not 1 or g.x()) end
assert(f() == 'xixi')
g = debug.getinfo(f)
assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
function f (x, name) -- local!
name = name or 'f'
local a = debug.getinfo(1)
assert(a.name == name and a.namewhat == 'local')
return x
end
-- breaks in different conditions
if 3>4 then break end; f()
if 3<4 then a=1 else break end; f()
while 1 do local x=10; break end; f()
local b = 1
if 3>4 then return math.sin(1) end; f()
a = 3<4; f()
a = 3<4 or 1; f()
repeat local x=20; if 4>3 then f() else break end; f() until 1
g = {}
f(g).x = f(2) and f(10)+f(9)
assert(g.x == f(19))
function g(x) if not x then return 3 end return (x('a', 'x')) end
assert(g(f) == 'a')
until 1
test([[if
math.sin(1)
then
a=1
else
a=2
end
]], {2,3,4,7})
test([[--
if nil then
a=1
else
a=2
end
]], {2,5,6})
test([[a=1
repeat
a=a+1
until a==3
]], {1,3,4,3,4})
test([[ do
return
end
]], {2})
test([[local a
a=1
while a<=3 do
a=a+1
end
]], {1,2,3,4,3,4,3,4,3,5})
test([[while math.sin(1) do
if math.sin(1)
then break
end
end
a=1]], {1,2,3,6})
test([[for i=1,3 do
a=i
end
]], {1,2,1,2,1,2,1,3})
test([[for i,v in pairs{'a','b'} do
a=tostring(i) .. v
end
]], {1,2,1,2,1,3})
test([[for i=1,4 do a=1 end]], {1,1,1,1})
do -- testing line info/trace with large gaps in source
local a = {1, 2, 3, 10, 124, 125, 126, 127, 128, 129, 130,
255, 256, 257, 500, 1000}
local s = [[
local b = {10}
a = b[1] X + Y b[1]
b = 4
]]
for _, i in ipairs(a) do
local subs = {X = string.rep("\n", i)}
for _, j in ipairs(a) do
subs.Y = string.rep("\n", j)
local s = string.gsub(s, "[XY]", subs)
test(s, {1, 2 + i, 2 + i + j, 2 + i, 2 + i + j, 3 + i + j})
end
end
end
print'+'
-- invalid levels in [gs]etlocal
assert(not pcall(debug.getlocal, 20, 1))
assert(not pcall(debug.setlocal, -1, 1, 10))
-- parameter names
local function foo (a,b,...) local d, e end
local co = coroutine.create(foo)
assert(debug.getlocal(foo, 1) == 'a')
assert(debug.getlocal(foo, 2) == 'b')
assert(not debug.getlocal(foo, 3))
assert(debug.getlocal(co, foo, 1) == 'a')
assert(debug.getlocal(co, foo, 2) == 'b')
assert(not debug.getlocal(co, foo, 3))
assert(not debug.getlocal(print, 1))
local function foo () return (debug.getlocal(1, -1)) end
assert(not foo(10))
-- varargs
local function foo (a, ...)
local t = table.pack(...)
for i = 1, t.n do
local n, v = debug.getlocal(1, -i)
assert(n == "(vararg)" and v == t[i])
end
assert(not debug.getlocal(1, -(t.n + 1)))
assert(not debug.setlocal(1, -(t.n + 1), 30))
if t.n > 0 then
(function (x)
assert(debug.setlocal(2, -1, x) == "(vararg)")
assert(debug.setlocal(2, -t.n, x) == "(vararg)")
end)(430)
assert(... == 430)
end
end
foo()
foo(print)
foo(200, 3, 4)
local a = {}
for i = 1, (_soft and 100 or 1000) do a[i] = i end
foo(table.unpack(a))
a = nil
do -- test hook presence in debug info
assert(not debug.gethook())
local count = 0
local function f ()
assert(debug.getinfo(1).namewhat == "hook")
local sndline = string.match(debug.traceback(), "\n(.-)\n")
assert(string.find(sndline, "hook"))
count = count + 1
end
debug.sethook(f, "l")
local a = 0
_ENV.a = a
a = 1
debug.sethook()
assert(count == 4)
end
-- hook table has weak keys
assert(getmetatable(debug.getregistry()._HOOKKEY).__mode == 'k')
a = {}; L = nil
local glob = 1
local oldglob = glob
debug.sethook(function (e,l)
collectgarbage() -- force GC during a hook
local f, m, c = debug.gethook()
assert(m == 'crl' and c == 0)
if e == "line" then
if glob ~= oldglob then
L = l-1 -- get the first line where "glob" has changed
oldglob = glob
end
elseif e == "call" then
local f = debug.getinfo(2, "f").func
a[f] = 1
else assert(e == "return")
end
end, "crl")
function f(a,b)
collectgarbage()
local _, x = debug.getlocal(1, 1)
local _, y = debug.getlocal(1, 2)
assert(x == a and y == b)
assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
assert(debug.setlocal(2, 4, "maçã") == "B")
x = debug.getinfo(2)
assert(x.func == g and x.what == "Lua" and x.name == 'g' and
x.nups == 2 and string.find(x.source, "^@.*db%.lua$"))
glob = glob+1
assert(debug.getinfo(1, "l").currentline == L+1)
assert(debug.getinfo(1, "l").currentline == L+2)
end
function foo()
glob = glob+1
assert(debug.getinfo(1, "l").currentline == L+1)
end; foo() -- set L
-- check line counting inside strings and empty lines
_ = 'alo\
alo' .. [[
]]
--[[
]]
assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
function g (...)
local arg = {...}
do local a,b,c; a=math.sin(40); end
local feijao
local AAAA,B = "xuxu", "mamão"
f(AAAA,B)
assert(AAAA == "pera" and B == "maçã")
do
local B = 13
local x,y = debug.getlocal(1,5)
assert(x == 'B' and y == 13)
end
end
g()
assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
-- tests for manipulating non-registered locals (C and Lua temporaries)
local n, v = debug.getlocal(0, 1)
assert(v == 0 and n == "(C temporary)")
local n, v = debug.getlocal(0, 2)
assert(v == 2 and n == "(C temporary)")
assert(not debug.getlocal(0, 3))
assert(not debug.getlocal(0, 0))
function f()
assert(select(2, debug.getlocal(2,3)) == 1)
assert(not debug.getlocal(2,4))
debug.setlocal(2, 3, 10)
return 20
end
function g(a,b) return (a+1) + f() end
assert(g(0,0) == 30)
debug.sethook(nil);
assert(not debug.gethook())
-- minimal tests for setuservalue/getuservalue
do
assert(not debug.setuservalue(io.stdin, 10))
local a, b = debug.getuservalue(io.stdin, 10)
assert(a == nil and not b)
end
-- testing iteraction between multiple values x hooks
do
local function f(...) return 3, ... end
local count = 0
local a = {}
for i = 1, 100 do a[i] = i end
debug.sethook(function () count = count + 1 end, "", 1)
local t = {table.unpack(a)}
assert(#t == 100)
t = {table.unpack(a, 1, 3)}
assert(#t == 3)
t = {f(table.unpack(a, 1, 30))}
assert(#t == 31)
end
-- testing access to function arguments
local function collectlocals (level)
local tab = {}
for i = 1, math.huge do
local n, v = debug.getlocal(level + 1, i)
if not (n and string.find(n, "^[a-zA-Z0-9_]+$")) then
break -- consider only real variables
end
tab[n] = v
end
return tab
end
X = nil
a = {}
function a:f (a, b, ...) local arg = {...}; local c = 13 end
debug.sethook(function (e)
assert(e == "call")
dostring("XX = 12") -- test dostring inside hooks
-- testing errors inside hooks
assert(not pcall(load("a='joao'+1")))
debug.sethook(function (e, l)
assert(debug.getinfo(2, "l").currentline == l)
local f,m,c = debug.gethook()
assert(e == "line")
assert(m == 'l' and c == 0)
debug.sethook(nil) -- hook is called only once
assert(not X) -- check that
X = collectlocals(2)
end, "l")
end, "c")
a:f(1,2,3,4,5)
assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
assert(XX == 12)
assert(not debug.gethook())
-- testing access to local variables in return hook (bug in 5.2)
do
local X = false
local function foo (a, b, ...)
do local x,y,z end
local c, d = 10, 20
return
end
local function aux ()
if debug.getinfo(2).name == "foo" then
X = true -- to signal that it found 'foo'
local tab = {a = 100, b = 200, c = 10, d = 20}
for n, v in pairs(collectlocals(2)) do
assert(tab[n] == v)
tab[n] = undef
end
assert(next(tab) == nil) -- 'tab' must be empty
end
end
debug.sethook(aux, "r"); foo(100, 200); debug.sethook()
assert(X)
end
local function eqseq (t1, t2)
assert(#t1 == #t2)
for i = 1, #t1 do
assert(t1[i] == t2[i])
end
end
do print("testing inspection of parameters/returned values")
local on = false
local inp, out
local function hook (event)
if not on then return end
local ar = debug.getinfo(2, "ruS")
local t = {}
for i = ar.ftransfer, ar.ftransfer + ar.ntransfer - 1 do
local _, v = debug.getlocal(2, i)
t[#t + 1] = v
end
if event == "return" then
out = t
else
inp = t
end
end
debug.sethook(hook, "cr")
on = true; math.sin(3); on = false
eqseq(inp, {3}); eqseq(out, {math.sin(3)})
on = true; select(2, 10, 20, 30, 40); on = false
eqseq(inp, {2, 10, 20, 30, 40}); eqseq(out, {20, 30, 40})
local function foo (a, ...) return ... end
local function foo1 () on = not on; return foo(20, 10, 0) end
foo1(); on = false
eqseq(inp, {20}); eqseq(out, {10, 0})
debug.sethook()
end
-- testing upvalue access
local function getupvalues (f)
local t = {}
local i = 1
while true do
local name, value = debug.getupvalue(f, i)
if not name then break end
assert(not t[name])
t[name] = value
i = i + 1
end
return t
end
local a,b,c = 1,2,3
local function foo1 (a) b = a; return c end
local function foo2 (x) a = x; return c+b end
assert(not debug.getupvalue(foo1, 3))
assert(not debug.getupvalue(foo1, 0))
assert(not debug.setupvalue(foo1, 3, "xuxu"))
local t = getupvalues(foo1)
assert(t.a == nil and t.b == 2 and t.c == 3)
t = getupvalues(foo2)
assert(t.a == 1 and t.b == 2 and t.c == 3)
assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
-- upvalues of C functions are allways "called" "" (the empty string)
assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")
-- testing count hooks
local a=0
debug.sethook(function (e) a=a+1 end, "", 1)
a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
debug.sethook(function (e) a=a+1 end, "", 4)
a=0; for i=1,1000 do end; assert(250 < a and a < 255)
local f,m,c = debug.gethook()
assert(m == "" and c == 4)
debug.sethook(function (e) a=a+1 end, "", 4000)
a=0; for i=1,1000 do end; assert(a == 0)
do
debug.sethook(print, "", 2^24 - 1) -- count upperbound
local f,m,c = debug.gethook()
assert(({debug.gethook()})[3] == 2^24 - 1)
end
debug.sethook()
-- tests for tail calls
local function f (x)
if x then
assert(debug.getinfo(1, "S").what == "Lua")
assert(debug.getinfo(1, "t").istailcall == true)
local tail = debug.getinfo(2)
assert(tail.func == g1 and tail.istailcall == true)
assert(debug.getinfo(3, "S").what == "main")
print"+"
end
end
function g(x) return f(x) end
function g1(x) g(x) end
local function h (x) local f=g1; return f(x) end
h(true)
local b = {}
debug.sethook(function (e) table.insert(b, e) end, "cr")
h(false)
debug.sethook()
local res = {"return", -- first return (from sethook)
"call", "tail call", "call", "tail call",
"return", "return",
"call", -- last call (to sethook)
}
for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
b = 0
debug.sethook(function (e)
if e == "tail call" then
b = b + 1
assert(debug.getinfo(2, "t").istailcall == true)
else
assert(debug.getinfo(2, "t").istailcall == false)
end
end, "c")
h(false)
debug.sethook()
assert(b == 2) -- two tail calls
lim = _soft and 3000 or 30000
local function foo (x)
if x==0 then
assert(debug.getinfo(2).what == "main")
local info = debug.getinfo(1)
assert(info.istailcall == true and info.func == foo)
else return foo(x-1)
end
end
foo(lim)
print"+"
-- testing local function information
co = load[[
local A = function ()
return x
end
return
]]
local a = 0
-- 'A' should be visible to debugger only after its complete definition
debug.sethook(function (e, l)
if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(temporary)")
elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
end
end, "l")
co() -- run local function definition
debug.sethook() -- turn off hook
assert(a == 2) -- ensure all two lines where hooked
-- testing traceback
assert(debug.traceback(print) == print)
assert(debug.traceback(print, 4) == print)
assert(string.find(debug.traceback("hi", 4), "^hi\n"))
assert(string.find(debug.traceback("hi"), "^hi\n"))
assert(not string.find(debug.traceback("hi"), "'debug.traceback'"))
assert(string.find(debug.traceback("hi", 0), "'debug.traceback'"))
assert(string.find(debug.traceback(), "^stack traceback:\n"))
do -- C-function names in traceback
local st, msg = (function () return pcall end)()(debug.traceback)
assert(st == true and string.find(msg, "pcall"))
end
-- testing nparams, nups e isvararg
local t = debug.getinfo(print, "u")
assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
t = debug.getinfo(function (a,b,c) end, "u")
assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
t = debug.getinfo(function (a,b,...) return t[a] end, "u")
assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
t = debug.getinfo(1) -- main
assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
debug.getupvalue(t.func, 1) == "_ENV")
t = debug.getinfo(math.sin) -- C function
assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
t = debug.getinfo(string.gmatch("abc", "a")) -- C closure
assert(t.isvararg == true and t.nparams == 0 and t.nups > 0)
-- testing debugging of coroutines
local function checktraceback (co, p, level)
local tb = debug.traceback(co, nil, level)
local i = 0
for l in string.gmatch(tb, "[^\n]+\n?") do
assert(i == 0 or string.find(l, p[i]))
i = i+1
end
assert(p[i] == undef)
end
local function f (n)
if n > 0 then f(n-1)
else coroutine.yield() end
end
local co = coroutine.create(f)
coroutine.resume(co, 3)
checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
checktraceback(co, {"db.lua"}, 4)
checktraceback(co, {}, 40)
co = coroutine.create(function (x)
local a = 1
coroutine.yield(debug.getinfo(1, "l"))
coroutine.yield(debug.getinfo(1, "l").currentline)
return a
end)
local tr = {}
local foo = function (e, l) if l then table.insert(tr, l) end end
debug.sethook(co, foo, "lcr")
local _, l = coroutine.resume(co, 10)
local x = debug.getinfo(co, 1, "lfLS")
assert(x.currentline == l.currentline and x.activelines[x.currentline])
assert(type(x.func) == "function")
for i=x.linedefined + 1, x.lastlinedefined do
assert(x.activelines[i])
x.activelines[i] = undef
end
assert(next(x.activelines) == nil) -- no 'extra' elements
assert(not debug.getinfo(co, 2))
local a,b = debug.getlocal(co, 1, 1)
assert(a == "x" and b == 10)
a,b = debug.getlocal(co, 1, 2)
assert(a == "a" and b == 1)
debug.setlocal(co, 1, 2, "hi")
assert(debug.gethook(co) == foo)
assert(#tr == 2 and
tr[1] == l.currentline-1 and tr[2] == l.currentline)
a,b,c = pcall(coroutine.resume, co)
assert(a and b and c == l.currentline+1)
checktraceback(co, {"yield", "in function <"})
a,b = coroutine.resume(co)
assert(a and b == "hi")
assert(#tr == 4 and tr[4] == l.currentline+2)
assert(debug.gethook(co) == foo)
assert(not debug.gethook())
checktraceback(co, {})
-- check get/setlocal in coroutines
co = coroutine.create(function (x)
local a, b = coroutine.yield(x)
assert(a == 100 and b == nil)
return x
end)
a, b = coroutine.resume(co, 10)
assert(a and b == 10)
a, b = debug.getlocal(co, 1, 1)
assert(a == "x" and b == 10)
assert(not debug.getlocal(co, 1, 5))
assert(debug.setlocal(co, 1, 1, 30) == "x")
assert(not debug.setlocal(co, 1, 5, 40))
a, b = coroutine.resume(co, 100)
assert(a and b == 30)
-- check traceback of suspended (or dead with error) coroutines
function f(i)
if i == 0 then error(i)
else coroutine.yield(); f(i-1)
end
end
co = coroutine.create(function (x) f(x) end)
a, b = coroutine.resume(co, 3)
t = {"'coroutine.yield'", "'f'", "in function <"}
while coroutine.status(co) == "suspended" do
checktraceback(co, t)
a, b = coroutine.resume(co)
table.insert(t, 2, "'f'") -- one more recursive call to 'f'
end
t[1] = "'error'"
checktraceback(co, t)
-- test acessing line numbers of a coroutine from a resume inside
-- a C function (this is a known bug in Lua 5.0)
local function g(x)
coroutine.yield(x)
end
local function f (i)
debug.sethook(function () end, "l")
for j=1,1000 do
g(i+j)
end
end
local co = coroutine.wrap(f)
co(10)
pcall(co)
pcall(co)
assert(type(debug.getregistry()) == "table")
-- test tagmethod information
local a = {}
local function f (t)
local info = debug.getinfo(1);
assert(info.namewhat == "metamethod")
a.op = info.name
return info.name
end
setmetatable(a, {
__index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
__mul = f; __idiv = f; __unm = f; __len = f; __sub = f;
__shl = f; __shr = f; __bor = f; __bxor = f;
__eq = f; __le = f; __lt = f; __unm = f; __len = f; __band = f;
__bnot = f;
})
local b = setmetatable({}, getmetatable(a))
assert(a[3] == "index" and a^3 == "pow" and a..a == "concat")
assert(a/3 == "div" and 3%a == "mod")
assert(a+3 == "add" and 3-a == "sub" and a*3 == "mul" and
-a == "unm" and #a == "len" and a&3 == "band")
assert(a + 30000 == "add" and a - 3.0 == "sub" and a * 3.0 == "mul" and
-a == "unm" and #a == "len" and a & 3 == "band")
assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shl" and a>>1 == "shr")
assert (a==b and a.op == "eq")
assert (a>=b and a.op == "order")
assert (a>b and a.op == "order")
assert(~a == "bnot")
do -- testing for-iterator name
local function f()
assert(debug.getinfo(1).name == "for iterator")
end
for i in f do end
end
do -- testing debug info for finalizers
local name = nil
-- create a piece of garbage with a finalizer
setmetatable({}, {__gc = function ()
local t = debug.getinfo(2) -- get callee information
assert(t.namewhat == "metamethod")
name = t.name
end})
-- repeat until previous finalizer runs (setting 'name')
repeat local a = {} until name
assert(name == "__gc")
end
do
print("testing traceback sizes")
local function countlines (s)
return select(2, string.gsub(s, "\n", ""))
end
local function deep (lvl, n)
if lvl == 0 then
return (debug.traceback("message", n))
else
return (deep(lvl-1, n))
end
end
local function checkdeep (total, start)
local s = deep(total, start)
local rest = string.match(s, "^message\nstack traceback:\n(.*)$")
local cl = countlines(rest)
-- at most 10 lines in first part, 11 in second, plus '...'
assert(cl <= 10 + 11 + 1)
local brk = string.find(rest, "%.%.%.")
if brk then -- does message have '...'?
local rest1 = string.sub(rest, 1, brk)
local rest2 = string.sub(rest, brk, #rest)
assert(countlines(rest1) == 10 and countlines(rest2) == 11)
else
assert(cl == total - start + 2)
end
end
for d = 1, 51, 10 do
for l = 1, d do
-- use coroutines to ensure complete control of the stack
coroutine.wrap(checkdeep)(d, l)
end
end
end
print("testing debug functions on chunk without debug info")
prog = [[-- program to be loaded without debug information
local debug = require'debug'
local a = 12 -- a local variable
local n, v = debug.getlocal(1, 1)
assert(n == "(temporary)" and v == debug) -- unkown name but known value
n, v = debug.getlocal(1, 2)
assert(n == "(temporary)" and v == 12) -- unkown name but known value
-- a function with an upvalue
local f = function () local x; return a end
n, v = debug.getupvalue(f, 1)
assert(n == "(no name)" and v == 12)
assert(debug.setupvalue(f, 1, 13) == "(no name)")
assert(a == 13)
local t = debug.getinfo(f)
assert(t.name == nil and t.linedefined > 0 and
t.lastlinedefined == t.linedefined and
t.short_src == "?")
assert(debug.getinfo(1).currentline == -1)
t = debug.getinfo(f, "L").activelines
assert(next(t) == nil) -- active lines are empty
-- dump/load a function without debug info
f = load(string.dump(f))
t = debug.getinfo(f)
assert(t.name == nil and t.linedefined > 0 and
t.lastlinedefined == t.linedefined and
t.short_src == "?")
assert(debug.getinfo(1).currentline == -1)
return a
]]
-- load 'prog' without debug info
local f = assert(load(string.dump(load(prog), true)))
assert(f() == 13)
do -- tests for 'source' in binary dumps
local prog = [[
return function (x)
return function (y)
return x + y
end
end
]]
local name = string.rep("x", 1000)
local p = assert(load(prog, name))
-- load 'p' as a binary chunk with debug information
local c = string.dump(p)
assert(#c > 1000 and #c < 2000) -- no repetition of 'source' in dump
local f = assert(load(c))
local g = f()
local h = g(3)
assert(h(5) == 8)
assert(debug.getinfo(f).source == name and -- all functions have 'source'
debug.getinfo(g).source == name and
debug.getinfo(h).source == name)
-- again, without debug info
local c = string.dump(p, true)
assert(#c < 500) -- no 'source' in dump
local f = assert(load(c))
local g = f()
local h = g(30)
assert(h(50) == 80)
assert(debug.getinfo(f).source == '=?' and -- no function has 'source'
debug.getinfo(g).source == '=?' and
debug.getinfo(h).source == '=?')
end
print"OK"
+589
View File
@@ -0,0 +1,589 @@
-- $Id: testes/errors.lua $
-- See Copyright Notice in file all.lua
print("testing errors")
local debug = require"debug"
-- avoid problems with 'strict' module (which may generate other error messages)
local mt = getmetatable(_G) or {}
local oldmm = mt.__index
mt.__index = nil
local function checkerr (msg, f, ...)
local st, err = pcall(f, ...)
assert(not st and string.find(err, msg))
end
local function doit (s)
local f, msg = load(s)
if not f then return msg end
local cond, msg = pcall(f)
return (not cond) and msg
end
local function checkmessage (prog, msg)
local m = doit(prog)
assert(string.find(m, msg, 1, true))
end
local function checksyntax (prog, extra, token, line)
local msg = doit(prog)
if not string.find(token, "^<%a") and not string.find(token, "^char%(")
then token = "'"..token.."'" end
token = string.gsub(token, "(%p)", "%%%1")
local pt = string.format([[^%%[string ".*"%%]:%d: .- near %s$]],
line, token)
assert(string.find(msg, pt))
assert(string.find(msg, msg, 1, true))
end
-- test error message with no extra info
assert(doit("error('hi', 0)") == 'hi')
-- test error message with no info
assert(doit("error()") == nil)
-- test common errors/errors that crashed in the past
assert(doit("table.unpack({}, 1, n=2^30)"))
assert(doit("a=math.sin()"))
assert(not doit("tostring(1)") and doit("tostring()"))
assert(doit"tonumber()")
assert(doit"repeat until 1; a")
assert(doit"return;;")
assert(doit"assert(false)")
assert(doit"assert(nil)")
assert(doit("function a (... , ...) end"))
assert(doit("function a (, ...) end"))
assert(doit("local t={}; t = t[#t] + 1"))
checksyntax([[
local a = {4
]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
if not T then
(Message or print)
('\n >>> testC not active: skipping memory message test <<<\n')
else
print "testing memory error message"
local a = {}
for i = 1, 10000 do a[i] = true end -- preallocate array
collectgarbage()
T.totalmem(T.totalmem() + 10000)
-- force a memory error (by a small margin)
local st, msg = pcall(function()
for i = 1, 100000 do a[i] = tostring(i) end
end)
T.totalmem(0)
assert(not st and msg == "not enough" .. " memory")
end
-- tests for better error messages
checkmessage("a = {} + 1", "arithmetic")
checkmessage("a = {} | 1", "bitwise operation")
checkmessage("a = {} < 1", "attempt to compare")
checkmessage("a = {} <= 1", "attempt to compare")
checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
checkmessage("a=(1)..{}", "a table value")
-- tail calls
checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
checkmessage("a={}; do local a=1 end; return a:bbbb(3)", "method 'bbbb'")
checkmessage("a = #print", "length of a function value")
checkmessage("a = #3", "length of a number value")
aaa = nil
checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
checkmessage("local a,b,c; (function () a = b+1.1 end)()", "upvalue 'b'")
assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
-- upvalues being indexed do not go to the stack
checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
checkmessage("b=1; local aaa={}; x=aaa+b", "local 'aaa'")
checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
checkmessage("aaa=2; b=nil;x=aaa*b", "global 'b'")
checkmessage("aaa={}; x=-aaa", "global 'aaa'")
-- short circuit
checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
"local 'bbbb'")
checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'")
checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
checkmessage("print(print < 10)", "function with number")
checkmessage("print(print < print)", "two function values")
checkmessage("print('10' < 10)", "string with number")
checkmessage("print(10 < '23')", "number with string")
-- float->integer conversions
checkmessage("local a = 2.0^100; x = a << 2", "local a")
checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
checkmessage("local a = 10.1 << 2.0^100", "has no integer representation")
checkmessage("local a = 2.0^100 & 1", "has no integer representation")
checkmessage("local a = 2.0^100 & 1e100", "has no integer representation")
checkmessage("local a = 2.0 | 1e40", "has no integer representation")
checkmessage("local a = 2e100 ~ 1", "has no integer representation")
checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
checkmessage("string.rep('a', 3.3)", "has no integer representation")
checkmessage("return 6e40 & 7", "has no integer representation")
checkmessage("return 34 << 7e30", "has no integer representation")
checkmessage("return ~-3e40", "has no integer representation")
checkmessage("return ~-3.009", "has no integer representation")
checkmessage("return 3.009 & 1", "has no integer representation")
checkmessage("return 34 >> {}", "table value")
checkmessage("a = 24 // 0", "divide by zero")
checkmessage("a = 1 % 0", "'n%0'")
-- numeric for loops
checkmessage("for i = {}, 10 do end", "table")
checkmessage("for i = io.stdin, 10 do end", "FILE")
checkmessage("for i = {}, 10 do end", "initial value")
checkmessage("for i = 1, 'x', 10 do end", "string")
checkmessage("for i = 1, {}, 10 do end", "limit")
checkmessage("for i = 1, {} do end", "limit")
checkmessage("for i = 1, 10, print do end", "step")
checkmessage("for i = 1, 10, print do end", "function")
-- passing light userdata instead of full userdata
_G.D = debug
checkmessage([[
-- create light udata
local x = D.upvalueid(function () return debug end, 1)
D.setuservalue(x, {})
]], "light userdata")
_G.D = nil
do -- named objects (field '__name')
checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
_G.XX = setmetatable({}, {__name = "My Type"})
assert(string.find(tostring(XX), "^My Type"))
checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
checkmessage("return XX + 1", "on a My Type value")
checkmessage("return ~io.stdin", "on a FILE* value")
checkmessage("return XX < XX", "two My Type values")
checkmessage("return {} < XX", "table with My Type")
checkmessage("return XX < io.stdin", "My Type with FILE*")
_G.XX = nil
end
-- global functions
checkmessage("(io.write or print){}", "io.write")
checkmessage("(collectgarbage or print){}", "collectgarbage")
-- errors in functions without debug info
do
local f = function (a) return a + 1 end
f = assert(load(string.dump(f, true)))
assert(f(3) == 4)
checkerr("^%?:%-1:", f, {})
-- code with a move to a local var ('OP_MOV A B' with A<B)
f = function () local a; a = {}; return a + 2 end
-- no debug info (so that 'a' is unknown)
f = assert(load(string.dump(f, true)))
-- symbolic execution should not get lost
checkerr("^%?:%-1:.*table value", f)
end
-- tests for field accesses after RK limit
local t = {}
for i = 1, 1000 do
t[i] = "a = x" .. i
end
local s = table.concat(t, "; ")
t = nil
checkmessage(s.."; a = bbb + 1", "global 'bbb'")
checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'")
checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'")
checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
checkmessage([[aaa=9
repeat until 3==3
local x=math.sin(math.cos(3))
if math.sin(1) == x then return math.sin(1) end -- tail call
local a,b = 1, {
{x='a'..'b'..'c', y='b', z=x},
{1,2,3,4,5} or 3+3<=3+3,
3+1>3+1,
{d = x and aaa[x or y]}}
]], "global 'aaa'")
checkmessage([[
local x,y = {},1
if math.sin(1) == 0 then return 3 end -- return
x.a()]], "field 'a'")
checkmessage([[
prefix = nil
insert = nil
while 1 do
local a
if nil then break end
insert(prefix, a)
end]], "global 'insert'")
checkmessage([[ -- tail call
return math.sin("a")
]], "'sin'")
checkmessage([[collectgarbage("nooption")]], "invalid option")
checkmessage([[x = print .. "a"]], "concatenate")
checkmessage([[x = "a" .. false]], "concatenate")
checkmessage([[x = {} .. 2]], "concatenate")
checkmessage("getmetatable(io.stdin).__gc()", "no value")
checkmessage([[
local Var
local function main()
NoSuchName (function() Var=0 end)
end
main()
]], "global 'NoSuchName'")
print'+'
a = {}; setmetatable(a, {__index = string})
checkmessage("a:sub()", "bad self")
checkmessage("string.sub('a', {})", "#2")
checkmessage("('a'):sub{}", "#1")
checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
-- tests for errors in coroutines
local function f (n)
local c = coroutine.create(f)
local a,b = coroutine.resume(c)
return b
end
assert(string.find(f(), "C stack overflow"))
checkmessage("coroutine.yield()", "outside a coroutine")
f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
checkerr("yield across", f)
-- testing size of 'source' info; size of buffer for that info is
-- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
idsize = 60 - 1
local function checksize (source)
-- syntax error
local _, msg = load("x", source)
msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
assert(msg:len() <= idsize)
end
for i = 60 - 10, 60 + 10 do -- check border cases around 60
checksize("@" .. string.rep("x", i)) -- file names
checksize(string.rep("x", i - 10)) -- string sources
checksize("=" .. string.rep("x", i)) -- exact sources
end
-- testing line error
local function lineerror (s, l)
local err,msg = pcall(load(s))
local line = tonumber(string.match(msg, ":(%d+):"))
assert(line == l or (not line and not l))
end
lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3)
lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4)
lineerror("function a.x.y ()\na=a+1\nend", 1)
lineerror("a = \na\n+\n{}", 3)
lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6)
lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3)
lineerror("a\n=\n-\n\nprint\n;", 3)
lineerror([[
a
(
23)
]], 1)
lineerror([[
local a = {x = 13}
a
.
x
(
23
)
]], 2)
lineerror([[
local a = {x = 13}
a
.
x
(
23 + a
)
]], 6)
local p = [[
function g() f() end
function f(x) error('a', X) end
g()
]]
X=3;lineerror((p), 3)
X=0;lineerror((p), false)
X=1;lineerror((p), 2)
X=2;lineerror((p), 1)
lineerror([[
local b = false
if not b then
error 'test'
end]], 3)
lineerror([[
local b = false
if not b then
if not b then
if not b then
error 'test'
end
end
end]], 5)
if not _soft then
-- several tests that exaust the Lua stack
collectgarbage()
print"testing stack overflow"
C = 0
local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
local function checkstackmessage (m)
return (string.find(m, "stack overflow"))
end
-- repeated stack overflows (to check stack recovery)
assert(checkstackmessage(doit('y()')))
print('+')
assert(checkstackmessage(doit('y()')))
print('+')
assert(checkstackmessage(doit('y()')))
print('+')
-- error lines in stack overflow
C = 0
local l1
local function g(x)
l1 = debug.getinfo(x, "l").currentline; y()
end
local _, stackmsg = xpcall(g, debug.traceback, 1)
print('+')
local stack = {}
for line in string.gmatch(stackmsg, "[^\n]*") do
local curr = string.match(line, ":(%d+):")
if curr then table.insert(stack, tonumber(curr)) end
end
local i=1
while stack[i] ~= l1 do
assert(stack[i] == l)
i = i+1
end
assert(i > 15)
-- error in error handling
local res, msg = xpcall(error, error)
assert(not res and type(msg) == 'string')
print('+')
local function f (x)
if x==0 then error('a\n')
else
local aux = function () return f(x-1) end
local a,b = xpcall(aux, aux)
return a,b
end
end
f(3)
local function loop (x,y,z) return 1 + loop(x, y, z) end
local res, msg = xpcall(loop, function (m)
assert(string.find(m, "stack overflow"))
checkerr("error handling", loop)
assert(math.sin(0) == 0)
return 15
end)
assert(msg == 15)
local f = function ()
for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
end
checkerr("too many results", f)
end
do
-- non string messages
local t = {}
local res, msg = pcall(function () error(t) end)
assert(not res and msg == t)
res, msg = pcall(function () error(nil) end)
assert(not res and msg == nil)
local function f() error{msg='x'} end
res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
assert(msg.msg == 'xy')
-- 'assert' with extra arguments
res, msg = pcall(assert, false, "X", t)
assert(not res and msg == "X")
-- 'assert' with no message
res, msg = pcall(function () assert(false) end)
local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
-- 'assert' with non-string messages
res, msg = pcall(assert, false, t)
assert(not res and msg == t)
res, msg = pcall(assert, nil, nil)
assert(not res and msg == nil)
-- 'assert' without arguments
res, msg = pcall(assert)
assert(not res and string.find(msg, "value expected"))
end
-- xpcall with arguments
a, b, c = xpcall(string.find, error, "alo", "al")
assert(a and b == 1 and c == 2)
a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
assert(not a and type(b) == "table" and c == nil)
print("testing tokens in error messages")
checksyntax("syntax error", "", "error", 1)
checksyntax("1.000", "", "1.000", 1)
checksyntax("[[a]]", "", "[[a]]", 1)
checksyntax("'aa'", "", "'aa'", 1)
checksyntax("while << do end", "", "<<", 1)
checksyntax("for >> do end", "", ">>", 1)
-- test invalid non-printable char in a chunk
checksyntax("a\1a = 1", "", "<\\1>", 1)
-- test 255 as first char in a chunk
checksyntax("\255a = 1", "", "<\\255>", 1)
doit('I = load("a=9+"); a=3')
assert(a==3 and not I)
print('+')
lim = 1000
if _soft then lim = 100 end
for i=1,lim do
doit('a = ')
doit('a = 4+nil')
end
-- testing syntax limits
local function testrep (init, rep, close, repc, finalresult)
local s = init .. string.rep(rep, 100) .. close .. string.rep(repc, 100)
local res, msg = load(s)
assert(res) -- 100 levels is OK
if (finalresult) then
assert(res() == finalresult)
end
s = init .. string.rep(rep, 10000)
local res, msg = load(s) -- 10000 levels not ok
assert(not res and (string.find(msg, "too many registers") or
string.find(msg, "stack overflow")))
end
testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
testrep("local a; a=", "{", "0", "}")
testrep("return ", "(", "2", ")", 2)
testrep("local function a (x) return x end; return ", "a(", "2.2", ")", 2.2)
testrep("", "do ", "", " end")
testrep("", "while a do ", "", " end")
testrep("local a; ", "if a then else ", "", " end")
testrep("", "function foo () ", "", " end")
testrep("local a = ''; return ", "a..", "'a'", "", "a")
testrep("local a = 1; return ", "a^", "a", "", 1)
checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
-- testing other limits
-- upvalues
local lim = 127
local s = "local function fooA ()\n local "
for j = 1,lim do
s = s.."a"..j..", "
end
s = s.."b,c\n"
s = s.."local function fooB ()\n local "
for j = 1,lim do
s = s.."b"..j..", "
end
s = s.."b\n"
s = s.."function fooC () return b+c"
local c = 1+2
for j = 1,lim do
s = s.."+a"..j.."+b"..j
c = c + 2
end
s = s.."\nend end end"
local a,b = load(s)
assert(c > 255 and string.find(b, "too many upvalues") and
string.find(b, "line 5"))
-- local variables
s = "\nfunction foo ()\n local "
for j = 1,300 do
s = s.."a"..j..", "
end
s = s.."b\n"
local a,b = load(s)
assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
mt.__index = oldmm
print('OK')
+477
View File
@@ -0,0 +1,477 @@
-- $Id: testes/events.lua $
-- See Copyright Notice in file all.lua
print('testing metatables')
local debug = require'debug'
X = 20; B = 30
_ENV = setmetatable({}, {__index=_G})
collectgarbage()
X = X+10
assert(X == 30 and _G.X == 20)
B = false
assert(B == false)
_ENV["B"] = undef
assert(B == 30)
assert(getmetatable{} == nil)
assert(getmetatable(4) == nil)
assert(getmetatable(nil) == nil)
a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
__tostring=function(x) return x.name end})
assert(getmetatable(a) == "xuxu")
assert(tostring(a) == "NAME")
-- cannot change a protected metatable
assert(pcall(setmetatable, a, {}) == false)
a.name = "gororoba"
assert(tostring(a) == "gororoba")
local a, t = {10,20,30; x="10", y="20"}, {}
assert(setmetatable(a,t) == a)
assert(getmetatable(a) == t)
assert(setmetatable(a,nil) == a)
assert(getmetatable(a) == nil)
assert(setmetatable(a,t) == a)
function f (t, i, e)
assert(not e)
local p = rawget(t, "parent")
return (p and p[i]+3), "dummy return"
end
t.__index = f
a.parent = {z=25, x=12, [4] = 24}
assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
collectgarbage()
a = setmetatable({}, t)
function f(t, i, v) rawset(t, i, v-3) end
setmetatable(t, t) -- causes a bug in 5.1 !
t.__newindex = f
a[1] = 30; a.x = "101"; a[5] = 200
assert(a[1] == 27 and a.x == 98 and a[5] == 197)
do -- bug in Lua 5.3.2
local mt = {}
mt.__newindex = mt
local t = setmetatable({}, mt)
t[1] = 10 -- will segfault on some machines
assert(mt[1] == 10)
end
local c = {}
a = setmetatable({}, t)
t.__newindex = c
t.__index = c
a[1] = 10; a[2] = 20; a[3] = 90;
for i = 4, 20 do a[i] = i * 10 end
assert(a[1] == 10 and a[2] == 20 and a[3] == 90)
for i = 4, 20 do assert(a[i] == i * 10) end
assert(next(a) == nil)
do
local a;
a = setmetatable({}, {__index = setmetatable({},
{__index = setmetatable({},
{__index = function (_,n) return a[n-3]+4, "lixo" end})})})
a[0] = 20
for i=0,10 do
assert(a[i*3] == 20 + i*4)
end
end
do -- newindex
local foi
local a = {}
for i=1,10 do a[i] = 0; a['a'..i] = 0; end
setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
foi = false; a[1]=0; assert(not foi)
foi = false; a['a1']=0; assert(not foi)
foi = false; a['a11']=0; assert(foi)
foi = false; a[11]=0; assert(foi)
foi = false; a[1]=undef; assert(not foi)
a[1] = undef
foi = false; a[1]=nil; assert(foi)
end
setmetatable(t, nil)
function f (t, ...) return t, {...} end
t.__call = f
do
local x,y = a(table.unpack{'a', 1})
assert(x==a and y[1]=='a' and y[2]==1 and y[3]==undef)
x,y = a()
assert(x==a and y[1]==undef)
end
local b = setmetatable({}, t)
setmetatable(b,t)
function f(op)
return function (...) cap = {[0] = op, ...} ; return (...) end
end
t.__add = f("add")
t.__sub = f("sub")
t.__mul = f("mul")
t.__div = f("div")
t.__idiv = f("idiv")
t.__mod = f("mod")
t.__unm = f("unm")
t.__pow = f("pow")
t.__len = f("len")
t.__band = f("band")
t.__bor = f("bor")
t.__bxor = f("bxor")
t.__shl = f("shl")
t.__shr = f("shr")
t.__bnot = f("bnot")
t.__lt = f("lt")
t.__le = f("le")
local function checkcap (t)
assert(#cap + 1 == #t)
for i = 1, #t do
assert(cap[i - 1] == t[i])
assert(math.type(cap[i - 1]) == math.type(t[i]))
end
end
-- Some tests are done inside small anonymous functions to ensure
-- that constants go to constant table even in debug compilation,
-- when the constant table is very small.
assert(b+5 == b); checkcap{"add", b, 5}
assert(5.2 + b == 5.2); checkcap{"add", 5.2, b}
assert(b+'5' == b); checkcap{"add", b, '5'}
assert(5+b == 5); checkcap{"add", 5, b}
assert('5'+b == '5'); checkcap{"add", '5', b}
b=b-3; assert(getmetatable(b) == t); checkcap{"sub", b, 3}
assert(5-a == 5); checkcap{"sub", 5, a}
assert('5'-a == '5'); checkcap{"sub", '5', a}
assert(a*a == a); checkcap{"mul", a, a}
assert(a/0 == a); checkcap{"div", a, 0}
assert(a/0.0 == a); checkcap{"div", a, 0.0}
assert(a%2 == a); checkcap{"mod", a, 2}
assert(a // (1/0) == a); checkcap{"idiv", a, 1/0}
;(function () assert(a & "hi" == a) end)(); checkcap{"band", a, "hi"}
;(function () assert(10 & a == 10) end)(); checkcap{"band", 10, a}
;(function () assert(a | 10 == a) end)(); checkcap{"bor", a, 10}
assert(a | "hi" == a); checkcap{"bor", a, "hi"}
assert("hi" ~ a == "hi"); checkcap{"bxor", "hi", a}
;(function () assert(10 ~ a == 10) end)(); checkcap{"bxor", 10, a}
assert(-a == a); checkcap{"unm", a, a}
assert(a^4.0 == a); checkcap{"pow", a, 4.0}
assert(a^'4' == a); checkcap{"pow", a, '4'}
assert(4^a == 4); checkcap{"pow", 4, a}
assert('4'^a == '4'); checkcap{"pow", '4', a}
assert(#a == a); checkcap{"len", a, a}
assert(~a == a); checkcap{"bnot", a, a}
assert(a << 3 == a); checkcap{"shl", a, 3}
assert(1.5 >> a == 1.5); checkcap{"shr", 1.5, a}
-- for comparison operators, all results are true
assert(5.0 > a); checkcap{"lt", a, 5.0}
assert(a >= 10); checkcap{"le", 10, a}
assert(a <= -10.0); checkcap{"le", a, -10.0}
assert(a < -10); checkcap{"lt", a, -10}
-- test for rawlen
t = setmetatable({1,2,3}, {__len = function () return 10 end})
assert(#t == 10 and rawlen(t) == 3)
assert(rawlen"abc" == 3)
assert(not pcall(rawlen, io.stdin))
assert(not pcall(rawlen, 34))
assert(not pcall(rawlen))
-- rawlen for long strings
assert(rawlen(string.rep('a', 1000)) == 1000)
t = {}
t.__lt = function (a,b,c)
collectgarbage()
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<b, "dummy"
end
t.__le = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a<=b, "dummy"
end
t.__eq = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.x end
if type(b) == 'table' then b = b.x end
return a == b, "dummy"
end
function Op(x) return setmetatable({x=x}, t) end
local function test (a, b, c)
assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
assert(Op(1) == Op(1) and Op(1) ~= Op(2))
assert(Op('a') == Op('a') and Op('a') ~= Op('b'))
assert(a == a and a ~= b)
assert(Op(3) == c)
end
test(Op(1), Op(2), Op(3))
-- test `partial order'
local function rawSet(x)
local y = {}
for _,k in pairs(x) do y[k] = 1 end
return y
end
local function Set(x)
return setmetatable(rawSet(x), t)
end
t.__lt = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
b[k] = undef
end
return next(b) ~= nil
end
t.__le = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
end
return true
end
assert(Set{1,2,3} < Set{1,2,3,4})
assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
assert((Set{1,2,3,4} <= Set{1,2,3,4}))
assert((Set{1,2,3,4} >= Set{1,2,3,4}))
assert(not (Set{1,3} <= Set{3,5}))
assert(not(Set{1,3} <= Set{3,5}))
assert(not(Set{1,3} >= Set{3,5}))
t.__eq = function (a,b)
for k in pairs(a) do
if not b[k] then return false end
b[k] = undef
end
return next(b) == nil
end
local s = Set{1,3,5}
assert(s == Set{3,5,1})
assert(not rawequal(s, Set{3,5,1}))
assert(rawequal(s, s))
assert(Set{1,3,5,1} == rawSet{3,5,1})
assert(rawSet{1,3,5,1} == Set{3,5,1})
assert(Set{1,3,5} ~= Set{3,5,1,6})
-- '__eq' is not used for table accesses
t[Set{1,3,5}] = 1
assert(t[Set{1,3,5}] == undef)
if not T then
(Message or print)('\n >>> testC not active: skipping tests for \z
userdata <<<\n')
else
local u1 = T.newuserdata(0, 1)
local u2 = T.newuserdata(0, 1)
local u3 = T.newuserdata(0, 1)
assert(u1 ~= u2 and u1 ~= u3)
debug.setuservalue(u1, 1);
debug.setuservalue(u2, 2);
debug.setuservalue(u3, 1);
debug.setmetatable(u1, {__eq = function (a, b)
return debug.getuservalue(a) == debug.getuservalue(b)
end})
debug.setmetatable(u2, {__eq = function (a, b)
return true
end})
assert(u1 == u3 and u3 == u1 and u1 ~= u2)
assert(u2 == u1 and u2 == u3 and u3 == u2)
assert(u2 ~= {}) -- different types cannot be equal
assert(rawequal(u1, u1) and not rawequal(u1, u3))
local mirror = {}
debug.setmetatable(u3, {__index = mirror, __newindex = mirror})
for i = 1, 10 do u3[i] = i end
for i = 1, 10 do assert(u3[i] == i) end
end
t.__concat = function (a,b,c)
assert(c == nil)
if type(a) == 'table' then a = a.val end
if type(b) == 'table' then b = b.val end
if A then return a..b
else
return setmetatable({val=a..b}, t)
end
end
c = {val="c"}; setmetatable(c, t)
d = {val="d"}; setmetatable(d, t)
A = true
assert(c..d == 'cd')
assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
A = false
assert((c..d..c..d).val == 'cdcd')
x = c..d
assert(getmetatable(x) == t and x.val == 'cd')
x = 0 .."a".."b"..c..d.."e".."f".."g"
assert(x.val == "0abcdefg")
-- concat metamethod x numbers (bug in 5.1.1)
c = {}
local x
setmetatable(c, {__concat = function (a,b)
assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
return c
end})
assert(c..5 == c and 5 .. c == c)
assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
-- test comparison compatibilities
local t1, t2, c, d
t1 = {}; c = {}; setmetatable(c, t1)
d = {}
t1.__eq = function () return true end
t1.__lt = function () return true end
t1.__le = function () return false end
setmetatable(d, t1)
assert(c == d and c < d and not(d <= c))
t2 = {}
t2.__eq = t1.__eq
t2.__lt = t1.__lt
setmetatable(d, t2)
assert(c == d and c < d and not(d <= c))
-- test for several levels of calls
local i
local tt = {
__call = function (t, ...)
i = i+1
if t.f then return t.f(...)
else return {...}
end
end
}
local a = setmetatable({}, tt)
local b = setmetatable({f=a}, tt)
local c = setmetatable({f=b}, tt)
i = 0
x = c(3,4,5)
assert(i == 3 and x[1] == 3 and x[3] == 5)
assert(_G.X == 20)
print'+'
local _g = _G
_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
a = {}
rawset(a, "x", 1, 2, 3)
assert(a.x == 1 and rawget(a, "x", 3) == 1)
print '+'
-- testing metatables for basic types
mt = {__index = function (a,b) return a+b end,
__len = function (x) return math.floor(x) end}
debug.setmetatable(10, mt)
assert(getmetatable(-2) == mt)
assert((10)[3] == 13)
assert((10)["3"] == 13)
assert(#3.45 == 3)
debug.setmetatable(23, nil)
assert(getmetatable(-2) == nil)
debug.setmetatable(true, mt)
assert(getmetatable(false) == mt)
mt.__index = function (a,b) return a or b end
assert((true)[false] == true)
assert((false)[false] == false)
debug.setmetatable(false, nil)
assert(getmetatable(true) == nil)
debug.setmetatable(nil, mt)
assert(getmetatable(nil) == mt)
mt.__add = function (a,b) return (a or 1) + (b or 2) end
assert(10 + nil == 12)
assert(nil + 23 == 24)
assert(nil + nil == 3)
debug.setmetatable(nil, nil)
assert(getmetatable(nil) == nil)
debug.setmetatable(nil, {})
-- loops in delegation
a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a
assert(not pcall(function (a,b) return a[b] end, a, 10))
assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true))
-- bug in 5.1
T, K, V = nil
grandparent = {}
grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
parent = {}
parent.__newindex = parent
setmetatable(parent, grandparent)
child = setmetatable({}, parent)
child.foo = 10 --> CRASH (on some machines)
assert(T == parent and K == "foo" and V == 10)
print 'OK'
return 12
+925
View File
@@ -0,0 +1,925 @@
-- $Id: testes/files.lua $
-- See Copyright Notice in file all.lua
local debug = require "debug"
local maxint = math.maxinteger
assert(type(os.getenv"PATH") == "string")
assert(io.input(io.stdin) == io.stdin)
assert(not pcall(io.input, "non-existent-file"))
assert(io.output(io.stdout) == io.stdout)
local function testerr (msg, f, ...)
local stat, err = pcall(f, ...)
return (not stat and string.find(err, msg, 1, true))
end
local function checkerr (msg, f, ...)
assert(testerr(msg, f, ...))
end
-- cannot close standard files
assert(not io.close(io.stdin) and
not io.stdout:close() and
not io.stderr:close())
-- cannot call close method without an argument (new in 5.3.5)
checkerr("got no value", io.stdin.close)
assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
assert(type(io.stdin) == "userdata" and io.type(io.stderr) == "file")
assert(not io.type(8))
local a = {}; setmetatable(a, {})
assert(not io.type(a))
assert(getmetatable(io.input()).__name == "FILE*")
local a,b,c = io.open('xuxu_nao_existe')
assert(not a and type(b) == "string" and type(c) == "number")
a,b,c = io.open('/a/b/c/d', 'w')
assert(not a and type(b) == "string" and type(c) == "number")
local file = os.tmpname()
local f, msg = io.open(file, "w")
if not f then
(Message or print)("'os.tmpname' file cannot be open; skipping file tests")
else --{ most tests here need tmpname
f:close()
print('testing i/o')
local otherfile = os.tmpname()
checkerr("invalid mode", io.open, file, "rw")
checkerr("invalid mode", io.open, file, "rb+")
checkerr("invalid mode", io.open, file, "r+bk")
checkerr("invalid mode", io.open, file, "")
checkerr("invalid mode", io.open, file, "+")
checkerr("invalid mode", io.open, file, "b")
assert(io.open(file, "r+b")):close()
assert(io.open(file, "r+")):close()
assert(io.open(file, "rb")):close()
assert(os.setlocale('C', 'all'))
io.input(io.stdin); io.output(io.stdout);
os.remove(file)
assert(not loadfile(file))
checkerr("", dofile, file)
assert(not io.open(file))
io.output(file)
assert(io.output() ~= io.stdout)
if not _port then -- invalid seek
local status, msg, code = io.stdin:seek("set", 1000)
assert(not status and type(msg) == "string" and type(code) == "number")
end
assert(io.output():seek() == 0)
assert(io.write("alo alo"):seek() == string.len("alo alo"))
assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
assert(io.write("joao"))
assert(io.output():seek("end") == string.len("alo joao"))
assert(io.output():seek("set") == 0)
assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
assert(io.write('çfourth_line'))
io.output(io.stdout)
collectgarbage() -- file should be closed by GC
assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
print('+')
-- test GC for files
collectgarbage()
for i=1,120 do
for i=1,5 do
io.input(file)
assert(io.open(file, 'r'))
io.lines(file)
end
collectgarbage()
end
io.input():close()
io.close()
assert(os.rename(file, otherfile))
assert(not os.rename(file, otherfile))
io.output(io.open(otherfile, "ab"))
assert(io.write("\n\n\t\t ", 3450, "\n"));
io.close()
do
-- closing file by scope
local F = nil
do
local f <close> = assert(io.open(file, "w"))
F = f
end
assert(tostring(F) == "file (closed)")
end
assert(os.remove(file))
do
-- test writing/reading numbers
local f <close> = assert(io.open(file, "w"))
f:write(maxint, '\n')
f:write(string.format("0X%x\n", maxint))
f:write("0xABCp-3", '\n')
f:write(0, '\n')
f:write(-maxint, '\n')
f:write(string.format("0x%X\n", -maxint))
f:write("-0xABCp-3", '\n')
assert(f:close())
local f <close> = assert(io.open(file, "r"))
assert(f:read("n") == maxint)
assert(f:read("n") == maxint)
assert(f:read("n") == 0xABCp-3)
assert(f:read("n") == 0)
assert(f:read("*n") == -maxint) -- test old format (with '*')
assert(f:read("n") == -maxint)
assert(f:read("*n") == -0xABCp-3) -- test old format (with '*')
end
assert(os.remove(file))
-- testing multiple arguments to io.read
do
local f <close> = assert(io.open(file, "w"))
f:write[[
a line
another line
1234
3.45
one
two
three
]]
local l1, l2, l3, l4, n1, n2, c, dummy
assert(f:close())
local f <close> = assert(io.open(file, "r"))
l1, l2, n1, n2, dummy = f:read("l", "L", "n", "n")
assert(l1 == "a line" and l2 == "another line\n" and
n1 == 1234 and n2 == 3.45 and dummy == nil)
assert(f:close())
local f <close> = assert(io.open(file, "r"))
l1, l2, n1, n2, c, l3, l4, dummy = f:read(7, "l", "n", "n", 1, "l", "l")
assert(l1 == "a line\n" and l2 == "another line" and c == '\n' and
n1 == 1234 and n2 == 3.45 and l3 == "one" and l4 == "two"
and dummy == nil)
assert(f:close())
local f <close> = assert(io.open(file, "r"))
-- second item failing
l1, n1, n2, dummy = f:read("l", "n", "n", "l")
assert(l1 == "a line" and not n1)
end
assert(os.remove(file))
-- test yielding during 'dofile'
f = assert(io.open(file, "w"))
f:write[[
local x, z = coroutine.yield(10)
local y = coroutine.yield(20)
return x + y * z
]]
assert(f:close())
f = coroutine.wrap(dofile)
assert(f(file) == 10)
assert(f(100, 101) == 20)
assert(f(200) == 100 + 200 * 101)
assert(os.remove(file))
f = assert(io.open(file, "w"))
-- test number termination
f:write[[
-12.3- -0xffff+ .3|5.E-3X +234e+13E 0xDEADBEEFDEADBEEFx
0x1.13Ap+3e
]]
-- very long number
f:write("1234"); for i = 1, 1000 do f:write("0") end; f:write("\n")
-- invalid sequences (must read and discard valid prefixes)
f:write[[
.e+ 0.e; --; 0xX;
]]
assert(f:close())
f = assert(io.open(file, "r"))
assert(f:read("n") == -12.3); assert(f:read(1) == "-")
assert(f:read("n") == -0xffff); assert(f:read(2) == "+ ")
assert(f:read("n") == 0.3); assert(f:read(1) == "|")
assert(f:read("n") == 5e-3); assert(f:read(1) == "X")
assert(f:read("n") == 234e13); assert(f:read(1) == "E")
assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
do -- attempt to read too long number
assert(not f:read("n")) -- fails
local s = f:read("L") -- read rest of line
assert(string.find(s, "^00*\n$")) -- lots of 0's left
end
assert(not f:read("n")); assert(f:read(2) == "e+")
assert(not f:read("n")); assert(f:read(1) == ";")
assert(not f:read("n")); assert(f:read(2) == "-;")
assert(not f:read("n")); assert(f:read(1) == "X")
assert(not f:read("n")); assert(f:read(1) == ";")
assert(not f:read("n")); assert(not f:read(0)) -- end of file
assert(f:close())
assert(os.remove(file))
-- test line generators
assert(not pcall(io.lines, "non-existent-file"))
assert(os.rename(otherfile, file))
io.output(otherfile)
local n = 0
local f = io.lines(file)
while f() do n = n + 1 end;
assert(n == 6) -- number of lines in the file
checkerr("file is already closed", f)
checkerr("file is already closed", f)
-- copy from file to otherfile
n = 0
for l in io.lines(file) do io.write(l, "\n"); n = n + 1 end
io.close()
assert(n == 6)
-- copy from otherfile back to file
local f = assert(io.open(otherfile))
assert(io.type(f) == "file")
io.output(file)
assert(not io.output():read())
n = 0
for l in f:lines() do io.write(l, "\n"); n = n + 1 end
assert(tostring(f):sub(1, 5) == "file ")
assert(f:close()); io.close()
assert(n == 6)
checkerr("closed file", io.close, f)
assert(tostring(f) == "file (closed)")
assert(io.type(f) == "closed file")
io.input(file)
f = io.open(otherfile):lines()
n = 0
for l in io.lines() do assert(l == f()); n = n + 1 end
f = nil; collectgarbage()
assert(n == 6)
assert(os.remove(otherfile))
do -- bug in 5.3.1
io.output(otherfile)
io.write(string.rep("a", 300), "\n")
io.close()
local t ={}; for i = 1, 250 do t[i] = 1 end
t = {io.lines(otherfile, table.unpack(t))()}
-- everything ok here
assert(#t == 250 and t[1] == 'a' and t[#t] == 'a')
t[#t + 1] = 1 -- one too many
checkerr("too many arguments", io.lines, otherfile, table.unpack(t))
collectgarbage() -- ensure 'otherfile' is closed
assert(os.remove(otherfile))
end
io.input(file)
do -- test error returns
local a,b,c = io.input():write("xuxu")
assert(not a and type(b) == "string" and type(c) == "number")
end
checkerr("invalid format", io.read, "x")
assert(io.read(0) == "") -- not eof
assert(io.read(5, 'l') == '"álo"')
assert(io.read(0) == "")
assert(io.read() == "second line")
local x = io.input():seek()
assert(io.read() == "third line ")
assert(io.input():seek("set", x))
assert(io.read('L') == "third line \n")
assert(io.read(1) == "ç")
assert(io.read(string.len"fourth_line") == "fourth_line")
assert(io.input():seek("cur", -string.len"fourth_line"))
assert(io.read() == "fourth_line")
assert(io.read() == "") -- empty line
assert(io.read('n') == 3450)
assert(io.read(1) == '\n')
assert(not io.read(0)) -- end of file
assert(not io.read(1)) -- end of file
assert(not io.read(30000)) -- end of file
assert(({io.read(1)})[2] == undef)
assert(not io.read()) -- end of file
assert(({io.read()})[2] == undef)
assert(not io.read('n')) -- end of file
assert(({io.read('n')})[2] == undef)
assert(io.read('a') == '') -- end of file (OK for 'a')
assert(io.read('a') == '') -- end of file (OK for 'a')
collectgarbage()
print('+')
io.close(io.input())
checkerr(" input file is closed", io.read)
assert(os.remove(file))
local t = '0123456789'
for i=1,10 do t = t..t; end
assert(string.len(t) == 10*2^10)
io.output(file)
io.write("alo"):write("\n")
io.close()
checkerr(" output file is closed", io.write)
local f = io.open(file, "a+b")
io.output(f)
collectgarbage()
assert(io.write(' ' .. t .. ' '))
assert(io.write(';', 'end of file\n'))
f:flush(); io.flush()
f:close()
print('+')
io.input(file)
assert(io.read() == "alo")
assert(io.read(1) == ' ')
assert(io.read(string.len(t)) == t)
assert(io.read(1) == ' ')
assert(io.read(0))
assert(io.read('a') == ';end of file\n')
assert(not io.read(0))
assert(io.close(io.input()))
-- test errors in read/write
do
local function ismsg (m)
-- error message is not a code number
return (type(m) == "string" and not tonumber(m))
end
-- read
local f = io.open(file, "w")
local r, m, c = f:read()
assert(not r and ismsg(m) and type(c) == "number")
assert(f:close())
-- write
f = io.open(file, "r")
r, m, c = f:write("whatever")
assert(not r and ismsg(m) and type(c) == "number")
assert(f:close())
-- lines
f = io.open(file, "w")
r, m = pcall(f:lines())
assert(r == false and ismsg(m))
assert(f:close())
end
assert(os.remove(file))
-- test for L format
io.output(file); io.write"\n\nline\nother":close()
io.input(file)
assert(io.read"L" == "\n")
assert(io.read"L" == "\n")
assert(io.read"L" == "line\n")
assert(io.read"L" == "other")
assert(not io.read"L")
io.input():close()
local f = assert(io.open(file))
local s = ""
for l in f:lines("L") do s = s .. l end
assert(s == "\n\nline\nother")
f:close()
io.input(file)
s = ""
for l in io.lines(nil, "L") do s = s .. l end
assert(s == "\n\nline\nother")
io.input():close()
s = ""
for l in io.lines(file, "L") do s = s .. l end
assert(s == "\n\nline\nother")
s = ""
for l in io.lines(file, "l") do s = s .. l end
assert(s == "lineother")
io.output(file); io.write"a = 10 + 34\na = 2*a\na = -a\n":close()
local t = {}
assert(load(io.lines(file, "L"), nil, nil, t))()
assert(t.a == -((10 + 34) * 2))
do -- testing closing file in line iteration
-- get the to-be-closed variable from a loop
local function gettoclose (lv)
lv = lv + 1
local stvar = 0 -- to-be-closed is 4th state variable in the loop
for i = 1, 1000 do
local n, v = debug.getlocal(lv, i)
if n == "(for state)" then
stvar = stvar + 1
if stvar == 4 then return v end
end
end
end
local f
for l in io.lines(file) do
f = gettoclose(1)
assert(io.type(f) == "file")
break
end
assert(io.type(f) == "closed file")
f = nil
local function foo (name)
for l in io.lines(name) do
f = gettoclose(1)
assert(io.type(f) == "file")
error(f) -- exit loop with an error
end
end
local st, msg = pcall(foo, file)
assert(st == false and io.type(msg) == "closed file")
end
-- test for multipe arguments in 'lines'
io.output(file); io.write"0123456789\n":close()
for a,b in io.lines(file, 1, 1) do
if a == "\n" then assert(not b)
else assert(tonumber(a) == tonumber(b) - 1)
end
end
for a,b,c in io.lines(file, 1, 2, "a") do
assert(a == "0" and b == "12" and c == "3456789\n")
end
for a,b,c in io.lines(file, "a", 0, 1) do
if a == "" then break end
assert(a == "0123456789\n" and not b and not c)
end
collectgarbage() -- to close file in previous iteration
io.output(file); io.write"00\n10\n20\n30\n40\n":close()
for a, b in io.lines(file, "n", "n") do
if a == 40 then assert(not b)
else assert(a == b - 10)
end
end
-- test load x lines
io.output(file);
io.write[[
local y
= X
X =
X *
2 +
X;
X =
X
- y;
]]:close()
_G.X = 1
assert(not load((io.lines(file))))
collectgarbage() -- to close file in previous iteration
load((io.lines(file, "L")))()
assert(_G.X == 2)
load((io.lines(file, 1)))()
assert(_G.X == 4)
load((io.lines(file, 3)))()
assert(_G.X == 8)
print('+')
local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
io.output(file)
assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
io.close()
assert(loadfile(file))()
assert(x1 == x2)
print('+')
assert(os.remove(file))
assert(not os.remove(file))
assert(not os.remove(otherfile))
-- testing loadfile
local function testloadfile (s, expres)
io.output(file)
if s then io.write(s) end
io.close()
local res = assert(loadfile(file))()
assert(os.remove(file))
assert(res == expres)
end
-- loading empty file
testloadfile(nil, nil)
-- loading file with initial comment without end of line
testloadfile("# a non-ending comment", nil)
-- checking Unicode BOM in files
testloadfile("\xEF\xBB\xBF# some comment\nreturn 234", 234)
testloadfile("\xEF\xBB\xBFreturn 239", 239)
testloadfile("\xEF\xBB\xBF", nil) -- empty file with a BOM
-- checking line numbers in files with initial comments
testloadfile("# a comment\nreturn require'debug'.getinfo(1).currentline", 2)
-- loading binary file
io.output(io.open(file, "wb"))
assert(io.write(string.dump(function () return 10, '\0alo\255', 'hi' end)))
io.close()
a, b, c = assert(loadfile(file))()
assert(a == 10 and b == "\0alo\255" and c == "hi")
assert(os.remove(file))
-- bug in 5.2.1
do
io.output(io.open(file, "wb"))
-- save function with no upvalues
assert(io.write(string.dump(function () return 1 end)))
io.close()
f = assert(loadfile(file, "b", {}))
assert(type(f) == "function" and f() == 1)
assert(os.remove(file))
end
-- loading binary file with initial comment
io.output(io.open(file, "wb"))
assert(io.write("#this is a comment for a binary file\0\n",
string.dump(function () return 20, '\0\0\0' end)))
io.close()
a, b, c = assert(loadfile(file))()
assert(a == 20 and b == "\0\0\0" and c == nil)
assert(os.remove(file))
-- 'loadfile' with 'env'
do
local f = io.open(file, 'w')
f:write[[
if (...) then a = 15; return b, c, d
else return _ENV
end
]]
f:close()
local t = {b = 12, c = "xuxu", d = print}
local f = assert(loadfile(file, 't', t))
local b, c, d = f(1)
assert(t.a == 15 and b == 12 and c == t.c and d == print)
assert(f() == t)
f = assert(loadfile(file, 't', nil))
assert(f() == nil)
f = assert(loadfile(file))
assert(f() == _G)
assert(os.remove(file))
end
-- 'loadfile' x modes
do
io.open(file, 'w'):write("return 10"):close()
local s, m = loadfile(file, 'b')
assert(not s and string.find(m, "a text chunk"))
io.open(file, 'w'):write("\27 return 10"):close()
local s, m = loadfile(file, 't')
assert(not s and string.find(m, "a binary chunk"))
assert(os.remove(file))
end
io.output(file)
assert(io.write("qualquer coisa\n"))
assert(io.write("mais qualquer coisa"))
io.close()
assert(io.output(assert(io.open(otherfile, 'wb')))
:write("outra coisa\0\1\3\0\0\0\0\255\0")
:close())
local filehandle = assert(io.open(file, 'r+'))
local otherfilehandle = assert(io.open(otherfile, 'rb'))
assert(filehandle ~= otherfilehandle)
assert(type(filehandle) == "userdata")
assert(filehandle:read('l') == "qualquer coisa")
io.input(otherfilehandle)
assert(io.read(string.len"outra coisa") == "outra coisa")
assert(filehandle:read('l') == "mais qualquer coisa")
filehandle:close();
assert(type(filehandle) == "userdata")
io.input(otherfilehandle)
assert(io.read(4) == "\0\1\3\0")
assert(io.read(3) == "\0\0\0")
assert(io.read(0) == "") -- 255 is not eof
assert(io.read(1) == "\255")
assert(io.read('a') == "\0")
assert(not io.read(0))
assert(otherfilehandle == io.input())
otherfilehandle:close()
assert(os.remove(file))
assert(os.remove(otherfile))
collectgarbage()
io.output(file)
:write[[
123.4 -56e-2 not a number
second line
third line
and the rest of the file
]]
:close()
io.input(file)
local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
assert(io.close(io.input()))
assert(_ == ' ' and not __)
assert(type(a) == 'number' and a==123.4 and b==-56e-2)
assert(d=='second line' and e=='third line')
assert(h==[[
and the rest of the file
]])
assert(os.remove(file))
collectgarbage()
-- testing buffers
do
local f = assert(io.open(file, "w"))
local fr = assert(io.open(file, "r"))
assert(f:setvbuf("full", 2000))
f:write("x")
assert(fr:read("all") == "") -- full buffer; output not written yet
f:close()
fr:seek("set")
assert(fr:read("all") == "x") -- `close' flushes it
f = assert(io.open(file), "w")
assert(f:setvbuf("no"))
f:write("x")
fr:seek("set")
assert(fr:read("all") == "x") -- no buffer; output is ready
f:close()
f = assert(io.open(file, "a"))
assert(f:setvbuf("line"))
f:write("x")
fr:seek("set", 1)
assert(fr:read("all") == "") -- line buffer; no output without `\n'
f:write("a\n"):seek("set", 1)
assert(fr:read("all") == "xa\n") -- now we have a whole line
f:close(); fr:close()
assert(os.remove(file))
end
if not _soft then
print("testing large files (> BUFSIZ)")
io.output(file)
for i=1,5001 do io.write('0123456789123') end
io.write('\n12346'):close()
io.input(file)
local x = io.read('a')
io.input():seek('set', 0)
local y = io.read(30001)..io.read(1005)..io.read(0)..
io.read(1)..io.read(100003)
assert(x == y and string.len(x) == 5001*13 + 6)
io.input():seek('set', 0)
y = io.read() -- huge line
assert(x == y..'\n'..io.read())
assert(not io.read())
io.close(io.input())
assert(os.remove(file))
x = nil; y = nil
end
if not _port then
local progname
do -- get name of running executable
local arg = arg or ARG
local i = 0
while arg[i] do i = i - 1 end
progname = '"' .. arg[i + 1] .. '"'
end
print("testing popen/pclose and execute")
local tests = {
-- command, what, code
{"ls > /dev/null", "ok"},
{"not-to-be-found-command", "exit"},
{"exit 3", "exit", 3},
{"exit 129", "exit", 129},
{"kill -s HUP $$", "signal", 1},
{"kill -s KILL $$", "signal", 9},
{"sh -c 'kill -s HUP $$'", "exit"},
{progname .. ' -e " "', "ok"},
{progname .. ' -e "os.exit(0, true)"', "ok"},
{progname .. ' -e "os.exit(20, true)"', "exit", 20},
}
print("\n(some error messages are expected now)")
for _, v in ipairs(tests) do
local x, y, z = io.popen(v[1]):close()
local x1, y1, z1 = os.execute(v[1])
assert(x == x1 and y == y1 and z == z1)
if v[2] == "ok" then
assert(x and y == 'exit' and z == 0)
else
assert(not x and y == v[2]) -- correct status and 'what'
-- correct code if known (but always different from 0)
assert((v[3] == nil and z > 0) or v[3] == z)
end
end
end
-- testing tmpfile
f = io.tmpfile()
assert(io.type(f) == "file")
f:write("alo")
f:seek("set")
assert(f:read"a" == "alo")
end --}
print'+'
print("testing date/time")
assert(os.date("") == "")
assert(os.date("!") == "")
assert(os.date("\0\0") == "\0\0")
assert(os.date("!\0\0") == "\0\0")
local x = string.rep("a", 10000)
assert(os.date(x) == x)
local t = os.time()
D = os.date("*t", t)
assert(os.date(string.rep("%d", 1000), t) ==
string.rep(os.date("%d", t), 1000))
assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
local function checkDateTable (t)
_G.D = os.date("*t", t)
assert(os.time(D) == t)
load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
D.hour==%H and D.min==%M and D.sec==%S and
D.wday==%w+1 and D.yday==%j)]], t))()
_G.D = nil
end
checkDateTable(os.time())
if not _port then
-- assume that time_t can represent these values
checkDateTable(0)
checkDateTable(1)
checkDateTable(1000)
checkDateTable(0x7fffffff)
checkDateTable(0x80000000)
end
checkerr("invalid conversion specifier", os.date, "%")
checkerr("invalid conversion specifier", os.date, "%9")
checkerr("invalid conversion specifier", os.date, "%")
checkerr("invalid conversion specifier", os.date, "%O")
checkerr("invalid conversion specifier", os.date, "%E")
checkerr("invalid conversion specifier", os.date, "%Ea")
checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour='x'})
checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour=1.5})
checkerr("missing", os.time, {hour = 12}) -- missing date
if string.packsize("i") == 4 then -- 4-byte ints
checkerr("field 'year' is out-of-bound", os.time,
{year = -(1 << 31) + 1899, month = 1, day = 1})
end
if not _port then
-- test Posix-specific modifiers
assert(type(os.date("%Ex")) == 'string')
assert(type(os.date("%Oy")) == 'string')
-- test large dates (assume at least 4-byte ints and time_t)
local t0 = os.time{year = 1970, month = 1, day = 0}
local t1 = os.time{year = 1970, month = 1, day = 0, sec = (1 << 31) - 1}
assert(t1 - t0 == (1 << 31) - 1)
t0 = os.time{year = 1970, month = 1, day = 1}
t1 = os.time{year = 1970, month = 1, day = 1, sec = -(1 << 31)}
assert(t1 - t0 == -(1 << 31))
-- test out-of-range dates (at least for Unix)
if maxint >= 2^62 then -- cannot do these tests in Small Lua
-- no arith overflows
checkerr("out-of-bound", os.time, {year = -maxint, month = 1, day = 1})
if string.packsize("i") == 4 then -- 4-byte ints
if testerr("out-of-bound", os.date, "%Y", 2^40) then
-- time_t has 4 bytes and therefore cannot represent year 4000
print(" 4-byte time_t")
checkerr("cannot be represented", os.time, {year=4000, month=1, day=1})
else
-- time_t has 8 bytes; an int year cannot represent a huge time
print(" 8-byte time_t")
checkerr("cannot be represented", os.date, "%Y", 2^60)
-- this is the maximum year
assert(tonumber(os.time
{year=(1 << 31) + 1899, month=12, day=31, hour=23, min=59, sec=59}))
-- this is too much
checkerr("represented", os.time,
{year=(1 << 31) + 1899, month=12, day=31, hour=23, min=59, sec=60})
end
-- internal 'int' fields cannot hold these values
checkerr("field 'day' is out-of-bound", os.time,
{year = 0, month = 1, day = 2^32})
checkerr("field 'month' is out-of-bound", os.time,
{year = 0, month = -((1 << 31) + 1), day = 1})
checkerr("field 'year' is out-of-bound", os.time,
{year = (1 << 31) + 1900, month = 1, day = 1})
else -- 8-byte ints
-- assume time_t has 8 bytes too
print(" 8-byte time_t")
assert(tonumber(os.date("%Y", 2^60)))
-- but still cannot represent a huge year
checkerr("cannot be represented", os.time, {year=2^60, month=1, day=1})
end
end
end
do
local D = os.date("*t")
local t = os.time(D)
if D.isdst == nil then
print("no daylight saving information")
else
assert(type(D.isdst) == 'boolean')
end
D.isdst = nil
local t1 = os.time(D)
assert(t == t1) -- if isdst is absent uses correct default
end
local D = os.date("*t")
t = os.time(D)
D.year = D.year-1;
local t1 = os.time(D)
-- allow for leap years
assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
-- should not take more than 1 second to execute these two lines
t = os.time()
t1 = os.time(os.date("*t"))
local diff = os.difftime(t1,t)
assert(0 <= diff and diff <= 1)
diff = os.difftime(t,t1)
assert(-1 <= diff and diff <= 0)
local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12}
local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
assert(os.difftime(t1,t2) == 60*2-19)
-- since 5.3.3, 'os.time' normalizes table fields
t1 = {year = 2005, month = 1, day = 1, hour = 1, min = 0, sec = -3602}
os.time(t1)
assert(t1.day == 31 and t1.month == 12 and t1.year == 2004 and
t1.hour == 23 and t1.min == 59 and t1.sec == 58 and
t1.yday == 366)
io.output(io.stdout)
local t = os.date('%d %m %Y %H %M %S')
local d, m, a, h, min, s = string.match(t,
"(%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")
d = tonumber(d)
m = tonumber(m)
a = tonumber(a)
h = tonumber(h)
min = tonumber(min)
s = tonumber(s)
io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
io.write(string.format('%s\n', _VERSION))
+681
View File
@@ -0,0 +1,681 @@
-- $Id: testes/gc.lua $
-- See Copyright Notice in file all.lua
print('testing incremental garbage collection')
local debug = require"debug"
assert(collectgarbage("isrunning"))
collectgarbage()
local oldmode = collectgarbage("incremental")
-- changing modes should return previous mode
assert(collectgarbage("generational") == "incremental")
assert(collectgarbage("generational") == "generational")
assert(collectgarbage("incremental") == "generational")
assert(collectgarbage("incremental") == "incremental")
local function nop () end
local function gcinfo ()
return collectgarbage"count" * 1024
end
-- test weird parameters to 'collectgarbage'
do
-- save original parameters
local a = collectgarbage("setpause", 200)
local b = collectgarbage("setstepmul", 200)
local t = {0, 2, 10, 90, 500, 5000, 30000, 0x7ffffffe}
for i = 1, #t do
local p = t[i]
for j = 1, #t do
local m = t[j]
collectgarbage("setpause", p)
collectgarbage("setstepmul", m)
collectgarbage("step", 0)
collectgarbage("step", 10000)
end
end
-- restore original parameters
collectgarbage("setpause", a)
collectgarbage("setstepmul", b)
collectgarbage()
end
_G["while"] = 234
--
-- tests for GC activation when creating different kinds of objects
--
local function GC1 ()
local u
local b -- (above 'u' it in the stack)
local finish = false
u = setmetatable({}, {__gc = function () finish = true end})
b = {34}
repeat u = {} until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
finish = false; local i = 1
u = setmetatable({}, {__gc = function () finish = true end})
repeat i = i + 1; u = tostring(i) .. tostring(i) until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
finish = false
u = setmetatable({}, {__gc = function () finish = true end})
repeat local i; u = function () return i end until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
end
local function GC2 ()
local u
local finish = false
u = {setmetatable({}, {__gc = function () finish = true end})}
local b = {34}
repeat u = {{}} until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
finish = false; local i = 1
u = {setmetatable({}, {__gc = function () finish = true end})}
repeat i = i + 1; u = {tostring(i) .. tostring(i)} until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
finish = false
u = {setmetatable({}, {__gc = function () finish = true end})}
repeat local i; u = {function () return i end} until finish
assert(b[1] == 34) -- 'u' was collected, but 'b' was not
end
local function GC() GC1(); GC2() end
do
print("creating many objects")
local limit = 5000
for i = 1, limit do
local a = {}; a = nil
end
local a = "a"
for i = 1, limit do
a = i .. "b";
a = string.gsub(a, '(%d%d*)', "%1 %1")
a = "a"
end
a = {}
function a:test ()
for i = 1, limit do
load(string.format("function temp(a) return 'a%d' end", i), "")()
assert(temp() == string.format('a%d', i))
end
end
a:test()
end
-- collection of functions without locals, globals, etc.
do local f = function () end end
print("functions with errors")
prog = [[
do
a = 10;
function foo(x,y)
a = sin(a+0.456-0.23e-12);
return function (z) return sin(%x+z) end
end
local x = function (w) a=a+w; end
end
]]
do
local step = 1
if _soft then step = 13 end
for i=1, string.len(prog), step do
for j=i, string.len(prog), step do
pcall(load(string.sub(prog, i, j), ""))
end
end
end
foo = nil
print('long strings')
x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
assert(string.len(x)==80)
s = ''
k = math.min(300, (math.maxinteger // 80) // 2)
for n = 1, k do s = s..x; j=tostring(n) end
assert(string.len(s) == k*80)
s = string.sub(s, 1, 10000)
s, i = string.gsub(s, '(%d%d%d%d)', '')
assert(i==10000 // 4)
s = nil
x = nil
assert(_G["while"] == 234)
--
-- test the "size" of basic GC steps (whatever they mean...)
--
do
print("steps")
print("steps (2)")
local function dosteps (siz)
collectgarbage()
local a = {}
for i=1,100 do a[i] = {{}}; local b = {} end
local x = gcinfo()
local i = 0
repeat -- do steps until it completes a collection cycle
i = i+1
until collectgarbage("step", siz)
assert(gcinfo() < x)
return i -- number of steps
end
collectgarbage"stop"
if not _port then
assert(dosteps(10) < dosteps(2))
end
-- collector should do a full collection with so many steps
assert(dosteps(20000) == 1)
assert(collectgarbage("step", 20000) == true)
assert(collectgarbage("step", 20000) == true)
assert(not collectgarbage("isrunning"))
collectgarbage"restart"
assert(collectgarbage("isrunning"))
end
if not _port then
-- test the pace of the collector
collectgarbage(); collectgarbage()
local x = gcinfo()
collectgarbage"stop"
repeat
local a = {}
until gcinfo() > 3 * x
collectgarbage"restart"
assert(collectgarbage("isrunning"))
repeat
local a = {}
until gcinfo() <= x * 2
end
print("clearing tables")
lim = 15
a = {}
-- fill a with `collectable' indices
for i=1,lim do a[{}] = i end
b = {}
for k,v in pairs(a) do b[k]=v end
-- remove all indices and collect them
for n in pairs(b) do
a[n] = undef
assert(type(n) == 'table' and next(n) == nil)
collectgarbage()
end
b = nil
collectgarbage()
for n in pairs(a) do error'cannot be here' end
for i=1,lim do a[i] = i end
for i=1,lim do assert(a[i] == i) end
print('weak tables')
a = {}; setmetatable(a, {__mode = 'k'});
-- fill a with some `collectable' indices
for i=1,lim do a[{}] = i end
-- and some non-collectable ones
for i=1,lim do a[i] = i end
for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end
collectgarbage()
local i = 0
for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end
assert(i == 2*lim)
a = {}; setmetatable(a, {__mode = 'v'});
a[1] = string.rep('b', 21)
collectgarbage()
assert(a[1]) -- strings are *values*
a[1] = undef
-- fill a with some `collectable' values (in both parts of the table)
for i=1,lim do a[i] = {} end
for i=1,lim do a[i..'x'] = {} end
-- and some non-collectable ones
for i=1,lim do local t={}; a[t]=t end
for i=1,lim do a[i+lim]=i..'x' end
collectgarbage()
local i = 0
for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end
assert(i == 2*lim)
a = {}; setmetatable(a, {__mode = 'kv'});
local x, y, z = {}, {}, {}
-- keep only some items
a[1], a[2], a[3] = x, y, z
a[string.rep('$', 11)] = string.rep('$', 11)
-- fill a with some `collectable' values
for i=4,lim do a[i] = {} end
for i=1,lim do a[{}] = i end
for i=1,lim do local t={}; a[t]=t end
collectgarbage()
assert(next(a) ~= nil)
local i = 0
for k,v in pairs(a) do
assert((k == 1 and v == x) or
(k == 2 and v == y) or
(k == 3 and v == z) or k==v);
i = i+1
end
assert(i == 4)
x,y,z=nil
collectgarbage()
assert(next(a) == string.rep('$', 11))
-- 'bug' in 5.1
a = {}
local t = {x = 10}
local C = setmetatable({key = t}, {__mode = 'v'})
local C1 = setmetatable({[t] = 1}, {__mode = 'k'})
a.x = t -- this should not prevent 't' from being removed from
-- weak table 'C' by the time 'a' is finalized
setmetatable(a, {__gc = function (u)
assert(C.key == nil)
assert(type(next(C1)) == 'table')
end})
a, t = nil
collectgarbage()
collectgarbage()
assert(next(C) == nil and next(C1) == nil)
C, C1 = nil
-- ephemerons
local mt = {__mode = 'k'}
a = {{10},{20},{30},{40}}; setmetatable(a, mt)
x = nil
for i = 1, 100 do local n = {}; a[n] = {k = {x}}; x = n end
GC()
local n = x
local i = 0
while n do n = a[n].k[1]; i = i + 1 end
assert(i == 100)
x = nil
GC()
for i = 1, 4 do assert(a[i][1] == i * 10); a[i] = undef end
assert(next(a) == nil)
local K = {}
a[K] = {}
for i=1,10 do a[K][i] = {}; a[a[K][i]] = setmetatable({}, mt) end
x = nil
local k = 1
for j = 1,100 do
local n = {}; local nk = k%10 + 1
a[a[K][nk]][n] = {x, k = k}; x = n; k = nk
end
GC()
local n = x
local i = 0
while n do local t = a[a[K][k]][n]; n = t[1]; k = t.k; i = i + 1 end
assert(i == 100)
K = nil
GC()
-- assert(next(a) == nil)
-- testing errors during GC
if T then
collectgarbage("stop") -- stop collection
local u = {}
local s = {}; setmetatable(s, {__mode = 'k'})
setmetatable(u, {__gc = function (o)
local i = s[o]
s[i] = true
assert(not s[i - 1]) -- check proper finalization order
if i == 8 then error("@expected@") end -- error during GC
end})
for i = 6, 10 do
local n = setmetatable({}, getmetatable(u))
s[n] = i
end
warn("@on"); warn("@store")
collectgarbage()
assert(string.find(_WARN, "error in __gc metamethod"))
assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = nil
for i = 8, 10 do assert(s[i]) end
for i = 1, 5 do
local n = setmetatable({}, getmetatable(u))
s[n] = i
end
collectgarbage()
for i = 1, 10 do assert(s[i]) end
getmetatable(u).__gc = nil
warn("@normal")
end
print '+'
-- testing userdata
if T==nil then
(Message or print)('\n >>> testC not active: skipping userdata GC tests <<<\n')
else
local function newproxy(u)
return debug.setmetatable(T.newuserdata(0), debug.getmetatable(u))
end
collectgarbage("stop") -- stop collection
local u = newproxy(nil)
debug.setmetatable(u, {__gc = true})
local s = 0
local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'})
for i=1,10 do a[newproxy(u)] = i end
for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end
local a1 = {}; for k,v in pairs(a) do a1[k] = v end
for k,v in pairs(a1) do a[v] = k end
for i =1,10 do assert(a[i]) end
getmetatable(u).a = a1
getmetatable(u).u = u
do
local u = u
getmetatable(u).__gc = function (o)
assert(a[o] == 10-s)
assert(a[10-s] == undef) -- udata already removed from weak table
assert(getmetatable(o) == getmetatable(u))
assert(getmetatable(o).a[o] == 10-s)
s=s+1
end
end
a1, u = nil
assert(next(a) ~= nil)
collectgarbage()
assert(s==11)
collectgarbage()
assert(next(a) == nil) -- finalized keys are removed in two cycles
end
-- __gc x weak tables
local u = setmetatable({}, {__gc = true})
-- __gc metamethod should be collected before running
setmetatable(getmetatable(u), {__mode = "v"})
getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen
u = nil
collectgarbage()
local u = setmetatable({}, {__gc = true})
local m = getmetatable(u)
m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"});
m.__gc = function (o)
assert(next(getmetatable(o).x) == nil)
m = 10
end
u, m = nil
collectgarbage()
assert(m==10)
do -- tests for string keys in weak tables
collectgarbage(); collectgarbage()
local m = collectgarbage("count") -- current memory
local a = setmetatable({}, {__mode = "kv"})
a[string.rep("a", 2^22)] = 25 -- long string key -> number value
a[string.rep("b", 2^22)] = {} -- long string key -> colectable value
a[{}] = 14 -- colectable key
assert(collectgarbage("count") > m + 2^13) -- 2^13 == 2 * 2^22 in KB
collectgarbage()
assert(collectgarbage("count") >= m + 2^12 and
collectgarbage("count") < m + 2^13) -- one key was collected
local k, v = next(a) -- string key with number value preserved
assert(k == string.rep("a", 2^22) and v == 25)
assert(next(a, k) == nil) -- everything else cleared
assert(a[string.rep("b", 2^22)] == undef)
a[k] = undef -- erase this last entry
k = nil
collectgarbage()
assert(next(a) == nil)
-- make sure will not try to compare with dead key
assert(a[string.rep("b", 100)] == undef)
assert(collectgarbage("count") <= m + 1) -- eveything collected
end
-- errors during collection
if T then
warn("@store")
u = setmetatable({}, {__gc = function () error "@expected error" end})
u = nil
collectgarbage()
assert(string.find(_WARN, "@expected error")); _WARN = nil
warn("@normal")
end
if not _soft then
print("long list")
local a = {}
for i = 1,200000 do
a = {next = a}
end
a = nil
collectgarbage()
end
-- create many threads with self-references and open upvalues
print("self-referenced threads")
local thread_id = 0
local threads = {}
local function fn (thread)
local x = {}
threads[thread_id] = function()
thread = x
end
coroutine.yield()
end
while thread_id < 1000 do
local thread = coroutine.create(fn)
coroutine.resume(thread, thread)
thread_id = thread_id + 1
end
-- Create a closure (function inside 'f') with an upvalue ('param') that
-- points (through a table) to the closure itself and to the thread
-- ('co' and the initial value of 'param') where closure is running.
-- Then, assert that table (and therefore everything else) will be
-- collected.
do
local collected = false -- to detect collection
collectgarbage(); collectgarbage("stop")
do
local function f (param)
;(function ()
assert(type(f) == 'function' and type(param) == 'thread')
param = {param, f}
setmetatable(param, {__gc = function () collected = true end})
coroutine.yield(100)
end)()
end
local co = coroutine.create(f)
assert(coroutine.resume(co, co))
end
-- Now, thread and closure are not reacheable any more.
collectgarbage()
assert(collected)
collectgarbage("restart")
end
do
collectgarbage()
collectgarbage"stop"
collectgarbage("step", 0) -- steps should not unblock the collector
local x = gcinfo()
repeat
for i=1,1000 do _ENV.a = {} end -- no collection during the loop
until gcinfo() > 2 * x
collectgarbage"restart"
end
if T then -- tests for weird cases collecting upvalues
local function foo ()
local a = {x = 20}
coroutine.yield(function () return a.x end) -- will run collector
assert(a.x == 20) -- 'a' is 'ok'
a = {x = 30} -- create a new object
assert(T.gccolor(a) == "white") -- of course it is new...
coroutine.yield(100) -- 'a' is still local to this thread
end
local t = setmetatable({}, {__mode = "kv"})
collectgarbage(); collectgarbage('stop')
-- create coroutine in a weak table, so it will never be marked
t.co = coroutine.wrap(foo)
local f = t.co() -- create function to access local 'a'
T.gcstate("atomic") -- ensure all objects are traversed
assert(T.gcstate() == "atomic")
assert(t.co() == 100) -- resume coroutine, creating new table for 'a'
assert(T.gccolor(t.co) == "white") -- thread was not traversed
T.gcstate("pause") -- collect thread, but should mark 'a' before that
assert(t.co == nil and f() == 30) -- ensure correct access to 'a'
collectgarbage("restart")
-- test barrier in sweep phase (backing userdata to gray)
local u = T.newuserdata(0, 1) -- create a userdata
collectgarbage()
collectgarbage"stop"
local a = {} -- avoid 'u' as first element in 'allgc'
T.gcstate"atomic"
T.gcstate"sweepallgc"
local x = {}
assert(T.gccolor(u) == "black") -- userdata is "old" (black)
assert(T.gccolor(x) == "white") -- table is "new" (white)
debug.setuservalue(u, x) -- trigger barrier
assert(T.gccolor(u) == "gray") -- userdata changed back to gray
collectgarbage"restart"
print"+"
end
if T then
local debug = require "debug"
collectgarbage("stop")
local x = T.newuserdata(0)
local y = T.newuserdata(0)
debug.setmetatable(y, {__gc = nop}) -- bless the new udata before...
debug.setmetatable(x, {__gc = nop}) -- ...the old one
assert(T.gccolor(y) == "white")
T.checkmemory()
collectgarbage("restart")
end
if T then
print("emergency collections")
collectgarbage()
collectgarbage()
T.totalmem(T.totalmem() + 200)
for i=1,200 do local a = {} end
T.totalmem(0)
collectgarbage()
local t = T.totalmem("table")
local a = {{}, {}, {}} -- create 4 new tables
assert(T.totalmem("table") == t + 4)
t = T.totalmem("function")
a = function () end -- create 1 new closure
assert(T.totalmem("function") == t + 1)
t = T.totalmem("thread")
a = coroutine.create(function () end) -- create 1 new coroutine
assert(T.totalmem("thread") == t + 1)
end
-- create an object to be collected when state is closed
do
local setmetatable,assert,type,print,getmetatable =
setmetatable,assert,type,print,getmetatable
local tt = {}
tt.__gc = function (o)
assert(getmetatable(o) == tt)
-- create new objects during GC
local a = 'xuxu'..(10+3)..'joao', {}
___Glob = o -- ressurrect object!
setmetatable({}, tt) -- creates a new one with same metatable
print(">>> closing state " .. "<<<\n")
end
local u = setmetatable({}, tt)
___Glob = {u} -- avoid object being collected before program end
end
-- create several objects to raise errors when collected while closing state
if T then
local error, assert, find, warn = error, assert, string.find, warn
local n = 0
local lastmsg
local mt = {__gc = function (o)
n = n + 1
assert(n == o[1])
if n == 1 then
_WARN = nil
elseif n == 2 then
assert(find(_WARN, "@expected warning"))
lastmsg = _WARN -- get message from previous error (first 'o')
else
assert(lastmsg == _WARN) -- subsequent error messages are equal
end
warn("@store"); _WARN = nil
error"@expected warning"
end}
for i = 10, 1, -1 do
-- create object and preserve it until the end
table.insert(___Glob, setmetatable({i}, mt))
end
end
-- just to make sure
assert(collectgarbage'isrunning')
collectgarbage(oldmode)
print('OK')
+83
View File
@@ -0,0 +1,83 @@
-- $Id: testes/gengc.lua $
-- See Copyright Notice in file all.lua
print('testing generational garbage collection')
local debug = require"debug"
assert(collectgarbage("isrunning"))
collectgarbage()
local oldmode = collectgarbage("generational")
-- ensure that table barrier evolves correctly
do
local U = {}
-- full collection makes 'U' old
collectgarbage()
assert(not T or T.gcage(U) == "old")
-- U refers to a new table, so it becomes 'touched1'
U[1] = {x = {234}}
assert(not T or (T.gcage(U) == "touched1" and T.gcage(U[1]) == "new"))
-- both U and the table survive one more collection
collectgarbage("step", 0)
assert(not T or (T.gcage(U) == "touched2" and T.gcage(U[1]) == "survival"))
-- both U and the table survive yet another collection
-- now everything is old
collectgarbage("step", 0)
assert(not T or (T.gcage(U) == "old" and T.gcage(U[1]) == "old1"))
-- data was not corrupted
assert(U[1].x[1] == 234)
end
if T == nil then
(Message or print)('\n >>> testC not active: \z
skipping some generational tests <<<\n')
print 'OK'
return
end
-- ensure that userdata barrier evolves correctly
do
local U = T.newuserdata(0, 1)
-- full collection makes 'U' old
collectgarbage()
assert(T.gcage(U) == "old")
-- U refers to a new table, so it becomes 'touched1'
debug.setuservalue(U, {x = {234}})
assert(T.gcage(U) == "touched1" and
T.gcage(debug.getuservalue(U)) == "new")
-- both U and the table survive one more collection
collectgarbage("step", 0)
assert(T.gcage(U) == "touched2" and
T.gcage(debug.getuservalue(U)) == "survival")
-- both U and the table survive yet another collection
-- now everything is old
collectgarbage("step", 0)
assert(T.gcage(U) == "old" and
T.gcage(debug.getuservalue(U)) == "old1")
-- data was not corrupted
assert(debug.getuservalue(U).x[1] == 234)
end
-- just to make sure
assert(collectgarbage'isrunning')
collectgarbage(oldmode)
print('OK')
+271
View File
@@ -0,0 +1,271 @@
-- $Id: testes/goto.lua $
-- See Copyright Notice in file all.lua
collectgarbage()
local function errmsg (code, m)
local st, msg = load(code)
assert(not st and string.find(msg, m))
end
-- cannot see label inside block
errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
-- repeated label
errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'")
-- undefined label
errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
-- jumping over variable definition
errmsg([[
do local bb, cc; goto l1; end
local aa
::l1:: print(3)
]], "local 'aa'")
-- jumping into a block
errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
-- cannot continue a repeat-until with variables
errmsg([[
repeat
if x then goto cont end
local xuxu = 10
::cont::
until xuxu < x
]], "local 'xuxu'")
-- simple gotos
local x
do
local y = 12
goto l1
::l2:: x = x + 1; goto l3
::l1:: x = y; goto l2
end
::l3:: ::l3_1:: assert(x == 13)
-- long labels
do
local prog = [[
do
local a = 1
goto l%sa; a = a + 1
::l%sa:: a = a + 10
goto l%sb; a = a + 2
::l%sb:: a = a + 20
return a
end
]]
local label = string.rep("0123456789", 40)
prog = string.format(prog, label, label, label, label)
assert(assert(load(prog))() == 31)
end
-- ok to jump over local dec. to end of block
do
goto l1
local a = 23
x = a
::l1::;
end
while true do
goto l4
goto l1 -- ok to jump over local dec. to end of block
goto l1 -- multiple uses of same label
local x = 45
::l1:: ;;;
end
::l4:: assert(x == 13)
if print then
goto l1 -- ok to jump over local dec. to end of block
error("should not be here")
goto l2 -- ok to jump over local dec. to end of block
local x
::l1:: ; ::l2:: ;;
else end
-- to repeat a label in a different function is OK
local function foo ()
local a = {}
goto l3
::l1:: a[#a + 1] = 1; goto l2;
::l2:: a[#a + 1] = 2; goto l5;
::l3::
::l3a:: a[#a + 1] = 3; goto l1;
::l4:: a[#a + 1] = 4; goto l6;
::l5:: a[#a + 1] = 5; goto l4;
::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
a[4] == 5 and a[5] == 4)
if not a[6] then a[6] = true; goto l3a end -- do it twice
end
::l6:: foo()
do -- bug in 5.2 -> 5.3.2
local x
::L1::
local y -- cannot join this SETNIL with previous one
assert(y == nil)
y = true
if x == nil then
x = 1
goto L1
else
x = x + 1
end
assert(x == 2 and y == true)
end
-- bug in 5.3
do
local first = true
local a = false
if true then
goto LBL
::loop::
a = true
::LBL::
if first then
first = false
goto loop
end
end
assert(a)
end
do -- compiling infinite loops
goto escape -- do not run the infinite loops
::a:: goto a
::b:: goto c
::c:: goto b
end
::escape::
--------------------------------------------------------------------------------
-- testing closing of upvalues
local debug = require 'debug'
local function foo ()
local t = {}
do
local i = 1
local a, b, c, d
t[1] = function () return a, b, c, d end
::l1::
local b
do
local c
t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
if i > 2 then goto l2 end
do
local d
t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
i = i + 1
local a
goto l1
end
end
end
::l2:: return t
end
local a = foo()
assert(#a == 6)
-- all functions share same 'a'
for i = 2, 6 do
assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
end
-- 'b' and 'c' are shared among some of them
for i = 2, 6 do
-- only a[1] uses external 'b'/'b'
assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
end
for i = 3, 5, 2 do
-- inner functions share 'b'/'c' with previous ones
assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
-- but not with next ones
assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
end
-- only external 'd' is shared
for i = 2, 6, 2 do
assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
end
-- internal 'd's are all different
for i = 3, 5, 2 do
for j = 1, 6 do
assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
== (i == j))
end
end
--------------------------------------------------------------------------------
-- testing if x goto optimizations
local function testG (a)
if a == 1 then
goto l1
error("should never be here!")
elseif a == 2 then goto l2
elseif a == 3 then goto l3
elseif a == 4 then
goto l1 -- go to inside the block
error("should never be here!")
::l1:: a = a + 1 -- must go to 'if' end
else
goto l4
::l4a:: a = a * 2; goto l4b
error("should never be here!")
::l4:: goto l4a
error("should never be here!")
::l4b::
end
do return a end
::l2:: do return "2" end
::l3:: do return "3" end
::l1:: return "1"
end
assert(testG(1) == "1")
assert(testG(2) == "2")
assert(testG(3) == "3")
assert(testG(4) == 5)
assert(testG(5) == 10)
do
-- if x back goto out of scope of upvalue
local X
goto L1
::L2:: goto L3
::L1:: do
local a <close> = setmetatable({}, {__close = function () X = true end})
assert(X == nil)
if a then goto L2 end -- jumping back out of scope of 'a'
end
::L3:: assert(X == true) -- checks that 'a' was correctly closed
end
--------------------------------------------------------------------------------
print'OK'
+173
View File
@@ -0,0 +1,173 @@
-- $Id: heavy.lua,v 1.7 2017/12/29 15:42:15 roberto Exp $
-- See Copyright Notice in file all.lua
local function teststring ()
print("creating a string too long")
do
local a = "x"
local st, msg = pcall(function ()
while true do
a = a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
.. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
print(string.format("string with %d bytes", #a))
end
end)
assert(not st and
(string.find(msg, "string length overflow") or
string.find(msg, "not enough memory")))
print("string length overflow with " .. #a * 100)
end
print('+')
end
local function loadrep (x, what)
local p = 1<<20
local s = string.rep(x, p)
local count = 0
local function f()
count = count + p
if count % (0x80*p) == 0 then
io.stderr:write("(", count // 2^20, " M)")
end
return s
end
local st, msg = load(f, "=big")
print("\nmemory: ", collectgarbage'count' * 1024)
msg = string.match(msg, "^[^\n]+") -- get only first line
print(string.format("total: 0x%x %s ('%s')", count, what, msg))
return st, msg
end
function controlstruct ()
print("control structure too long")
local lim = ((1 << 24) - 2) // 3
local s = string.rep("a = a + 1\n", lim)
s = "while true do " .. s .. "end"
assert(load(s))
print("ok with " .. lim .. " lines")
lim = lim + 3
s = string.rep("a = a + 1\n", lim)
s = "while true do " .. s .. "end"
local st, msg = load(s)
assert(not st and string.find(msg, "too long"))
print(msg)
end
function manylines ()
print("loading chunk with too many lines")
local st, msg = loadrep("\n", "lines")
assert(not st and string.find(msg, "too many lines"))
print('+')
end
function hugeid ()
print("loading chunk with huge identifier")
local st, msg = loadrep("a", "chars")
assert(not st and
(string.find(msg, "lexical element too long") or
string.find(msg, "not enough memory")))
print('+')
end
function toomanyinst ()
print("loading chunk with too many instructions")
local st, msg = loadrep("a = 10; ", "instructions")
print('+')
end
local function loadrepfunc (prefix, f)
local count = -1
local function aux ()
count = count + 1
if count == 0 then
return prefix
else
if count % (0x100000) == 0 then
io.stderr:write("(", count // 2^20, " M)")
end
return f(count)
end
end
local st, msg = load(aux, "k")
print("\nmemory: ", collectgarbage'count' * 1024)
msg = string.match(msg, "^[^\n]+") -- get only first line
print("expected error: ", msg)
end
function toomanyconst ()
print("loading function with too many constants")
loadrepfunc("function foo () return {0,",
function (n)
-- convert 'n' to a string in the format [["...",]],
-- where '...' is a kind of number in base 128
-- (in a range that does not include either the double quote
-- and the escape.)
return string.char(34,
((n // 128^0) & 127) + 128,
((n // 128^1) & 127) + 128,
((n // 128^2) & 127) + 128,
((n // 128^3) & 127) + 128,
((n // 128^4) & 127) + 128,
34, 44)
end)
end
function toomanystr ()
local a = {}
local st, msg = pcall(function ()
for i = 1, math.huge do
if i % (0x100000) == 0 then
io.stderr:write("(", i // 2^20, " M)")
end
a[i] = string.pack("I", i)
end
end)
local size = #a
a = collectgarbage'count'
print("\nmemory:", a * 1024)
print("expected error:", msg)
print("size:", size)
end
function toomanyidx ()
local a = {}
local st, msg = pcall(function ()
for i = 1, math.huge do
if i % (0x100000) == 0 then
io.stderr:write("(", i // 2^20, " M)")
end
a[i] = i
end
end)
print("\nmemory: ", collectgarbage'count' * 1024)
print("expected error: ", msg)
print("size:", #a)
end
-- teststring()
-- controlstruct()
-- manylines()
-- hugeid()
-- toomanyinst()
-- toomanyconst()
-- toomanystr()
toomanyidx()
print "OK"
+2
View File
@@ -0,0 +1,2 @@
# This is a dummy file just to make git keep the otherwise empty
# directory 'P1' in the repository.
+44
View File
@@ -0,0 +1,44 @@
#include "lua.h"
#include "lauxlib.h"
static int id (lua_State *L) {
return lua_gettop(L);
}
static const struct luaL_Reg funcs[] = {
{"id", id},
{NULL, NULL}
};
/* function used by lib11.c */
LUAMOD_API int lib1_export (lua_State *L) {
lua_pushstring(L, "exported");
return 1;
}
LUAMOD_API int onefunction (lua_State *L) {
luaL_checkversion(L);
lua_settop(L, 2);
lua_pushvalue(L, 1);
return 2;
}
LUAMOD_API int anotherfunc (lua_State *L) {
luaL_checkversion(L);
lua_pushfstring(L, "%d%%%d\n", (int)lua_tointeger(L, 1),
(int)lua_tointeger(L, 2));
return 1;
}
LUAMOD_API int luaopen_lib1_sub (lua_State *L) {
lua_setglobal(L, "y"); /* 2nd arg: extra value (file name) */
lua_setglobal(L, "x"); /* 1st arg: module name */
luaL_newlib(L, funcs);
return 1;
}
+10
View File
@@ -0,0 +1,10 @@
#include "lua.h"
/* function from lib1.c */
int lib1_export (lua_State *L);
LUAMOD_API int luaopen_lib11 (lua_State *L) {
return lib1_export(L);
}
+23
View File
@@ -0,0 +1,23 @@
#include "lua.h"
#include "lauxlib.h"
static int id (lua_State *L) {
return lua_gettop(L);
}
static const struct luaL_Reg funcs[] = {
{"id", id},
{NULL, NULL}
};
LUAMOD_API int luaopen_lib2 (lua_State *L) {
lua_settop(L, 2);
lua_setglobal(L, "y"); /* y gets 2nd parameter */
lua_setglobal(L, "x"); /* x gets 1st parameter */
luaL_newlib(L, funcs);
return 1;
}
+10
View File
@@ -0,0 +1,10 @@
#include "lua.h"
int luaopen_lib2 (lua_State *L);
LUAMOD_API int luaopen_lib21 (lua_State *L) {
return luaopen_lib2(L);
}
+25
View File
@@ -0,0 +1,25 @@
#include "lua.h"
#include "lauxlib.h"
static int id (lua_State *L) {
lua_pushboolean(L, 1);
lua_insert(L, 1);
return lua_gettop(L);
}
static const struct luaL_Reg funcs[] = {
{"id", id},
{NULL, NULL}
};
LUAMOD_API int luaopen_lib2 (lua_State *L) {
lua_settop(L, 2);
lua_setglobal(L, "y"); /* y gets 2nd parameter */
lua_setglobal(L, "x"); /* x gets 1st parameter */
luaL_newlib(L, funcs);
return 1;
}
+27
View File
@@ -0,0 +1,27 @@
# change this variable to point to the directory with Lua headers
# of the version being tested
LUA_DIR = ../../
CC = gcc
# compilation should generate Dynamic-Link Libraries
CFLAGS = -Wall -std=gnu99 -O2 -I$(LUA_DIR) -fPIC -shared
# libraries used by the tests
all: lib1.so lib11.so lib2.so lib21.so lib2-v2.so
touch all
lib1.so: lib1.c $(LUA_DIR)/luaconf.h
$(CC) $(CFLAGS) -o lib1.so lib1.c
lib11.so: lib11.c $(LUA_DIR)/luaconf.h
$(CC) $(CFLAGS) -o lib11.so lib11.c
lib2.so: lib2.c $(LUA_DIR)/luaconf.h
$(CC) $(CFLAGS) -o lib2.so lib2.c
lib21.so: lib21.c $(LUA_DIR)/luaconf.h
$(CC) $(CFLAGS) -o lib21.so lib21.c
lib2-v2.so: lib21.c $(LUA_DIR)/luaconf.h
$(CC) $(CFLAGS) -o lib2-v2.so lib22.c
+318
View File
@@ -0,0 +1,318 @@
-- $Id: testes/literals.lua $
-- See Copyright Notice in file all.lua
print('testing scanner')
local debug = require "debug"
local function dostring (x) return assert(load(x), "")() end
dostring("x \v\f = \t\r 'a\0a' \v\f\f")
assert(x == 'a\0a' and string.len(x) == 3)
-- escape sequences
assert('\n\"\'\\' == [[
"'\]])
assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$"))
-- assume ASCII just for tests:
assert("\09912" == 'c12')
assert("\99ab" == 'cab')
assert("\099" == '\99')
assert("\099\n" == 'c\10')
assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo')
assert(010 .. 020 .. -030 == "1020-30")
-- hexadecimal escapes
assert("\x00\x05\x10\x1f\x3C\xfF\xe8" == "\0\5\16\31\60\255\232")
local function lexstring (x, y, n)
local f = assert(load('return ' .. x ..
', require"debug".getinfo(1).currentline', ''))
local s, l = f()
assert(s == y and l == n)
end
lexstring("'abc\\z \n efg'", "abcefg", 2)
lexstring("'abc\\z \n\n\n'", "abc", 4)
lexstring("'\\z \n\t\f\v\n'", "", 3)
lexstring("[[\nalo\nalo\n\n]]", "alo\nalo\n\n", 5)
lexstring("[[\nalo\ralo\n\n]]", "alo\nalo\n\n", 5)
lexstring("[[\nalo\ralo\r\n]]", "alo\nalo\n", 4)
lexstring("[[\ralo\n\ralo\r\n]]", "alo\nalo\n", 4)
lexstring("[[alo]\n]alo]]", "alo]\n]alo", 2)
assert("abc\z
def\z
ghi\z
" == 'abcdefghi')
-- UTF-8 sequences
assert("\u{0}\u{00000000}\x00\0" == string.char(0, 0, 0, 0))
-- limits for 1-byte sequences
assert("\u{0}\u{7F}" == "\x00\x7F")
-- limits for 2-byte sequences
assert("\u{80}\u{7FF}" == "\xC2\x80\xDF\xBF")
-- limits for 3-byte sequences
assert("\u{800}\u{FFFF}" == "\xE0\xA0\x80\xEF\xBF\xBF")
-- limits for 4-byte sequences
assert("\u{10000}\u{1FFFFF}" == "\xF0\x90\x80\x80\xF7\xBF\xBF\xBF")
-- limits for 5-byte sequences
assert("\u{200000}\u{3FFFFFF}" == "\xF8\x88\x80\x80\x80\xFB\xBF\xBF\xBF\xBF")
-- limits for 6-byte sequences
assert("\u{4000000}\u{7FFFFFFF}" ==
"\xFC\x84\x80\x80\x80\x80\xFD\xBF\xBF\xBF\xBF\xBF")
-- Error in escape sequences
local function lexerror (s, err)
local st, msg = load('return ' .. s, '')
if err ~= '<eof>' then err = err .. "'" end
assert(not st and string.find(msg, "near .-" .. err))
end
lexerror([["abc\x"]], [[\x"]])
lexerror([["abc\x]], [[\x]])
lexerror([["\x]], [[\x]])
lexerror([["\x5"]], [[\x5"]])
lexerror([["\x5]], [[\x5]])
lexerror([["\xr"]], [[\xr]])
lexerror([["\xr]], [[\xr]])
lexerror([["\x.]], [[\x.]])
lexerror([["\x8%"]], [[\x8%%]])
lexerror([["\xAG]], [[\xAG]])
lexerror([["\g"]], [[\g]])
lexerror([["\g]], [[\g]])
lexerror([["\."]], [[\%.]])
lexerror([["\999"]], [[\999"]])
lexerror([["xyz\300"]], [[\300"]])
lexerror([[" \256"]], [[\256"]])
-- errors in UTF-8 sequences
lexerror([["abc\u{100000000}"]], [[abc\u{100000000]]) -- too large
lexerror([["abc\u11r"]], [[abc\u1]]) -- missing '{'
lexerror([["abc\u"]], [[abc\u"]]) -- missing '{'
lexerror([["abc\u{11r"]], [[abc\u{11r]]) -- missing '}'
lexerror([["abc\u{11"]], [[abc\u{11"]]) -- missing '}'
lexerror([["abc\u{11]], [[abc\u{11]]) -- missing '}'
lexerror([["abc\u{r"]], [[abc\u{r]]) -- no digits
-- unfinished strings
lexerror("[=[alo]]", "<eof>")
lexerror("[=[alo]=", "<eof>")
lexerror("[=[alo]", "<eof>")
lexerror("'alo", "<eof>")
lexerror("'alo \\z \n\n", "<eof>")
lexerror("'alo \\z", "<eof>")
lexerror([['alo \98]], "<eof>")
-- valid characters in variable names
for i = 0, 255 do
local s = string.char(i)
assert(not string.find(s, "[a-zA-Z_]") == not load(s .. "=1", ""))
assert(not string.find(s, "[a-zA-Z_0-9]") ==
not load("a" .. s .. "1 = 1", ""))
end
-- long variable names
var1 = string.rep('a', 15000) .. '1'
var2 = string.rep('a', 15000) .. '2'
prog = string.format([[
%s = 5
%s = %s + 1
return function () return %s - %s end
]], var1, var2, var1, var1, var2)
local f = dostring(prog)
assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1)
var1, var2, f = nil
print('+')
-- escapes --
assert("\n\t" == [[
]])
assert([[
$debug]] == "\n $debug")
assert([[ [ ]] ~= [[ ] ]])
-- long strings --
b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960)
prog = [=[
print('+')
a1 = [["this is a 'string' with several 'quotes'"]]
a2 = "'quotes'"
assert(string.find(a1, a2) == 34)
print('+')
a1 = [==[temp = [[an arbitrary value]]; ]==]
assert(load(a1))()
assert(temp == 'an arbitrary value')
-- long strings --
b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960)
print('+')
a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789
]]
assert(string.len(a) == 1863)
assert(string.sub(a, 1, 40) == string.sub(b, 1, 40))
x = 1
]=]
print('+')
x = nil
dostring(prog)
assert(x)
prog = nil
a = nil
b = nil
-- testing line ends
prog = [[
a = 1 -- a comment
b = 2
x = [=[
hi
]=]
y = "\
hello\r\n\
"
return require"debug".getinfo(1).currentline
]]
for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
local prog, nn = string.gsub(prog, "\n", n)
assert(dostring(prog) == nn)
assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
end
-- testing comments and strings with long brackets
a = [==[]=]==]
assert(a == "]=")
a = [==[[===[[=[]]=][====[]]===]===]==]
assert(a == "[===[[=[]]=][====[]]===]===")
a = [====[[===[[=[]]=][====[]]===]===]====]
assert(a == "[===[[=[]]=][====[]]===]===")
a = [=[]]]]]]]]]=]
assert(a == "]]]]]]]]")
--[===[
x y z [==[ blu foo
]==
]
]=]==]
error error]=]===]
-- generate all strings of four of these chars
local x = {"=", "[", "]", "\n"}
local len = 4
local function gen (c, n)
if n==0 then coroutine.yield(c)
else
for _, a in pairs(x) do
gen(c..a, n-1)
end
end
end
for s in coroutine.wrap(function () gen("", len) end) do
assert(s == load("return [====[\n"..s.."]====]", "")())
end
-- testing decimal point locale
if os.setlocale("pt_BR") or os.setlocale("ptb") then
assert(tonumber("3,4") == 3.4 and tonumber"3.4" == 3.4)
assert(tonumber(" -.4 ") == -0.4)
assert(tonumber(" +0x.41 ") == 0X0.41)
assert(not load("a = (3,4)"))
assert(assert(load("return 3.4"))() == 3.4)
assert(assert(load("return .4,3"))() == .4)
assert(assert(load("return 4."))() == 4.)
assert(assert(load("return 4.+.5"))() == 4.5)
assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1)
assert(not tonumber"inf" and not tonumber"NAN")
assert(assert(load(string.format("return %q", 4.51)))() == 4.51)
local a,b = load("return 4.5.")
assert(string.find(b, "'4%.5%.'"))
assert(os.setlocale("C"))
else
(Message or print)(
'\n >>> pt_BR locale not available: skipping decimal point tests <<<\n')
end
-- testing %q x line ends
local s = "a string with \r and \n and \r\n and \n\r"
local c = string.format("return %q", s)
assert(assert(load(c))() == s)
-- testing errors
assert(not load"a = 'non-ending string")
assert(not load"a = 'non-ending string\n'")
assert(not load"a = '\\345'")
assert(not load"a = [=x]")
local function malformednum (n, exp)
local s, msg = load("return " .. n)
assert(not s and string.find(msg, exp))
end
malformednum("0xe-", "near <eof>")
malformednum("0xep-p", "malformed number")
malformednum("1print()", "malformed number")
print('OK')
+736
View File
@@ -0,0 +1,736 @@
-- $Id: testes/locals.lua $
-- See Copyright Notice in file all.lua
print('testing local variables and environments')
local debug = require"debug"
-- bug in 5.1:
local function f(x) x = nil; return x end
assert(f(10) == nil)
local function f() local x; return x end
assert(f(10) == nil)
local function f(x) x = nil; local y; return x, y end
assert(f(10) == nil and select(2, f(20)) == nil)
do
local i = 10
do local i = 100; assert(i==100) end
do local i = 1000; assert(i==1000) end
assert(i == 10)
if i ~= 10 then
local i = 20
else
local i = 30
assert(i == 30)
end
end
f = nil
local f
x = 1
a = nil
load('local a = {}')()
assert(a == nil)
function f (a)
local _1, _2, _3, _4, _5
local _6, _7, _8, _9, _10
local x = 3
local b = a
local c,d = a,b
if (d == b) then
local x = 'q'
x = b
assert(x == 2)
else
assert(nil)
end
assert(x == 3)
local f = 10
end
local b=10
local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3
assert(x == 1)
f(2)
assert(type(f) == 'function')
local function getenv (f)
local a,b = debug.getupvalue(f, 1)
assert(a == '_ENV')
return b
end
-- test for global table of loaded chunks
assert(getenv(load"a=3") == _G)
local c = {}; local f = load("a = 3", nil, nil, c)
assert(getenv(f) == c)
assert(c.a == nil)
f()
assert(c.a == 3)
-- old test for limits for special instructions
do
local i = 2
local p = 4 -- p == 2^i
repeat
for j=-3,3 do
assert(load(string.format([[local a=%s;
a=a+%s;
assert(a ==2^%s)]], j, p-j, i), '')) ()
assert(load(string.format([[local a=%s;
a=a-%s;
assert(a==-2^%s)]], -j, p-j, i), '')) ()
assert(load(string.format([[local a,b=0,%s;
a=b-%s;
assert(a==-2^%s)]], -j, p-j, i), '')) ()
end
p = 2 * p; i = i + 1
until p <= 0
end
print'+'
if rawget(_G, "T") then
-- testing clearing of dead elements from tables
collectgarbage("stop") -- stop GC
local a = {[{}] = 4, [3] = 0, alo = 1,
a1234567890123456789012345678901234567890 = 10}
local t = T.querytab(a)
for k,_ in pairs(a) do a[k] = undef end
collectgarbage() -- restore GC and collect dead fields in 'a'
for i=0,t-1 do
local k = querytab(a, i)
assert(k == nil or type(k) == 'number' or k == 'alo')
end
-- testing allocation errors during table insertions
local a = {}
local function additems ()
a.x = true; a.y = true; a.z = true
a[1] = true
a[2] = true
end
for i = 1, math.huge do
T.alloccount(i)
local st, msg = pcall(additems)
T.alloccount()
local count = 0
for k, v in pairs(a) do
assert(a[k] == v)
count = count + 1
end
if st then assert(count == 5); break end
end
end
-- testing lexical environments
assert(_ENV == _G)
do
local dummy
local _ENV = (function (...) return ... end)(_G, dummy) -- {
do local _ENV = {assert=assert}; assert(true) end
mt = {_G = _G}
local foo,x
A = false -- "declare" A
do local _ENV = mt
function foo (x)
A = x
do local _ENV = _G; A = 1000 end
return function (x) return A .. x end
end
end
assert(getenv(foo) == mt)
x = foo('hi'); assert(mt.A == 'hi' and A == 1000)
assert(x('*') == mt.A .. '*')
do local _ENV = {assert=assert, A=10};
do local _ENV = {assert=assert, A=20};
assert(A==20);x=A
end
assert(A==10 and x==20)
end
assert(x==20)
do -- constants
local a<const>, b, c<const> = 10, 20, 30
b = a + c + b -- 'b' is not constant
assert(a == 10 and b == 60 and c == 30)
local function checkro (name, code)
local st, msg = load(code)
local gab = string.format("attempt to assign to const variable '%s'", name)
assert(not st and string.find(msg, gab))
end
checkro("y", "local x, y <const>, z = 10, 20, 30; x = 11; y = 12")
checkro("x", "local x <const>, y, z <const> = 10, 20, 30; x = 11")
checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11")
checkro("z", [[
local a, z <const>, b = 10;
function foo() a = 20; z = 32; end
]])
checkro("var1", [[
local a, var1 <const> = 10;
function foo() a = 20; z = function () var1 = 12; end end
]])
end
print"testing to-be-closed variables"
local function stack(n) n = ((n == 0) or stack(n - 1)) end
local function func2close (f, x, y)
local obj = setmetatable({}, {__close = f})
if x then
return x, obj, y
else
return obj
end
end
do
local a = {}
do
local b <close> = false -- not to be closed
local x <close> = setmetatable({"x"}, {__close = function (self)
a[#a + 1] = self[1] end})
local w, y <close>, z = func2close(function (self, err)
assert(err == nil); a[#a + 1] = "y"
end, 10, 20)
local c <close> = nil -- not to be closed
a[#a + 1] = "in"
assert(w == 10 and z == 20)
end
a[#a + 1] = "out"
assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out")
end
do
local X = false
local x, closescope = func2close(function () stack(10); X = true end, 100)
assert(x == 100); x = 101; -- 'x' is not read-only
-- closing functions do not corrupt returning values
local function foo (x)
local _ <close> = closescope
return x, X, 23
end
local a, b, c = foo(1.5)
assert(a == 1.5 and b == false and c == 23 and X == true)
X = false
foo = function (x)
local _<close> = closescope
local y = 15
return y
end
assert(foo() == 15 and X == true)
X = false
foo = function ()
local x <close> = closescope
return x
end
assert(foo() == closescope and X == true)
end
-- testing to-be-closed x compile-time constants
-- (there were some bugs here in Lua 5.4-rc3, due to a confusion
-- between compile levels and stack levels of variables)
do
local flag = false
local x = setmetatable({},
{__close = function() assert(flag == false); flag = true end})
local y <const> = nil
local z <const> = nil
do
local a <close> = x
end
assert(flag) -- 'x' must be closed here
end
do
-- similar problem, but with implicit close in for loops
local flag = false
local x = setmetatable({},
{__close = function () assert(flag == false); flag = true end})
-- return an empty iterator, nil, nil, and 'x' to be closed
local function a ()
return (function () return nil end), nil, nil, x
end
local v <const> = 1
local w <const> = 1
local x <const> = 1
local y <const> = 1
local z <const> = 1
for k in a() do
a = k
end -- ending the loop must close 'x'
assert(flag) -- 'x' must be closed here
end
do
-- calls cannot be tail in the scope of to-be-closed variables
local X, Y
local function foo ()
local _ <close> = func2close(function () Y = 10 end)
assert(X == true and Y == nil) -- 'X' not closed yet
return 1,2,3
end
local function bar ()
local _ <close> = func2close(function () X = false end)
X = true
do
return foo() -- not a tail call!
end
end
local a, b, c, d = bar()
assert(a == 1 and b == 2 and c == 3 and X == false and Y == 10 and d == nil)
end
-- auxiliary functions for testing warnings in '__close'
local function prepwarn ()
if not T then -- no test library?
warn("@off") -- do not show (lots of) warnings
else
warn("@store") -- to test the warnings
end
end
local function endwarn ()
if not T then
warn("@on") -- back to normal
else
assert(_WARN == nil)
warn("@normal")
end
end
local function checkwarn (msg)
if T then
assert(string.find(_WARN, msg))
_WARN = nil -- reset variable to check next warning
end
end
warn("@on")
do print("testing errors in __close")
prepwarn()
-- original error is in __close
local function foo ()
local x <close> =
func2close(function (self, msg)
assert(string.find(msg, "@z"))
error("@x")
end)
local x1 <close> =
func2close(function (self, msg)
checkwarn("@y")
assert(string.find(msg, "@z"))
end)
local gc <close> = func2close(function () collectgarbage() end)
local y <close> =
func2close(function (self, msg)
assert(string.find(msg, "@z")) -- first error in 'z'
checkwarn("@z") -- second error in 'z' generated a warning
error("@y")
end)
local first = true
local z <close> =
-- 'z' close is called twice
func2close(function (self, msg)
if first then
assert(msg == nil)
first = false
else
assert(string.find(msg, "@z")) -- own error
end
error("@z")
end)
return 200
end
local stat, msg = pcall(foo, false)
assert(string.find(msg, "@z"))
checkwarn("@x")
-- original error not in __close
local function foo ()
local x <close> =
func2close(function (self, msg)
assert(msg == 4)
end)
local x1 <close> =
func2close(function (self, msg)
checkwarn("@y")
assert(msg == 4)
error("@x1")
end)
local gc <close> = func2close(function () collectgarbage() end)
local y <close> =
func2close(function (self, msg)
assert(msg == 4) -- error in body
checkwarn("@z")
error("@y")
end)
local first = true
local z <close> =
func2close(function (self, msg)
-- 'z' close is called once
assert(first and msg == 4)
first = false
error("@z")
end)
error(4) -- original error
end
local stat, msg = pcall(foo, true)
assert(msg == 4)
checkwarn("@x1") -- last error
-- error leaving a block
local function foo (...)
do
local x1 <close> =
func2close(function ()
checkwarn("@X")
error("@Y")
end)
local x123 <close> =
func2close(function ()
error("@X")
end)
end
os.exit(false) -- should not run
end
local st, msg = xpcall(foo, debug.traceback)
assert(string.match(msg, "^[^ ]* @X"))
assert(string.find(msg, "in metamethod 'close'"))
checkwarn("@Y")
-- error in toclose in vararg function
local function foo (...)
local x123 <close> = func2close(function () error("@x123") end)
end
local st, msg = xpcall(foo, debug.traceback)
assert(string.match(msg, "^[^ ]* @x123"))
assert(string.find(msg, "in metamethod 'close'"))
checkwarn("@x123") -- from second call to close 'x123'
endwarn()
end
do -- errors due to non-closable values
local function foo ()
local x <close> = {}
os.exit(false) -- should not run
end
local stat, msg = pcall(foo)
assert(not stat and
string.find(msg, "variable 'x' got a non%-closable value"))
local function foo ()
local xyz <close> = setmetatable({}, {__close = print})
getmetatable(xyz).__close = nil -- remove metamethod
end
local stat, msg = pcall(foo)
assert(not stat and
string.find(msg, "attempt to close non%-closable variable 'xyz'"))
end
if rawget(_G, "T") then
warn("@off")
-- memory error inside closing function
local function foo ()
local y <close> = func2close(function () T.alloccount() end)
local x <close> = setmetatable({}, {__close = function ()
T.alloccount(0); local x = {} -- force a memory error
end})
error(1000) -- common error inside the function's body
end
stack(5) -- ensure a minimal number of CI structures
-- despite memory error, 'y' will be executed and
-- memory limit will be lifted
local _, msg = pcall(foo)
assert(msg == 1000)
local close = func2close(function (self, msg)
T.alloccount()
assert(msg == "not enough memory")
end)
-- set a memory limit and return a closing object to remove the limit
local function enter (count)
stack(10) -- reserve some stack space
T.alloccount(count)
return close
end
local function test ()
local x <close> = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
assert(false) -- should not run
end
local _, msg = pcall(test)
assert(msg == "not enough memory")
-- now use metamethod for closing
close = setmetatable({}, {__close = function ()
T.alloccount()
end})
-- repeat test with extra closing upvalues
local function test ()
local xxx <close> = func2close(function (self, msg)
assert(msg == "not enough memory");
error(1000) -- raise another error
end)
local xx <close> = func2close(function (self, msg)
assert(msg == "not enough memory");
end)
local x <close> = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
os.exit(false) -- should not run
end
local _, msg = pcall(test)
assert(msg == "not enough memory") -- reported error is the first one
do -- testing 'toclose' in C string buffer
collectgarbage()
local s = string.rep('a', 10000) -- large string
local m = T.totalmem()
collectgarbage("stop")
s = string.upper(s) -- allocate buffer + new string (10K each)
-- ensure buffer was deallocated
assert(T.totalmem() - m <= 11000)
collectgarbage("restart")
end
do -- now some tests for freeing buffer in case of errors
local lim = 10000 -- some size larger than the static buffer
local extra = 2000 -- some extra memory (for callinfo, etc.)
local s = string.rep("a", lim)
-- concat this table needs two buffer resizes (one for each 's')
local a = {s, s}
collectgarbage()
m = T.totalmem()
collectgarbage("stop")
-- error in the first buffer allocation
T. totalmem(m + extra)
assert(not pcall(table.concat, a))
-- first buffer was not even allocated
assert(T.totalmem() - m <= extra)
-- error in the second buffer allocation
T. totalmem(m + lim + extra)
assert(not pcall(table.concat, a))
-- first buffer was released by 'toclose'
assert(T.totalmem() - m <= extra)
-- error in creation of final string
T.totalmem(m + 2 * lim + extra)
assert(not pcall(table.concat, a))
-- second buffer was released by 'toclose'
assert(T.totalmem() - m <= extra)
-- userdata, upvalue, buffer, buffer, final string
T.totalmem(m + 4*lim + extra)
assert(#table.concat(a) == 2*lim)
T.totalmem(0) -- remove memory limit
collectgarbage("restart")
print'+'
end
warn("@on")
end
print "to-be-closed variables in coroutines"
do
-- an error in a wrapped coroutine closes variables
local x = false
local y = false
local co = coroutine.wrap(function ()
local xv <close> = func2close(function () x = true end)
do
local yv <close> = func2close(function () y = true end)
coroutine.yield(100) -- yield doesn't close variable
end
coroutine.yield(200) -- yield doesn't close variable
error(23) -- error does
end)
local b = co()
assert(b == 100 and not x and not y)
b = co()
assert(b == 200 and not x and y)
local a, b = pcall(co)
assert(not a and b == 23 and x and y)
end
do
prepwarn()
-- error in a wrapped coroutine raising errors when closing a variable
local x = 0
local co = coroutine.wrap(function ()
local xx <close> = func2close(function () x = x + 1; error("@YYY") end)
local xv <close> = func2close(function () x = x + 1; error("@XXX") end)
coroutine.yield(100)
error(200)
end)
assert(co() == 100); assert(x == 0)
local st, msg = pcall(co); assert(x == 2)
assert(not st and msg == 200) -- should get first error raised
checkwarn("@YYY")
local x = 0
local y = 0
co = coroutine.wrap(function ()
local xx <close> = func2close(function () y = y + 1; error("YYY") end)
local xv <close> = func2close(function () x = x + 1; error("XXX") end)
coroutine.yield(100)
return 200
end)
assert(co() == 100); assert(x == 0)
local st, msg = pcall(co)
assert(x == 2 and y == 1) -- first close is called twice
-- should get first error raised
assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
checkwarn("YYY")
endwarn()
end
-- a suspended coroutine should not close its variables when collected
local co
co = coroutine.wrap(function()
-- should not run
local x <close> = func2close(function () os.exit(false) end)
co = nil
coroutine.yield()
end)
co() -- start coroutine
assert(co == nil) -- eventually it will be collected
collectgarbage()
-- to-be-closed variables in generic for loops
do
local numopen = 0
local function open (x)
numopen = numopen + 1
return
function () -- iteraction function
x = x - 1
if x > 0 then return x end
end,
nil, -- state
nil, -- control variable
func2close(function () numopen = numopen - 1 end) -- closing function
end
local s = 0
for i in open(10) do
s = s + i
end
assert(s == 45 and numopen == 0)
local s = 0
for i in open(10) do
if i < 5 then break end
s = s + i
end
assert(s == 35 and numopen == 0)
local s = 0
for i in open(10) do
for j in open(10) do
if i + j < 5 then goto endloop end
s = s + i
end
end
::endloop::
assert(s == 375 and numopen == 0)
end
print('OK')
return 5,f
end -- }
+468
View File
@@ -0,0 +1,468 @@
# testing special comment on first line
-- $Id: testes/main.lua $
-- See Copyright Notice in file all.lua
-- most (all?) tests here assume a reasonable "Unix-like" shell
if _port then return end
-- use only "double quotes" inside shell scripts (better change to
-- run on Windows)
print ("testing stand-alone interpreter")
assert(os.execute()) -- machine has a system command
local arg = arg or ARG
local prog = os.tmpname()
local otherprog = os.tmpname()
local out = os.tmpname()
local progname
do
local i = 0
while arg[i] do i=i-1 end
progname = arg[i+1]
end
print("progname: "..progname)
local prepfile = function (s, p)
p = p or prog
io.output(p)
io.write(s)
assert(io.close())
end
local function getoutput ()
io.input(out)
local t = io.read("a")
io.input():close()
assert(os.remove(out))
return t
end
local function checkprogout (s)
-- expected result must end with new line
assert(string.sub(s, -1) == "\n")
local t = getoutput()
for line in string.gmatch(s, ".-\n") do
assert(string.find(t, line, 1, true))
end
end
local function checkout (s)
local t = getoutput()
if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end
assert(s == t)
return t
end
local function RUN (p, ...)
p = string.gsub(p, "lua", '"'..progname..'"', 1)
local s = string.format(p, ...)
assert(os.execute(s))
end
local function NoRun (msg, p, ...)
p = string.gsub(p, "lua", '"'..progname..'"', 1)
local s = string.format(p, ...)
s = string.format("%s 2> %s", s, out) -- will send error to 'out'
assert(not os.execute(s))
assert(string.find(getoutput(), msg, 1, true)) -- check error message
end
RUN('lua -v')
print(string.format("(temporary program file used in these tests: %s)", prog))
-- running stdin as a file
prepfile""
RUN('lua - < %s > %s', prog, out)
checkout("")
prepfile[[
print(
1, a
)
]]
RUN('lua - < %s > %s', prog, out)
checkout("1\tnil\n")
RUN('echo "print(10)\nprint(2)\n" | lua > %s', out)
checkout("10\n2\n")
-- test option '-'
RUN('echo "print(arg[1])" | lua - -h > %s', out)
checkout("-h\n")
-- test environment variables used by Lua
prepfile("print(package.path)")
-- test LUA_PATH
RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out)
checkout("x\n")
-- test LUA_PATH_version
RUN('env LUA_INIT= LUA_PATH_5_4=y LUA_PATH=x lua %s > %s', prog, out)
checkout("y\n")
-- test LUA_CPATH
prepfile("print(package.cpath)")
RUN('env LUA_INIT= LUA_CPATH=xuxu lua %s > %s', prog, out)
checkout("xuxu\n")
-- test LUA_CPATH_version
RUN('env LUA_INIT= LUA_CPATH_5_4=yacc LUA_CPATH=x lua %s > %s', prog, out)
checkout("yacc\n")
-- test LUA_INIT (and its access to 'arg' table)
prepfile("print(X)")
RUN('env LUA_INIT="X=tonumber(arg[1])" lua %s 3.2 > %s', prog, out)
checkout("3.2\n")
-- test LUA_INIT_version
prepfile("print(X)")
RUN('env LUA_INIT_5_4="X=10" LUA_INIT="X=3" lua %s > %s', prog, out)
checkout("10\n")
-- test LUA_INIT for files
prepfile("x = x or 10; print(x); x = x + 1")
RUN('env LUA_INIT="@%s" lua %s > %s', prog, prog, out)
checkout("10\n11\n")
-- test errors in LUA_INIT
NoRun('LUA_INIT:1: msg', 'env LUA_INIT="error(\'msg\')" lua')
-- test option '-E'
local defaultpath, defaultCpath
do
prepfile("print(package.path, package.cpath)")
RUN('env LUA_INIT="error(10)" LUA_PATH=xxx LUA_CPATH=xxx lua -E %s > %s',
prog, out)
local output = getoutput()
defaultpath = string.match(output, "^(.-)\t")
defaultCpath = string.match(output, "\t(.-)$")
-- running with an empty environment
RUN('env -i lua %s > %s', prog, out)
local out = getoutput()
assert(defaultpath == string.match(output, "^(.-)\t"))
assert(defaultCpath == string.match(output, "\t(.-)$"))
end
-- paths did not change
assert(not string.find(defaultpath, "xxx") and
string.find(defaultpath, "lua") and
not string.find(defaultCpath, "xxx") and
string.find(defaultCpath, "lua"))
-- test replacement of ';;' to default path
local function convert (p)
prepfile("print(package.path)")
RUN('env LUA_PATH="%s" lua %s > %s', p, prog, out)
local expected = getoutput()
expected = string.sub(expected, 1, -2) -- cut final end of line
if string.find(p, ";;") then
p = string.gsub(p, ";;", ";"..defaultpath..";")
p = string.gsub(p, "^;", "") -- remove ';' at the beginning
p = string.gsub(p, ";$", "") -- remove ';' at the end
end
assert(p == expected)
end
convert(";")
convert(";;")
convert("a;;b")
convert(";;b")
convert("a;;")
convert("a;b;;c")
-- test -l over multiple libraries
prepfile("print(1); a=2; return {x=15}")
prepfile(("print(a); print(_G['%s'].x)"):format(prog), otherprog)
RUN('env LUA_PATH="?;;" lua -l %s -l%s -lstring -l io %s > %s', prog, otherprog, otherprog, out)
checkout("1\n2\n15\n2\n15\n")
-- test 'arg' table
local a = [[
assert(#arg == 3 and arg[1] == 'a' and
arg[2] == 'b' and arg[3] == 'c')
assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == '%s')
assert(arg[4] == undef and arg[-4] == undef)
local a, b, c = ...
assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
]]
a = string.format(a, progname)
prepfile(a)
RUN('lua "-e " -- %s a b c', prog) -- "-e " runs an empty command
-- test 'arg' availability in libraries
prepfile"assert(arg)"
prepfile("assert(arg)", otherprog)
RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog)
-- test messing up the 'arg' table
RUN('echo "print(...)" | lua -e "arg[1] = 100" - > %s', out)
checkout("100\n")
NoRun("'arg' is not a table", 'echo "" | lua -e "arg = 1" -')
-- test error in 'print'
RUN('echo 10 | lua -e "print=nil" -i > /dev/null 2> %s', out)
assert(string.find(getoutput(), "error calling 'print'"))
-- test 'debug.debug'
RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out)
checkout("lua_debug> 1000lua_debug> ")
print("testing warnings")
-- no warnings by default
RUN('echo "io.stderr:write(1); warn[[XXX]]" | lua 2> %s', out)
checkout("1")
prepfile[[
warn("@allow") -- unknown control, ignored
warn("@off", "XXX", "@off") -- these are not control messages
warn("@off") -- this one is
warn("@on", "YYY", "@on") -- not control, but warn is off
warn("@off") -- keep it off
warn("@on") -- restart warnings
warn("", "@on") -- again, no control, real warning
warn("@on") -- keep it "started"
warn("Z", "Z", "Z") -- common warning
]]
RUN('lua -W %s 2> %s', prog, out)
checkout[[
Lua warning: @offXXX@off
Lua warning: @on
Lua warning: ZZZ
]]
prepfile[[
warn("@allow")
-- create two objects to be finalized when closing state
-- the errors in the finalizers must generate warnings
u1 = setmetatable({}, {__gc = function () error("XYZ") end})
u2 = setmetatable({}, {__gc = function () error("ZYX") end})
]]
RUN('lua -W %s 2> %s', prog, out)
checkprogout("ZYX)\nXYZ)\n")
-- test many arguments
prepfile[[print(({...})[30])]]
RUN('lua %s %s > %s', prog, string.rep(" a", 30), out)
checkout("a\n")
RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
checkout("1\n3\n")
-- test iteractive mode
prepfile[[
(6*2-6) -- ===
a =
10
print(a)
a]]
RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
checkprogout("6\n10\n10\n\n")
prepfile("a = [[b\nc\nd\ne]]\n=a")
RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
checkprogout("b\nc\nd\ne\n\n")
prompt = "alo"
prepfile[[ --
a = 2
]]
RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
local t = getoutput()
assert(string.find(t, prompt .. ".*" .. prompt .. ".*" .. prompt))
-- test for error objects
prepfile[[
debug = require "debug"
m = {x=0}
setmetatable(m, {__tostring = function(x)
return tostring(debug.getinfo(4).currentline + x.x)
end})
error(m)
]]
NoRun(progname .. ": 6\n", [[lua %s]], prog)
prepfile("error{}")
NoRun("error object is a table value", [[lua %s]], prog)
-- chunk broken in many lines
s = [=[ --
function f ( x )
local a = [[
xuxu
]]
local b = "\
xuxu\n"
if x == 11 then return 1 + 12 , 2 + 20 end --[[ test multiple returns ]]
return x + 1
--\\
end
return( f( 100 ) )
assert( a == b )
do return f( 11 ) end ]=]
s = string.gsub(s, ' ', '\n\n') -- change all spaces for newlines
prepfile(s)
RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
checkprogout("101\n13\t22\n\n")
prepfile[[#comment in 1st line without \n at the end]]
RUN('lua %s', prog)
prepfile[[#test line number when file starts with comment line
debug = require"debug"
print(debug.getinfo(1).currentline)
]]
RUN('lua %s > %s', prog, out)
checkprogout('3\n')
-- close Lua with an open file
prepfile(string.format([[io.output(%q); io.write('alo')]], out))
RUN('lua %s', prog)
checkout('alo')
-- bug in 5.2 beta (extra \0 after version line)
RUN([[lua -v -e"print'hello'" > %s]], out)
t = getoutput()
assert(string.find(t, "PUC%-Rio\nhello"))
-- testing os.exit
prepfile("os.exit(nil, true)")
RUN('lua %s', prog)
prepfile("os.exit(0, true)")
RUN('lua %s', prog)
prepfile("os.exit(true, true)")
RUN('lua %s', prog)
prepfile("os.exit(1, true)")
NoRun("", "lua %s", prog) -- no message
prepfile("os.exit(false, true)")
NoRun("", "lua %s", prog) -- no message
-- to-be-closed variables in main chunk
prepfile[[
local x <close> = setmetatable({},
{__close = function (self, err)
assert(err == nil)
print("Ok")
end})
local e1 <close> = setmetatable({}, {__close = function () print(120) end})
os.exit(true, true)
]]
RUN('lua %s > %s', prog, out)
checkprogout("120\nOk\n")
-- remove temporary files
assert(os.remove(prog))
assert(os.remove(otherprog))
assert(not os.remove(out))
-- invalid options
NoRun("unrecognized option '-h'", "lua -h")
NoRun("unrecognized option '---'", "lua ---")
NoRun("unrecognized option '-Ex'", "lua -Ex")
NoRun("unrecognized option '-vv'", "lua -vv")
NoRun("unrecognized option '-iv'", "lua -iv")
NoRun("'-e' needs argument", "lua -e")
NoRun("syntax error", "lua -e a")
NoRun("'-l' needs argument", "lua -l")
if T then -- test library?
print("testing 'not enough memory' to create a state")
NoRun("not enough memory", "env MEMLIMIT=100 lua")
-- testing 'warn'
warn("@store")
warn("@123", "456", "789")
assert(_WARN == "@123456789"); _WARN = nil
warn("zip", "", " ", "zap")
assert(_WARN == "zip zap"); _WARN = nil
warn("ZIP", "", " ", "ZAP")
assert(_WARN == "ZIP ZAP"); _WARN = nil
warn("@normal")
end
do
-- 'warn' must get at least one argument
local st, msg = pcall(warn)
assert(string.find(msg, "string expected"))
-- 'warn' does not leave unfinished warning in case of errors
-- (message would appear in next warning)
st, msg = pcall(warn, "SHOULD NOT APPEAR", {})
assert(string.find(msg, "string expected"))
end
print('+')
print('testing Ctrl C')
do
-- interrupt a script
local function kill (pid)
return os.execute(string.format('kill -INT %s 2> /dev/null', pid))
end
-- function to run a script in background, returning its output file
-- descriptor and its pid
local function runback (luaprg)
-- shell script to run 'luaprg' in background and echo its pid
local shellprg = string.format('%s -e "%s" & echo $!', progname, luaprg)
local f = io.popen(shellprg, "r") -- run shell script
local pid = f:read() -- get pid for Lua script
print("(if test fails now, it may leave a Lua script running in \z
background, pid " .. pid .. ")")
return f, pid
end
-- Lua script that runs protected infinite loop and then prints '42'
local f, pid = runback[[
pcall(function () print(12); while true do end end); print(42)]]
-- wait until script is inside 'pcall'
assert(f:read() == "12")
kill(pid) -- send INT signal to Lua script
-- check that 'pcall' captured the exception and script continued running
assert(f:read() == "42") -- expected output
assert(f:close())
print("done")
-- Lua script in a long unbreakable search
local f, pid = runback[[
print(15); string.find(string.rep('a', 100000), '.*b')]]
-- wait (so script can reach the loop)
assert(f:read() == "15")
assert(os.execute("sleep 1"))
-- must send at least two INT signals to stop this Lua script
local n = 100
for i = 0, 100 do -- keep sending signals
if not kill(pid) then -- until it fails
n = i -- number of non-failed kills
break
end
end
assert(f:close())
assert(n >= 2)
print(string.format("done (with %d kills)", n))
end
print("OK")
+1023
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More