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

Compare commits

...

3572 Commits

Author SHA1 Message Date
Roberto Ierusalimschy 6e22fedb74 New release number, updated copyright year 2025-05-21 13:52:56 -03:00
Roberto Ierusalimschy 267ef461d0 Bug: check for constructor overflow in [exp] fields
The check for constructor overflow was considering only fields with
explicit names, ignoring fields with syntax '[exp]=exp'.
2025-05-20 17:55:08 -03:00
Roberto Ierusalimschy d1ee2a4deb Bug: Bad error message with fields of string _ENV
Errors with fields of the string _ENV (e.g., ("_ENV").u + 1) report
the error as comming from a global.
2025-05-15 15:14:56 -03:00
Roberto Ierusalimschy 3fe7be956f Bug: message handler can be overwritten
A __close metamethod can overwrite a message handler in the stack
when closing a thread or a state.
2025-03-17 16:14:17 -03:00
Roberto Ierusalimschy 983bc433e6 Bug: Use after free in 'luaV_finishset'
If a metatable is a weak table, its __newindex field could be collected
by an emergency collection while being used in 'luaV_finishset'. (This
bug has similarities with bug 5.3.2-1, fixed in commit a272fa66.)
2025-03-13 15:42:39 -03:00
Roberto Ierusalimschy 25da574fcb Bug: 'luaD_seterrorobj' should not raise errors
This function can be called unprotected, so it should not raise any
kind of errors. (It could raise a memory-allocation error when creating
a message).
2025-03-12 16:01:03 -03:00
Roberto Ierusalimschy f5e55be2a0 Bug: Missing error status in panic function
'luaD_throw' may call 'luaE_resetthread', which returns an error code
but clears 'L->status'; so, 'luaD_throw' should set that status again.
2025-01-16 16:25:11 -03:00
Roberto Ierusalimschy 9f0c0fe0de Bug: Wrong limit for local variables in 16-bit systems
USHRT_MAX does not fit in an 'int' in 16-bit systems.
2024-09-10 11:34:42 -03:00
Roberto Ierusalimschy 782ef85b22 Bug: wrong code gen. for indices with comparisons
In function 'luaK_exp2val', used to generate code for indices: Macro
'hasjumps' does not consider the case when the whole expression is a
"jump" (a test). In all other of its uses, the surrounding code ensures
that the expression cannot be VJMP.
2024-08-17 12:37:04 -03:00
Roberto Ierusalimschy 30982bec96 Bug: Bad stack manipulation in 'multiline' (REPL)
'incomplete' was popping error message that should be used in case
there is no more lines to complete the input, that is, 'pushline'
returns NULL, due to end of file.
2024-07-05 14:31:07 -03:00
Roberto Ierusalimschy 1ab3208a1f 'lua.h' back to redundancy in version definitions
Several tools inspect 'lua.h' to extract version information, and
they assume the file will have some specific format.
2024-06-13 15:13:52 -03:00
Roberto Ierusalimschy 21ff8de33a Bug: Tricky _PROMPT may trigger undefined behavior 2024-06-05 13:37:16 -03:00
Roberto Ierusalimschy 7eb1ed21b7 More permissive use of 'errno'
Assume that no function will put garbage on errno (although ISO C allows
that). If any function during an operation set errno, and the operation
result in an error, assume that errno has something to say.
2024-06-05 11:50:42 -03:00
Roberto Ierusalimschy 2db966fcbf Bug: luaL_traceback may need more than 5 stack slots 2024-06-04 16:40:53 -03:00
Roberto Ierusalimschy ae9a0cbbb4 Bug: overlapping assignments
ISO C forbids assignment of a union field to another field of the same
union.
2024-06-04 12:52:52 -03:00
Roberto Ierusalimschy d5212c13b0 More disciplined use of 'errno'
Set errno to zero before calling any function where we may use its
errno, and check errno for zero before using it (as functions may
not set it even in error).
2024-06-04 12:48:29 -03:00
Roberto Ierusalimschy e0efebdbe4 Detail in the manual
Function 'lua_toclose' can raise a non-memory error (but not a
memory error).
2024-05-14 17:59:54 -03:00
Roberto Ierusalimschy e84f7bf198 Details
Typos in comments.
2024-05-13 13:23:45 -03:00
Roberto Ierusalimschy dfbde4c7d5 Bug: Active-lines for stripped vararg functions
Lua seg. faults when asked to create the 'activelines' table for a
vararg function with no debug information.
2024-05-13 13:10:35 -03:00
Roberto Ierusalimschy de794a6527 Towards release 5.4.7 2024-04-26 14:55:18 -03:00
Roberto Ierusalimschy 8b83417de9 Avoids a warning when lua_Number is 'float' 2024-02-07 14:17:03 -03:00
Roberto Ierusalimschy e288c5a918 Bug: Yielding in a hook stops in the wrong instruction
Yielding in a hook must decrease the program counter, because it already
counted an instruction that, in the end, was not executed. However,
that decrement should be done only when about to restart the thread.
Otherwise, inspecting the thread with the debug library shows it one
instruction behind of where it really is.
2024-01-11 13:44:16 -03:00
Roberto Ierusalimschy 5853c37a83 Bug: Buffer overflow in string concatenation
Even if the string fits in size_t, the whole size of the TString object
can overflow when we add the header.
2023-12-21 13:37:51 -03:00
Roberto Ierusalimschy 842a83f09c Panic functions should not raise errors
The standard panic function was using 'lua_tostring', which may raise
a memory-allocation error if error value is a number.
2023-11-24 16:08:55 -03:00
Roberto Ierusalimschy 7923dbbf72 Bug: Recursion in 'getobjname' can stack overflow
'getobjname' now broken in two, a basic version that handles locals,
upvalues, and constants, and a full version, which uses the basic
version to handle table accesses (globals and fields).
2023-11-01 12:00:54 -03:00
Roberto Ierusalimschy 81e4fce530 Simpler test in 'luaH_getint'
The test whether key is inside the array part of a table uses a bit
trick to avoid computing the real size of the array part.
2023-10-26 16:12:25 -03:00
Roberto Ierusalimschy 6baee9ef9d Removed test for "corrupted binary dump"
Test is too non portable. (For instance, it does not work for
different number types.)
2023-09-08 16:19:21 -03:00
Roberto Ierusalimschy edd8589f47 Avoid casts from unsigned long to floating-point
Old Microsoft compilers do not support those casts.
2023-09-08 11:34:39 -03:00
Roberto Ierusalimschy 07a9eab23a Cannot use 'getshrstr' before setting 'shrlen' 2023-08-25 15:55:14 -03:00
Roberto Ierusalimschy 9363a8b990 Documentation for "LUA_NOENV"
Registry field "LUA_NOENV" (that signals to libraries that option -E
is on) now part of the "official" API of Lua stand-alone.
2023-08-23 13:50:38 -03:00
Roberto Ierusalimschy 5ab6a5756b Bug: Wrong line number for function calls 2023-08-23 13:49:27 -03:00
Roberto Ierusalimschy 9b4f39ab14 More disciplined use of 'getstr' and 'tsslen'
We may want to add other string variants in the future; this change
documents better where the code may need to handle those variants.
2023-08-17 15:59:28 -03:00
Roberto Ierusalimschy f4211a5ea4 More control over encoding of test files
The few UTF-8 test files are commented as such, and there is only one
non UTF-8 test file (to test non UTF-8 sources).
2023-08-17 10:42:56 -03:00
Roberto Ierusalimschy 1b3f507f62 Bug: Call hook may be called twice when count hook yields
Took the opportunity and moved the code that controls call hooks
in 'luaV_execute' into a function.
2023-07-25 16:50:44 -03:00
Roberto Ierusalimschy 6b51133a98 Thread stacks resized in the atomic phase
Although stack resize can be a little expensive, it seems unusual to
have too many threads needing resize during one GC cycle. On the other
hand, the change allows full collections to skip the propagate phase,
going straight from a pause to the atomic phase.
2023-07-13 14:55:46 -03:00
Roberto Ierusalimschy cbae016202 Details 2023-07-03 14:12:54 -03:00
Roberto Ierusalimschy ea39042e13 Removed redundancy in definitions of version/release
String rendering now derived from the numeric original definitions.
2023-06-21 15:04:24 -03:00
Roberto Ierusalimschy 05ec55f16b Avoid inclusion loop in 'ltm.h' 2023-06-16 11:52:14 -03:00
Roberto Ierusalimschy f623b96932 Bug: read overflow in 'l_strcmp'
Equality according to 'strcoll' does not imply that strings have
the same length.
2023-06-14 14:38:07 -03:00
Roberto Ierusalimschy 9be74ccc21 Several functions turned 'static'
Several functions that were already being used only inside their
own file have been declared as 'static'.
2023-05-22 14:47:54 -03:00
Roberto Ierusalimschy 09f3c2372f Option '-l' discards version sufix from file name
Like 'require', the command-line option '-l' discards an optional
version suffix (everything after an hyphen) from a file name when
creating the module name.
2023-05-15 13:46:38 -03:00
Roberto Ierusalimschy c197885cb0 Small improvements in tests 2023-05-15 10:20:13 -03:00
Roberto Ierusalimschy 934e77a286 Details
- Better comments about short strings in opcodes.
- luaH_newkey made static.
2023-05-15 10:07:25 -03:00
Roberto Ierusalimschy 6443185167 "Emergency" new version 5.4.6
'lua_resetthread' is back to its original signature, to avoid
incompatibilities in the ABI between releases of the same version.
New function 'lua_closethread' added with the "correct" signature.
2023-05-02 16:41:43 -03:00
Roberto Ierusalimschy e15f1f2bb7 Details
Typos in comments and details in the manual.
2023-04-18 09:44:10 -03:00
Roberto Ierusalimschy b5c65705ca New year (2023)
Also, small tweak in makefile. (-Wsign-compare is already enabled by
-Wextra.)
2023-03-31 11:47:31 -03:00
Roberto Ierusalimschy 7ca8105a2e More orderliness in casts of enumerations 2023-03-27 16:29:39 -03:00
Roberto Ierusalimschy 94689ac3ad More regularity in uses of enums in 'lcode.c' 2023-03-24 15:52:03 -03:00
Roberto Ierusalimschy ab859fe59b Bug: Loading a corrupted binary file can segfault
The size of the list of upvalue names are stored separated from the
size of the list of upvalues, but they share the same array.
2023-03-17 15:52:09 -03:00
Roberto Ierusalimschy c4b71b7ba0 Details
Comments in 'onelua.c'
2023-03-09 11:12:11 -03:00
Roberto Ierusalimschy 1de2f31694 Corrected support for 16-bit systems
We still need access to a 16-bit system to correctly test
these changes.
2023-03-09 11:10:04 -03:00
Roberto Ierusalimschy 02bab9fc25 Bug: Wrong line in error message for arith. errors
It also causes 'L->top' to be wrong when the error happens,
triggering an 'assert'.
2023-02-08 14:15:41 -03:00
Roberto Ierusalimschy 5e08b41567 Simpler definition for LUA_STRFTIMEOPTIONS
There is no need for those intermediate definitions.
2023-02-07 10:48:39 -03:00
Roberto Ierusalimschy cf08915d62 New macro LUA_USE_IOS
Do not try to detect automatically whether system is iOS; it is
simpler and more reliable to let the programmer inform that.
2023-02-02 13:43:41 -03:00
Roberto Ierusalimschy c888ae0aea Small changes in hash of pointers
When converting from pointer to integer, use 'uintptr_t' if available;
otherwise try 'uintmax_t', and use 'size_t' as last resource.
2023-02-02 13:37:11 -03:00
Roberto Ierusalimschy d69789da1c Fix absence of 'system' in iOS
Despite claiming to be ISO, the C library in some Apple platforms
does not implement 'system'.
2023-01-24 15:04:17 -03:00
Roberto Ierusalimschy 314745ed84 Avoid excessive name pollution in test files
Test files are more polite regarding the use of globals when locals
would do, and when globals are necessary deleting them after use.
2022-12-28 18:34:11 -03:00
Roberto Ierusalimschy 0825cf237d Detail in make file for testes/libs
Everything depends on the Lua version (as given by 'lua.h')
2022-12-23 11:28:11 -03:00
Roberto Ierusalimschy f874d37fa2 Small change in barrier macros
Reuse macros for objects when defining the macros for values.
2022-12-15 14:18:03 -03:00
Roberto Ierusalimschy 35e01ed21d Small improvements in 'lmem.c'
Added some auxiliary macros + fixed a bug in compilation option
EMERGENCYGCTESTS. (It should not try to force an emergency collection
when it cannot run one.)
2022-12-15 10:44:55 -03:00
Roberto Ierusalimschy 6aabf4b15e Details in some header files
Identifier LUA_NUMTAGS was deprecated (changed to LUA_NUMTYPES) +
better handling of some inclusion loops.
2022-12-14 16:20:39 -03:00
Roberto Ierusalimschy fa2f294dd1 Reduce calls to 'luaC_step' when GC is stopped 2022-12-09 16:35:19 -03:00
Roberto Ierusalimschy 82fae58e25 Details
Parentheses and comments.
2022-12-02 11:33:09 -03:00
Roberto Ierusalimschy 9a77f57edc Stop GC while building initial state 2022-11-23 14:17:28 -03:00
Roberto Ierusalimschy be908a7d4d Removed unused field 'UpVal.tbc' 2022-11-08 10:15:10 -03:00
Roberto Ierusalimschy 9ede317c70 Threads are created like other objects
Using a version of 'luaC_newobj' that allows offsets (extra space
before the object itself).
2022-11-01 17:14:01 -03:00
Roberto Ierusalimschy ee645472eb Stack reallocation done with a single realloc
To avoid the need of both the old and the new stack addresses valid
at the same time, to correct the pointers to the stack, these pointers
are changed to offsets before the reallocation and then changed back
to pointers after the reallocation.
2022-10-31 15:06:20 -03:00
Roberto Ierusalimschy 413a393e62 Stack indices changed to union's
That will allow to change pointers to offsets while reallocating
the stack.
2022-10-29 12:06:37 -03:00
Roberto Ierusalimschy ba089bcb08 Details
Added comments in the makefile about other useful '-fsanitize' options.
2022-10-26 10:15:09 -03:00
Roberto Ierusalimschy 1e64c1391f Bug: stack overflow with nesting of coroutine.close 2022-10-25 16:44:06 -03:00
Roberto Ierusalimschy b85816b9a8 Removed test function 'luaH_isdummy'
It was not being used anywhere.
2022-10-21 09:18:13 -03:00
Roberto Ierusalimschy c954db3924 Option '-l g=mod' added to the manual
Plus some other improvements in the manual.
2022-10-19 16:30:39 -03:00
Roberto Ierusalimschy 14d2803e55 Details
Some cast operations rewritten to use respective macros.
2022-10-19 16:29:54 -03:00
Roberto Ierusalimschy 7f12bf40c4 Portability issue in a test for 'string.format' 2022-10-19 16:20:11 -03:00
Roberto Ierusalimschy 26be27459b Negation in constant folding of '>>' may overflow 2022-09-23 11:08:10 -03:00
Roberto Ierusalimschy cfbe378f90 Small simplification in overflow check in 'getfield'
Subtracting a small non-negative int from a non-negative int cannot
overflow, and adding a non-negative int to INT_MIN cannot overflow.
2022-09-23 10:57:35 -03:00
Roberto Ierusalimschy a1089b415a Bug: 'utf8.codes' accepts spurious continuation bytes 2022-09-23 10:41:16 -03:00
Roberto Ierusalimschy f8c4c4fcf2 New test for table rehash 2022-09-16 17:05:22 -03:00
Roberto Ierusalimschy 71bc69c2af Note in the manual about using '...' as an expression 2022-09-08 17:21:02 -03:00
Roberto Ierusalimschy cd56f222b7 Corrected error message in 'table.remove' 2022-09-07 12:21:46 -03:00
Roberto Ierusalimschy 69b77b6fde Changed the growth rate of string buffers
The growth rate of string buffers was reduced from 2 to 1.5 (3/2).
As string buffers start larger (256~1024 bytes), they don't need to
grow that fast. Moreover, a lower rate allows multiplicative growth up
to larger sizes (3/2 of the maximum). (After that, the growth becomes
linear, which is mostly useless.)
2022-09-06 10:58:55 -03:00
Roberto Ierusalimschy 997f11f543 Bug: 'break' may not properly close variable in a 'for' loop
Function 'leaveblock' was generating "break" label before removing
variables from the closing block. If 'createlabel' created a 'close'
instruction (which it did when matching a goto/break that exited
the scope of an upvalue), that instruction would use the wrong level.
2022-08-24 17:36:47 -03:00
Roberto Ierusalimschy 02060b7a37 Simpler handling of Byte Order Mark (BOM) 2022-08-23 16:08:53 -03:00
Roberto Ierusalimschy a1f77a234a Bug: set correct pause when (re)entering gen. collection. 2022-08-23 16:06:23 -03:00
Roberto Ierusalimschy c6cea857a4 Better documentation for 'multires' expressions
Manual has a new section explaining multires expressions, lists of
expressions, and adjustments. This commit also corrects some comments
in the code.
2022-08-19 14:10:18 -03:00
Roberto Ierusalimschy d61b0c6028 More checks and documentation for uses of EXTRA_STACK 2022-05-26 15:14:54 -03:00
Roberto Ierusalimschy 196bb94d66 Bug: 'lua_settop' may use an invalid pointer to stack 2022-05-25 17:41:39 -03:00
Roberto Ierusalimschy 603b2c64ad 'luaV_concat' can use invalidated pointer to stack
Bug introduced in commit 42d40581.
2022-05-23 17:50:47 -03:00
Roberto Ierusalimschy 4a00f61276 'lua_checkstack' doesn't need to check stack overflow
'luaD_growstack' already checks that. This commit also fixes an
internal bug in 'luaD_growstack': a large 'n' could cause an arithmetic
overflow when computing 'needed'.
2022-05-23 10:38:03 -03:00
Roberto Ierusalimschy 42d40581dd Save stack space while handling errors
Because error handling (luaG_errormsg) uses slots from EXTRA_STACK,
and some errors can recur (e.g., string overflow while creating an
error message in 'luaG_runerror', or a C-stack overflow before calling
the message handler), the code should use stack slots with parsimony.

This commit fixes the bug "Lua-stack overflow when C stack overflows
while handling an error".
2022-05-20 13:14:33 -03:00
Roberto Ierusalimschy e435aaabef Details (identation and typos) 2022-05-10 11:13:39 -03:00
Roberto Ierusalimschy 315639d3bb Factoring out common parts of 'codearith' and 'codebitwise' 2022-05-06 17:52:46 -03:00
Roberto Ierusalimschy c764ca71a6 Bug: Wrong code generation in bitwise operations 2022-04-25 14:42:51 -03:00
Roberto Ierusalimschy 295cde9454 New release number (5.4.5) 2022-04-07 10:52:15 -03:00
Roberto Ierusalimschy f3cfd5bf2b Details
Comments + manual + identation + asserts about stack limits that were
not allowing the use of the full stack
2022-04-01 13:55:44 -03:00
Roberto Ierusalimschy 8426d9b4d4 Avoid computing invalid addresses
luaV_execute should compute 'ra' only when the instruction uses it.
Computing an illegal address is undefined behavior even if the address
is never dereferenced.
2022-02-18 13:22:25 -03:00
Roberto Ierusalimschy 1f3c6f4534 Bug: Lua can generate wrong code when _ENV is <const> 2022-02-15 12:28:46 -03:00
Roberto Ierusalimschy 25b143dd34 Bug: lua.c assumes that argv has at least one element 2022-02-07 10:16:35 -03:00
Roberto Ierusalimschy 5d708c3f9c Explanation of borders in the manual
The explanation includes the limit case of maxinteger being a border.
It also avoids the term "natural", which might include large floats
with natural values.
2022-01-13 08:15:03 -03:00
Roberto Ierusalimschy 8dd2c912d2 Detail
Warnings with clang when using long double for Lua floats.
2022-01-03 09:12:17 -03:00
Roberto Ierusalimschy 05ac2409ee New year (2022) 2022-01-02 07:11:08 -03:00
Roberto Ierusalimschy 597a53bbc6 Bug: finalizer calling exit can corrupt finalization order
'os.exit' can call lua_close again, separating new finalizers
created after all previous finalizers were already separated.
2021-12-22 09:00:52 -03:00
Roberto Ierusalimschy 86ec152433 Details
correction in macro for hard tests + type in comment
2021-12-21 07:39:25 -03:00
Roberto Ierusalimschy cf613cdc6f Bug: finalizers can be called with an invalid stack
The call to 'checkstackGC' can run finalizers, which will find an
inconsistent CallInfo, as 'ci' is half updated at the point of call.
2021-12-15 11:29:07 -03:00
Roberto Ierusalimschy 066e0f93c4 Fix debug information about finalizers
The flag CIST_FIN does not mark a finalizer, but the function that was
running when the finalizer was called. (So, the function did not call
the finalizer, but it looks that way in the stack.)
2021-12-14 12:50:05 -03:00
Roberto Ierusalimschy 0bfc572e51 Bug: GC is not reentrant
As the GC is not reentrant, finalizers should not be able to invoke it.
2021-12-13 10:41:17 -03:00
Roberto Ierusalimschy 1de95e97ef Bug: Lua stack still active when closing a state 2021-12-10 10:53:54 -03:00
Roberto Ierusalimschy ad3942adba Main 'mainposition' replaced by 'mainpositionTV'
Handle values in table keys as the special cases they are, and not
the other way around.
2021-11-25 11:07:17 -03:00
Roberto Ierusalimschy 48835c76c8 Wrong assert in 'collectvalidlines' 2021-11-25 10:11:05 -03:00
Roberto Ierusalimschy 6b3e116d44 Corrected bug in 'luaD_tryfuncTM'
The pointer to the metamethod can be invalidated by a finalizer that
can run during a GC in 'checkstackGCp'. (This commit also fixes a
detail in the manual.) Bug introduced in commit 91673a8ec.
2021-11-16 14:35:06 -03:00
Roberto Ierusalimschy e8deac5a41 Avoid OP_VARARGPREP for active lines
when building the table 'activelines' for a vararg function, this
first instruction does not make the first line active.
2021-11-10 15:07:14 -03:00
Roberto Ierusalimschy bfbff3703e Bug: Wrong status in coroutine during reset
When closing variables during 'coroutine.close' or 'lua_resetthread',
the status of a coroutine must be set to LUA_OK; a coroutine should
not run with any other status. (See assertion in 'lua_callk'.)

After the reset, the status should be kept as normal, as any error
was already reported.
2021-11-08 11:55:25 -03:00
Roberto Ierusalimschy 74d99057a5 Bug: C stack overflow with coroutines
'coroutine.resume' did not increment counter of C calls when
continuing execution after a protected error (that is,
while running 'precover').
2021-11-03 15:04:18 -03:00
Roberto Ierusalimschy 1fce5bea81 More uniform implementation for tail calls
'luaD_pretailcall' mimics 'luaD_precall', handling call metamethods
and calling C functions directly. That makes the code in the
interpreter loop simpler.

This commit also goes back to emulating the tail call in 'luaD_precall'
with a goto, as C compilers may not do proper tail calls and the C
stack can overflow much sooner than the Lua stack (which grows as the
metamethod is added to it).
2021-10-29 13:41:24 -03:00
Roberto Ierusalimschy 3699446aaf Removed goto's in 'luaD_precall'
(plus a detail in lauxlib.h.)
2021-10-18 11:58:40 -03:00
Roberto Ierusalimschy 0e5071b5fb Avoid taking the address of a 'TValue' field
That structure can be packed in the future.
2021-10-11 13:52:26 -03:00
Roberto Ierusalimschy 87a9573b2e Documentation
Better explanation about the guaranties of multiple assignment in
the manual.
2021-10-11 13:49:13 -03:00
Roberto Ierusalimschy deac067ed3 Avoid overflows when incrementing parameters in C
Any C function can receive maxinteger as an integer argument, and
therefore cannot increment it without some care (e.g., doing unsigned
arithmetic as the core does).
2021-09-22 13:10:39 -03:00
Roberto Ierusalimschy 2ff3471722 Using 'inline' in some functions
According to ISO C, "making a function an inline function suggests that
calls to the function be as fast as possible." (Not available in C89.)
2021-09-15 11:18:41 -03:00
Roberto Ierusalimschy 9db4bfed6b Revamp of format validation in 'string.format'
When calling 'sprintf', not all conversion specifiers accept all
flags; some combinations are undefined behavior.
2021-09-03 13:14:56 -03:00
Roberto Ierusalimschy 91673a8ec0 'luaD_tryfuncTM' checks stack space by itself 2021-08-18 12:05:06 -03:00
Roberto Ierusalimschy 41871f1803 Undo simplification of tail calls (commit 901d760)
Not that simpler and slower.
2021-08-18 11:21:33 -03:00
Roberto Ierusalimschy a393ac2554 Detail in 'testes/math.lua'
Added a print with the random seeds used in the tests of 'random'.
2021-08-18 10:46:18 -03:00
Roberto Ierusalimschy 65434b4d1b Option '-l' can give a name for the global variable.
Sintax for this option now is '-l [globname=]modname'.
2021-08-16 13:57:19 -03:00
Roberto Ierusalimschy 59acd79c05 Added tests for string reuse by the scanner 2021-08-11 11:19:33 -03:00
Roberto Ierusalimschy e2c07dcbf7 Improved documentation for 'lua_getinfo' 2021-08-11 11:18:10 -03:00
Roberto Ierusalimschy 439e45a2f6 Bug: luaL_tolstring may get confused with negative index
When object has a '__name' metafield, 'luaL_tolstring' used the
received index after pushing a string on the stack.
2021-07-22 13:48:43 -03:00
Roberto Ierusalimschy 62fb934427 Bug: Negation in 'luaV_shiftr' may overflow
Negation of an unchecked lua_Integer overflows with mininteger.
2021-07-22 13:44:53 -03:00
Roberto Ierusalimschy 8a32e0aa4a Correction on documentation of string-buffer operations
All string-buffer operations can potentially change the stack in
unspecified ways; the push/pop documentation in the manual should
reflect that.
2021-07-21 11:33:58 -03:00
Roberto Ierusalimschy dbdc74dc55 Simplification in the parameters of 'luaD_precall'
The parameters 'nresults' and 'delta1', in 'luaD_precall', were never
meaningful simultaneously. So, they were combined in a single parameter
'retdel'.
2021-06-30 12:53:21 -03:00
Roberto Ierusalimschy 6a0dace25a Bug: 'local function' can assign to '<const>' variables 2021-06-20 15:36:36 -03:00
Roberto Ierusalimschy 04e19712a5 C functions can be tail called, too
A tail call to a C function can have the behavior of a "real" tail
call, reusing the stack frame of the caller.
2021-06-14 13:28:21 -03:00
Roberto Ierusalimschy 901d760093 Simpler implementation for tail calls
Tail calls handled by 'luaD_precall', like regular calls, to avoid
code duplication.
2021-06-11 13:41:07 -03:00
Roberto Ierusalimschy c0ed74c1e1 Avoid the term "undefined behavior" in the manual 2021-06-09 13:24:49 -03:00
Roberto Ierusalimschy fc6c74f100 'index2value' more robust
'index2value' accepts pseudo-indices also when called from a Lua
function, through a hook.
2021-05-24 16:48:43 -03:00
Roberto Ierusalimschy 1e6918d553 Details
- Removed unused (and trivial) definition LUA_UNSIGNEDBITS
- Alignment structure in pack/unpack moved to a narrower scope
2021-05-24 16:48:09 -03:00
Roberto Ierusalimschy 681297187e Bug: yielding in '__close' mess up number of returns
Yielding in a __close metamethod called when returning vararg results
changes the top and so messes up the number of returned values.
2021-04-16 15:41:44 -03:00
Roberto Ierusalimschy 5148954eed Align error messages for calling non-callable values
'pcall(foo)' message was "attempt to call a table value", while
'pcall(function () foo() end) message was "global 'foo' is not callable".
2021-04-12 16:50:34 -03:00
Roberto Ierusalimschy d205f3a484 Bug: Lua source should not use C99 comments ("//") 2021-04-10 10:19:21 -03:00
Roberto Ierusalimschy 47cffdc723 Bug: tbc variables in "for" loops don't avoid tail calls 2021-04-07 14:59:26 -03:00
Roberto Ierusalimschy 36de01d988 Changes in cache for function constants
In 'lcode.c', when adding constants to the list of constants of a
function, integers represent themselves in the cache and floats
with integral values get a small delta to avoid collision with
integers. (This change avoids creating artificial addresses; the old
implementation converted integers to pointers to index the cache.)
2021-03-30 14:49:18 -03:00
Roberto Ierusalimschy 7fbe215808 New hash function for integer keys
When integer keys do not form a sequence, it is better to use all their
bits to compute their hashes. (The previous implementation was quite bad
for integer keys with common lower bits, and disastrous for integer keys
changing only in their upper 32 bits.)
2021-03-29 15:47:18 -03:00
Roberto Ierusalimschy bf10593a3a Allow yields inside '__pairs' 2021-03-29 12:57:32 -03:00
Roberto Ierusalimschy bef250eb8d Details
Comments and small improvements in the manual.
2021-03-29 11:47:12 -03:00
Roberto Ierusalimschy ba81adaad9 Next release number (5.4.4) 2021-03-29 11:26:07 -03:00
Roberto Ierusalimschy eadd8c7178 Added option LUA_NOBUILTIN
This option allows external code to avoid the use of gcc builtin macro
'__builtin_expect' in the Lua API.
2021-03-12 15:03:33 -03:00
Roberto Ierusalimschy 014daf43cb Details
Comments and order of hashing macros in 'ltable.c'.
2021-03-12 11:29:34 -03:00
Roberto Ierusalimschy 05b13651f9 File 'tracegc.lua' added to 'packtests' 2021-03-10 10:35:57 -03:00
Roberto Ierusalimschy 81c6021fb4 New implementation for 'tbclist'
- Fixes a bug, by removing dummy nodes together with the node
itself. (The previous implementation could leave dummy nodes in frames
which otherwise had no tbc variables, and therefore would not close
variables; that could leave 'tbclist' pointing higher than 'top', which
could dangle if the stack shrank.)

- Computes MAXDELTA based on the type of delta, to ease changing its
type if needed.

- Instead of 'isdummy', uses 'delta==0' to signal dummy nodes. (Dummy
nodes always have MAXDELTA for their real delta.)
2021-03-10 10:27:19 -03:00
Roberto Ierusalimschy a7b8b27dd3 Uses of "likely" in macros active to all users
The use of 'l_likely' in auxlib macros 'luaL_argcheck' and
'luaL_argexpected' should not be restricted to Lua's own code.
For that, 'l_likely' was renamed to 'luai_likely' to be exported
to external code.
2021-03-09 12:50:59 -03:00
Roberto Ierusalimschy 511d53a826 lua_settop/lua_pop closes to-be-closed variables
The existence of 'lua_closeslot' is no reason for lua_pop not to close
to-be-closed variables too.  It is too error-prone for lua_pop not to
close tbc variables being popped from the stack.
2021-03-09 11:42:45 -03:00
Roberto Ierusalimschy f5df7f91f7 Wrong assertion in 'getbaseline'
The assertion cannot compute 'f->abslineinfo[i]' when the initial
estimate 'i' is -1.
2021-03-05 12:10:34 -03:00
Roberto Ierusalimschy e7803f7dbc New release number (5.4.3) 2021-03-03 09:44:20 -03:00
Roberto Ierusalimschy b7eb21c1ef Normalization of metamethod typography in the manual 2021-03-02 13:50:00 -03:00
Roberto Ierusalimschy cf23a93d82 Added assertions for proper use of string buffers 2021-03-02 11:39:42 -03:00
Roberto Ierusalimschy 9a2de786de Stack check in warning function for tests
The warning function using for tests need to check the stack before
pushing anything. (Warning functions are not expected to access a
Lua state, therefore they have no preallocated stack space.)
2021-03-02 11:35:40 -03:00
Roberto Ierusalimschy 5276973224 New test module 'tracegc'
New module easies the inclusion of GC tracing in individual test files.
2021-03-01 13:54:29 -03:00
Roberto Ierusalimschy f9d857a81b Stack reallocation done in two phases
$he stack reallocation is done in two steps (allocation + free) because
the correction of the pointers pointing into the stack must be done
while both addresses (the old stack and the new one) are valid.  In ISO
C, any pointer use after the pointer has been deallocated is undefined
behavior. The compiler option '-fsanitize=pointer-subtract' (plus what
it needs to work) complained about the old implementation.
2021-02-27 12:56:09 -03:00
Roberto Ierusalimschy 1537d6680b New control for reentrancy of emergency collections
Instead of assuming that shrinking a block may be an emergency
collection, use an explicit field ('gcstopem') to stop emergency
collections while GC is working.
2021-02-26 11:41:02 -03:00
Roberto Ierusalimschy e0260eb2d4 Bug (kind of) in 'isinstack'
The function 'isinstack' tried to work around the undefined behavior
of subtracting two pointers that do not point to the same object,
but the compiler killed to trick. (It optimizes out the safety check,
because in a correct execution it will be always true.)
2021-02-25 13:39:36 -03:00
Roberto Ierusalimschy 5205f073c5 Don't use tointegerns when luaV_tointegerns will do
Some places don't need the "fast path" macro tointegerns, either
because speed is not essential (lcode.c) or because the value is not
supposed to be an integer already (luaV_equalobj and luaG_tointerror).
Moreover, luaV_equalobj should always use F2Ieq, even if Lua is
compiled to "round to floor".
2021-02-24 12:24:42 -03:00
Roberto Ierusalimschy 31925e4cc2 Details
Added documentation and asserts that constants for arithmetic opcodes
must be numbers.
2021-02-24 11:30:46 -03:00
Roberto Ierusalimschy 59c88f846d Broadening the use of branch hints
More uses of macros 'likely'/'unlikely' (renamed to
'l_likely'/'l_unlikely'), both in range (extended to the
libraries) and in scope (extended to hooks, stack growth).
2021-02-24 11:14:44 -03:00
Roberto Ierusalimschy c03c527fd2 Bug: 'string.concat' error message uses wrong format 2021-02-15 13:31:45 -03:00
Roberto Ierusalimschy 38cc7d40a4 Bug: cannot allow the call 'debug.getinfo(0, ">")'
A 'what' argument starting with '>' indicates that there is a function
in the C stack, which won't be there if the first argument is not a
function.
2021-02-15 10:38:09 -03:00
Roberto Ierusalimschy bc970005ce '__close' methods can yield in the return of a C function
When, inside a coroutine, a C function with to-be-closed slots return,
the corresponding metamethods can yield. ('__close' metamethods called
through 'lua_closeslot' still cannot yield, as there is no continuation
to go when resuming.)
2021-02-12 13:36:30 -03:00
Roberto Ierusalimschy f79ccdca9b Eases the use of clang in the makefile
New definition in the makefile for warnings that are valid for gcc but
not for clang (CWARNGCC).
2021-02-10 14:11:51 -03:00
Roberto Ierusalimschy 4e47f81188 New implementation for to-be-closed variables
To-be-closed variables are linked in their own list, embedded into the
stack elements. (Due to alignment, this information does not change
the size of the stack elements in most architectures.)  This new list
does not produce garbage and avoids memory errors when creating tbc
variables.
2021-02-09 14:00:05 -03:00
Roberto Ierusalimschy c63e5d212b New macro 'completestate' 2021-02-05 17:51:25 -03:00
Roberto Ierusalimschy dee6433a89 Forbid changing numerical types through compiler options
'luaconf.h' always defines options LUA_32BITS, LUA_C89_NUMBERS,
LUA_INT_TYPE, and LUA_FLOAT_TYPE (using 0/1 for the first two),
to avoid they being set through compiler options. (It is too easy
to forget these options when compiling other software that
interoperates with Lua.)
2021-02-05 15:30:34 -03:00
Roberto Ierusalimschy 2bfa13e520 Fixed some bugs around stack reallocation
Long time without using HARDSTACKTESTS...
2021-02-05 11:00:28 -03:00
Roberto Ierusalimschy e500892e18 Optimization/simplification of 'getbaseline'
By producing absolute line information at regular intervals, a simple
division can compute the correct entry for a given instruction.
2021-02-02 14:43:55 -03:00
Roberto Ierusalimschy 949187b049 Optimizations for line hook
The function 'changedline' tries harder to avoid calling
'luaG_getfuncline' plus small changes in the use of 'L->oldpc'.
2021-01-28 14:40:29 -03:00
Roberto Ierusalimschy 58aa09a0b9 Small improvements in hooks
- 'L->top' is set once in 'luaD_hook', instead of being set in
'luaD_hookcall' and 'rethook';

- resume discard arguments when returning after an yield inside a hook
(arguments may interfere with the coroutine stack);

- yield inside a hook asserts it has no arguments.
2021-01-26 16:53:51 -03:00
Roberto Ierusalimschy 1f81baffad Janitorial work
Comments, code details, identation.
2021-01-25 10:39:18 -03:00
Roberto Ierusalimschy 0e9254dfa0 Correct order of return hooks vs. close metamethods
The return hook should be called only after closing variables (which
are still part of the function). C functions were calling the hook
before the metamethods.
2021-01-21 10:27:22 -03:00
Roberto Ierusalimschy 6ccd24eff5 Simpler handling of errors when creating tbc variables
New field 'lua_State.ptbc' keeps to-be-closed variable until its
upvalue is created, so that it can be closed in case of a
memory-allocation error.
2021-01-19 10:03:13 -03:00
Roberto Ierusalimschy d0f34d9137 Allow yields in '__close' metamethods ater errors
Completes commit b07fc10e91. '__close' metamethods can yield even
when they are being called due to an error. '__close' metamethods from
C functions are still not allowed to yield.
2021-01-18 11:40:45 -03:00
Roberto Ierusalimschy 825ac8eca8 Corrected documentation for 'table.sort'
The sort function must define a (strict) weak order for a correct
sorting. A partial order is not enough.
2021-01-14 13:26:55 -03:00
Roberto Ierusalimschy b07fc10e91 Allow yields inside '__close' metamethods
Initial implementation to allow yields inside '__close' metamethods.
This current version still does not allow a '__close' metamethod
to yield when called due to an error. '__close' metamethods from
C functions also are not allowed to yield.
2021-01-13 13:54:10 -03:00
Roberto Ierusalimschy cc1692515e New API function 'lua_closeslot'
Closing a to-be-closed variable with 'lua_settop' is too restrictive,
as it erases all slots above the variable. Moreover, it adds side
effects to 'lua_settop', which should be a fairly basic function.
2021-01-11 15:03:01 -03:00
Roberto Ierusalimschy ce101dcaf7 Handles '__close' errors in coroutines in "coroutine style"
Errors in '__close' metamethods in coroutines are handled by the same
logic that handles other errors, through 'recover'.
2020-12-30 11:20:22 -03:00
Roberto Ierusalimschy 553b37ce4f Do not insert nil values into tables 2020-12-29 13:38:47 -03:00
Roberto Ierusalimschy 4bd10b6fe8 Better error messages for calling non-callable objects
When available, use the calling code to find a suitable name for what
was being called; this is particularly useful for errors of non-callable
metamethods. This commit also improved the debug information for
order metamethods.
2020-12-29 13:15:54 -03:00
Roberto Ierusalimschy 59e565d955 No need to recheck close method before calling it
A to-be-closed variable is constant and it must have a close metamethod
when it is created. A program has to go out of its way (e.g., by
changing the variable's metamethod) to invalidate that check. So,
it is not worth to test that again. If the program tampers with the
metamethod, Lua will raise a regular error when attempting to call it.
2020-12-29 10:23:02 -03:00
Roberto Ierusalimschy 6188f3a654 Reset thread before panicking
Before panicking, it is simpler to reset the thread instead of closing
its variables and adjust the top manually.
2020-12-28 16:34:07 -03:00
Roberto Ierusalimschy 7af27ef59d Cleaner handling of errors in '__close' metamethods
Instead of protecting each individual metamethod call, protect the
entire call to 'luaF_close'.
2020-12-28 11:40:30 -03:00
Roberto Ierusalimschy 0ceada8da9 Report last error in closing methods
When there are multiple errors around closing methods, report the
last error instead of the original.
2020-12-22 10:54:25 -03:00
Roberto Ierusalimschy f9d29b0c44 Upvalues removed from 'openupval' before being closed
Undo commit c220b0a5d0: '__close' is not called again in case of
errors. (Upvalue is removed from the list before the call.) The
common error that justified that change was C stack overflows, which
are much rarer with the stackless implementation.
2020-12-21 15:21:45 -03:00
Roberto Ierusalimschy 409256b784 'coroutine.close'/'lua_resetthread' report original errors
Besides errors in closing methods, 'coroutine.close' and
'lua_resetthread' also consider the original error that stopped the
thread, if any.
2020-12-18 11:22:42 -03:00
Roberto Ierusalimschy b17178b27a Cleaner handling of floats in pack/unpack 2020-12-16 11:23:51 -03:00
Roberto Ierusalimschy e1ceea5674 Cleaner definition for macro 'ttisclosure' 2020-12-16 11:02:40 -03:00
Roberto Ierusalimschy 748d6d4e7a Review of asserts in 'ltests.c'
The module 'ltests.c' must work correctly with asserts off, too.
2020-12-08 11:54:21 -03:00
Roberto Ierusalimschy e2ea3b31c9 Details (do not affect regular code)
* Avoids multiple definitions of 'lua_assert' in test file.
* Smaller C-stack limit in test mode.
* Note in the manual about the use of false
* Extra test for constant reuse.
2020-12-07 11:17:30 -03:00
Roberto Ierusalimschy 23051e830a Changes in the API of 'luaH_set' and related functions
Functions to set values in a table (luaH_set, luaH_newkey, etc.) receive
the new value, instead of returning a slot where to put the value.
2020-12-04 11:08:42 -03:00
Roberto Ierusalimschy f15589f3b0 Added test cases for error messages about goto/label 2020-12-03 12:11:15 -03:00
Roberto Ierusalimschy 754ca0060f n Windows, 'popen' accepts "[rw][bt]?" as valid modes
Added the modifiers 'b' and 't' to valid modes for 'popen' in Windows.
2020-12-03 12:09:50 -03:00
Roberto Ierusalimschy c36ced53c9 Avoid "bad programming habits" in the reference system
References were using both 0 indices and nils as values in arrays.
Both do not fit in the concept of a sequence, which is the kind
of use that guides all Lua optimizations.
2020-12-03 12:00:32 -03:00
Roberto Ierusalimschy d41c36bf67 'lua_assert' moved from 'lualib.h' to 'lauxlib.h'
The macro is useful also in 'lauxlib.c', which does not include
'lualib.h'. Also, the definition was corrected to be "on" when
LUAI_ASSERT is defined.
2020-12-03 10:39:38 -03:00
Roberto Ierusalimschy d9d2904f09 Details
Names in the parser and other details that do not change actual code.
2020-12-02 15:13:13 -03:00
Roberto Ierusalimschy 65d2294454 Changed access to global table in the registry
The global table is always in the array part of the registry; we can
use this fact to make its access slightly more efficient.
2020-11-26 18:23:40 -03:00
Roberto Ierusalimschy 131e3fd814 Avoid using 'signal' when 'sigaction' is available
The semantics of 'signal' varies a lot among different implementations;
'sigaction' ensures a more consistent behavior.
2020-11-24 14:41:50 -03:00
Roberto Ierusalimschy 9d067ab73b Optimization for 'n^2'
Squares are much more common than other exponentiations, and 'n*n' is
much more efficient than 'pow'.
2020-11-13 09:59:07 -03:00
Roberto Ierusalimschy 2f4162bc47 Compiler optimization back to '-O2'
Undo commit 6a10f03ff. Compiler performance is important, too.
2020-11-11 15:10:51 -03:00
Roberto Ierusalimschy ab1aca94e8 Removed optimization for «if ... then goto»
That optimization was too complex and caused some weird traces when
debugging. The more common case «if ... then break» was kept.
2020-11-11 14:41:41 -03:00
Roberto Ierusalimschy d282652561 Bug when growing a stack
When a stack grows, its extra area can be in use, and it becomes part
of the common area. So, the extra area must be kept correct all the
times. (Bug introduced by commit 5aa36e894f5.)
2020-11-08 11:52:26 -03:00
Roberto Ierusalimschy 58216600eb 'luaL_newstate' should not allocate extra memory
The allocation of a userdata for the state of the warn system can
cause a panic if it fails; 'luaL_ref' also can fail. This commit
re-implements the warn system so that it does not need an explicit
state. Instead, the system uses different functions to represent
the different states.
2020-11-03 16:34:36 -03:00
Roberto Ierusalimschy 94cbe46511 Details
- small corrections in the manual
- ldo.c: 'docall' -> 'ccall' ('docall' already used in 'lua.c')
- comments
2020-10-30 10:18:54 -03:00
Roberto Ierusalimschy 69b71a6919 _PROMPT can have non-string values
'get_prompt' uses 'luaL_tolstring' to convert _PROMPT or _PROMPT2
value to a string. That conversion may invoke a '__tostring'
metamethod.
2020-10-26 11:15:51 -03:00
Roberto Ierusalimschy d742a193e5 Comments 2020-10-22 15:54:46 -03:00
Roberto Ierusalimschy e4a38eb0e8 Fixed wrong trace of vararg functions
Trace of vararg functions was skipping an instruction when returning
from a call. (Bug introduced by commit 5d8ce05b3.)
2020-10-19 15:55:25 -03:00
Roberto Ierusalimschy f07de22576 Fixed compiler option -DHARDSTACKTESTS to commit 5aa36e8 2020-10-19 15:43:59 -03:00
Roberto Ierusalimschy 52c8679760 Fixed bug of keys removed from tables vs 'next'
Fixed the bug that a key removed from a table might not be found
again by 'next'. (This is needed to allow keys to be removed during a
traversal.) This bug was introduced in commit 73ec04fc.
2020-10-14 15:46:58 -03:00
Roberto Ierusalimschy 849b2ecbd2 New release number (5.4.2) 2020-10-12 14:52:39 -03:00
Roberto Ierusalimschy 30528049f1 'lua_upvalueid' returns NULL on invalid upvalue index 2020-10-12 14:51:28 -03:00
Roberto Ierusalimschy 9a89fb1c9d Hash always use all characters in a long string
Hashes for long strings are computed only when they are used as keys
in a table, not a too common case. And, in that case, it is to easy to
force collisions changing only the characters which are not part of the
hash.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy c23cc86c54 Details
- After converting a generic GCObject to a specific type ('gco2*'),
  avoid using the original GCObject (to reduce aliasing).
- Small corrections in comments in 'lopcodes.h'
- Added tests about who calls __close metamethods
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 171dcd7d74 'recover' finish of 'luaD_pcall' should follow the original 2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 5aa36e894f No more field 'lua_State.stacksize'
The stack size is derived from 'stack_last', when needed. Moreover,
the handling of stack sizes is more consistent, always excluding the
extra space except when allocating/deallocating the array.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 9ecd446141 Avoid shrinking stacks to often
Shrink a stack only when the final stack size can be at most 2/3 the
previous size with half of its entries empty. This commit also
improves the clarity of 'luaD_growstack'.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy fb172d0a92 No need for 'volatile' in string.pack/unpack
Type punning an address to 'char *' should be always safe.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 0085db4596 Avoid GCs when testing stack overflow
A GC step may invoke some finalizer, which may error and emit
a warning due to stack overflfow.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 490d42b5f8 Correct handling of 'luaV_execute' invocations
The previous stackless implementations marked all 'luaV_execute'
invocations as fresh. However, re-entering 'luaV_execute' when
resuming a coroutine should not be a fresh invocation. (It works
because 'unroll' called 'luaV_execute' for each call entry, but
it was slower than letting 'luaV_execute' finish all non-fresh
invocations.)
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 287b302acb Revision of stackless implementation
- more organized handling of 'nCcalls'
- comments
- deprecation of 'setcstacklimit'
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy 5d8ce05b3f Back to a stackless implementation
A "with stack" implementation gains too little in performance to be
worth all the noise from C-stack overflows.

This commit is almost a sketch, to test performance. There are several
pending stuff:

- review control of C-stack overflow and error messages;
- what to do with setcstacklimit;
- review comments;
- review unroll of Lua calls.
2020-10-12 12:29:09 -03:00
Roberto Ierusalimschy f83de8e34e Wrong cast in 'str_unpack' 2020-09-30 15:10:12 -03:00
Roberto Ierusalimschy 9f791535cd Merge branch 'master' of https://github.com/lua/lua
Adding file README.md to local repository.
2020-09-29 10:25:50 -03:00
lhf 51c29ec0c4 Create README.md 2020-09-28 14:34:44 +00:00
Roberto Ierusalimschy fbaf040f5e Details in the manual 2020-09-25 10:49:29 -03:00
Roberto Ierusalimschy e51564d1be Details in comments and documentation 2020-09-16 14:57:51 -03:00
Roberto Ierusalimschy 98ec799591 Detail
Code for multi-character tokens can start right after maximum char.
2020-09-15 14:29:52 -03:00
Roberto Ierusalimschy b6888a158b New release number (5.4.1) 2020-09-15 14:27:10 -03:00
Roberto Ierusalimschy 613513d09f Better documentation for the GC of strings in the C API
Plus some other small changes.
2020-09-09 17:28:25 -03:00
Roberto Ierusalimschy 8496112a18 Better documentation for 'lctype.h'
The old documentation said that 'ltolower' only works for alphabetic
characters. However, 'l_str2d' uses it (correctly) also on dots ('.').
2020-09-03 09:52:43 -03:00
Roberto Ierusalimschy 6bc0f13505 Fixed bug of long strings in binary chunks
When "undumping" a long string, the function 'loadVector' can call the
reader function, which can run the garbage collector, which can collect
the string being read. So, the string must be anchored during the call
to 'loadVector'.
2020-08-18 14:42:11 -03:00
Roberto Ierusalimschy 8a89da07ba Better control of gray objects
Avoid turning an object to gray except at the moment it is inserted in a
gray list or in the explicit exceptional cases such as open upvalues and
fixed strings.
2020-08-17 15:38:51 -03:00
Roberto Ierusalimschy f849885a4b Small changes in macros that change GC colors
- Macro 'gray2black' was renamed 'nw2black' (Non-White to black), as it
was already being used on objects that could be already black.

- Macros 'white2gray' and 'black2gray' were unified in 'set2gray'; no
reason to have two macros when one will do and, again, 'black2gray' was
already being used on objects that could be already gray.

Moreover, macros 'maskcolors' and 'maskgcbits' were negated to have
ones in the described bits, instead of zeros. (This naming seems more
intuitive.)
2020-08-13 15:23:21 -03:00
Roberto Ierusalimschy f7ce7e5faa TOUCHED2 objects are not always black
This commit fixes a bug introduced in commit 9cf3299fa. TOUCHED2
objects are always black while the mutator runs, but they can become
temporarily gray inside a minor collection (e.g., if the object is a
weak table).
2020-08-13 14:31:27 -03:00
Roberto Ierusalimschy 65141832d2 Open upvalues should be gray when entering gen. mode
Open upvalues are never black; so, when entering generational mode,
they must be colored gray, not black.
2020-08-07 14:53:38 -03:00
Roberto Ierusalimschy f13dc59416 Better tests for gray lists
Test uses an extra bit in 'marked' to mark all elements in gray lists
and then check against elements colored gray.
2020-08-07 14:45:20 -03:00
Roberto Ierusalimschy 7c3cb71fa4 Free bit 7 of GC 'marked' field
Tables were using this bit to indicate their array sizes were real
('isrealasize'), but this bit can be useful for tests. Instead, they
can use bit 7 of their 'flag' field for that purpose. (There are only
six fast-access metamethods.) This 'flag' field only exists in tables,
so this use does not affect other types.
2020-08-07 11:21:44 -03:00
Roberto Ierusalimschy 68109afcdb Detail (in asserts)
Macro 'checkconsistency' replaced by the similar 'checkliveness".
2020-08-03 16:05:10 -03:00
Roberto Ierusalimschy 9cf3299faf Threads don't need to always go to 'grayagain'
In incremental mode, threads don't need to be visited again once
visited in the atomic phase. In generational mode (where all visits
are in the atomic phase), only old threads need to be kept in the
'grayagain' list for the next cycle.
2020-08-03 14:28:13 -03:00
Roberto Ierusalimschy b9b554e0f6 Clearer handling of gray lists when entering generational mode
When entering generational mode, all objects are old. So, the only
objects that need to be in a gray list are threads, which can be
assigned without barriers. Changes in anything else (e.g., weak
tables) will trigger barriers that, if needed, will add the object
to a gray list.
2020-08-03 13:22:57 -03:00
Roberto Ierusalimschy 0dc5deca1c Optimization in 'markold'
OLD1 objects can be potentially anywhere in the 'allgc' list (up
to 'reallyold'), but frequently they are all after 'old1' (natural
evolution of survivals) or do not exist at all (when all objects die
young). So, instead of 'markold' starts looking for them always
from the start of 'allgc', the collector keeps an extra pointer,
'firstold1', that points to the first OLD1 object in the 'allgc' list,
or is NULL if there are no OLD1 objects in that list.
2020-07-29 17:05:47 -03:00
Roberto Ierusalimschy b4c353434f Details
The fields 'old' and 'finobjold' were renamed 'old1' and 'finobjold1',
respectively, to make clearer the main ages of their elements.
2020-07-29 11:34:08 -03:00
Roberto Ierusalimschy 71f70df327 OLD1 ages advanced by 'markold'
Objects aged OLD1 have their ages advanced by 'markold', which has to
visit them anyway. So, the GC doesn't need to "sweep" the old1 list.
2020-07-29 09:58:25 -03:00
Roberto Ierusalimschy 663f83f647 Same changes around 'correctgraylist'
Instead of adding all tables and userdata back to the 'grayagain' list
to be checked by 'correctgraylist', the collector adds only the objects
that will remain in that list (objects aged TOUCHED1). This commit
also rewrites 'correctgraylist' with a clearer logic.
2020-07-28 15:51:07 -03:00
Roberto Ierusalimschy ae5b5ba529 Fixed bug: line hooks in stripped functions
Line-hook handling was accessing debug info. without checking whether
it was present.
2020-07-27 13:23:05 -03:00
Roberto Ierusalimschy a585eae6e7 Fixed bug: Negation overflow in getlocal/setlocal 2020-07-27 12:01:38 -03:00
Roberto Ierusalimschy d2c2e32e8a All objects are kept 'new' in incremental GC
Small changes to ensure that all objects are kept 'new' in incremental
GC (except for fixed strings, which are always old) and to make that
fact clearer.
2020-07-27 11:39:42 -03:00
Roberto Ierusalimschy 8c7c9ea065 Function 'printobj' in 'ltests.c' made public
It helps to have this function available for debugging.
2020-07-27 11:24:03 -03:00
Roberto Ierusalimschy a6da1472c0 Fixed bug: barriers cannot be active during sweep
Barriers cannot be active during sweep, even in generational mode.
(Although gen. mode is not incremental, it can hit a barrier when
deleting a thread and closing its upvalues.)  The colors of objects are
being changed during sweep and, therefore, cannot be trusted.
2020-07-27 10:26:20 -03:00
Roberto Ierusalimschy 34affe7a63 Fixed bug: 'luaD_callnoyield' called twice in a row
In luaD_callnoyield, when there is a possible stack overflow, it
zeros the number of CallInfos to force a check when calling the
function. However, if the "function" is not a function, the code will
raise an error before checking the stack. Then, the error handling calls
luaD_callnoyield again and nCcalls is decremented again, crossing the
stack redzone without raising an error. (This loop can only happens
once, because the error handler must be a function.  But once is enough
to cross the redzone.)
2020-07-17 14:54:26 -03:00
Roberto Ierusalimschy a2195644d8 Fixed bug: invalid 'oldpc' when returning to a function
The field 'L->oldpc' is not always updated when control returns to a
function; an invalid value can seg. fault when computing 'changedline'.
(One example is an error in a finalizer; control can return to
'luaV_execute' without executing 'luaD_poscall'.) Instead of trying to
fix all possible corner cases, it seems safer to be resilient to invalid
values for 'oldpc'. Valid but wrong values at most cause an extra call
to a line hook.
2020-07-17 11:01:05 -03:00
Roberto Ierusalimschy 1ecfbfa1a1 Fixed bug: invalid mode can crash 'io.popen' 2020-07-15 16:01:03 -03:00
Roberto Ierusalimschy e1d8770f12 Fixed bug: wrong stack limit when entering a coroutine
When entering a coroutine, the computation of nCcalls added 'from->nci'
to correct for preallocated CallInfos, but 'nci' includes also the
Callinfos already used.
2020-07-13 13:39:02 -03:00
Roberto Ierusalimschy 0f1cd0eba9 Added test for fix 127e7a6c89 2020-07-13 13:37:01 -03:00
Roberto Ierusalimschy 127e7a6c89 Fixed bug of old finalized objects in the GC
When an object aged OLD1 is finalized, it is moved from the list
'finobj' to the *beginning* of the list 'allgc'. So, this part of the
list (and not only the survival list) must be visited by 'markold'.
2020-07-10 14:13:50 -03:00
Roberto Ierusalimschy 6f5bd5072d Macro LUAI_ASSERT eases turning assertions on 2020-07-08 15:51:55 -03:00
Roberto Ierusalimschy 56ec432281 Change in macro HARDMEMTESTS for testing GC
Macro HARDMEMTESTS broke in two: HARDMEMTESTS forces a full GC cycle
at every point where the GC can run. New macro EMERGENCYGCTESTS
forces an emergency collection at every memory allocation.
2020-07-08 15:36:48 -03:00
Roberto Ierusalimschy 31b8c2d438 Fixed bug of access violation in finalizers
Errors in finalizers need a valid 'pc' to produce an error message,
even if the error is not propagated. Therefore, calls to the GC (which
may call finalizers) inside luaV_execute must save the 'pc'.
2020-07-08 12:02:56 -03:00
Roberto Ierusalimschy eb41999461 Fixed bugs of stack reallocation x GC
Macro 'checkstackGC' was doing a GC step after resizing the stack;
the GC could shrink the stack and undo the resize. Moreover, macro
'checkstackp' also does a GC step, which could remove the preallocated
CallInfo when calling a function. (Its name has been changed to
'checkstackGCp' to emphasize that it calls the GC.)
2020-07-07 18:03:48 -03:00
Roberto Ierusalimschy 314c6057b7 Avoid any code before locks in the API
For consistency in the C API, avoid any initializations before
callling lua_lock.
2020-07-06 14:06:47 -03:00
Roberto Ierusalimschy d39ea8b3ce Make sure that main thread is non yieldable
Main thread must be non yieldable even at "level 0" (bare API), outside
the 'pcall' from 'lua.c'.
2020-07-06 13:54:01 -03:00
Roberto Ierusalimschy 6298903e35 Keep minimum size when shrinking a stack
When shrinking a stack (during GC), do not make it smaller than the
initial stack size.
2020-07-06 12:11:54 -03:00
Roberto Ierusalimschy b57574d6fb Keep memory errors as memory errors
Allow memory errors to be raised through the API (throwing the
error with the memory error message); error in external allocations
raises a memory error; memory errors in coroutines are re-raised
as memory errors.
2020-07-06 12:09:44 -03:00
Roberto Ierusalimschy bfcf06d91a Avoid memory allocation in some functions from 'ltests.c'
To allow their use in memory tests, some functions in 'ltests.c'
should never allocate memory. To avoid this allocation, the
library registers the strings used for status codes, and keeps
the variable '_WARN' always defined (with false instead of nil).
2020-07-04 16:40:18 -03:00
Roberto Ierusalimschy 0280407fc5 Details
Comments in makefile and function 'l_str2d'.
2020-07-03 13:02:41 -03:00
Roberto Ierusalimschy ae809e9fd1 'luaV_concat' can "concat" one single value
Several of its callers needed that case and had to do the check
themselves.
2020-07-03 11:54:58 -03:00
Roberto Ierusalimschy e96385aded Simplification and smaller buffers for 'lua_pushfstring'
The function 'lua_pushfstring' is seldom called with large strings,
there is no need to optimize too much for that cases.
2020-07-03 11:36:56 -03:00
Roberto Ierusalimschy 56a165bf0f Added '.gitignore' to the repository 2020-07-02 16:55:23 -03:00
Roberto Ierusalimschy 422ce50d2e Fixed detail in 'loadUpvalues'
In 'lundump.c', when loading the upvalues of a function, there can be
a read error if the chunk is truncated. In that case, the creation
of the error message can trigger an emergency collection while the
prototype is still anchored. So, the prototype must be GC consistent
before loading the upvales, which implies that it the 'name' fields
must be filled with NULL before the reading.
2020-06-30 15:36:26 -03:00
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
112 changed files with 53299 additions and 12987 deletions
+15
View File
@@ -0,0 +1,15 @@
.gitattributes
*.so
*.o
*.a
manual/manual.html
testes/time.txt
testes/time-debug.txt
testes/libs/all
temp
lua
+7
View File
@@ -0,0 +1,7 @@
# Lua
This is the repository of Lua development code, as seen by the Lua team. It contains the full history of all commits but is mirrored irregularly. For complete information about Lua, visit [Lua.org](https://www.lua.org/).
Please **do not** send pull requests. To report issues, post a message to the [Lua mailing list](https://www.lua.org/lua-l.html).
Download official Lua releases from [Lua.org](https://www.lua.org/download.html).
Executable
+9
View File
@@ -0,0 +1,9 @@
make -s -j
cd testes/libs; make -s
cd .. # back to directory 'testes'
ulimit -S -s 1100
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)
+1052 -354
View File
File diff suppressed because it is too large Load Diff
+39 -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,45 @@
#define lapi_h
#include "lobject.h"
#include "llimits.h"
#include "lstate.h"
void luaA_pushobject (lua_State *L, const TObject *o);
/* Increments 'L->top.p', checking for stack overflows */
#define api_incr_top(L) {L->top.p++; \
api_check(L, L->top.p <= L->ci->top.p, \
"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.p').
*/
#define adjustresults(L,nres) \
{ if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \
L->ci->top.p = L->top.p; }
/* Ensure the stack has at least 'n' elements */
#define api_checknelems(L,n) \
api_check(L, (n) < (L->top.p - L->ci->func.p), \
"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)
/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */
#define codeNresults(n) (-(n) - 3)
#define decodeNresults(n) (-(n) - 3)
#endif
+922 -242
View File
File diff suppressed because it is too large Load Diff
+237 -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
*/
@@ -12,52 +12,110 @@
#include <stddef.h>
#include <stdio.h>
#include "luaconf.h"
#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 +123,63 @@ 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)(luai_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
#define luaL_argexpected(L,cond,arg,tname) \
((void)(luai_likely(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)
/*
** Perform arithmetic operations on lua_Integer values with wrap-around
** semantics, as the Lua core does.
*/
#define luaL_intop(op,v1,v2) \
((lua_Integer)((lua_Unsigned)(v1) op (lua_Unsigned)(v2)))
/* push the value used to represent failure/error */
#define luaL_pushfail(L) lua_pushnil(L)
/*
** Internal assertions for in-house debugging
*/
#if !defined(lua_assert)
#if defined LUAI_ASSERT
#include <assert.h>
#define lua_assert(c) assert(c)
#else
#define lua_assert(c) ((void)0)
#endif
#endif
/*
@@ -81,48 +188,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
+389 -465
View File
File diff suppressed because it is too large Load Diff
+1541 -410
View File
File diff suppressed because it is too large Load Diff
+64 -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,81 @@
/*
** 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_codeABCk (FuncState *fs, OpCode o, int A,
int B, int C, int k);
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 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
+210
View File
@@ -0,0 +1,210 @@
/*
** $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 (l_unlikely(!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 (l_likely(status == LUA_OK || status == LUA_YIELD)) {
if (l_unlikely(!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 (l_unlikely(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 (l_unlikely(r < 0)) { /* error? */
int stat = lua_status(co);
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
stat = lua_closethread(co, L); /* close its tbc variables */
lua_assert(stat != LUA_OK);
lua_xmove(co, L, 1); /* move error message to the caller */
}
if (stat != LUA_ERRMEM && /* not a memory error and ... */
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_closethread(co, L);
if (status == LUA_OK) {
lua_pushboolean(L, 1);
return 1;
}
else {
lua_pushboolean(L, 0);
lua_xmove(co, L, 1); /* move 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 /* } */
+101
View File
@@ -0,0 +1,101 @@
/*
** $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))
/*
** In ASCII, this 'ltolower' is correct for alphabetic characters and
** for '.'. That is enough for Lua needs. ('check_exp' ensures that
** the character either is an upper-case letter or is unchanged by
** the transformation, which holds for lower-case letters and '.'.)
*/
#define ltolower(c) \
check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \
(c) | ('A' ^ 'a'))
/* one entry for each character and for -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
+408 -189
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,339 @@
#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_unlikely(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);
luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
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 (l_unlikely(!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 (l_unlikely(!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 void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
void *id;
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
id = lua_upvalueid(L, argf, nup);
if (pnup) {
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
*pnup = nup;
}
return id;
}
static int db_upvalueid (lua_State *L) {
void *id = checkupval(L, 1, 2, NULL);
if (id != NULL)
lua_pushlightuserdata(L, id);
else
luaL_pushfail(L);
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1, n2;
checkupval(L, 1, 2, &n1);
checkupval(L, 3, 4, &n2);
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 +362,122 @@ 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_pushliteral(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);
if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
lua_writestringerror("%s", "lua_debug> ");
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
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);
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;
}
+776 -357
View File
File diff suppressed because it is too large Load Diff
+47 -16
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,54 @@
#include "lstate.h"
#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 = lua_getmaskcount(L->hookmask))
#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond))
#define allowhook(L) ((L->hookmask) & 1)
#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 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);
/* Active Lua function (given call info) */
#define ci_func(ci) (clLvalue(s2v((ci)->func.p)))
#define resethookcount(L) (L->hookcount = L->basehookcount)
/*
** mark for entries in 'lineinfo' array that has absolute information in
** 'abslineinfo' array
*/
#define ABSLINEINFO (-0x80)
/*
** MAXimum number of successive Instructions WiTHout ABSolute line
** information. (A power of two allows fast divisions.)
*/
#if !defined(MAXIWTHABS)
#define MAXIWTHABS 128
#endif
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_callerror (lua_State *L, const TValue *o);
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);
LUAI_FUNC int luaG_tracecall (lua_State *L);
#endif
+902 -328
View File
File diff suppressed because it is too large Load Diff
+64 -28
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
*/
@@ -8,45 +8,81 @@
#define ldo_h
#include "llimits.h"
#include "lobject.h"
#include "lstate.h"
#include "lzio.h"
/*
** 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.
** It also allows the running of one GC step when the stack is
** reallocated.
** '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_unlikely(L->stack_last.p - L->top.p <= (n))) \
{ pre; luaD_growstack(L, n, 1); pos; } \
else { condmovestack(L,pre,pos); }
#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)))
/* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
/* type of protected functions, to be ran by `runprotected' */
#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p))
#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n))
/* macro to check stack size, preserving 'p' */
#define checkstackp(L,n,p) \
luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
/* macro to check stack size and GC, preserving 'p' */
#define checkstackGCp(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), luaC_checkGC(L), (void)0)
/* 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 l_noret luaD_errerr (lua_State *L);
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 int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
int narg1, int delta);
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
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
+230
View File
@@ -0,0 +1,230 @@
/*
** $Id: ldump.c $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
#define ldump_c
#define LUA_CORE
#include "lprefix.h"
#include <limits.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);
}
/*
** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6"
** rounds up the division.)
*/
#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7)
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;
}
+224 -63
View File
@@ -1,122 +1,283 @@
/*
** $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.p = &uv->u.value; /* make it closed */
setnilvalue(uv->v.p);
cl->upvals[i] = uv;
luaC_objbarrier(L, cl, uv);
}
}
/*
** 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, StkId level, UpVal **prev) {
GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal));
UpVal *uv = gco2upv(o);
UpVal *next = *prev;
uv->v.p = s2v(level); /* current value lives in the stack */
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, 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;
/*
** Call closing method for object 'obj' with error message 'err'. The
** boolean 'yy' controls whether the call is yieldable.
** (This function assumes EXTRA_STACK.)
*/
static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) {
StkId top = L->top.p;
const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
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.p = top + 3; /* add function and arguments */
if (yy)
luaD_call(L, top, 0);
else
luaD_callnoyield(L, top, 0);
}
/*
** Check whether object at given level has a close metamethod and raise
** an error if not.
*/
static void checkclosemth (lua_State *L, StkId level) {
const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE);
if (ttisnil(tm)) { /* no metamethod? */
int idx = cast_int(level - L->ci->func.p); /* variable index */
const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
if (vname == NULL) vname = "?";
luaG_runerror(L, "variable '%s' got a non-closable value", vname);
}
}
/*
** Prepare and call a closing method.
** If status is CLOSEKTOP, the call to the closing method will be pushed
** at the top of the stack. Otherwise, values can be pushed right after
** the 'level' of the upvalue being closed, as everything after that
** won't be used again.
*/
static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) {
TValue *uv = s2v(level); /* value being closed */
TValue *errobj;
if (status == CLOSEKTOP)
errobj = &G(L)->nilvalue; /* error object is nil */
else { /* 'luaD_seterrorobj' will set top to level + 2 */
errobj = s2v(level + 1); /* error object goes after 'uv' */
luaD_seterrorobj(L, status, level + 1); /* set error object */
}
callclosemethod(L, uv, errobj, yy);
}
/*
** Maximum value for deltas in 'tbclist', dependent on the type
** of delta. (This macro assumes that an 'L' is in scope where it
** is used.)
*/
#define MAXDELTA \
((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1)
/*
** Insert a variable in the list of to-be-closed variables.
*/
void luaF_newtbcupval (lua_State *L, StkId level) {
lua_assert(level > L->tbclist.p);
if (l_isfalse(s2v(level)))
return; /* false doesn't need to be closed */
checkclosemth(L, level); /* value must have a close method */
while (cast_uint(level - L->tbclist.p) > MAXDELTA) {
L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */
L->tbclist.p->tbclist.delta = 0;
}
level->tbclist.delta = cast(unsigned short, level - L->tbclist.p);
L->tbclist.p = level;
}
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;
}
/*
** Close all upvalues up to the given stack level.
*/
void luaF_closeupval (lua_State *L, StkId level) {
UpVal *uv;
StkId upl; /* stack index pointed by 'uv' */
while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
TValue *slot = &uv->u.value; /* new position for value */
lua_assert(uplevel(uv) < L->top.p);
luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */
setobj(L, slot, uv->v.p); /* move value to upvalue slot */
uv->v.p = slot; /* now current value lives here */
if (!iswhite(uv)) { /* neither white nor dead? */
nw2black(uv); /* closed upvalues cannot be gray */
luaC_barrier(L, uv, slot);
}
}
}
/*
** Remove first element from the tbclist plus its dummy nodes.
*/
static void poptbclist (lua_State *L) {
StkId tbc = L->tbclist.p;
lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */
tbc -= tbc->tbclist.delta;
while (tbc > L->stack.p && tbc->tbclist.delta == 0)
tbc -= MAXDELTA; /* remove dummy nodes */
L->tbclist.p = tbc;
}
/*
** Close all upvalues and to-be-closed variables up to the given stack
** level. Return restored 'level'.
*/
StkId luaF_close (lua_State *L, StkId level, int status, int yy) {
ptrdiff_t levelrel = savestack(L, level);
luaF_closeupval(L, level); /* first, close the upvalues */
while (L->tbclist.p >= level) { /* traverse tbc's down to that level */
StkId tbc = L->tbclist.p; /* get variable index */
poptbclist(L); /* remove it from list */
prepcallclosemth(L, tbc, status, yy); /* close variable */
level = restorestack(L, levelrel);
}
return level;
}
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) {
+48 -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,54 @@
#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.p != &(up)->u.value)
#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p))
/*
** maximum number of misses before giving up the cache of closures
** in prototypes
*/
#define MAXMISS 10
/* special status to close upvalues preserving the top of the stack */
#define CLOSEKTOP (-1)
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 void luaF_closeupval (lua_State *L, StkId level);
LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy);
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
+1645 -396
View File
File diff suppressed because it is too large Load Diff
+185 -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,194 @@
#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. (Open
** upvalues are an exception to this rule.) 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 used
** by tests.
*/
#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 TESTBIT 7
#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 nw2black(x) \
check_exp(!iswhite(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)
/*
** Control when GC is running:
*/
#define GCSTPUSR 1 /* bit true when GC stopped by user */
#define GCSTPGC 2 /* bit true when GC stopped by itself */
#define GCSTPCLS 4 /* bit true when closing Lua state */
#define gcrunning(g) ((g)->gcstp == 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_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
#define luaC_barrier(L,p,v) ( \
iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0))
#define luaC_objbarrierback(L,p,o) ( \
(isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0))
#define luaC_barrierback(L,p,v) ( \
iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : 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 GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz,
size_t offset);
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 */
}
}
+611 -400
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
};
+483 -311
View File
@@ -1,132 +1,185 @@
/*
** $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? */
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. It also internalizes long strings,
** ensuring there is only one copy of each unique string. The table
** here is used as a set: the string enters as the key, while its value
** is irrelevant. We use the string itself as the value only because it
** is a TValue readily available. Later, the code generation can change
** this value.
*/
TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
lua_State *L = ls->L;
TString *ts = luaS_newlstr(L, str, l); /* create new string */
const TValue *o = luaH_getstr(ls->h, ts);
if (!ttisnil(o)) /* string already present? */
ts = keystrval(nodefromval(o)); /* get saved copy */
else { /* not in use yet */
TValue *stv = s2v(L->top.p++); /* reserve stack space for string */
setsvalue(L, stv, ts); /* temporarily anchor the string */
luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */
/* table is not a metatable, so it does not need to invalidate cache */
luaC_checkGC(L);
L->top.p--; /* 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 +188,394 @@ 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);
/*
** read a sequence '[=*[' or ']=*]', leaving the last bracket. If
** sequence is well formed, return its number of '='s + 2; otherwise,
** return 1 if it is a single bracket (no '='s and no 2nd bracket);
** otherwise (an unfinished '[==...') return 0.
*/
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;
}
+36 -17
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
*/
@@ -7,14 +7,22 @@
#ifndef llex_h
#define llex_h
#include <limits.h>
#include "lobject.h"
#include "lzio.h"
#define FIRST_RESERVED 257
/*
** Single-char tokens (terminal symbols) are represented by their own
** numeric code. Other tokens start at the following value.
*/
#define FIRST_RESERVED (UCHAR_MAX + 1)
/* maximum length of a reserved word */
#define TOKEN_LEN (sizeof("function")/sizeof(char))
#if !defined(LUA_ENV)
#define LUA_ENV "_ENV"
#endif
/*
@@ -25,19 +33,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 +59,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
+326 -99
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,365 @@
/*
** 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
** this is for hashing only; there is no problem if the integer
** cannot hold the whole pointer value
** 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 IntPoint(p) ((lu_hash)(p))
/* type to ensure maximum alignment */
#ifndef LUSER_ALIGNMENT_T
#define LUSER_ALIGNMENT_T double
#endif
union L_Umaxalign { LUSER_ALIGNMENT_T u; void *s; long l; };
#ifndef lua_assert
#define lua_assert(c) /* empty */
#endif
#ifndef check_exp
#define check_exp(c,e) (e)
#endif
#ifndef UNUSED
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
#endif
#ifndef cast
#define cast(t, exp) ((t)(exp))
#endif
#define log2maxs(t) (sizeof(t) * 8 - 2)
/*
** type for virtual-machine instructions
** 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. (In strict ISO C this may cause undefined behavior, but no
** actual machine seems to bother.)
*/
#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \
__STDC_VERSION__ >= 199901L
#include <stdint.h>
#if defined(UINTPTR_MAX) /* even in C99 this type is optional */
#define L_P2I uintptr_t
#else /* no 'intptr'? */
#define L_P2I uintmax_t /* use the largest available integer */
#endif
#else /* C89 option */
#define L_P2I size_t
#endif
#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX))
/* 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 LUAI_ASSERT
#undef NDEBUG
#include <assert.h>
#define lua_assert(c) assert(c)
#endif
#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
/*
** 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)
/* macro to avoid warnings about unused variables */
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x))
#endif
/* type casts (a macro highlights casts in the code) */
#define cast(t, exp) ((t)(exp))
#define cast_void(i) cast(void, (i))
#define cast_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
/*
** 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
/*
** Inline functions
*/
#if !defined(LUA_USE_C89)
#define l_inline inline
#elif defined(__GNUC__)
#define l_inline __inline__
#else
#define l_inline /* empty */
#endif
#define l_sinline static l_inline
/*
** type for virtual-machine instructions;
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
typedef unsigned long Instruction;
#if LUAI_IS32INT
typedef unsigned int l_uint32;
#else
typedef unsigned long l_uint32;
#endif
typedef l_uint32 Instruction;
/* maximum depth for calls */
#ifndef LUA_MAXCALLS
#define LUA_MAXCALLS 4096
/*
** 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
/* maximum size for the C stack */
#ifndef LUA_MAXCSTACK
#define LUA_MAXCSTACK 2048
/*
** 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
/* 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) */
/*
** 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
/* maximum number of upvalues per function */
#ifndef MAXUPVALUES
#define MAXUPVALUES 32
/* minimum size for string buffer */
#if !defined(LUA_MINBUFFER)
#define LUA_MINBUFFER 32
#endif
/* maximum number of parameters in a function */
#ifndef MAXPARAMS
#define MAXPARAMS 100 /* arbitrary limit (<MAXLOCALS) */
/*
** Maximum depth for nested C calls, syntactical nested non-terminals,
** and other features implemented through recursion in C. (Value must
** fit in a 16-bit unsigned integer. It must also be compatible with
** the size of the C stack.)
*/
#if !defined(LUAI_MAXCCALLS)
#define LUAI_MAXCCALLS 200
#endif
/* minimum size for the string table (must be power of 2) */
#ifndef MINSTRTABSIZE
#define MINSTRTABSIZE 32
/*
** 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
/*
** The luai_num* macros define the primitive operations over numbers.
*/
/* floor division (defined as 'floor(a/b)') */
#if !defined(luai_numidiv)
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
#endif
/* float division */
#if !defined(luai_numdiv)
#define luai_numdiv(L,a,b) ((a)/(b))
#endif
/*
** modulo: defined as 'a - floor(a/b)*b'; 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, (b == 2) ? (a)*(a) : 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
/*
** 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_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; }
#endif
#if !defined(HARDMEMTESTS)
#define condchangemem(L,pre,pos) ((void)0)
#else
#define condchangemem(L,pre,pos) \
{ if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } }
#endif
#endif
+647 -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,741 @@
#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 (l_likely(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**'.
** ===================================================================
*/
/*
** This code uses lots of shifts. ANSI C does not allow shifts greater
** than or equal to the width of the type being shifted, so some shifts
** are written in convoluted ways to match that restriction. For
** preprocessor tests, it assumes a width of 32 bits, so the maximum
** shift there is 31 bits.
*/
/* 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
#define SRand64 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
#define SRand64 long long
#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3
/* 'lua_Unsigned' has at least 64 bits */
#define Rand64 lua_Unsigned
#define SRand64 lua_Integer
#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;
}
/*
** 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.
** Some old Microsoft compilers cannot cast an unsigned long
** to a floating-point number, so we use a signed long as an
** intermediary. When lua_Number is float or double, the shift ensures
** that 'sx' is non negative; in that case, a good compiler will remove
** the correction.
*/
/* must throw out the extra (64 - FIGS) bits */
#define shift64_FIG (64 - FIGS)
/* 2^(-FIGS) == 2^-1 / 2^(FIGS-1) */
#define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))
static lua_Number I2d (Rand64 x) {
SRand64 sx = (SRand64)(trim64(x) >> shift64_FIG);
lua_Number res = (lua_Number)(sx) * scaleFIG;
if (sx < 0)
res += l_mathop(1.0); /* correct the two's complement if negative */
lua_assert(0 <= res && res < 1);
return res;
}
/* 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 */
/* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */
#define scaleFIG \
(l_mathop(1.0) / (UONE << 30) / l_mathop(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)) * l_mathop(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 +765,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;
}
+180 -44
View File
@@ -1,16 +1,22 @@
/*
** $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"
@@ -18,62 +24,192 @@
/*
** 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.)
** 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.
*/
#ifndef l_realloc
#define l_realloc(b,os,s) realloc(b,s)
/*
** Macro to call the allocation function.
*/
#define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns))
/*
** When an allocation fails, it will try again after an emergency
** collection, except when it cannot run a collection. The GC should
** not be called while the state is not fully built, as the collector
** is not yet fully initialized. Also, it should not be called when
** 'gcstopem' is true, because then the interpreter is in the middle of
** a collection step.
*/
#define cantryagain(g) (completestate(g) && !g->gcstopem)
#if defined(EMERGENCYGCTESTS)
/*
** First allocation will fail except when freeing a block (frees never
** fail) and when it cannot try again; this fail will trigger 'tryagain'
** and a full GC cycle at every allocation.
*/
static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
if (ns > 0 && cantryagain(g))
return NULL; /* fail */
else /* normal allocation */
return callfrealloc(g, block, os, ns);
}
#else
#define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns)
#endif
/*
** {==================================================================
** 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 (l_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));
callfrealloc(g, block, osize, 0);
g->GCdebt -= osize;
}
/*
** In case of allocation fail, this function will do an emergency
** collection to free some memory and then try the allocation again.
*/
static void *tryagain (lua_State *L, void *block,
size_t osize, size_t nsize) {
global_State *g = G(L);
if (cantryagain(g)) {
luaC_fullgc(L, 1); /* try to free some memory... */
return callfrealloc(g, block, osize, nsize); /* try again */
}
else return NULL; /* cannot run an emergency collection */
}
/*
** Generic allocation routine.
*/
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 (l_unlikely(newblock == NULL && nsize > 0)) {
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 (l_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 (l_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
+758
View File
@@ -0,0 +1,758 @@
/*
** $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_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 (l_unlikely(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 (l_unlikely(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 (l_likely(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 (l_unlikely(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 (l_likely(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 (l_unlikely(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 (l_unlikely(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 */
}
+547 -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,520 @@
#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_shiftr(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 = l_mathop(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 l_mathop(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 * l_mathop(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 l_mathop(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 l_mathop(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 to be converted to a number */
#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) {
/*
** Convert string 's' to a Lua number (put in 'result'). Return NULL on
** fail or the address of the ending '\0' on success. ('mode' == 'x')
** means a hexadecimal numeral.
*/
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 iff no trailing chars */
}
/*
** Convert string 's' to a Lua number (put in 'result') handling the
** current locale.
** 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.
** The variable 'mode' checks for special characters in the string:
** - 'n' means 'inf' or 'nan' (which should be rejected)
** - 'x' means a hexadecimal numeral
** - '.' just optimizes the search for the common case (no special chars)
*/
static const char *l_str2d (const char *s, lua_Number *result) {
const char *endptr;
const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */
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 (pdot == NULL || strlen(s) > L_MAXLENNUM)
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. Must be
** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT.
** (For a long long int, this is 19 digits plus a sign and a final '\0',
** adding to 21. For a long double, it can go to a sign, 33 digits,
** the dot, an exponent letter, an exponent sign, 5 exponent digits,
** and a final '\0', adding to 43.)
*/
#define MAXNUMBER2STR 44
/*
** 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'. It should be
** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages,
** so that 'luaG_addinfo' can work directly on the buffer.
*/
#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95)
/* buffer used by 'luaO_pushvfstring' */
typedef struct BuffFS {
lua_State *L;
int pushed; /* true if there is a part of the result 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 result, and
** join it to previous partial result if there is one.
** It may call 'luaV_concat' while using one slot from EXTRA_STACK.
** This call cannot invoke metamethods, as both operands must be
** strings. It can, however, raise an error if the result is too
** long. In that case, 'luaV_concat' frees the extra slot before
** raising the error.
*/
static void pushstr (BuffFS *buff, const char *str, size_t lstr) {
lua_State *L = buff->L;
setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr));
L->top.p++; /* may use one slot from EXTRA_STACK */
if (!buff->pushed) /* no previous string on the stack? */
buff->pushed = 1; /* now there is one */
else /* join previous string with new one */
luaV_concat(L, 2);
}
/* 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 numeral 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 */
lua_assert(buff.pushed == 1);
return getstr(tsvalue(s2v(L->top.p - 1)));
}
@@ -159,37 +555,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));
}
}
+710 -160
View File
@@ -1,153 +1,527 @@
/*
** $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 */
#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */
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 but excluding DEADKEY)
*/
#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 */
/* not used, but may avoid warnings for uninitialized value */
lu_byte ub;
} 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. The option 'L == NULL' allows other
** macros using this one to be used where L is not available.
*/
#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 'obj2' to 'obj1') */
#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 a Lua stack. Field 'tbclist' forms a list of all
** to-be-closed variables active in this stack. Dummy entries are
** used when the distance between two tbc variables does not fit
** in an unsigned short. They are represented by delta==0, and
** their real delta is always the maximum value that fits in
** that field.
*/
typedef union TString {
union L_Umaxalign dummy; /* ensures maximum alignment for strings */
typedef union StackValue {
TValue val;
struct {
lu_hash hash;
size_t len;
int marked;
union TString *nexthash; /* chain for hash table */
} tsv;
TValuefields;
unsigned short delta;
} tbclist;
} StackValue;
/* index to stack elements */
typedef StackValue *StkId;
/*
** When reallocating the stack, change all pointers to the stack into
** proper offsets.
*/
typedef union {
StkId p; /* actual pointer */
ptrdiff_t offset; /* used while the stack is being reallocated */
} StkIdRel;
/* 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, 0xFF for long 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)
#define svalue(o) getstr(tsvalue(o))
/*
** Get the actual string (array of bytes) from a 'TString'. (Generic
** version and specialized versions for long and short strings.)
*/
#define getstr(ts) ((ts)->contents)
#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
/* get string length from 'TString *s' */
#define tsslen(s) \
((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
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 +529,132 @@ 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;
/* }================================================================== */
/*
** {==================================================================
** Functions
** ===================================================================
*/
#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 ttisLclosure(o) checktag((o), ctb(LUA_VLCL))
#define ttislcf(o) checktag((o), LUA_VLCF)
#define ttisCclosure(o) checktag((o), ctb(LUA_VCCL))
#define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o))
#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;
union {
TValue *p; /* points to stack or to its own value */
ptrdiff_t offset; /* used while the stack is being reallocated */
} v;
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 +664,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)->flags & BITRAS))
#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS))
#define setnorealasize(t) ((t)->flags |= 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)
/*
** Dead keys in tables have the tag DEADKEY but keep their original
** gcvalue. This distinguishes them from regular keys but allows them to
** be found when searched in a special way. ('next' needs that to find
** keys removed from a table during a traversal.)
*/
#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
/* }================================================================== */
/*
** '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 */
};
+301 -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,395 @@
/*===========================================================================
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 (signed)(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. Opcodes marked with a (*)
** has extra descriptions in the notes after the enumeration.
*/
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]:shortstring] */
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]:shortstring] */
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]:shortstring] := 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]:shortstring] := 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]:number */
OP_SUBK,/* A B C R[A] := R[B] - K[C]:number */
OP_MULK,/* A B C R[A] := R[B] * K[C]:number */
OP_MODK,/* A B C R[A] := R[B] % K[C]:number */
OP_POWK,/* A B C R[A] := R[B] ^ K[C]:number */
OP_DIVK,/* A B C R[A] := R[B] / K[C]:number */
OP_IDIVK,/* A B C R[A] := R[B] // K[C]:number */
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] := #R[B] (length operator) */
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+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'.
(2) In OP_RETURN, if (B == 0) then return up to `top'
(*) Opcode OP_LFALSESKIP is used to convert a condition to a boolean
value, in a code equivalent to (not cond ? false : true). (It
produces false and skips the next instruction producing true.)
(3) For comparisons, B specifies what conditions the test should accept.
(*) Opcodes OP_MMBIN and variants follow each arithmetic and
bitwise opcode. If the operation succeeds, it skips this next
opcode. Otherwise, this opcode calls the corresponding metamethod.
(*) Opcode OP_TESTSET is used in short-circuit expressions that need
both to jump and to produce a value, such as (a = b or c).
(*) 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'.
(*) In OP_VARARG, if (C == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
(*) In OP_RETURN, if (B == 0) then return up to 'top'.
(*) In OP_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) /* { */
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%"
#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
#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 /* } */
/* }================================================================== */
#if !defined(l_system)
#if defined(LUA_USE_IOS)
/* Despite claiming to be ISO C, iOS does not implement 'system'. */
#define l_system(cmd) ((cmd) == NULL ? 0 : -1)
#else
#define l_system(cmd) system(cmd) /* default definition */
#endif
#endif
static int os_execute (lua_State *L) {
const char *cmd = luaL_optstring(L, 1, NULL);
int stat;
errno = 0;
stat = l_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);
errno = 0;
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);
errno = 0;
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 (l_unlikely(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 (l_unlikely(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 (l_unlikely(t != LUA_TNIL)) /* some other value? */
return luaL_error(L, "field '%s' is not an integer", key);
else if (l_unlikely(d < 0)) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key);
res = d;
}
else {
if (!(res >= 0 ? res - delta <= INT_MAX : 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;
}
+1346 -689
View File
File diff suppressed because it is too large Load Diff
+132 -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,163 @@
#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 of 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.ridx = register index;
var.vidx = relative index in 'actvar.arr' */
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VCONST, /* compile-time <const> variable;
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 ridx; /* register holding the variable */
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 ridx; /* register holding the variable */
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
+385 -129
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,420 @@
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);
}
#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) {
UNUSED(L); UNUSED(limit);
return LUAI_MAXCCALLS; /* warning?? */
}
CallInfo *luaE_extendCI (lua_State *L) {
CallInfo *ci;
lua_assert(L->ci->next == NULL);
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;
}
/*
** open parts that may cause memory-allocation errors
** free all CallInfo structures not in use by a thread
*/
static void freeCI (lua_State *L) {
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
ci->next = NULL;
while ((ci = next) != NULL) {
next = ci->next;
luaM_free(L, ci);
L->nci--;
}
}
/*
** free half of the CallInfo structures not in use by a thread,
** 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 */
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 */
}
}
}
/*
** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS.
** If equal, raises an overflow error. If value is larger than
** LUAI_MAXCCALLS (which means it is handling an overflow) but
** not much larger, does not report an error (to allow overflow
** handling to work).
*/
void luaE_checkcstack (lua_State *L) {
if (getCcalls(L) == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
luaD_errerr(L); /* error while handling stack error */
}
LUAI_FUNC void luaE_incCstack (lua_State *L) {
L->nCcalls++;
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
luaE_checkcstack(L);
}
static void stack_init (lua_State *L1, lua_State *L) {
int i; CallInfo *ci;
/* initialize stack array */
L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
L1->tbclist.p = L1->stack.p;
for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */
L1->top.p = L1->stack.p;
L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
/* initialize first ci */
ci = &L1->base_ci;
ci->next = ci->previous = NULL;
ci->callstatus = CIST_C;
ci->func.p = L1->top.p;
ci->u.c.k = NULL;
ci->nresults = 0;
setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */
L1->top.p++;
ci->top.p = L1->top.p + LUA_MINSTACK;
L1->ci = ci;
}
static void freestack (lua_State *L) {
if (L->stack.p == NULL)
return; /* stack not completely built yet */
L->ci = &L->base_ci; /* free the entire 'ci' list */
freeCI(L);
lua_assert(L->nci == 0);
luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */
}
/*
** Create registry table and its predefined values
*/
static void init_registry (lua_State *L, global_State *g) {
/* 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, &registry->array[LUA_RIDX_MAINTHREAD - 1], L);
/* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
sethvalue(L, &registry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L));
}
/*
** open parts of the state that may cause memory-allocation errors.
*/
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->gcstp = 0; /* allow gc */
setnilvalue(&g->nilvalue); /* now state is complete */
luai_userstateopen(L);
}
static void preinit_state (lua_State *L) {
L->stack = NULL;
L->stacksize = 0;
/*
** 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.p = NULL;
L->ci = NULL;
L->nci = 0;
L->twups = L; /* thread has no upvalues */
L->nCcalls = 0;
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);
L->oldpc = 0;
}
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);
global_State *g = G(L);
if (!completestate(g)) /* closing a partially built state? */
luaC_freeallobjects(L); /* just collect its objects */
else { /* closing a fully built state */
L->ci = &L->base_ci; /* unwind CallInfo list */
L->errfunc = 0; /* stack unwind can "throw away" the error function */
luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
L->top.p = L->stack.p + 1; /* empty the stack to run finalizers */
luaC_freeallobjects(L); /* collect all objects */
luai_userstateclose(L);
}
luaE_closethread(NULL, 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);
GCObject *o;
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 */
o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l));
L1 = gco2th(o);
/* anchor it on L stack */
setthvalue2s(L, L->top.p, L1);
api_incr_top(L);
preinit_thread(L1, g);
L1->hookmask = L->hookmask;
L1->basehookcount = L->basehookcount;
L1->hook = L->hook;
resethookcount(L1);
/* initialize L1 extra space */
memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
LUA_EXTRASPACE);
luai_userstatethread(L, L1);
stack_init(L1, L); /* init stack */
lua_unlock(L);
return L1;
}
void luaE_freethread (lua_State *L, lua_State *L1) {
LX *l = fromstate(L1);
luaF_closeupval(L1, L1->stack.p); /* close all upvalues */
lua_assert(L1->openupval == NULL);
luai_userstatefree(L, L1);
freestack(L1);
luaM_free(L, l);
}
int luaE_resetthread (lua_State *L, int status) {
CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */
setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */
ci->func.p = L->stack.p;
ci->callstatus = CIST_C;
if (status == LUA_YIELD)
status = LUA_OK;
L->status = LUA_OK; /* so it can run __close metamethods */
L->errfunc = 0; /* stack unwind can "throw away" the error function */
status = luaD_closeprotected(L, 1, status);
if (status != LUA_OK) /* errors? */
luaD_seterrorobj(L, status, L->stack.p + 1);
else
L->top.p = L->stack.p + 1;
ci->top.p = L->top.p + LUA_MINSTACK;
luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0);
return status;
}
LUA_API int lua_closethread (lua_State *L, lua_State *from) {
int status;
lua_lock(L);
L->nCcalls = (from) ? getCcalls(from) : 0;
status = luaE_resetthread(L, L->status);
lua_unlock(L);
return status;
}
/*
** Deprecated! Use 'lua_closethread' instead.
*/
LUA_API int lua_resetthread (lua_State *L) {
return lua_closethread(L, NULL);
}
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;
incnny(L); /* main thread is always non yieldable */
g->frealloc = f;
g->ud = ud;
g->warnf = NULL;
g->ud_warn = NULL;
g->mainthread = L;
g->seed = luai_makeseed(L);
g->gcstp = GCSTPGC; /* 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->gcstopem = 0;
g->gcemergency = 0;
g->finobj = g->tobefnz = g->fixedgc = NULL;
g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
g->finobjsur = g->finobjold1 = 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) {
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);
L = G(L)->mainthread; /* only the main thread can be closed */
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.p - 1); /* error object */
const char *msg = (ttisstring(errobj))
? getstr(tsvalue(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);
}
+327 -91
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
*/
@@ -9,164 +9,400 @@
#include "lua.h"
/* Some header files included here need this definition */
typedef struct CallInfo CallInfo;
#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;
** 'old1' -> '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' -> 'finobjold1': survived """";
** 'finobjold1' -> 'finobjrold': just old """";
** 'finobjrold' -> NULL: really old """".
**
** All lists can contain elements older than their main ages, due
** to 'luaC_checkfinalizer' and 'udata2finalize', which move
** objects between the normal lists and the "marked for finalization"
** lists. Moreover, barriers can age young objects in young lists as
** OLD0, which then become OLD1. However, a list never contains
** elements younger than their main ages.
**
** The generational collector also uses a pointer 'firstold1', which
** points to the first OLD1 object in the list. It is used to optimize
** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc'
** and 'reallyold', but often the list has no OLD1 objects or they are
** after 'old1'.) Note the difference between it and 'old1':
** 'firstold1': no OLD1 objects before this point; there can be all
** ages after it.
** 'old1': no objects younger than OLD1 after this point.
*/
#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 (with two exceptions explained below):
**
** '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.
**
** The exceptions to that "gray rule" are:
** - TOUCHED2 objects in generational mode stay in a gray list (because
** they must be visited again at the end of the cycle), but they are
** marked black because assignments to them must activate barriers (to
** move them back to TOUCHED1).
** - Open upvales are kept gray to avoid barriers, but they stay out
** of gray lists. (They don't even have a 'gclist' field.)
*/
#ifndef LUA_USERSTATE
#define LUA_USERSTATE
#endif
#ifndef lua_userstateopen
#define lua_userstateopen(l)
#endif
/*
** About 'nCcalls': This count has two parts: the lower 16 bits counts
** the number of recursive invocations in the C stack; the higher
** 16 bits counts the number of non-yieldable calls in the stack.
** (They are together so that we can change and save both with one
** instruction.)
*/
/* 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)
/* Non-yieldable call increment */
#define nyci (0x10000 | 1)
struct lua_longjmp; /* defined in ldo.c */
/*
** Atomic type (relative to signals) to better ensure that 'lua_sethook'
** is thread safe
*/
#if !defined(l_signalT)
#include <signal.h>
#define l_signalT sig_atomic_t
#endif
/*
** array of `global' objects
** Extra stack space to handle TM calls and some other extras. This
** space is not included in 'stack_last'. It is used only to avoid stack
** checks, either because the element will be promptly popped or because
** there will be a stack check soon after the push. Function frames
** never use this extra space, so it does not need to be kept clean.
*/
#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)
/* 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)
#define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p)
/* 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.
** About union 'u':
** - field 'l' is used only for Lua functions;
** - field 'c' is used only for C functions.
** About union 'u2':
** - field 'funcidx' is used only by C functions while doing a
** protected call;
** - field 'nyield' is used only while a function is "doing" an
** yield (from the yield until the next resume);
** - field 'nres' is used only while closing tbc variables when
** returning from a function;
** - field 'transferinfo' is used only during call/returnhooks,
** before the function starts or after it ends.
*/
typedef struct CallInfo {
StkId base; /* base for called function */
StkId top; /* top for this function */
int state; /* bit fields; see below */
struct CallInfo {
StkIdRel func; /* function index in the stack */
StkIdRel top; /* top for this function */
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; /* function is tracing lines/counts */
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;
} CallInfo;
union {
int funcidx; /* called-function index */
int nyield; /* number of values yielded */
int nres; /* number of values returned */
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;
};
/*
** 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 ci_func(ci) (clvalue((ci)->base - 1))
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
#define CIST_C (1<<1) /* call is running a C function */
#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
#define CIST_HOOKED (1<<3) /* call is running a debug hook */
#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
#define CIST_TAIL (1<<5) /* call was tail called */
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
#define CIST_FIN (1<<7) /* function "called" a finalizer */
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
/* Bits 10-12 are used for CIST_RECST (see below) */
#define CIST_RECST 10
#if defined(LUA_COMPAT_LT_LE)
#define CIST_LEQ (1<<13) /* using __lt for __le */
#endif
/*
** `global state', shared by all threads of this state
** Field CIST_RECST stores the "recover status", used to keep the error
** status while closing to-be-closed variables in coroutines, so that
** Lua can correctly resume after an yield from a __close method called
** because of an error. (Three bits are enough for error status.)
*/
#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7)
#define setcistrecst(ci,st) \
check_exp(((st) & 7) == (st), /* status must fit in three bits */ \
((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \
| ((st) << CIST_RECST)))
/* active function is a Lua function */
#define isLua(ci) (!((ci)->callstatus & CIST_C))
/* 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
*/
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 gcstopem; /* stops emergency collections */
lu_byte genminormul; /* control for minor generational collections */
lu_byte genmajormul; /* control for major generational collections */
lu_byte gcstp; /* control whether 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 *old1; /* start of old1 objects */
GCObject *reallyold; /* objects more than one cycle old ("really old") */
GCObject *firstold1; /* first OLD1 object in the list (if any) */
GCObject *finobjsur; /* list of survival objects with finalizers */
GCObject *finobjold1; /* list of old1 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_NUMTYPES]; /* 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' */
} global_State;
/*
** `per thread' state
** 'per thread' state
*/
struct lua_State {
LUA_USERSTATE
StkId top; /* first free slot in the stack */
CommonHeader;
lu_byte status;
lu_byte allowhook;
unsigned short nci; /* number of items in 'ci' list */
StkIdRel top; /* first free slot in the stack */
global_State *l_G;
CallInfo *ci; /* call info for current function */
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;
StkIdRel stack_last; /* end of stack (last element + 1) */
StkIdRel stack; /* stack base */
UpVal *openupval; /* list of open upvalues in this stack */
StkIdRel tbclist; /* list of to-be-closed variables */
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 nested (non-yieldable | C) calls */
int oldpc; /* last pc traced */
int basehookcount;
int hookcount;
volatile l_signalT hookmask;
};
#define G(L) (L->l_G)
/*
** 'g->nilvalue' being a nil value flags that the state was completely
** build.
*/
#define completestate(g) ttisnil(&g->nilvalue)
/*
** Union of all collectable objects (only for conversions)
** ISO C99, 6.5.2.3 p.5:
** "if a union contains several structures that share a common initial
** sequence [...], and if the union object currently contains one
** of these structures, it is permitted to inspect the common initial
** part of any of them anywhere that a declaration of the complete type
** of the union is visible."
*/
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;
};
/*
** ISO C99, 6.7.2.1 p.14:
** "A pointer to a union object, suitably converted, points to each of
** its members [...], and vice versa."
*/
#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_shrinkCI (lua_State *L);
LUAI_FUNC void luaE_checkcstack (lua_State *L);
LUAI_FUNC void luaE_incCstack (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);
LUAI_FUNC int luaE_resetthread (lua_State *L, int status);
void luaE_closethread (lua_State *OL, lua_State *L);
#endif
+237 -60
View File
@@ -1,97 +1,274 @@
/*
** $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"
/*
** Maximum size for string table.
*/
#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*))
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 *);
/*
** 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(getlngstr(a), getlngstr(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) {
unsigned int h = seed ^ cast_uint(l);
for (; l > 0; l--)
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;
ts->hash = luaS_hash(getlngstr(ts), len, ts->hash);
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 (l_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;
ts->shrlen = 0xFF; /* signals that it is a long string */
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 (l_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);
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, getshrstr(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);
ts->shrlen = cast_byte(l);
memcpy(getshrstr(ts), str, l * sizeof(char));
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 (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
luaM_toobig(L);
ts = luaS_createlngstrobj(L, l);
memcpy(getlngstr(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 (l_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;
}
+34 -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,51 @@
#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);
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
+1497 -335
View File
File diff suppressed because it is too large Load Diff
+852 -346
View File
File diff suppressed because it is too large Load Diff
+46 -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,54 @@
#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);
/*
** Clear all bits of fast-access metamethods, which means that the table
** may have any of these metamethods. (First access that fails after the
** clearing will set the bit again.)
*/
#define invalidateTMcache(t) ((t)->flags &= ~maskflags)
/* 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 void luaH_set (lua_State *L, Table *t, const TValue *key,
TValue *value);
LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,
const TValue *slot, TValue *value);
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);
#endif
#endif
+351 -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,411 @@
#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 pos; /* where to insert new element */
lua_Integer e = aux_getn(L, 1, TAB_RW);
e = luaL_intop(+, e, 1); /* first empty 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, 2,
"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 (l_unlikely(!lua_isstring(L, -1)))
luaL_error(L, "invalid value (%s) at index %I in table for 'concat'",
luaL_typename(L, -1), (LUAI_UACINT)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 (l_unlikely(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 (l_unlikely(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 (l_unlikely(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;
}
+1604 -340
View File
File diff suppressed because it is too large Load Diff
+112 -22
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,144 @@
#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
#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)
/* turn on assertions */
#define LUAI_ASSERT
/* 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 {
int failnext;
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
*/
LUAI_FUNC int lua_checkmemory (lua_State *L);
/*
** Function to print an object GC-friendly
*/
struct GCObject;
LUAI_FUNC void lua_printobj (lua_State *L, struct GCObject *o);
/* 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]; }
/*
** This one is not compatible with tests for opcode optimizations,
** as it blocks some optimizations
#define MAXINDEXRK 0
*/
/* make stack-overflow tests run faster */
#undef LUAI_MAXSTACK
#define LUAI_MAXSTACK 50000
/* test mode uses more stack space */
#undef LUAI_MAXCCALLS
#define LUAI_MAXCCALLS 180
/* force Lua to use its own implementations */
#undef lua_strx2number
#undef lua_number2strx
#endif
+221 -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,215 @@ 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.p;
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.p = 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.p;
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.p += 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.p); /* 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 (l_unlikely(!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.p;
if (l_unlikely(!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.p, event)) /* try original event */
return !l_isfalse(s2v(L->top.p));
#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.p, TM_LT)) {
L->ci->callstatus ^= CIST_LEQ; /* clear mark */
return l_isfalse(s2v(L->top.p));
}
/* 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.p - ci->func.p) - 1; /* number of arguments */
int nextra = actual - nfixparams; /* number of extra arguments */
ci->u.l.nextraargs = nextra;
luaD_checkstack(L, p->maxstacksize + 1);
/* copy function to the top of the stack */
setobjs2s(L, L->top.p++, ci->func.p);
/* move fixed parameters to the top of the stack */
for (i = 1; i <= nfixparams; i++) {
setobjs2s(L, L->top.p++, ci->func.p + i);
setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
}
ci->func.p += actual + 1;
ci->top.p += actual + 1;
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
}
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 */
checkstackGCp(L, nextra, where); /* ensure stack space */
L->top.p = where + nextra; /* next instruction will need top */
}
for (i = 0; i < wanted && i < nextra; i++)
setobjs2s(L, where + i, ci->func.p - nextra + i);
for (; i < wanted; i++) /* complete required results with nil */
setnilvalue(s2v(where + i));
}
+66 -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,91 @@
/*
* 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]))
/*
** Mask with 1 in all fast-access methods. A 1 in any of these bits
** in the flag of a (meta)table means the metatable does not have the
** corresponding metamethod field. (Bit 7 of the flag is used for
** 'isrealasize'.)
*/
#define maskflags (~(~0u << (TM_EQ + 1)))
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);
/*
** Test whether there is no tagmethod.
** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
*/
#define notm(tm) ttisnil(tm)
#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
+598 -296
View File
@@ -1,385 +1,687 @@
/*
** $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;
#if defined(LUA_USE_POSIX) /* { */
/*
** generic extra include file
** Use 'sigaction' when available.
*/
#ifdef LUA_USERCONFIG
#include LUA_USERCONFIG
#endif
static void setsignal (int sig, void (*handler)(int)) {
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); /* do not mask any signal */
sigaction(sig, &sa, NULL);
}
#else /* }{ */
#define setsignal signal
#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) {
/*
** Hook set by signal function to stop the interpreter.
*/
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
lua_sethook(l, 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;
setsignal(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 mod require library 'mod' into global 'mod'\n"
" -l g=mod require library 'mod' into global 'g'\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.
*/
static int report (lua_State *L, int status) {
if (status != LUA_OK) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL)
msg = "(error message not a string)";
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' */
setsignal(SIGINT, laction); /* set C-signal handler */
status = lua_pcall(L, narg, nres, base);
setsignal(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.
** (If there is no interpreter's name either, 'script' is -1, so
** table sizes are zero.)
*/
static void createargtable (lua_State *L, char **argv, int argc, int script) {
int i, narg;
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
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
** If there is no explicit modname and globname contains a '-', cut
** the suffix after '-' (the "version") to make the global name.
*/
#ifndef lua_saveline
#define lua_saveline(L,line) /* empty */
#endif
/*
** this macro defines a function to show the prompt and reads the
** next line for manual input
*/
#ifndef lua_readline
#define lua_readline(L,prompt) readline(L,prompt)
/* maximum length of an input line */
#ifndef MAXINPUT
#define MAXINPUT 512
#endif
static int readline (lua_State *l, const char *prompt) {
static char buffer[MAXINPUT];
if (prompt) {
fputs(prompt, stdout);
fflush(stdout);
static int dolibrary (lua_State *L, char *globname) {
int status;
char *suffix = NULL;
char *modname = strchr(globname, '=');
if (modname == NULL) { /* no explicit name? */
modname = globname; /* module name is equal to global name */
suffix = strchr(modname, *LUA_IGMARK); /* look for a suffix mark */
}
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return 0; /* read fails */
else {
lua_pushstring(l, buffer);
return 1;
*modname = '\0'; /* global name ends here */
modname++; /* module name starts after the '=' */
}
}
#endif
static const char *get_prompt (int firstline) {
const char *p = NULL;
lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2");
p = lua_tostring(L, -1);
if (p == NULL) p = (firstline ? PROMPT : PROMPT2);
lua_pop(L, 1); /* remove global */
return p;
lua_getglobal(L, "require");
lua_pushstring(L, modname);
status = docall(L, 1, 1); /* call 'require(modname)' */
if (status == LUA_OK) {
if (suffix != NULL) /* is there a suffix mark? */
*suffix = '\0'; /* remove suffix from global name */
lua_setglobal(L, globname); /* globname = require(modname) */
}
return report(L, status);
}
static int incomplete (int status) {
if (status == LUA_ERRSYNTAX &&
strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
lua_pop(L, 1);
return 1;
/*
** 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);
}
else
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. In case of error, 'first' is the index of the bad
** argument. Otherwise, 'first' is -1 if there is no program name,
** 0 if there is no script name, or the index of the script name.
*/
static int collectargs (char **argv, int *first) {
int args = 0;
int i;
if (argv[0] != NULL) { /* is there a program name? */
if (argv[0][0]) /* not empty? */
progname = argv[0]; /* save it */
}
else { /* no program name */
*first = -1;
return 0;
}
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 */
}
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 */
return status;
}
static void manual_input (void) {
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'");
for (i = 1; argv[i] != NULL; i++) { /* handle arguments */
*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 = 0; /* 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;
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
/*
** lua_stdin_is_tty detects whether the standard input is a 'tty' (that
** is, whether we're running lua interactively).
*/
#if !defined(lua_stdin_is_tty) /* { */
#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 /* } */
/*
** 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) /* { */
#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 /* } */
/*
** Return the string to be used as a prompt by the interpreter. Leave
** the string (or nil, if using the default value) on the stack, to keep
** it anchored.
*/
static const char *get_prompt (lua_State *L, int firstline) {
if (lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2") == LUA_TNIL)
return (firstline ? LUA_PROMPT : LUA_PROMPT2); /* use the default */
else { /* apply 'tostring' over the value */
const char *p = luaL_tolstring(L, -1, NULL);
lua_remove(L, -2); /* remove original value */
return p;
}
}
/* mark in error messages for incomplete statements */
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
/*
** Check whether 'status' signals a syntax error and the error
** message at the top of the stack ends with the above mark for
** incomplete statements.
*/
static int incomplete (lua_State *L, int status) {
if (status == LUA_ERRSYNTAX) {
size_t lmsg;
const char *msg = lua_tolstring(L, -1, &lmsg);
if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0)
return 1;
}
return 0; /* else... */
}
/*
** Prompt the user, read a line, and push it into the Lua stack.
*/
static int pushline (lua_State *L, int firstline) {
char buffer[LUA_MAXINPUT];
char *b = buffer;
size_t l;
const char *prmt = get_prompt(L, firstline);
int readstatus = lua_readline(L, b, prmt);
lua_pop(L, 1); /* remove prompt */
if (readstatus == 0)
return 0; /* no input */
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 */
}
else
lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
return status;
}
/*
** Read multiple lines until a complete Lua statement
*/
static int multiline (lua_State *L) {
for (;;) { /* repeat until gets a complete statement */
size_t len;
const char *line = lua_tolstring(L, 1, &len); /* get what it has */
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
if (!incomplete(L, status) || !pushline(L, 0)) {
lua_saveline(L, line); /* keep history */
return status; /* should not or cannot try to add continuation line */
}
lua_remove(L, -2); /* remove error message (from incomplete 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; /* 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);
int optlim = (script > 0) ? script : argc; /* first argv not an option */
luaL_checkversion(L); /* check that interpreter has correct version */
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_GCRESTART); /* start GC... */
lua_gc(L, LUA_GCGEN, 0, 0); /* ...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, optlim)) /* execute arguments -e and -l */
return 0; /* something failed */
if (script > 0) { /* execute main script (if there is one) */
if (handle_script(L, argv + script) != LUA_OK)
return 0; /* interrupt in case of error */
}
if (args & has_i) /* -i option? */
doREPL(L); /* do read-eval-print loop */
else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */
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_gc(L, LUA_GCSTOP); /* stop GC while building state */
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;
}
+347 -206
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,424 @@
#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 "8"
/* option for multiple returns in `lua_pcall' and `lua_call' */
#define LUA_VERSION_NUM 504
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 8)
#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-2025 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);
/*
** Type used by the debug API to collect debug information
*/
typedef struct lua_Debug lua_Debug;
/*
** Functions to be called by the debugger in specific events
*/
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
/*
** 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_closethread) (lua_State *L, lua_State *from);
LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */
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);
LUA_API void (lua_closeslot) (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 +434,70 @@ 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)
typedef struct lua_Debug lua_Debug; /* activation record */
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
/*
** 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)
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-2025 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
+802
View File
@@ -0,0 +1,802 @@
/*
** $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): They are commented out or 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.
** =====================================================================
*/
/*
@@ 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
#if defined(LUA_USE_IOS)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN
#endif
/*
@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits.
*/
#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3)
/* }================================================================== */
/*
** {==================================================================
** Configuration for Number types. These options should not be
** set externally, because any other code connected to Lua must
** use the same configuration.
** ===================================================================
*/
/*
@@ 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
/* Default configuration ('long long' and 'double', for 64-bit Lua) */
#define LUA_INT_DEFAULT LUA_INT_LONGLONG
#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE
/*
@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
*/
#define LUA_32BITS 0
/*
@@ 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 1
#else
#define LUA_C89_NUMBERS 0
#endif
#if 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 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
#else /* }{ */
/* use defaults */
#define LUA_INT_TYPE LUA_INT_DEFAULT
#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT
#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
/*
** LUA_IGMARK is a mark to ignore all after it when building the
** module name (e.g., used to build the luaopen_ function name).
** Typically, the suffix after the mark is the module version,
** as in "mod-v1.2.so".
*/
#define LUA_IGMARK "-"
/* }================================================================== */
/*
** {==================================================================
** 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 (low-level part).
** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
** satisfy your needs.
** ===================================================================
*/
/*
@@ 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_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_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
/* 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
/*
** macros to improve jump prediction, used mostly for error handling
** and debug facilities. (Some macros in the Lua API use these macros.
** Define LUA_NOBUILTIN if you do not want '__builtin_expect' in your
** code.)
*/
#if !defined(luai_likely)
#if defined(__GNUC__) && !defined(LUA_NOBUILTIN)
#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
#else
#define luai_likely(x) (x)
#define luai_unlikely(x) (x)
#endif
#endif
#if defined(LUA_CORE) || defined(LUA_LIB)
/* shorter names for Lua's own use */
#define l_likely(x) luai_likely(x)
#define l_unlikely(x) luai_unlikely(x)
#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 and max(int)/2.)
*/
#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 initial 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
+22 -14
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,42 @@
#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 */
#endif
/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);
#endif
+310 -249
View File
@@ -1,274 +1,335 @@
/*
** $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, MAX_SIZET);
}
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 */
setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */
luaD_inctop(L);
loadVector(S, getlngstr(ts), size); /* load directly in final place */
L->top.p--; /* pop string */
}
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);
}
}
/*
** Load the upvalues for a function. The names must be filled first,
** because the filling of the other fields can raise read errors and
** the creation of the error message can call an emergency collection;
** in that case all prototypes must be consistent for the GC.
*/
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++) /* make array valid for GC */
f->upvalues[i].name = NULL;
for (i = 0; i < n; i++) { /* following calls can raise errors */
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);
if (n != 0) /* does it have debug information? */
n = f->sizeupvalues; /* must be this many */
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.p, 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;
}
+20 -21
View File
@@ -1,36 +1,35 @@
/*
** $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 LUAC_VERSION (((LUA_VERSION_NUM / 100) * 16) + LUA_VERSION_NUM % 100)
#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
+291
View File
@@ -0,0 +1,291 @@
/*
** $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
#define MSGInvalid "invalid UTF-8 code"
/*
** 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(c) (((c) & 0xC0) == 0x80)
#define iscontp(p) iscont(*(p))
/* 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 (!iscont(cc)) /* 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, MSGInvalid);
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 && iscontp(s + posi)) posi--;
}
else {
if (iscontp(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 && iscontp(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 (iscontp(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_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2);
if (n < len) {
while (iscontp(s + n)) n++; /* go to next character */
}
if (n >= len) /* (also handles original 'n' being negative) */
return 0; /* no more codepoints */
else {
utfint code;
const char *next = utf8_decode(s + n, &code, strict);
if (next == NULL || iscontp(next))
return luaL_error(L, MSGInvalid);
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);
const char *s = luaL_checkstring(L, 1);
luaL_argcheck(L, !iscontp(s), 1, MSGInvalid);
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;
}
+1768 -603
View File
File diff suppressed because it is too large Load Diff
+123 -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,129 @@
#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) \
(l_likely(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) \
(l_likely(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); }
/*
** Shift right is the same as shift left with a negative 'y'
*/
#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y))
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
+190 -140
View File
@@ -1,160 +1,210 @@
#
## $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= \
-Wfatal-errors \
-Wextra \
-Wshadow \
-Wundef \
-Wwrite-strings \
# -Wtraditional \
# -Wcast-qual
CFLAGS = $(CONFIG) $(CWARNS) -ansi
-Wredundant-decls \
-Wdisabled-optimization \
-Wdouble-promotion \
-Wmissing-declarations \
# 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 \
# To make early versions
CO_OPTIONS =
# Warnings for gcc, not valid for clang
CWARNGCC= \
-Wlogical-op \
-Wno-aggressive-loop-optimizations \
AR = ar
ARFLAGS = rvl
# 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 \
# 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
CWARNS= $(CWARNSCPP) $(CWARNSC) $(CWARNGCC)
LIBOBJS = \
lauxlib.o \
lbaselib.o \
ltablib.o \
lmathlib.o \
liolib.o \
lstrlib.o \
ldblib.o
# Some useful compiler options for internal tests:
# -DLUAI_ASSERT turns on all assertions inside Lua.
# -DHARDSTACKTESTS forces a reallocation of the stack at every point where
# the stack can be reallocated.
# -DHARDMEMTESTS forces a full collection at all points where the collector
# can run.
# -DEMERGENCYGCTESTS forces an emergency collection at every single allocation.
# -DEXTERNMEMCHECK removes internal consistency checking of blocks being
# deallocated (useful when an external tool like valgrind does the check).
# -DMAXINDEXRK=k limits range of constants in RK instruction operands.
# -DLUA_COMPAT_5_3
# -pg -malign-double
# -DLUA_USE_CTYPE -DLUA_USE_APICHECK
# The following options help detect "undefined behavior"s that seldom
# create problems; some are only available in newer gcc versions. To
# use some of them, we also have to define an environment variable
# ASAN_OPTIONS="detect_invalid_pointer_pairs=2".
# -fsanitize=undefined
# -fsanitize=pointer-subtract -fsanitize=address -fsanitize=pointer-compare
# TESTS= -DLUA_USER_H='"ltests.h"' -O0 -g
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)
LOCAL = $(TESTS) $(CWARNS)
clear :
rcsclean
rm -f *.o *.a
# enable Linux goodies
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_USE_READLINE
MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS= -ldl -lreadline
%.h : RCS/%.h,v
co $(CO_OPTIONS) $@
%.c : RCS/%.c,v
co $(CO_OPTIONS) $@
CC= gcc
CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
AR= ar rc
RANLIB= ranlib
RM= rm -f
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 \
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
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
ALL_T= $(CORE_T) $(LUA_T)
ALL_O= $(CORE_O) $(LUA_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)
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; 2025 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)
+9458
View File
File diff suppressed because it is too large Load Diff
+121
View File
@@ -0,0 +1,121 @@
/*
** Lua core, libraries, and interpreter in a single file.
** Compiling just this file generates a complete Lua stand-alone
** program:
**
** $ gcc -O2 -std=c99 -o lua onelua.c -lm
**
** or
**
** $ gcc -O2 -std=c89 -DLUA_USE_C89 -o lua onelua.c -lm
**
*/
/* 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. Default is no
** platform-specific features. Some of these options 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
+312
View File
@@ -0,0 +1,312 @@
#!../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 = T.stacklevel()
return ncalls -- number of C calls
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')
-- trace GC cycles
require"tracegc".start()
report"gc.lua"
local f = assert(loadfile('gc.lua'))
f()
dofile('db.lua')
assert(dofile('calls.lua') == deep and deep)
_G.deep = nil
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-2025 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.
*****************************************************************************
]]
+1547
View File
File diff suppressed because it is too large Load Diff
+527
View File
@@ -0,0 +1,527 @@
-- $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)
local 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
local 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
local a = require"names"
assert(a[1] == "names" and a[2] == D"names.lua")
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)
NAME, REQUIRED, AA, B = nil
-- 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)
AA = nil
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)
_ENV.x, _ENV.y = nil
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
local a, b = 1, 2+3
assert(a==1 and b==5)
a={}
local 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
local 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
local a, b, c
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)
do
-- _ENV constant
local function foo ()
local _ENV <const> = 11
X = "hi"
end
local st, msg = pcall(foo)
assert(not st and string.find(msg, "number"))
end
-- 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
local 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
local 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'
+363
View File
@@ -0,0 +1,363 @@
-- $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)
do -- constant folding
local code = string.format("return -1 >> %d", math.maxinteger)
assert(load(code)() == 0)
local code = string.format("return -1 >> %d", math.mininteger)
assert(load(code)() == 0)
local code = string.format("return -1 << %d", math.maxinteger)
assert(load(code)() == 0)
local code = string.format("return -1 << %d", math.mininteger)
assert(load(code)() == 0)
end
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(1 >> math.mininteger == 0)
assert(1 >> math.maxinteger == 0)
assert(1 << math.mininteger == 0)
assert(1 << math.maxinteger == 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
+497
View File
@@ -0,0 +1,497 @@
-- $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))
local 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)
fact = nil
-- testing declarations
local a = {i = 10}
local 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')
t = nil -- delete 't'
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')
local a,b = a()
assert(a == 120 and b == 3)
fat = nil
print('+')
local function err_on_n (n)
if n==0 then error(); exit(1);
else err_on_n (n-1); exit(1);
end
end
do
local function dummy (n)
if n > 0 then
assert(not pcall(err_on_n, n))
dummy(n-1)
end
end
dummy(10)
end
_G.deep = nil -- "declaration" (used by 'all.lua')
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 -- C-stack overflow while handling C-stack overflow
local function loop ()
assert(pcall(loop))
end
local err, msg = xpcall(loop, loop)
assert(not err and string.find(msg, "error"))
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
local Z = function (le)
local function a (f)
return le(function (x) return f(f)(x) end)
end
return a(a)
end
-- non-recursive factorial
local F = function (f)
return function (n)
if n == 0 then return 1
else return n*f(n-1) end
end
end
local 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
local f = g(10)
assert(f(9, 16) == 10+11+12+13+10+9+16+10)
print('+')
-- testing multiple returns
local function unlpack (t, i)
i = i or 1
if (i <= #t) then
return t[i], unlpack(t, i+1)
end
end
local 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
local function f() return 1,2,30,4 end
local 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'"
local function read1 (x)
local i = 0
return function ()
collectgarbage()
i=i+1
return string.sub(x, i, i)
end
end
local 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)
do -- another bug (in 5.4.0)
-- loading a binary long string interrupted by GC cycles
local f = string.dump(function ()
return '01234567890123456789012345678901234567890123456789'
end)
f = load(read1(f))
assert(f() == '01234567890123456789012345678901234567890123456789')
end
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"))
_G.x = nil
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)
XX = nil
-- 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), "read", "t"))
assert(a()(2)(3)(10) == 15)
-- repeat the test loading a binary chunk
x = string.dump(a)
a = assert(load(read1(x), "read", "b"))
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("c4BBc6BBB",
"\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)
)
local c = string.dump(function ()
local a = 1; local b = 3;
local f = function () return a + b + _ENV.c; end -- upvalues
local s1 = "a constant"
local s2 = "another constant"
return a + b * 3
end)
assert(assert(load(c))() == 10)
-- check header
assert(string.sub(c, 1, #header) == header)
-- check LUAC_INT and LUAC_NUM
local ci, cn = string.unpack("jn", c, #header + 1)
assert(ci == 0x5678 and cn == 370.5)
-- 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
end
print('OK')
return deep
+280
View File
@@ -0,0 +1,280 @@
-- $Id: testes/closure.lua $
-- See Copyright Notice in file all.lua
print "testing closures"
do -- bug in 5.4.7
_ENV[true] = 10
local function aux () return _ENV[1 < 2] end
assert(aux() == 10)
_ENV[true] = nil
end
local A,B = 0,{g=10}
local 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
local f
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 y, 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'
local foo1, foo2, foo3
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 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'
+449
View File
@@ -0,0 +1,449 @@
-- $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})
foo = function (f, a)
f(100 * 1000)
f(100.0 * 1000)
f(-100 * 1000)
f(-100 * 1000.0)
f(100000)
f(100000.0)
f(-100000)
f(-100000.0)
end
checkKlist(foo, {100000, 100000.0, -100000, -100000.0})
-- floats x integers
foo = function (t, a)
t[a] = 1; t[a] = 1.0
t[a] = 1; t[a] = 1.0
t[a] = 2; t[a] = 2.0
t[a] = 0; t[a] = 0.0
t[a] = 1; t[a] = 1.0
t[a] = 2; t[a] = 2.0
t[a] = 0; t[a] = 0.0
end
checkKlist(foo, {1, 1.0, 2, 2.0, 0, 0.0})
-- testing opcodes
-- check that 'f' opcodes match '...'
local 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'.
local 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
local 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 () 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'
+406
View File
@@ -0,0 +1,406 @@
-- $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
local a
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);
local 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);
local 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
local code = string.format("return XX %s %s", op, o2)
local res = assert(load(code))()
assert(res == gab)
_ENV.XX = o2
code = string.format("return (%s) %s XX", o1, op)
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
_ENV.XX = nil
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; local function f(x) x={a=1}; x={x=1}; x={G=1} end
end
do -- bug since 5.4.0
-- create code with a table using more than 256 constants
local code = {"local x = {"}
for i = 1, 257 do
code[#code + 1] = i .. ".1,"
end
code[#code + 1] = "};"
code = table.concat(code)
-- add "ret" to the end of that code and checks that
-- it produces the expected value "val"
local function check (ret, val)
local code = code .. ret
code = load(code)
assert(code() == val)
end
check("return (1 ~ (2 or 3))", 1 ~ 2)
check("return (1 | (2 or 3))", 1 | 2)
check("return (1 + (2 or 3))", 1 + 2)
check("return (1 << (2 or 3))", 1 << 2)
end
local 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;
local n=100;
local i=3;
local t = {};
local 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)
local function f (i)
while 1 do
if i>0 then i=i-1;
else return; end;
end;
end;
local 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
local 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
local 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
IX = nil
_G.GLOB1 = nil
------------------------------------------------------------------
-- testing some syntax errors (chosen through 'gcov')
checkload("for x do", "expected")
checkload("x:call", "expected")
print'OK'
+1175
View File
File diff suppressed because it is too large Load Diff
+197
View File
@@ -0,0 +1,197 @@
-- $Id: testes/cstack.lua $
-- See Copyright Notice in file all.lua
local tracegc = require"tracegc"
print"testing stack overflow detection"
-- Segmentation faults in these tests probably result from a C-stack
-- overflow. To avoid these errors, you should set a smaller limit for
-- the use of C stack by Lua, by changing the constant 'LUAI_MAXCCALLS'.
-- Alternatively, you can ensure a larger stack for the program.
local function checkerror (msg, f, ...)
local s, err = pcall(f, ...)
assert(not s and string.find(err, msg))
end
do print("testing stack overflow in message handling")
local count = 0
local function loop (x, y, z)
count = count + 1
return 1 + loop(x, y, z)
end
tracegc.stop() -- __gc should not be called with a full stack
local res, msg = xpcall(loop, loop)
tracegc.start()
assert(msg == "error in error handling")
print("final 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, 2000)
end
do print("testing stack-overflow in recursive 'gsub'")
local count = 0
local function foo ()
count = count + 1
string.gsub("a", ".", foo)
end
checkerror("stack overflow", foo)
print("final count: ", count)
print("testing stack-overflow in recursive 'gsub' with metatables")
local count = 0
local t = setmetatable({}, {__index = foo})
foo = function ()
count = count + 1
string.gsub("a", ".", t)
end
checkerror("stack overflow", foo)
print("final count: ", count)
end
do -- bug in 5.4.0
print("testing limits in coroutines inside deep calls")
local count = 0
local lim = 1000
local function stack (n)
if n > 0 then return stack(n - 1) + 1
else coroutine.wrap(function ()
count = count + 1
stack(lim)
end)()
end
end
local st, msg = xpcall(stack, function () return "ok" end, lim)
assert(not st and msg == "ok")
print("final count: ", count)
end
do -- bug since 5.4.0
local count = 0
print("chain of 'coroutine.close'")
-- create N coroutines forming a list so that each one, when closed,
-- closes the previous one. (With a large enough N, previous Lua
-- versions crash in this test.)
local coro = false
for i = 1, 1000 do
local previous = coro
coro = coroutine.create(function()
local cc <close> = setmetatable({}, {__close=function()
count = count + 1
if previous then
assert(coroutine.close(previous))
end
end})
coroutine.yield() -- leaves 'cc' pending to be closed
end)
assert(coroutine.resume(coro)) -- start it and run until it yields
end
local st, msg = coroutine.close(coro)
assert(not st and string.find(msg, "C stack overflow"))
print("final count: ", count)
end
do
print("nesting of resuming yielded coroutines")
local count = 0
local function body ()
coroutine.yield()
local f = coroutine.wrap(body)
f(); -- start new coroutine (will stop in previous yield)
count = count + 1
f() -- call it recursively
end
local f = coroutine.wrap(body)
f()
assert(not pcall(f))
print("final count: ", count)
end
do -- bug in 5.4.2
print("nesting coroutines running after recoverable errors")
local count = 0
local function foo()
count = count + 1
pcall(1) -- create an error
-- running now inside 'precover' ("protected recover")
coroutine.wrap(foo)() -- call another coroutine
end
checkerror("C stack overflow", foo)
print("final count: ", count)
end
if T then
print("testing stack recovery")
local N = 0 -- trace number of calls
local LIM = -1 -- will store N just before stack overflow
-- trace stack size; after stack overflow, it should be
-- the maximum allowed stack size.
local stack1
local dummy
local function err(msg)
assert(string.find(msg, "stack overflow"))
local _, stacknow = T.stacklevel()
assert(stacknow == stack1 + 200)
end
-- When LIM==-1, the 'if' is not executed, so this function only
-- counts and stores the stack limits up to overflow. Then, LIM
-- becomes N, and then the 'if' code is run when the stack is
-- full. Then, there is a stack overflow inside 'xpcall', after which
-- the stack must have been restored back to its maximum normal size.
local function f()
dummy, stack1 = T.stacklevel()
if N == LIM then
xpcall(f, err)
local _, stacknow = T.stacklevel()
assert(stacknow == stack1)
return
end
N = N + 1
f()
end
local topB, sizeB -- top and size Before overflow
local topA, sizeA -- top and size After overflow
topB, sizeB = T.stacklevel()
tracegc.stop() -- __gc should not be called with a full stack
xpcall(f, err)
tracegc.start()
topA, sizeA = T.stacklevel()
-- sizes should be comparable
assert(topA == topB and sizeA < sizeB * 2)
print(string.format("maximum stack size: %d", stack1))
LIM = N -- will stop recursion at maximum level
N = 0 -- to count again
tracegc.stop() -- __gc should not be called with a full stack
f()
tracegc.start()
print"+"
end
print'OK'
+1054
View File
File diff suppressed because it is too large Load Diff
+700
View File
@@ -0,0 +1,700 @@
-- $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, debug)
local m = doit(prog)
if debug then print(m, msg) end
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)
do -- testing errors in goto/break
local function checksyntax (prog, msg, line)
local st, err = load(prog)
assert(string.find(err, "line " .. line))
assert(string.find(err, msg, 1, true))
end
checksyntax([[
::A:: a = 1
::A::
]], "label 'A' already defined", 1)
checksyntax([[
a = 1
goto A
do ::A:: end
]], "no visible label 'A'", 2)
end
if not T then
(Message or print)
('\n >>> testC not active: skipping tests for messages in C <<<\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")
-- stack space for luaL_traceback (bug in 5.4.6)
local res = T.testC[[
# push 16 elements on the stack
pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
pushnum 1;
# traceback should work with 4 remaining slots
traceback xuxu 1;
return 1
]]
assert(string.find(res, "xuxu.-main chunk"))
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("aaa=1; bbbb=2; aaa=math.sin(3)+bbbb(3)", "global 'bbbb'")
checkmessage("aaa={}; do local aaa=1 end aaa:bbbb(3)", "method 'bbbb'")
checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'"))
checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
checkmessage("aaa=(1)..{}", "a table value")
-- bug in 5.4.6
checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
-- a similar bug in 5.4.7, since 5.4.0
checkmessage("print(('_ENV').x + 1)", "field 'x'")
_G.aaa, _G.bbbb = nil
-- calls
checkmessage("local a; a(13)", "local 'a'")
checkmessage([[
local a = setmetatable({}, {__add = 34})
a = a + 1
]], "metamethod 'add'")
checkmessage([[
local a = setmetatable({}, {__lt = {}})
a = a > a
]], "metamethod 'lt'")
-- tail calls
checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
checkmessage("aaa={}; do local aaa=1 end; return aaa:bbbb(3)", "method 'bbbb'")
checkmessage("aaa = #print", "length of a function value")
checkmessage("aaa = #3", "length of a number value")
_G.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("BB=1; local aaa={}; x=aaa+BB", "local 'aaa'")
checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
checkmessage("aaa=2; BB=nil;x=aaa*BB", "global 'BB'")
checkmessage("aaa={}; x=-aaa", "global 'aaa'")
-- short circuit
checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = math.sin(1) and bbbb(3)",
"local 'bbbb'")
checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = bbbb(1) or aaa(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("aaa = 24 // 0", "divide by zero")
checkmessage("aaa = 1 % 0", "'n%0'")
-- type error for an object which is neither in an upvalue nor a register.
-- The following code will try to index the value 10 that is stored in
-- the metatable, without moving it to a register.
checkmessage("local a = setmetatable({}, {__index = 10}).x",
"attempt to index a number value")
-- 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
if T then -- extra tests for 'luaL_tolstring'
-- bug in 5.4.3; 'luaL_tolstring' with negative indices
local x = setmetatable({}, {__name="TABLE"})
assert(T.testC("Ltolstring -1; return 1", x) == tostring(x))
local a, b = T.testC("pushint 10; Ltolstring -2; return 2", x)
assert(a == 10 and b == tostring(x))
setmetatable(x, {__tostring=function (o)
assert(o == x)
return "ABC"
end})
local a, b, c = T.testC("pushint 10; Ltolstring -2; return 3", x)
assert(a == x and b == 10 and c == "ABC")
end
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] = "aaa = x" .. i
end
local s = table.concat(t, "; ")
t = nil
checkmessage(s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage("local _ENV=_ENV;"..s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage(s.."; local t = {}; aaa = 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'+'
aaa = {}; setmetatable(aaa, {__index = string})
checkmessage("aaa: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'")
_G.aaa = nil
-- 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'.
local 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)
]], 2)
lineerror([[
local a = {x = 13}
a
.
x
( -- <<
23
)
]], 5)
lineerror([[
local a = {x = 13}
a
.
x
(
23 + a
)
]], 6)
local p = [[
function g() f() end
function f(x) error('a', XX) end
g()
]]
XX=3;lineerror((p), 3)
XX=0;lineerror((p), false)
XX=1;lineerror((p), 2)
XX=2;lineerror((p), 1)
_G.XX, _G.g, _G.f = nil
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)
-- bug in 5.4.0
lineerror([[
local a = 0
local b = 1
local c = b % a
]], 3)
do
-- Force a negative estimate for base line. Error in instruction 2
-- (after VARARGPREP, GETGLOBAL), with first absolute line information
-- (forced by too many lines) in instruction 0.
local s = string.format("%s return __A.x", string.rep("\n", 300))
lineerror(s, 301)
end
if not _soft then
-- several tests that exaust the Lua stack
collectgarbage()
print"testing stack overflow"
local C = 0
-- get line where stack overflow will happen
local l = debug.getinfo(1, "l").currentline + 1
local function auxy () C=C+1; auxy() end -- produce a stack overflow
function YY ()
collectgarbage("stop") -- avoid running finalizers without stack space
auxy()
collectgarbage("restart")
end
local function checkstackmessage (m)
print("(expected stack overflow after " .. C .. " calls)")
C = 0 -- prepare next count
return (string.find(m, "stack overflow"))
end
-- repeated stack overflows (to check stack recovery)
assert(checkstackmessage(doit('YY()')))
assert(checkstackmessage(doit('YY()')))
assert(checkstackmessage(doit('YY()')))
_G.YY = nil
-- error lines in stack overflow
local l1
local function g(x)
l1 = debug.getinfo(x, "l").currentline + 2
collectgarbage("stop") -- avoid running finalizers without stack space
auxy()
collectgarbage("restart")
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
local 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+"); aaa=3')
assert(_G.aaa==3 and not _G.I)
_G.I,_G.aaa = nil
print('+')
local 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, 500)
local res, msg = load(s) -- 500 levels not ok
assert(not res and (string.find(msg, "too many") or
string.find(msg, "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')
+504
View File
@@ -0,0 +1,504 @@
-- $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)
do -- test invalidating flags
local mt = {__eq = true}
local a = setmetatable({10}, mt)
local b = setmetatable({10}, mt)
mt.__eq = nil
assert(a ~= b) -- no metamethod
mt.__eq = function (x,y) return x[1] == y[1] end
assert(a == b) -- must use metamethod now
end
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")
do
-- bug since 5.4.1
local mt = setmetatable({__newindex={}}, {__mode='v'})
local t = setmetatable({}, mt)
if T then T.allocfailnext() end
-- seg. fault
for i=1, 10 do t[i] = 1 end
end
-- 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)
_G.X, _G.B = nil
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
+951
View File
@@ -0,0 +1,951 @@
-- $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('"alo"', "{a}\n", "second line\n", "third line \n"))
assert(io.write('Xfourth_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') == '"alo"')
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) == "X")
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)
_G.X = nil
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 == _G.X2)
_G.X2 = nil
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")
-- invalid mode for popen
checkerr("invalid mode", io.popen, "cat", "")
checkerr("invalid mode", io.popen, "cat", "r+")
checkerr("invalid mode", io.popen, "cat", "rw")
do -- basic tests for popen
local file = os.tmpname()
local f = assert(io.popen("cat - > " .. file, "w"))
f:write("a line")
assert(f:close())
local f = assert(io.popen("cat - < " .. file, "r"))
assert(f:read("a") == "a line")
assert(f:close())
assert(os.remove(file))
end
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})
checkerr("field 'year' is out-of-bound", os.time,
{year = -(1 << 31), month = 1, day = 1})
if math.maxinteger > 2^31 then -- larger lua_integer?
checkerr("field 'year' is out-of-bound", os.time,
{year = (1 << 31) + 1900, month = 1, day = 1})
end
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))
+695
View File
@@ -0,0 +1,695 @@
-- $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()
_G.temp = nil
end
-- collection of functions without locals, globals, etc.
do local f = function () end end
print("functions with errors")
local 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
rawset(_G, "a", nil)
_G.x = nil
do
foo = nil
print('long strings')
local x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
assert(string.len(x)==80)
local s = ''
local k = math.min(300, (math.maxinteger // 80) // 2)
for n = 1, k do s = s..x; local j=tostring(n) end
assert(string.len(s) == k*80)
s = string.sub(s, 1, 10000)
local s, i = string.gsub(s, '(%d%d%d%d)', '')
assert(i==10000 // 4)
assert(_G["while"] == 234)
_G["while"] = nil
end
--
-- 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")
local lim = 15
local 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"))
assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false
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 = false
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"
_ENV.a = nil
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 = false
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 = false
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')
do -- check that the collector is not reentrant in incremental mode
local res = true
setmetatable({}, {__gc = function ()
res = collectgarbage()
end})
collectgarbage()
assert(not res)
end
collectgarbage(oldmode)
print('OK')
+172
View File
@@ -0,0 +1,172 @@
-- $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
do
-- ensure that 'firstold1' is corrected when object is removed from
-- the 'allgc' list
local function foo () end
local old = {10}
collectgarbage() -- make 'old' old
assert(not T or T.gcage(old) == "old")
setmetatable(old, {}) -- new table becomes OLD0 (barrier)
assert(not T or T.gcage(getmetatable(old)) == "old0")
collectgarbage("step", 0) -- new table becomes OLD1 and firstold1
assert(not T or T.gcage(getmetatable(old)) == "old1")
setmetatable(getmetatable(old), {__gc = foo}) -- get it out of allgc list
collectgarbage("step", 0) -- should not seg. fault
end
do -- bug in 5.4.0
-- When an object aged OLD1 is finalized, it is moved from the list
-- 'finobj' to the *beginning* of the list 'allgc', but that part of the
-- list was not being visited by 'markold'.
local A = {}
A[1] = false -- old anchor for object
-- obj finalizer
local function gcf (obj)
A[1] = obj -- anchor object
assert(not T or T.gcage(obj) == "old1")
obj = nil -- remove it from the stack
collectgarbage("step", 0) -- do a young collection
print(getmetatable(A[1]).x) -- metatable was collected
end
collectgarbage() -- make A old
local obj = {} -- create a new object
collectgarbage("step", 0) -- make it a survival
assert(not T or T.gcage(obj) == "survival")
setmetatable(obj, {__gc = gcf, x = "+"}) -- create its metatable
assert(not T or T.gcage(getmetatable(obj)) == "new")
obj = nil -- clear object
collectgarbage("step", 0) -- will call obj's finalizer
end
do -- another bug in 5.4.0
local old = {10}
collectgarbage() -- make 'old' old
local co = coroutine.create(
function ()
local x = nil
local f = function ()
return x[1]
end
x = coroutine.yield(f)
coroutine.yield()
end
)
local _, f = coroutine.resume(co) -- create closure over 'x' in coroutine
collectgarbage("step", 0) -- make upvalue a survival
old[1] = {"hello"} -- 'old' go to grayagain as 'touched1'
coroutine.resume(co, {123}) -- its value will be new
co = nil
collectgarbage("step", 0) -- hit the barrier
assert(f() == 123 and old[1][1] == "hello")
collectgarbage("step", 0) -- run the collector once more
-- make sure old[1] was not collected
assert(f() == 123 and old[1][1] == "hello")
end
do -- bug introduced in commit 9cf3299fa
local t = setmetatable({}, {__mode = "kv"}) -- all-weak table
collectgarbage() -- full collection
assert(not T or T.gcage(t) == "old")
t[1] = {10}
assert(not T or (T.gcage(t) == "touched1" and T.gccolor(t) == "gray"))
collectgarbage("step", 0) -- minor collection
assert(not T or (T.gcage(t) == "touched2" and T.gccolor(t) == "black"))
collectgarbage("step", 0) -- minor collection
assert(not T or T.gcage(t) == "old") -- t should be black, but it was gray
t[1] = {10} -- no barrier here, so t was still old
collectgarbage("step", 0) -- minor collection
-- t, being old, is ignored by the collection, so it is not cleared
assert(t[1] == nil) -- fails with the bug
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')
-- 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 $(LUA_DIR)/lua.h
$(CC) $(CFLAGS) -o lib1.so lib1.c
lib11.so: lib11.c $(LUA_DIR)/luaconf.h $(LUA_DIR)/lua.h
$(CC) $(CFLAGS) -o lib11.so lib11.c
lib2.so: lib2.c $(LUA_DIR)/luaconf.h $(LUA_DIR)/lua.h
$(CC) $(CFLAGS) -o lib2.so lib2.c
lib21.so: lib21.c $(LUA_DIR)/luaconf.h $(LUA_DIR)/lua.h
$(CC) $(CFLAGS) -o lib21.so lib21.c
lib2-v2.so: lib21.c $(LUA_DIR)/luaconf.h $(LUA_DIR)/lua.h
$(CC) $(CFLAGS) -o lib2-v2.so lib22.c
+343
View File
@@ -0,0 +1,343 @@
-- $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)
_G.x = nil
-- 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
local var1 = string.rep('a', 15000) .. '1'
local var2 = string.rep('a', 15000) .. '2'
local 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)
_G[var1], _G[var2] = nil
print('+')
-- escapes --
assert("\n\t" == [[
]])
assert([[
$debug]] == "\n $debug")
assert([[ [ ]] ~= [[ ] ]])
-- long strings --
local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960)
prog = [=[
print('+')
local a1 = [["this is a 'string' with several 'quotes'"]]
local a2 = "'quotes'"
assert(string.find(a1, a2) == 34)
print('+')
a1 = [==[temp = [[an arbitrary value]]; ]==]
assert(load(a1))()
assert(temp == 'an arbitrary value')
_G.temp = nil
-- long strings --
local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960)
print('+')
local 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('+')
_G.x = nil
dostring(prog)
assert(x)
_G.x = nil
do -- reuse of long strings
-- get the address of a string
local function getadd (s) return string.format("%p", s) end
local s1 <const> = "01234567890123456789012345678901234567890123456789"
local s2 <const> = "01234567890123456789012345678901234567890123456789"
local s3 = "01234567890123456789012345678901234567890123456789"
local function foo() return s1 end
local function foo1() return s3 end
local function foo2()
return "01234567890123456789012345678901234567890123456789"
end
local a1 = getadd(s1)
assert(a1 == getadd(s2))
assert(a1 == getadd(foo()))
assert(a1 == getadd(foo1()))
assert(a1 == getadd(foo2()))
local sd = "0123456789" .. "0123456789012345678901234567890123456789"
assert(sd == s1 and getadd(sd) ~= a1)
end
-- testing line ends
prog = [[
local a = 1 -- a comment
local 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
_G.x, _G.y = nil
-- testing comments and strings with long brackets
local 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')
+1181
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