Compare commits

...

110 Commits

Author SHA1 Message Date
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
44 changed files with 1369 additions and 855 deletions

39
bugs
View File

@@ -2964,8 +2964,10 @@ patch = [[
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
+ sizeof(CallInfo) * n;
}
]]
}
-- [[]]
Bug{
what = [[Wrong assert when reporting concatenation errors
(manifests only when Lua is compiled in debug mode)]],
@@ -3456,6 +3458,43 @@ patch = [[
}
-----------------------------------------------------------------
-- Lua 5.3.1
Bug{
what = [['io.lines' does not check maximum number of options]],
report = [[Patrick Donnell, 2015/07/10]],
since = [[3.0]],
fix = nil,
example = [[
-- can segfault in some machines
t ={}; for i = 1, 253 do t[i] = 1 end
io.lines("someexistingfile", table.unpack(t))()
]],
patch = [[
--- liolib.c 2015/07/07 17:03:34 2.146
+++ liolib.c 2015/07/15 14:40:28 2.147
@@ -318,8 +318,15 @@
static int io_readline (lua_State *L);
+/*
+** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
+** in the limit for upvalues of a closure)
+*/
+#define MAXARGLINE 250
+
static void aux_lines (lua_State *L, int toclose) {
int n = lua_gettop(L) - 1; /* number of arguments to read */
+ luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
lua_pushinteger(L, n); /* number of arguments to read */
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
]]
}
--[=[
Bug{
what = [[ ]],

149
lapi.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 2.248 2015/03/28 19:14:47 roberto Exp roberto $
** $Id: lapi.c,v 2.256 2015/10/06 16:10:22 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -121,11 +121,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
lua_lock(to);
api_checknelems(from, n);
api_check(from, G(from) == G(to), "moving among independent states");
api_check(from, to->ci->top - to->top >= n, "not enough elements to move");
api_check(from, to->ci->top - to->top >= n, "stack overflow");
from->top -= n;
for (i = 0; i < n; i++) {
setobj2s(to, to->top, from->top + i);
api_incr_top(to);
to->top++; /* stack already checked by previous 'api_check' */
}
lua_unlock(to);
}
@@ -471,11 +471,16 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
}
/*
** Pushes on the stack a string with given length. Avoid using 's' when
** 'len' == 0 (as 's' can be NULL in that case), due to later use of
** 'memcmp' and 'memcpy'.
*/
LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
TString *ts;
lua_lock(L);
luaC_checkGC(L);
ts = luaS_newlstr(L, s, len);
ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
setsvalue2s(L, L->top, ts);
api_incr_top(L);
lua_unlock(L);
@@ -579,19 +584,30 @@ LUA_API int lua_pushthread (lua_State *L) {
*/
LUA_API int lua_getglobal (lua_State *L, const char *name) {
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt; /* global table */
lua_lock(L);
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
setsvalue2s(L, L->top, luaS_new(L, name));
api_incr_top(L);
luaV_gettable(L, gt, L->top - 1, L->top - 1);
static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux;
TString *str = luaS_new(L, k);
if (luaV_fastget(L, t, str, aux, luaH_getstr)) {
setobj2s(L, L->top, aux);
api_incr_top(L);
}
else {
setsvalue2s(L, L->top, str);
api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux);
}
lua_unlock(L);
return ttnov(L->top - 1);
}
LUA_API int lua_getglobal (lua_State *L, const char *name) {
Table *reg = hvalue(&G(L)->l_registry);
lua_lock(L);
return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
}
LUA_API int lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
@@ -603,24 +619,25 @@ LUA_API int lua_gettable (lua_State *L, int idx) {
LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
StkId t;
lua_lock(L);
t = index2addr(L, idx);
setsvalue2s(L, L->top, luaS_new(L, k));
api_incr_top(L);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
return ttnov(L->top - 1);
return auxgetstr(L, index2addr(L, idx), k);
}
LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
StkId t;
const TValue *aux;
lua_lock(L);
t = index2addr(L, idx);
setivalue(L->top, n);
api_incr_top(L);
luaV_gettable(L, t, L->top - 1, L->top - 1);
if (luaV_fastget(L, t, n, aux, luaH_getint)) {
setobj2s(L, L->top, aux);
api_incr_top(L);
}
else {
setivalue(L->top, n);
api_incr_top(L);
luaV_finishget(L, t, L->top - 1, L->top - 1, aux);
}
lua_unlock(L);
return ttnov(L->top - 1);
}
@@ -719,18 +736,29 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
** set functions (stack -> Lua)
*/
/*
** t[k] = value at the top of the stack (where 'k' is a string)
*/
static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
const TValue *aux;
TString *str = luaS_new(L, k);
api_checknelems(L, 1);
if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1))
L->top--; /* pop value */
else {
setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */
api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
L->top -= 2; /* pop value and key */
}
lua_unlock(L); /* lock done by caller */
}
LUA_API void lua_setglobal (lua_State *L, const char *name) {
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt; /* global table */
lua_lock(L);
api_checknelems(L, 1);
gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
setsvalue2s(L, L->top, luaS_new(L, name));
api_incr_top(L);
luaV_settable(L, gt, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
lua_unlock(L);
lua_lock(L); /* unlock done in 'auxsetstr' */
auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
}
@@ -746,42 +774,40 @@ LUA_API void lua_settable (lua_State *L, int idx) {
LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
StkId t;
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
setsvalue2s(L, L->top, luaS_new(L, k));
api_incr_top(L);
luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
lua_unlock(L);
lua_lock(L); /* unlock done in 'auxsetstr' */
auxsetstr(L, index2addr(L, idx), k);
}
LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
StkId t;
const TValue *aux;
lua_lock(L);
api_checknelems(L, 1);
t = index2addr(L, idx);
setivalue(L->top, n);
api_incr_top(L);
luaV_settable(L, t, L->top - 1, L->top - 2);
L->top -= 2; /* pop value and key */
if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1))
L->top--; /* pop value */
else {
setivalue(L->top, n);
api_incr_top(L);
luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
L->top -= 2; /* pop value and key */
}
lua_unlock(L);
}
LUA_API void lua_rawset (lua_State *L, int idx) {
StkId o;
Table *t;
TValue *slot;
lua_lock(L);
api_checknelems(L, 2);
o = index2addr(L, idx);
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
setobj2t(L, luaH_set(L, t, L->top-2), L->top-1);
invalidateTMcache(t);
luaC_barrierback(L, t, L->top-1);
slot = luaH_set(L, hvalue(o), L->top - 2);
setobj2t(L, slot, L->top - 1);
invalidateTMcache(hvalue(o));
luaC_barrierback(L, hvalue(o), L->top-1);
L->top -= 2;
lua_unlock(L);
}
@@ -789,14 +815,12 @@ LUA_API void lua_rawset (lua_State *L, int idx) {
LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
StkId o;
Table *t;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
luaH_setint(L, t, n, L->top - 1);
luaC_barrierback(L, t, L->top-1);
luaH_setint(L, hvalue(o), n, L->top - 1);
luaC_barrierback(L, hvalue(o), L->top-1);
L->top--;
lua_unlock(L);
}
@@ -804,16 +828,15 @@ 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) {
StkId o;
Table *t;
TValue k;
TValue k, *slot;
lua_lock(L);
api_checknelems(L, 1);
o = index2addr(L, idx);
api_check(L, ttistable(o), "table expected");
t = hvalue(o);
setpvalue(&k, cast(void *, p));
setobj2t(L, luaH_set(L, t, &k), L->top - 1);
luaC_barrierback(L, t, L->top - 1);
slot = luaH_set(L, hvalue(o), &k);
setobj2t(L, slot, L->top - 1);
luaC_barrierback(L, hvalue(o), L->top - 1);
L->top--;
lua_unlock(L);
}
@@ -895,10 +918,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
L->ci->u.c.k = k; /* save continuation */
L->ci->u.c.ctx = ctx; /* save context */
luaD_call(L, func, nresults, 1); /* do the call */
luaD_call(L, func, nresults); /* do the call */
}
else /* no continuation or no yieldable */
luaD_call(L, func, nresults, 0); /* just do the call */
luaD_callnoyield(L, func, nresults); /* just do the call */
adjustresults(L, nresults);
lua_unlock(L);
}
@@ -916,7 +939,7 @@ struct CallS { /* data to 'f_call' */
static void f_call (lua_State *L, void *ud) {
struct CallS *c = cast(struct CallS *, ud);
luaD_call(L, c->func, c->nresults, 0);
luaD_callnoyield(L, c->func, c->nresults);
}
@@ -954,7 +977,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
L->errfunc = func;
setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
ci->callstatus |= CIST_YPCALL; /* function can do error recovery */
luaD_call(L, c.func, nresults, 1); /* do the call */
luaD_call(L, c.func, nresults); /* do the call */
ci->callstatus &= ~CIST_YPCALL;
L->errfunc = ci->u.c.old_errfunc;
status = LUA_OK; /* if it is here, there were no errors */
@@ -1043,7 +1066,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
}
case LUA_GCSTEP: {
l_mem debt = 1; /* =1 to signal that it did an actual step */
int oldrunning = g->gcrunning;
lu_byte oldrunning = g->gcrunning;
g->gcrunning = 1; /* allow GC to run */
if (data == 0) {
luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp roberto $
** $Id: lauxlib.c,v 1.283 2015/10/06 16:10:22 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -33,8 +33,8 @@
*/
#define LEVELS1 12 /* size of the first part of the stack */
#define LEVELS2 10 /* size of the second part of the stack */
#define LEVELS1 10 /* size of the first part of the stack */
#define LEVELS2 11 /* size of the second part of the stack */
@@ -107,7 +107,7 @@ static void pushfuncname (lua_State *L, lua_Debug *ar) {
}
static int countlevels (lua_State *L) {
static int lastlevel (lua_State *L) {
lua_Debug ar;
int li = 1, le = 1;
/* find an upper bound */
@@ -126,14 +126,16 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
const char *msg, int level) {
lua_Debug ar;
int top = lua_gettop(L);
int numlevels = countlevels(L1);
int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
if (msg) lua_pushfstring(L, "%s\n", msg);
int last = lastlevel(L1);
int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
if (msg)
lua_pushfstring(L, "%s\n", msg);
luaL_checkstack(L, 10, NULL);
lua_pushliteral(L, "stack traceback:");
while (lua_getstack(L1, level++, &ar)) {
if (level == mark) { /* too many levels? */
if (n1-- == 0) { /* too many levels? */
lua_pushliteral(L, "\n\t..."); /* add a '...' */
level = numlevels - LEVELS2; /* and skip to last ones */
level = last - LEVELS2 + 1; /* and skip to last ones */
}
else {
lua_getinfo(L1, "Slnt", &ar);
@@ -289,7 +291,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
return 0; /* leave previous value on top, but return 0 */
lua_pop(L, 1);
lua_newtable(L); /* create metatable */
lua_createtable(L, 0, 2); /* create metatable */
lua_pushstring(L, tname);
lua_setfield(L, -2, "__name"); /* metatable.__name = tname */
lua_pushvalue(L, -1);
@@ -435,6 +437,47 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
** =======================================================
*/
/* userdata to box arbitrary data */
typedef struct UBox {
void *box;
size_t bsize;
} UBox;
static void *resizebox (lua_State *L, int idx, size_t newsize) {
void *ud;
lua_Alloc allocf = lua_getallocf(L, &ud);
UBox *box = (UBox *)lua_touserdata(L, idx);
void *temp = allocf(ud, box->box, box->bsize, newsize);
if (temp == NULL && newsize > 0) { /* allocation error? */
resizebox(L, idx, 0); /* free buffer */
luaL_error(L, "not enough memory for buffer allocation");
}
box->box = temp;
box->bsize = newsize;
return temp;
}
static int boxgc (lua_State *L) {
resizebox(L, 1, 0);
return 0;
}
static void *newbox (lua_State *L, size_t newsize) {
UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
box->box = NULL;
box->bsize = 0;
if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */
lua_pushcfunction(L, boxgc);
lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */
}
lua_setmetatable(L, -2);
return resizebox(L, -1, newsize);
}
/*
** check whether buffer is using a userdata on the stack as a temporary
** buffer
@@ -455,11 +498,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
if (newsize < B->n || newsize - B->n < sz)
luaL_error(L, "buffer too large");
/* create larger buffer */
newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
/* move content to new buffer */
memcpy(newbuff, B->b, B->n * sizeof(char));
if (buffonstack(B))
lua_remove(L, -2); /* remove old buffer */
newbuff = (char *)resizebox(L, -1, newsize);
else { /* no buffer yet */
newbuff = (char *)newbox(L, newsize);
memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
}
B->b = newbuff;
B->size = newsize;
}
@@ -468,9 +512,11 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
char *b = luaL_prepbuffsize(B, l);
memcpy(b, s, l * sizeof(char));
luaL_addsize(B, l);
if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */
char *b = luaL_prepbuffsize(B, l);
memcpy(b, s, l * sizeof(char));
luaL_addsize(B, l);
}
}
@@ -482,8 +528,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
lua_State *L = B->L;
lua_pushlstring(L, B->b, B->n);
if (buffonstack(B))
lua_remove(L, -2); /* remove old buffer */
if (buffonstack(B)) {
resizebox(L, -2, 0); /* delete old buffer */
lua_remove(L, -2); /* remove its header from the stack */
}
}
@@ -605,7 +653,7 @@ static int errfile (lua_State *L, const char *what, int fnameindex) {
static int skipBOM (LoadF *lf) {
const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */
const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
int c;
lf->n = 0;
do {

View File

@@ -1,5 +1,5 @@
/*
** $Id: lauxlib.h,v 1.127 2014/10/25 11:50:46 roberto Exp roberto $
** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -65,7 +65,7 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
/* pre-defined references */
/* predefined references */
#define LUA_NOREF (-2)
#define LUA_REFNIL (-1)

View File

@@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.309 2014/12/10 12:26:42 roberto Exp roberto $
** $Id: lbaselib.c,v 1.311 2015/06/26 19:25:45 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -86,8 +86,8 @@ static int luaB_tonumber (lua_State *L) {
const char *s;
lua_Integer n = 0; /* to avoid warnings */
lua_Integer base = luaL_checkinteger(L, 2);
luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */
s = luaL_checklstring(L, 1, &l);
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
s = lua_tolstring(L, 1, &l);
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
if (b_str2int(s, (int)base, &n) == s + l) {
lua_pushinteger(L, n);
@@ -198,12 +198,10 @@ static int luaB_collectgarbage (lua_State *L) {
}
/*
** This function has all type names as upvalues, to maximize performance.
*/
static int luaB_type (lua_State *L) {
luaL_checkany(L, 1);
lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 1));
int t = lua_type(L, 1);
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
lua_pushstring(L, lua_typename(L, t));
return 1;
}
@@ -243,18 +241,7 @@ static int luaB_pairs (lua_State *L) {
/*
** Traversal function for 'ipairs' for raw tables
*/
static int ipairsaux_raw (lua_State *L) {
lua_Integer i = luaL_checkinteger(L, 2) + 1;
luaL_checktype(L, 1, LUA_TTABLE);
lua_pushinteger(L, i);
return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2;
}
/*
** Traversal function for 'ipairs' for tables with metamethods
** Traversal function for 'ipairs'
*/
static int ipairsaux (lua_State *L) {
lua_Integer i = luaL_checkinteger(L, 2) + 1;
@@ -269,13 +256,11 @@ static int ipairsaux (lua_State *L) {
** that can affect the traversal.
*/
static int luaB_ipairs (lua_State *L) {
lua_CFunction iter = (luaL_getmetafield(L, 1, "__index") != LUA_TNIL)
? ipairsaux : ipairsaux_raw;
#if defined(LUA_COMPAT_IPAIRS)
return pairsmeta(L, "__ipairs", 1, iter);
return pairsmeta(L, "__ipairs", 1, ipairsaux);
#else
luaL_checkany(L, 1);
lua_pushcfunction(L, iter); /* iteration function */
lua_pushcfunction(L, ipairsaux); /* iteration function */
lua_pushvalue(L, 1); /* state */
lua_pushinteger(L, 0); /* initial value */
return 3;
@@ -490,9 +475,9 @@ static const luaL_Reg base_funcs[] = {
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
{"tostring", luaB_tostring},
{"type", luaB_type},
{"xpcall", luaB_xpcall},
/* placeholders */
{"type", NULL},
{"_G", NULL},
{"_VERSION", NULL},
{NULL, NULL}
@@ -500,7 +485,6 @@ static const luaL_Reg base_funcs[] = {
LUAMOD_API int luaopen_base (lua_State *L) {
int i;
/* open lib into global table */
lua_pushglobaltable(L);
luaL_setfuncs(L, base_funcs, 0);
@@ -510,11 +494,6 @@ LUAMOD_API int luaopen_base (lua_State *L) {
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
lua_setfield(L, -2, "_VERSION");
/* set function 'type' with proper upvalues */
for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */
lua_pushstring(L, lua_typename(L, i));
lua_pushcclosure(L, luaB_type, LUA_NUMTAGS);
lua_setfield(L, -2, "type");
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lbitlib.c,v 1.27 2014/10/01 11:54:56 roberto Exp roberto $
** $Id: lbitlib.c,v 1.29 2015/10/08 15:55:35 roberto Exp roberto $
** Standard library for bitwise operations
** See Copyright Notice in lua.h
*/
@@ -19,6 +19,10 @@
#if defined(LUA_COMPAT_BITLIB) /* { */
#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))
/* number of bits to consider in a number */
#if !defined(LUA_NBITS)
#define LUA_NBITS 32
@@ -46,14 +50,14 @@ static lua_Unsigned andaux (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = ~(lua_Unsigned)0;
for (i = 1; i <= n; i++)
r &= luaL_checkunsigned(L, i);
r &= checkunsigned(L, i);
return trim(r);
}
static int b_and (lua_State *L) {
lua_Unsigned r = andaux(L);
lua_pushunsigned(L, r);
pushunsigned(L, r);
return 1;
}
@@ -69,8 +73,8 @@ static int b_or (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r |= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
r |= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}
@@ -79,15 +83,15 @@ static int b_xor (lua_State *L) {
int i, n = lua_gettop(L);
lua_Unsigned r = 0;
for (i = 1; i <= n; i++)
r ^= luaL_checkunsigned(L, i);
lua_pushunsigned(L, trim(r));
r ^= checkunsigned(L, i);
pushunsigned(L, trim(r));
return 1;
}
static int b_not (lua_State *L) {
lua_Unsigned r = ~luaL_checkunsigned(L, 1);
lua_pushunsigned(L, trim(r));
lua_Unsigned r = ~checkunsigned(L, 1);
pushunsigned(L, trim(r));
return 1;
}
@@ -104,23 +108,23 @@ static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
else r <<= i;
r = trim(r);
}
lua_pushunsigned(L, r);
pushunsigned(L, r);
return 1;
}
static int b_lshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2));
return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
}
static int b_rshift (lua_State *L) {
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2));
return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
}
static int b_arshift (lua_State *L) {
lua_Unsigned r = luaL_checkunsigned(L, 1);
lua_Unsigned r = checkunsigned(L, 1);
lua_Integer i = luaL_checkinteger(L, 2);
if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
return b_shift(L, r, -i);
@@ -128,19 +132,19 @@ static int b_arshift (lua_State *L) {
if (i >= LUA_NBITS) r = ALLONES;
else
r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
lua_pushunsigned(L, r);
pushunsigned(L, r);
return 1;
}
}
static int b_rot (lua_State *L, lua_Integer d) {
lua_Unsigned r = luaL_checkunsigned(L, 1);
lua_Unsigned r = checkunsigned(L, 1);
int i = d & (LUA_NBITS - 1); /* i = d % NBITS */
r = trim(r);
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
r = (r << i) | (r >> (LUA_NBITS - i));
lua_pushunsigned(L, trim(r));
pushunsigned(L, trim(r));
return 1;
}
@@ -175,23 +179,22 @@ static int fieldargs (lua_State *L, int farg, int *width) {
static int b_extract (lua_State *L) {
int w;
lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
lua_Unsigned r = trim(checkunsigned(L, 1));
int f = fieldargs(L, 2, &w);
r = (r >> f) & mask(w);
lua_pushunsigned(L, r);
pushunsigned(L, r);
return 1;
}
static int b_replace (lua_State *L) {
int w;
lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
lua_Unsigned v = luaL_checkunsigned(L, 2);
lua_Unsigned r = trim(checkunsigned(L, 1));
lua_Unsigned v = trim(checkunsigned(L, 2));
int f = fieldargs(L, 3, &w);
int m = mask(w);
v &= m; /* erase bits outside given width */
r = (r & ~(m << f)) | (v << f);
lua_pushunsigned(L, r);
lua_Unsigned m = mask(w);
r = (r & ~(m << f)) | ((v & m) << f);
pushunsigned(L, r);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 2.100 2015/03/28 19:14:47 roberto Exp roberto $
** $Id: lcode.c,v 2.102 2015/10/26 14:27:47 roberto Exp roberto $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -37,7 +37,7 @@
static int tonumeral(expdesc *e, TValue *v) {
if (e->t != NO_JUMP || e->f != NO_JUMP)
if (hasjumps(e))
return 0; /* not a numeral */
switch (e->k) {
case VKINT:
@@ -816,7 +816,7 @@ static void codeexpval (FuncState *fs, OpCode op,
freeexp(fs, e1);
}
e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */
e1->k = VRELOCABLE; /* all those operations are relocable */
e1->k = VRELOCABLE; /* all those operations are relocatable */
luaK_fixline(fs, line);
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp roberto $
** $Id: ldblib.c,v 1.150 2015/11/19 19:16:22 roberto Exp roberto $
** Interface from Lua to its debug API
** See Copyright Notice in lua.h
*/
@@ -28,8 +28,8 @@ static const int HOOKKEY = 0;
/*
** If L1 != L, L1 can be in any state, and therefore there is no
** garanties about its stack space; any push in L1 must be
** 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) {

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 2.114 2015/03/28 19:14:47 roberto Exp roberto $
** $Id: ldebug.c,v 2.116 2015/10/22 14:40:47 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@@ -618,7 +618,7 @@ l_noret luaG_errormsg (lua_State *L) {
setobjs2s(L, L->top, L->top - 1); /* move argument */
setobjs2s(L, L->top - 1, errfunc); /* push function */
L->top++; /* assume EXTRA_STACK */
luaD_call(L, L->top - 2, 1, 0); /* call it */
luaD_callnoyield(L, L->top - 2, 1); /* call it */
}
luaD_throw(L, LUA_ERRRUN);
}
@@ -640,9 +640,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
void luaG_traceexec (lua_State *L) {
CallInfo *ci = L->ci;
lu_byte mask = L->hookmask;
int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
if (counthook)
resethookcount(L); /* reset count */
else if (!(mask & LUA_MASKLINE))
return; /* no line hook and count != 0; nothing to be done */
if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
return; /* do not call hook again (VM yielded, so it did not move) */

194
ldo.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 2.137 2015/03/30 16:05:23 roberto Exp roberto $
** $Id: ldo.c,v 2.149 2015/11/13 13:24:26 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -150,6 +150,11 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
/* }====================================================== */
/*
** {==================================================================
** Stack reallocation
** ===================================================================
*/
static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
UpVal *up;
@@ -221,14 +226,22 @@ void luaD_shrinkstack (lua_State *L) {
luaE_freeCI(L); /* free all CIs (list grew because of an error) */
else
luaE_shrinkCI(L); /* shrink list */
if (inuse > LUAI_MAXSTACK || /* still handling stack overflow? */
goodsize >= L->stacksize) /* would grow instead of shrink? */
condmovestack(L); /* don't change stack (change only for debugging) */
else
if (inuse <= LUAI_MAXSTACK && /* not handling stack overflow? */
goodsize < L->stacksize) /* trying to shrink? */
luaD_reallocstack(L, goodsize); /* shrink it */
else
condmovestack(L,,); /* don't change stack (change only for debugging) */
}
void luaD_inctop (lua_State *L) {
luaD_checkstack(L, 1);
L->top++;
}
/* }================================================================== */
void luaD_hook (lua_State *L, int event, int line) {
lua_Hook hook = L->hook;
if (hook && L->allowhook) {
@@ -273,15 +286,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
int i;
int nfixargs = p->numparams;
StkId base, fixed;
lua_assert(actual >= nfixargs);
/* move fixed parameters to final position */
luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */
fixed = L->top - actual; /* first fixed argument */
base = L->top; /* final position of first argument */
for (i=0; i<nfixargs; i++) {
for (i = 0; i < nfixargs && i < actual; i++) {
setobjs2s(L, L->top++, fixed + i);
setnilvalue(fixed + i);
setnilvalue(fixed + i); /* erase original copy (for GC) */
}
for (; i < nfixargs; i++)
setnilvalue(L->top++); /* complete missing arguments */
return base;
}
@@ -308,26 +321,36 @@ static void tryfuncTM (lua_State *L, StkId func) {
#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
/* macro to check stack size, preserving 'p' */
#define checkstackp(L,n,p) \
luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
luaC_checkGC(L), /* stack grow uses memory */ \
p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
/*
** returns true if function has been executed (C function)
** Prepares a function call: checks the stack, creates a new CallInfo
** entry, fills in the relevant information, calls hook if needed.
** If function is a C function, does the call, too. (Otherwise, leave
** the execution ('luaV_execute') to the caller, to allow stackless
** calls.) Returns true iff function has been executed (C function).
*/
int luaD_precall (lua_State *L, StkId func, int nresults) {
lua_CFunction f;
CallInfo *ci;
int n; /* number of arguments (Lua) or returns (C) */
ptrdiff_t funcr = savestack(L, func);
switch (ttype(func)) {
case LUA_TCCL: /* C closure */
f = clCvalue(func)->f;
goto Cfunc;
case LUA_TLCF: /* light C function */
f = fvalue(func);
goto Cfunc;
case LUA_TCCL: { /* C closure */
f = clCvalue(func)->f;
Cfunc:
luaC_checkGC(L); /* stack grow uses memory */
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
Cfunc: {
int n; /* number of returns */
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = restorestack(L, funcr);
ci->func = func;
ci->top = L->top + LUA_MINSTACK;
lua_assert(ci->top <= L->stack_last);
ci->callstatus = 0;
@@ -337,41 +360,36 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
n = (*f)(L); /* do the actual call */
lua_lock(L);
api_checknelems(L, n);
luaD_poscall(L, L->top - n, n);
luaD_poscall(L, ci, L->top - n, n);
return 1;
}
case LUA_TLCL: { /* Lua function: prepare its call */
StkId base;
Proto *p = clLvalue(func)->p;
n = cast_int(L->top - func) - 1; /* number of real arguments */
luaC_checkGC(L); /* stack grow uses memory */
luaD_checkstack(L, p->maxstacksize);
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
if (!p->is_vararg) {
func = restorestack(L, funcr);
int n = cast_int(L->top - func) - 1; /* number of real arguments */
int fsize = p->maxstacksize; /* frame size */
checkstackp(L, fsize, func);
if (p->is_vararg != 1) { /* do not use vararg? */
for (; n < p->numparams; n++)
setnilvalue(L->top++); /* complete missing arguments */
base = func + 1;
}
else {
else
base = adjust_varargs(L, p, n);
func = restorestack(L, funcr); /* previous call can change stack */
}
ci = next_ci(L); /* now 'enter' new function */
ci->nresults = nresults;
ci->func = func;
ci->u.l.base = base;
ci->top = base + p->maxstacksize;
L->top = ci->top = base + fsize;
lua_assert(ci->top <= L->stack_last);
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = CIST_LUA;
L->top = ci->top;
if (L->hookmask & LUA_MASKCALL)
callhook(L, ci);
return 0;
}
default: { /* not a function */
luaD_checkstack(L, 1); /* ensure space for metamethod */
func = restorestack(L, funcr); /* previous call may change stack */
checkstackp(L, 1, func); /* ensure space for metamethod */
tryfuncTM(L, func); /* try to get '__call' metamethod */
return luaD_precall(L, func, nresults); /* now it must be a function */
}
@@ -379,10 +397,57 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
}
int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
/*
** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
** Handle most typical cases (zero results for commands, one result for
** expressions, multiple results for tail calls/single parameters)
** separated.
*/
static int moveresults (lua_State *L, const TValue *firstResult, StkId res,
int nres, int wanted) {
switch (wanted) { /* handle typical cases separately */
case 0: break; /* nothing to move */
case 1: { /* one result needed */
if (nres == 0) /* no results? */
firstResult = luaO_nilobject; /* adjust with nil */
setobjs2s(L, res, firstResult); /* move it to proper place */
break;
}
case LUA_MULTRET: {
int i;
for (i = 0; i < nres; i++) /* move all results to correct place */
setobjs2s(L, res + i, firstResult + i);
L->top = res + nres;
return 0; /* wanted == LUA_MULTRET */
}
default: {
int i;
if (wanted <= nres) { /* enough results? */
for (i = 0; i < wanted; i++) /* move wanted results to correct place */
setobjs2s(L, res + i, firstResult + i);
}
else { /* not enough results; use all of them plus nils */
for (i = 0; i < nres; i++) /* move all results to correct place */
setobjs2s(L, res + i, firstResult + i);
for (; i < wanted; i++) /* complete wanted number of results */
setnilvalue(res + i);
}
break;
}
}
L->top = res + wanted; /* top points after the last result */
return 1;
}
/*
** Finishes a function call: calls hook if necessary, removes CallInfo,
** moves current number of results to proper place; returns 0 iff call
** wanted multiple (variable number of) results.
*/
int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
StkId res;
int wanted, i;
CallInfo *ci = L->ci;
int wanted = ci->nresults;
if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) {
if (L->hookmask & LUA_MASKRET) {
ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
@@ -392,15 +457,24 @@ int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */
}
res = ci->func; /* res == final position of 1st result */
wanted = ci->nresults;
L->ci = ci->previous; /* back to caller */
/* move results to correct place */
for (i = wanted; i != 0 && nres-- > 0; i--)
setobjs2s(L, res++, firstResult++);
while (i-- > 0)
setnilvalue(res++);
L->top = res;
return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */
/* move results to proper place */
return moveresults(L, firstResult, res, nres, wanted);
}
/*
** Check appropriate error for stack overflow ("regular" overflow or
** overflow while handling stack overflow). If 'nCalls' is larger than
** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but
** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to
** allow overflow handling to work)
*/
static void stackerror (lua_State *L) {
if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
@@ -410,21 +484,25 @@ int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
** When returns, all the results are on the stack, starting at the original
** function position.
*/
void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) {
if (++L->nCcalls >= LUAI_MAXCCALLS) {
if (L->nCcalls == LUAI_MAXCCALLS)
luaG_runerror(L, "C stack overflow");
else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
}
if (!allowyield) L->nny++;
void luaD_call (lua_State *L, StkId func, int nResults) {
if (++L->nCcalls >= LUAI_MAXCCALLS)
stackerror(L);
if (!luaD_precall(L, func, nResults)) /* is a Lua function? */
luaV_execute(L); /* call it */
if (!allowyield) L->nny--;
L->nCcalls--;
}
/*
** Similar to 'luaD_call', but does not allow yields during the call
*/
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
L->nny++;
luaD_call(L, func, nResults);
L->nny--;
}
/*
** Completes the execution of an interrupted C function, calling its
** continuation function.
@@ -449,7 +527,7 @@ static void finishCcall (lua_State *L, int status) {
lua_lock(L);
api_checknelems(L, n);
/* finish 'luaD_precall' */
luaD_poscall(L, L->top - n, n);
luaD_poscall(L, ci, L->top - n, n);
}
@@ -560,7 +638,7 @@ static void resume (lua_State *L, void *ud) {
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */
luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */
}
unroll(L, NULL); /* run continuation */
}
@@ -570,7 +648,7 @@ static void resume (lua_State *L, void *ud) {
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
int status;
int oldnny = L->nny; /* save "number of non-yieldable" calls */
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
lua_lock(L);
luai_userstateresume(L, nargs);
L->nCcalls = (from) ? from->nCcalls + 1 : 1;
@@ -684,7 +762,7 @@ static void f_parser (lua_State *L, void *ud) {
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary");
cl = luaU_undump(L, p->z, &p->buff, p->name);
cl = luaU_undump(L, p->z, p->name);
}
else {
checkmode(L, p->mode, "text");

26
ldo.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp roberto $
** $Id: ldo.h,v 2.27 2015/11/19 19:16:22 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -13,11 +13,21 @@
#include "lzio.h"
#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \
luaD_growstack(L, n); else condmovestack(L);
/*
** Macro to check stack size and grow stack if needed. Parameters
** 'pre'/'pos' allow the macro to preserve a pointer into the
** stack across reallocations, doing the work only when needed.
** 'condmovestack' is used in heavy tests to force a stack reallocation
** at every check.
*/
#define luaD_checkstackaux(L,n,pre,pos) \
if (L->stack_last - L->top <= (n)) \
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
/* In general, 'pre'/'pos' are empty (nothing to save) */
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,,)
#define incr_top(L) {L->top++; luaD_checkstack(L,0);}
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
#define restorestack(L,n) ((TValue *)((char *)L->stack + (n)))
@@ -30,14 +40,16 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode);
LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
int allowyield);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres);
LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
int nres);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
LUAI_FUNC void luaD_inctop (lua_State *L);
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);

View File

@@ -1,5 +1,5 @@
/*
** $Id: ldump.c,v 2.35 2015/01/16 16:54:37 roberto Exp roberto $
** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp roberto $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -38,7 +38,7 @@ typedef struct {
static void DumpBlock (const void *b, size_t size, DumpState *D) {
if (D->status == 0) {
if (D->status == 0 && size > 0) {
lua_unlock(D->L);
D->status = (*D->writer)(D->L, b, size, D->data);
lua_lock(D->L);

28
lgc.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.204 2015/03/04 13:51:55 roberto Exp roberto $
** $Id: lgc.c,v 2.209 2015/11/02 18:48:07 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -114,8 +114,13 @@ static void reallymarkobject (global_State *g, GCObject *o);
/*
** if key is not marked, mark its entry as dead (therefore removing it
** from the table)
** If key is not marked, mark its entry as dead. This allows key to be
** collected, but keeps its entry in the table. A dead node is needed
** when Lua looks up for a key (it may be part of a chain) and when
** traversing a weak table (key might be removed from the table during
** traversal). Other places never manipulate dead keys, because its
** associated nil value is enough to signal that the entry is logically
** empty.
*/
static void removeentry (Node *n) {
lua_assert(ttisnil(gval(n)));
@@ -542,7 +547,8 @@ static lu_mem traversethread (global_State *g, lua_State *th) {
}
else if (g->gckind != KGC_EMERGENCY)
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
return (sizeof(lua_State) + sizeof(TValue) * th->stacksize);
return (sizeof(lua_State) + sizeof(TValue) * th->stacksize +
sizeof(CallInfo) * th->nci);
}
@@ -769,12 +775,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) {
*/
/*
** If possible, free concatenation buffer and shrink string table
** If possible, shrink string table
*/
static void checkSizes (lua_State *L, global_State *g) {
if (g->gckind != KGC_EMERGENCY) {
l_mem olddebt = g->GCdebt;
luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */
if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
luaS_resize(L, g->strt.size / 2); /* shrink it a little */
g->GCestimate += g->GCdebt - olddebt; /* update estimate */
@@ -797,7 +802,7 @@ static GCObject *udata2finalize (global_State *g) {
static void dothecall (lua_State *L, void *ud) {
UNUSED(ud);
luaD_call(L, L->top - 2, 0, 0);
luaD_callnoyield(L, L->top - 2, 0);
}
@@ -1114,9 +1119,12 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
static l_mem getdebt (global_State *g) {
l_mem debt = g->GCdebt;
int stepmul = g->gcstepmul;
debt = (debt / STEPMULADJ) + 1;
debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
return debt;
if (debt <= 0) return 0; /* minimal debt */
else {
debt = (debt / STEPMULADJ) + 1;
debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
return debt;
}
}
/*

41
lgc.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lgc.h,v 2.85 2014/07/19 15:14:46 roberto Exp roberto $
** $Id: lgc.h,v 2.89 2015/10/20 18:00:19 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -101,26 +101,35 @@
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
#define luaC_condGC(L,c) \
{if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);)
/*
** Does one step of collection when debt becomes positive. 'pre'/'pos'
** allows some adjustments to be done only when needed. macro
** 'condchangemem' is used only for heavy tests (forcing a full
** GC cycle on every opportunity)
*/
#define luaC_condGC(L,pre,pos) \
{ if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \
condchangemem(L,pre,pos); }
/* more often than not, 'pre'/'pos' are empty */
#define luaC_checkGC(L) luaC_condGC(L,,)
#define luaC_barrier(L,p,v) { \
if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \
luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
#define luaC_barrier(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))
#define luaC_barrierback(L,p,v) { \
if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \
luaC_barrierback_(L,p); }
#define luaC_barrierback(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
luaC_barrierback_(L,p) : cast_void(0))
#define luaC_objbarrier(L,p,o) { \
if (isblack(p) && iswhite(o)) \
luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
#define luaC_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
#define luaC_upvalbarrier(L,uv) \
{ if (iscollectable((uv)->v) && !upisopen(uv)) \
luaC_upvalbarrier_(L,uv); }
#define luaC_upvalbarrier(L,uv) ( \
(iscollectable((uv)->v) && !upisopen(uv)) ? \
luaC_upvalbarrier_(L,uv) : cast_void(0))
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);

View File

@@ -1,5 +1,5 @@
/*
** $Id: liolib.c,v 2.143 2015/03/06 19:09:08 roberto Exp roberto $
** $Id: liolib.c,v 2.147 2015/07/15 14:40:28 roberto Exp roberto $
** Standard I/O (and system) library
** See Copyright Notice in lua.h
*/
@@ -23,18 +23,24 @@
#include "lualib.h"
#if !defined(l_checkmode)
/*
** Check whether 'mode' matches '[rwa]%+?b?'.
** Change this macro to accept other modes for 'fopen' besides
** the standard ones.
*/
#if !defined(l_checkmode)
/* accepted extensions to 'mode' in 'fopen' */
#if !defined(L_MODEEXT)
#define L_MODEEXT "b"
#endif
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
#define l_checkmode(mode) \
(*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \
(*mode != '+' || ++mode) && /* skip if char is '+' */ \
(*mode != 'b' || ++mode) && /* skip if char is 'b' */ \
(*mode == '\0'))
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ \
(strspn(mode, L_MODEEXT) == strlen(mode)))
#endif
@@ -176,7 +182,7 @@ static FILE *tofile (lua_State *L) {
/*
** When creating file handles, always creates a 'closed' file handle
** before opening the actual file; so, if there is a memory error, the
** file is not left opened.
** handle is in a consistent state.
*/
static LStream *newprefile (lua_State *L) {
LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
@@ -318,8 +324,15 @@ static int io_output (lua_State *L) {
static int io_readline (lua_State *L);
/*
** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
** in the limit for upvalues of a closure)
*/
#define MAXARGLINE 250
static void aux_lines (lua_State *L, int toclose) {
int n = lua_gettop(L) - 1; /* number of arguments to read */
luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
lua_pushinteger(L, n); /* number of arguments to read */
lua_pushboolean(L, toclose); /* close/not close file when finished */
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
@@ -462,7 +475,7 @@ static int read_line (lua_State *L, FILE *f, int chop) {
int c = '\0';
luaL_buffinit(L, &b);
while (c != EOF && c != '\n') { /* repeat until end of line */
char *buff = luaL_prepbuffer(&b); /* pre-allocate buffer */
char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
int i = 0;
l_lockfile(f); /* no memory errors can happen inside the lock */
while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
@@ -483,7 +496,7 @@ static void read_all (lua_State *L, FILE *f) {
luaL_Buffer b;
luaL_buffinit(L, &b);
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE);
char *p = luaL_prepbuffer(&b);
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
luaL_addsize(&b, nr);
} while (nr == LUAL_BUFFERSIZE);

10
llex.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: llex.c,v 2.92 2015/04/03 18:41:57 roberto Exp roberto $
** $Id: llex.c,v 2.94 2015/10/28 18:51:47 roberto Exp roberto $
** Lexical Analyzer
** See Copyright Notice in lua.h
*/
@@ -220,8 +220,6 @@ static void buffreplace (LexState *ls, char from, char to) {
}
#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0)
/*
** in case of format error, try to change decimal point separator to
** the one defined in the current locale and check again
@@ -230,7 +228,7 @@ static void trydecpoint (LexState *ls, TValue *o) {
char old = ls->decpoint;
ls->decpoint = lua_getlocaledecpoint();
buffreplace(ls, old, ls->decpoint); /* try new decimal separator */
if (!buff2num(ls->buff, o)) {
if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) {
/* format error with correct decimal point: no more options */
buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
lexerror(ls, "malformed number", TK_FLT);
@@ -262,7 +260,7 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
}
save(ls, '\0');
buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
if (!buff2num(ls->buff, &obj)) /* format error? */
if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */
trydecpoint(ls, &obj); /* try to update decimal point separator */
if (ttisinteger(&obj)) {
seminfo->i = ivalue(&obj);
@@ -277,7 +275,7 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
/*
** skip a sequence '[=*[' or ']=*]'; if sequence is wellformed, return
** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return
** its number of '='s; otherwise, return a negative number (-1 iff there
** are no '='s after initial bracket)
*/

View File

@@ -1,5 +1,5 @@
/*
** $Id: llimits.h,v 1.134 2015/03/06 19:49:50 roberto Exp roberto $
** $Id: llimits.h,v 1.140 2015/10/21 18:40:47 roberto Exp roberto $
** Limits, basic types, and some other 'installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -64,7 +64,13 @@ typedef unsigned char lu_byte;
#if defined(LUAI_USER_ALIGNMENT_T)
typedef LUAI_USER_ALIGNMENT_T L_Umaxalign;
#else
typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign;
typedef union {
lua_Number n;
double u;
void *s;
lua_Integer i;
long l;
} L_Umaxalign;
#endif
@@ -78,7 +84,7 @@ typedef LUAI_UACINT l_uacInt;
#if defined(lua_assert)
#define check_exp(c,e) (lua_assert(c), (e))
/* to avoid problems with conditions too long */
#define lua_longassert(c) { if (!(c)) lua_assert(0); }
#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0))
#else
#define lua_assert(c) ((void)0)
#define check_exp(c,e) (e)
@@ -184,10 +190,13 @@ typedef unsigned long Instruction;
/*
** Size of cache for strings in the API (better be a prime)
** 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_SIZE)
#define STRCACHE_SIZE 127
#if !defined(STRCACHE_N)
#define STRCACHE_N 53
#define STRCACHE_M 2
#endif
@@ -198,7 +207,7 @@ typedef unsigned long Instruction;
/*
** macros that are executed whenether program enters the Lua core
** macros that are executed whenever program enters the Lua core
** ('lua_lock') and leaves the core ('lua_unlock')
*/
#if !defined(lua_lock)
@@ -297,17 +306,18 @@ typedef unsigned long Instruction;
** macro to control inclusion of some hard tests on stack reallocation
*/
#if !defined(HARDSTACKTESTS)
#define condmovestack(L) ((void)0)
#define condmovestack(L,pre,pos) ((void)0)
#else
/* realloc stack keeping its size */
#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize)
#define condmovestack(L,pre,pos) \
{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
#endif
#if !defined(HARDMEMTESTS)
#define condchangemem(L) condmovestack(L)
#define condchangemem(L,pre,pos) ((void)0)
#else
#define condchangemem(L) \
((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
#define condchangemem(L,pre,pos) \
{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
#endif
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lmathlib.c,v 1.114 2014/12/27 20:32:26 roberto Exp roberto $
** $Id: lmathlib.c,v 1.116 2015/06/26 19:30:32 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -39,7 +39,7 @@
static int math_abs (lua_State *L) {
if (lua_isinteger(L, 1)) {
lua_Integer n = lua_tointeger(L, 1);
if (n < 0) n = (lua_Integer)(0u - n);
if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n);
lua_pushinteger(L, n);
}
else
@@ -273,7 +273,7 @@ static int math_random (lua_State *L) {
static int math_randomseed (lua_State *L) {
l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1));
(void)rand(); /* discard first value to avoid undesirable correlations */
(void)l_rand(); /* discard first value to avoid undesirable correlations */
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: loadlib.c,v 1.125 2015/01/13 13:18:04 roberto Exp roberto $
** $Id: loadlib.c,v 1.126 2015/02/16 13:14:33 roberto Exp roberto $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**
@@ -732,7 +732,7 @@ static void createsearcherstable (lua_State *L) {
int i;
/* create 'searchers' table */
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
/* fill it with pre-defined searchers */
/* fill it with predefined searchers */
for (i=0; searchers[i] != NULL; i++) {
lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */
lua_pushcclosure(L, searchers[i], 1);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 2.103 2015/03/28 19:14:47 roberto Exp roberto $
** $Id: lobject.c,v 2.107 2015/11/02 14:02:35 roberto Exp roberto $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -55,9 +55,7 @@ int luaO_int2fb (unsigned int x) {
/* converts back */
int luaO_fb2int (int x) {
int e = (x >> 3) & 0x1f;
if (e == 0) return x;
else return ((x & 7) + 8) << (e - 1);
return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1);
}
@@ -333,9 +331,9 @@ void luaO_tostring (lua_State *L, StkId obj) {
size_t len;
lua_assert(ttisnumber(obj));
if (ttisinteger(obj))
len = lua_integer2str(buff, ivalue(obj));
len = lua_integer2str(buff, sizeof(buff), ivalue(obj));
else {
len = lua_number2str(buff, fltvalue(obj));
len = lua_number2str(buff, sizeof(buff), fltvalue(obj));
#if !defined(LUA_COMPAT_FLOATSTRING)
if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */
buff[len++] = lua_getlocaledecpoint();
@@ -348,7 +346,8 @@ void luaO_tostring (lua_State *L, StkId obj) {
static void pushstr (lua_State *L, const char *str, size_t l) {
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
luaD_inctop(L);
}
@@ -359,7 +358,6 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
for (;;) {
const char *e = strchr(fmt, '%');
if (e == NULL) break;
luaD_checkstack(L, 2); /* fmt + item */
pushstr(L, fmt, e - fmt);
switch (*(e+1)) {
case 's': {
@@ -377,23 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
break;
}
case 'd': {
setivalue(L->top++, va_arg(argp, int));
luaO_tostring(L, L->top - 1);
break;
setivalue(L->top, va_arg(argp, int));
goto top2str;
}
case 'I': {
setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
luaO_tostring(L, L->top - 1);
break;
setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt)));
goto top2str;
}
case 'f': {
setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
top2str:
luaD_inctop(L);
luaO_tostring(L, L->top - 1);
break;
}
case 'p': {
char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */
int l = sprintf(buff, "%p", va_arg(argp, void *));
int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff, l);
break;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 2.110 2015/04/02 21:10:53 roberto Exp roberto $
** $Id: lobject.h,v 2.115 2015/10/28 17:28:40 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -19,8 +19,8 @@
/*
** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS
#define LUA_TDEADKEY (LUA_NUMTAGS+1)
#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */
#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */
/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
@@ -88,22 +88,32 @@ struct GCObject {
/*
** Union of all Lua values
*/
typedef union Value Value;
/*
** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
*/
/*
** Union of all Lua values
*/
typedef union Value {
GCObject *gc; /* collectable objects */
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
lua_Integer i; /* integer numbers */
lua_Number n; /* float numbers */
} Value;
#define TValuefields Value value_; int tt_
typedef struct lua_TValue TValue;
typedef struct lua_TValue {
TValuefields;
} TValue;
/* macro defining a nil value */
@@ -177,9 +187,9 @@ typedef struct lua_TValue TValue;
/* Macros for internal tests */
#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt)
#define checkliveness(g,obj) \
#define checkliveness(L,obj) \
lua_longassert(!iscollectable(obj) || \
(righttt(obj) && !isdead(g,gcvalue(obj))))
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)))))
/* Macros to set values */
@@ -215,32 +225,32 @@ typedef struct lua_TValue TValue;
#define setsvalue(L,obj,x) \
{ TValue *io = (obj); TString *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define setuvalue(L,obj,x) \
{ TValue *io = (obj); Udata *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define setthvalue(L,obj,x) \
{ TValue *io = (obj); lua_State *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define setclLvalue(L,obj,x) \
{ TValue *io = (obj); LClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define setclCvalue(L,obj,x) \
{ TValue *io = (obj); CClosure *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define sethvalue(L,obj,x) \
{ TValue *io = (obj); Table *x_ = (x); \
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
@@ -248,7 +258,7 @@ typedef struct lua_TValue TValue;
#define setobj(L,obj1,obj2) \
{ TValue *io1=(obj1); *io1 = *(obj2); \
(void)L; checkliveness(G(L),io1); }
(void)L; checkliveness(L,io1); }
/*
@@ -264,12 +274,13 @@ typedef struct lua_TValue TValue;
#define setptvalue2s setptvalue
/* from table to same table */
#define setobjt2t setobj
/* to table */
#define setobj2t setobj
/* to new object */
#define setobj2n setobj
#define setsvalue2n setsvalue
/* to table (define it as an expression to be used in macros) */
#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1)))
@@ -280,21 +291,6 @@ typedef struct lua_TValue TValue;
*/
union Value {
GCObject *gc; /* collectable objects */
void *p; /* light userdata */
int b; /* booleans */
lua_CFunction f; /* light C functions */
lua_Integer i; /* integer numbers */
lua_Number n; /* float numbers */
};
struct lua_TValue {
TValuefields;
};
typedef TValue *StkId; /* index to stack elements */
@@ -329,9 +325,9 @@ typedef union UTString {
** Get the actual string (array of bytes) from a 'TString'.
** (Access to 'extra' ensures that value is really a 'TString'.)
*/
#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString))
#define getstr(ts) \
check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts)))
check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString))
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(tsvalue(o))
@@ -375,13 +371,13 @@ typedef union UUdata {
#define setuservalue(L,u,o) \
{ const TValue *io=(o); Udata *iu = (u); \
iu->user_ = io->value_; iu->ttuv_ = rttype(io); \
checkliveness(G(L),io); }
checkliveness(L,io); }
#define getuservalue(L,u,o) \
{ TValue *io=(o); const Udata *iu = (u); \
io->value_ = iu->user_; settt_(io, iu->ttuv_); \
checkliveness(G(L),io); }
checkliveness(L,io); }
/*
@@ -411,7 +407,7 @@ typedef struct LocVar {
typedef struct Proto {
CommonHeader;
lu_byte numparams; /* number of fixed parameters */
lu_byte is_vararg;
lu_byte is_vararg; /* 2: declared vararg; 1: uses vararg */
lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues; /* size of 'upvalues' */
int sizek; /* size of 'k' */
@@ -419,8 +415,8 @@ typedef struct Proto {
int sizelineinfo;
int sizep; /* size of 'p' */
int sizelocvars;
int linedefined;
int lastlinedefined;
int linedefined; /* debug information */
int lastlinedefined; /* debug information */
TValue *k; /* constants used by the function */
Instruction *code; /* opcodes */
struct Proto **p; /* functions defined inside the function */
@@ -489,7 +485,7 @@ typedef union TKey {
#define setnodekey(L,key,obj) \
{ TKey *k_=(key); const TValue *io_=(obj); \
k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
(void)L; checkliveness(G(L),io_); }
(void)L; checkliveness(L,io_); }
typedef struct Node {

View File

@@ -1,5 +1,5 @@
/*
** $Id: loslib.c,v 1.56 2015/02/09 17:41:54 roberto Exp roberto $
** $Id: loslib.c,v 1.59 2015/07/06 15:16:51 roberto Exp roberto $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -54,7 +54,12 @@
*/
#define l_timet lua_Integer
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a))
static time_t l_checktime (lua_State *L, int arg) {
lua_Integer t = luaL_checkinteger(L, arg);
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
return (time_t)t;
}
#endif /* } */
@@ -198,17 +203,29 @@ static int getboolfield (lua_State *L, const char *key) {
}
static int getfield (lua_State *L, const char *key, int d) {
int res, isnum;
lua_getfield(L, -1, key);
res = (int)lua_tointegerx(L, -1, &isnum);
if (!isnum) {
if (d < 0)
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
#if !defined(L_MAXDATEFIELD)
#define L_MAXDATEFIELD (INT_MAX / 2)
#endif
static int getfield (lua_State *L, const char *key, int d, int delta) {
int isnum;
int t = lua_getfield(L, -1, key);
lua_Integer res = lua_tointegerx(L, -1, &isnum);
if (!isnum) { /* field is not a number? */
if (t != LUA_TNIL) /* some other value? */
return luaL_error(L, "field '%s' not an integer", key);
else if (d < 0) /* absent field; no default? */
return luaL_error(L, "field '%s' missing in date table", key);
res = d;
}
else {
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
return luaL_error(L, "field '%s' out-of-bounds", key);
res -= delta;
}
lua_pop(L, 1);
return res;
return (int)res;
}
@@ -236,6 +253,10 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) {
}
/* maximum size for an individual 'strftime' item */
#define SIZETIMEFMT 250
static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
@@ -247,8 +268,8 @@ static int os_date (lua_State *L) {
else
stm = l_localtime(&t, &tmr);
if (stm == NULL) /* invalid date? */
lua_pushnil(L);
else if (strcmp(s, "*t") == 0) {
luaL_error(L, "time result cannot be represented in this installation");
if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
@@ -266,14 +287,14 @@ static int os_date (lua_State *L) {
cc[0] = '%';
luaL_buffinit(L, &b);
while (*s) {
if (*s != '%') /* no conversion specifier? */
if (*s != '%') /* not a conversion specifier? */
luaL_addchar(&b, *s++);
else {
size_t reslen;
char buff[200]; /* should be big enough for any conversion result */
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
s = checkoption(L, s + 1, cc);
reslen = strftime(buff, sizeof(buff), cc, stm);
luaL_addlstring(&b, buff, reslen);
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
luaL_addsize(&b, reslen);
}
}
luaL_pushresult(&b);
@@ -290,21 +311,18 @@ static int os_time (lua_State *L) {
struct tm ts;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_sec = getfield(L, "sec", 0);
ts.tm_min = getfield(L, "min", 0);
ts.tm_hour = getfield(L, "hour", 12);
ts.tm_mday = getfield(L, "day", -1);
ts.tm_mon = getfield(L, "month", -1) - 1;
ts.tm_year = getfield(L, "year", -1) - 1900;
ts.tm_sec = getfield(L, "sec", 0, 0);
ts.tm_min = getfield(L, "min", 0, 0);
ts.tm_hour = getfield(L, "hour", 12, 0);
ts.tm_mday = getfield(L, "day", -1, 0);
ts.tm_mon = getfield(L, "month", -1, 1);
ts.tm_year = getfield(L, "year", -1, 1900);
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
}
if (t != (time_t)(l_timet)t)
luaL_error(L, "time result cannot be represented in this Lua installation");
else if (t == (time_t)(-1))
lua_pushnil(L);
else
l_pushtime(L, t);
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
luaL_error(L, "time result cannot be represented in this installation");
l_pushtime(L, t);
return 1;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 2.146 2014/11/27 18:41:43 roberto Exp roberto $
** $Id: lparser.c,v 2.148 2015/10/28 17:28:40 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -760,7 +760,7 @@ static void parlist (LexState *ls) {
}
case TK_DOTS: { /* param -> '...' */
luaX_next(ls);
f->is_vararg = 1;
f->is_vararg = 2; /* declared vararg */
break;
}
default: luaX_syntaxerror(ls, "<name> or '...' expected");
@@ -956,6 +956,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs;
check_condition(ls, fs->f->is_vararg,
"cannot use '...' outside a vararg function");
fs->f->is_vararg = 1; /* function actually uses vararg */
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
break;
}
@@ -1610,7 +1611,7 @@ static void mainfunc (LexState *ls, FuncState *fs) {
BlockCnt bl;
expdesc v;
open_func(ls, fs, &bl);
fs->f->is_vararg = 1; /* main function is always vararg */
fs->f->is_vararg = 2; /* main function is always declared vararg */
init_exp(&v, VLOCAL, 0); /* create and... */
newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
luaX_next(ls); /* read first token */
@@ -1626,10 +1627,10 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
FuncState funcstate;
LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */
setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */
incr_top(L);
luaD_inctop(L);
lexstate.h = luaH_new(L); /* create table for scanner */
sethvalue(L, L->top, lexstate.h); /* anchor it */
incr_top(L);
luaD_inctop(L);
funcstate.f = cl->p = luaF_newproto(L);
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
lua_assert(iswhite(funcstate.f)); /* do not need barrier here */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp roberto $
** $Id: lstate.c,v 2.132 2015/11/02 16:01:41 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -76,7 +76,7 @@ typedef struct LG {
*/
#define addbuff(b,p,e) \
{ size_t t = cast(size_t, e); \
memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); }
memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
static unsigned int makeseed (lua_State *L) {
char buff[4 * sizeof(size_t)];
@@ -93,10 +93,14 @@ static unsigned int makeseed (lua_State *L) {
/*
** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
** invariant
** invariant (and avoiding underflows in 'totalbytes')
*/
void luaE_setdebt (global_State *g, l_mem debt) {
g->totalbytes -= (debt - g->GCdebt);
l_mem tb = gettotalbytes(g);
lua_assert(tb > 0);
if (debt < tb - MAX_LMEM)
debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */
g->totalbytes = tb - debt;
g->GCdebt = debt;
}
@@ -107,6 +111,7 @@ CallInfo *luaE_extendCI (lua_State *L) {
L->ci->next = ci;
ci->previous = L->ci;
ci->next = NULL;
L->nci++;
return ci;
}
@@ -121,6 +126,7 @@ void luaE_freeCI (lua_State *L) {
while ((ci = next) != NULL) {
next = ci->next;
luaM_free(L, ci);
L->nci--;
}
}
@@ -130,13 +136,14 @@ void luaE_freeCI (lua_State *L) {
*/
void luaE_shrinkCI (lua_State *L) {
CallInfo *ci = L->ci;
while (ci->next != NULL) { /* while there is 'next' */
CallInfo *next2 = ci->next->next; /* next's next */
if (next2 == NULL) break;
luaM_free(L, ci->next); /* remove next */
CallInfo *next2; /* next's next */
/* while there are two nexts */
while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
luaM_free(L, ci->next); /* free next */
L->nci--;
ci->next = next2; /* remove 'next' from the list */
next2->previous = ci;
ci = next2;
ci = next2; /* keep next's next */
}
}
@@ -166,6 +173,7 @@ static void freestack (lua_State *L) {
return; /* stack not completely built yet */
L->ci = &L->base_ci; /* free the entire 'ci' list */
luaE_freeCI(L);
lua_assert(L->nci == 0);
luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
}
@@ -214,6 +222,7 @@ static void preinit_thread (lua_State *L, global_State *g) {
G(L) = g;
L->stack = NULL;
L->ci = NULL;
L->nci = 0;
L->stacksize = 0;
L->twups = L; /* thread has no upvalues */
L->errorJmp = NULL;
@@ -237,7 +246,6 @@ static void close_state (lua_State *L) {
if (g->version) /* closing a fully built state? */
luai_userstateclose(L);
luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
luaZ_freebuffer(L, &g->buff);
freestack(L);
lua_assert(gettotalbytes(g) == sizeof(LG));
(*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
@@ -306,7 +314,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL;
setnilvalue(&g->l_registry);
luaZ_initbuffer(L, &g->buff);
g->panic = NULL;
g->version = NULL;
g->gcstate = GCSpause;

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.121 2015/04/10 17:56:25 roberto Exp roberto $
** $Id: lstate.h,v 2.127 2015/11/02 16:01:41 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@@ -89,8 +89,8 @@ typedef struct CallInfo {
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
#define CIST_LUA (1<<1) /* call is running a Lua function */
#define CIST_HOOKED (1<<2) /* call is running a debug hook */
#define CIST_REENTRY (1<<3) /* call is running on same invocation of
luaV_execute of previous call */
#define CIST_FRESH (1<<3) /* call is running on a fresh invocation
of luaV_execute */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
#define CIST_TAIL (1<<5) /* call was tail called */
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
@@ -109,7 +109,7 @@ typedef struct CallInfo {
typedef struct global_State {
lua_Alloc frealloc; /* function to reallocate memory */
void *ud; /* auxiliary data to 'frealloc' */
lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
lu_mem GCmemtrav; /* memory traversed by the GC */
lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
@@ -131,7 +131,6 @@ typedef struct global_State {
GCObject *tobefnz; /* list of userdata to be GC */
GCObject *fixedgc; /* list of objects not to be collected */
struct lua_State *twups; /* list of threads with open upvalues */
Mbuffer buff; /* temporary buffer for string concatenation */
unsigned int gcfinnum; /* number of finalizers to call in each GC step */
int gcpause; /* size of pause between successive GCs */
int gcstepmul; /* GC 'granularity' */
@@ -141,7 +140,7 @@ typedef struct global_State {
TString *memerrmsg; /* memory-error message */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
} global_State;
@@ -150,6 +149,7 @@ typedef struct global_State {
*/
struct lua_State {
CommonHeader;
unsigned short nci; /* number of items in 'ci' list */
lu_byte status;
StkId top; /* first free slot in the stack */
global_State *l_G;
@@ -212,7 +212,7 @@ union GCUnion {
/* actual number of total bytes allocated */
#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt)
#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt)
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.c,v 2.48 2015/03/25 13:42:19 roberto Exp roberto $
** $Id: lstring.c,v 2.55 2015/11/03 15:36:01 roberto Exp roberto $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -48,14 +48,23 @@ int luaS_eqlngstr (TString *a, TString *b) {
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
unsigned int h = seed ^ cast(unsigned int, l);
size_t l1;
size_t step = (l >> LUAI_HASHLIMIT) + 1;
for (l1 = l; l1 >= step; l1 -= step)
h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
for (; l >= step; l -= step)
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
return h;
}
unsigned int luaS_hashlongstr (TString *ts) {
lua_assert(ts->tt == LUA_TLNGSTR);
if (ts->extra == 0) { /* no hash? */
ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash);
ts->extra = 1; /* now it has its hash */
}
return ts->hash;
}
/*
** resizes the string table
*/
@@ -92,11 +101,12 @@ void luaS_resize (lua_State *L, int newsize) {
** a non-collectable string.)
*/
void luaS_clearcache (global_State *g) {
int i;
for (i = 0; i < STRCACHE_SIZE; i++) {
if (iswhite(g->strcache[i][0])) /* will entry be collected? */
g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */
}
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 */
}
}
@@ -105,13 +115,14 @@ void luaS_clearcache (global_State *g) {
*/
void luaS_init (lua_State *L) {
global_State *g = G(L);
int i;
int i, j;
luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */
g->strcache[i][0] = g->memerrmsg;
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;
}
@@ -119,8 +130,7 @@ void luaS_init (lua_State *L) {
/*
** creates a new string object
*/
static TString *createstrobj (lua_State *L, const char *str, size_t l,
int tag, unsigned int h) {
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 */
@@ -129,8 +139,14 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
ts = gco2ts(o);
ts->hash = h;
ts->extra = 0;
memcpy(getaddrstr(ts), str, l * sizeof(char));
getaddrstr(ts)[l] = '\0'; /* ending 0 */
getstr(ts)[l] = '\0'; /* ending 0 */
return ts;
}
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed);
ts->u.lnglen = l;
return ts;
}
@@ -153,6 +169,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
global_State *g = G(L);
unsigned int h = luaS_hash(str, l, g->seed);
TString **list = &g->strt.hash[lmod(h, g->strt.size)];
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
if (l == ts->shrlen &&
(memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
@@ -166,7 +183,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
luaS_resize(L, g->strt.size * 2);
list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
}
ts = createstrobj(L, str, l, LUA_TSHRSTR, h);
ts = createstrobj(L, l, LUA_TSHRSTR, h);
memcpy(getstr(ts), str, l * sizeof(char));
ts->shrlen = cast_byte(l);
ts->u.hnext = *list;
*list = ts;
@@ -183,10 +201,10 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
return internshrstr(L, str, l);
else {
TString *ts;
if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char))
if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
luaM_toobig(L);
ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed);
ts->u.lnglen = l;
ts = luaS_createlngstrobj(L, l);
memcpy(getstr(ts), str, l * sizeof(char));
return ts;
}
}
@@ -199,15 +217,19 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
** check hits.
*/
TString *luaS_new (lua_State *L, const char *str) {
unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */
unsigned int i = point2uint(str) % STRCACHE_N; /* hash */
int j;
TString **p = G(L)->strcache[i];
if (strcmp(str, getstr(p[0])) == 0) /* hit? */
return p[0]; /* that it is */
else { /* normal route */
TString *s = luaS_newlstr(L, str, strlen(str));
p[0] = s;
return s;
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];
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstring.h,v 1.58 2015/03/04 13:31:21 roberto Exp roberto $
** $Id: lstring.h,v 1.60 2015/09/08 15:41:05 roberto Exp roberto $
** String table (keep all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -34,6 +34,7 @@
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);
@@ -42,6 +43,7 @@ LUAI_FUNC void luaS_remove (lua_State *L, TString *ts);
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
#endif

181
lstrlib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.228 2015/04/03 18:41:57 roberto Exp roberto $
** $Id: lstrlib.c,v 1.238 2015/11/23 11:31:21 roberto Exp roberto $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -41,8 +41,10 @@
** Some sizes are better limited to fit in 'int', but must also fit in
** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
*/
#define MAX_SIZET ((size_t)(~(size_t)0))
#define MAXSIZE \
(sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX))
(sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
@@ -208,11 +210,12 @@ static int str_dump (lua_State *L) {
typedef struct MatchState {
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
const char *src_init; /* init of source string */
const char *src_end; /* end ('\0') of source string */
const char *p_end; /* end ('\0') of pattern */
lua_State *L;
size_t nrep; /* limit to avoid non-linear complexity */
int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
int level; /* total number of captures (finished or unfinished) */
struct {
const char *init;
@@ -231,6 +234,17 @@ static const char *match (MatchState *ms, const char *s, const char *p);
#endif
/*
** parameters to control the maximum number of operators handled in
** a match (to avoid non-linear complexity). The maximum will be:
** (subject length) * A_REPS + B_REPS
*/
#if !defined(A_REPS)
#define A_REPS 4
#define B_REPS 100000
#endif
#define L_ESC '%'
#define SPECIALS "^$*+?.([%-"
@@ -488,6 +502,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
s = NULL; /* fail */
}
else { /* matched once */
if (ms->nrep-- == 0)
luaL_error(ms->L, "pattern too complex");
switch (*ep) { /* handle optional suffix */
case '?': { /* optional */
const char *res;
@@ -584,6 +600,26 @@ static int nospecials (const char *p, size_t l) {
}
static void prepstate (MatchState *ms, lua_State *L,
const char *s, size_t ls, const char *p, size_t lp) {
ms->L = L;
ms->matchdepth = MAXCCALLS;
ms->src_init = s;
ms->src_end = s + ls;
ms->p_end = p + lp;
if (ls < (MAX_SIZET - B_REPS) / A_REPS)
ms->nrep = A_REPS * ls + B_REPS;
else /* overflow (very long subject) */
ms->nrep = MAX_SIZET; /* no limit */
}
static void reprepstate (MatchState *ms) {
ms->level = 0;
lua_assert(ms->matchdepth == MAXCCALLS);
}
static int str_find_aux (lua_State *L, int find) {
size_t ls, lp;
const char *s = luaL_checklstring(L, 1, &ls);
@@ -611,15 +647,10 @@ static int str_find_aux (lua_State *L, int find) {
if (anchor) {
p++; lp--; /* skip anchor character */
}
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = s;
ms.src_end = s + ls;
ms.p_end = p + lp;
prepstate(&ms, L, s, ls, p, lp);
do {
const char *res;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
reprepstate(&ms);
if ((res=match(&ms, s1, p)) != NULL) {
if (find) {
lua_pushinteger(L, (s1 - s) + 1); /* start */
@@ -646,29 +677,26 @@ static int str_match (lua_State *L) {
}
/* state for 'gmatch' */
typedef struct GMatchState {
const char *src; /* current position */
const char *p; /* pattern */
MatchState ms; /* match state */
} GMatchState;
static int gmatch_aux (lua_State *L) {
MatchState ms;
size_t ls, lp;
const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
const char *src;
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = s;
ms.src_end = s+ls;
ms.p_end = p + lp;
for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
src <= ms.src_end;
src++) {
for (src = gm->src; src <= gm->ms.src_end; src++) {
const char *e;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
if ((e = match(&ms, src, p)) != NULL) {
lua_Integer newstart = e-s;
if (e == src) newstart++; /* empty match? go at least one position */
lua_pushinteger(L, newstart);
lua_replace(L, lua_upvalueindex(3));
return push_captures(&ms, src, e);
reprepstate(&gm->ms);
if ((e = match(&gm->ms, src, gm->p)) != NULL) {
if (e == src) /* empty match? */
gm->src =src + 1; /* go at least one position */
else
gm->src = e;
return push_captures(&gm->ms, src, e);
}
}
return 0; /* not found */
@@ -676,10 +704,14 @@ static int gmatch_aux (lua_State *L) {
static int gmatch (lua_State *L) {
luaL_checkstring(L, 1);
luaL_checkstring(L, 2);
lua_settop(L, 2);
lua_pushinteger(L, 0);
size_t ls, lp;
const char *s = luaL_checklstring(L, 1, &ls);
const char *p = luaL_checklstring(L, 2, &lp);
GMatchState *gm;
lua_settop(L, 2); /* keep them on closure to avoid being collected */
gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
prepstate(&gm->ms, L, s, ls, p, lp);
gm->src = s; gm->p = p;
lua_pushcclosure(L, gmatch_aux, 3);
return 1;
}
@@ -761,17 +793,11 @@ static int str_gsub (lua_State *L) {
if (anchor) {
p++; lp--; /* skip anchor character */
}
ms.L = L;
ms.matchdepth = MAXCCALLS;
ms.src_init = src;
ms.src_end = src+srcl;
ms.p_end = p + lp;
prepstate(&ms, L, src, srcl, p, lp);
while (n < max_s) {
const char *e;
ms.level = 0;
lua_assert(ms.matchdepth == MAXCCALLS);
e = match(&ms, src, p);
if (e) {
reprepstate(&ms);
if ((e = match(&ms, src, p)) != NULL) {
n++;
add_value(&ms, &b, src, e, tr);
}
@@ -830,13 +856,12 @@ static lua_Number adddigit (char *buff, int n, lua_Number x) {
}
static int num2straux (char *buff, lua_Number x) {
static int num2straux (char *buff, int sz, lua_Number x) {
if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */
return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */
return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */
else if (x == 0) { /* can be -0... */
sprintf(buff, LUA_NUMBER_FMT, x);
strcat(buff, "x0p+0"); /* reuses '0/-0' from 'sprintf'... */
return strlen(buff);
/* create "0" or "-0" followed by exponent */
return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x);
}
else {
int e;
@@ -855,15 +880,16 @@ static int num2straux (char *buff, lua_Number x) {
m = adddigit(buff, n++, m * 16);
} while (m > 0);
}
n += sprintf(buff + n, "p%+d", e); /* add exponent */
n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */
lua_assert(n < sz);
return n;
}
}
static int lua_number2strx (lua_State *L, char *buff, const char *fmt,
lua_Number x) {
int n = num2straux(buff, x);
static int lua_number2strx (lua_State *L, char *buff, int sz,
const char *fmt, lua_Number x) {
int n = num2straux(buff, sz, x);
if (fmt[SIZELENMOD] == 'A') {
int i;
for (i = 0; i < n; i++)
@@ -879,10 +905,12 @@ static int lua_number2strx (lua_State *L, char *buff, const char *fmt,
/*
** Maximum size of each formatted item. This maximum size is produced
** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') +
** number of decimal digits to represent minfloat.
** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
** and '\0') + number of decimal digits to represent maxfloat (which
** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
** expenses", such as locale-dependent stuff)
*/
#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
/* valid flags in a format specification */
@@ -906,9 +934,9 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
else if (*s == '\0' || iscntrl(uchar(*s))) {
char buff[10];
if (!isdigit(uchar(*(s+1))))
sprintf(buff, "\\%d", (int)uchar(*s));
l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
else
sprintf(buff, "\\%03d", (int)uchar(*s));
l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
luaL_addstring(b, buff);
}
else
@@ -975,24 +1003,25 @@ static int str_format (lua_State *L) {
strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
case 'c': {
nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg));
nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
break;
}
case 'd': case 'i':
case 'o': case 'u': case 'x': case 'X': {
lua_Integer n = luaL_checkinteger(L, arg);
addlenmod(form, LUA_INTEGER_FRMLEN);
nb = sprintf(buff, form, n);
nb = l_sprintf(buff, MAX_ITEM, form, n);
break;
}
case 'a': case 'A':
addlenmod(form, LUA_NUMBER_FRMLEN);
nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg));
nb = lua_number2strx(L, buff, MAX_ITEM, form,
luaL_checknumber(L, arg));
break;
case 'e': case 'E': case 'f':
case 'g': case 'G': {
addlenmod(form, LUA_NUMBER_FRMLEN);
nb = sprintf(buff, form, luaL_checknumber(L, arg));
nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg));
break;
}
case 'q': {
@@ -1002,14 +1031,18 @@ static int str_format (lua_State *L) {
case 's': {
size_t l;
const char *s = luaL_tolstring(L, arg, &l);
if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted;
keep original string */
luaL_addvalue(&b);
}
if (form[2] == '\0') /* no modifiers? */
luaL_addvalue(&b); /* keep entire string */
else {
nb = sprintf(buff, form, s);
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
if (!strchr(form, '.') && l >= 100) {
/* no precision and string is too long to be formatted */
luaL_addvalue(&b); /* keep entire string */
}
else { /* format the string into 'buff' */
nb = l_sprintf(buff, MAX_ITEM, form, s);
lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
}
}
break;
}
@@ -1018,6 +1051,7 @@ static int str_format (lua_State *L) {
*(strfrmt - 1));
}
}
lua_assert(nb < MAX_ITEM);
luaL_addsize(&b, nb);
}
}
@@ -1309,8 +1343,13 @@ static int str_pack (lua_State *L) {
case Kchar: { /* fixed-size string */
size_t len;
const char *s = luaL_checklstring(L, arg, &len);
luaL_argcheck(L, len == (size_t)size, arg, "wrong length");
luaL_addlstring(&b, s, size);
if ((size_t)size <= len) /* string larger than (or equal to) needed? */
luaL_addlstring(&b, s, size); /* truncate string to asked size */
else { /* string smaller than needed */
luaL_addlstring(&b, s, len); /* add it all */
while (len++ < (size_t)size) /* pad extra space */
luaL_addchar(&b, LUA_PACKPADBYTE);
}
break;
}
case Kstring: { /* strings with length count */
@@ -1360,7 +1399,7 @@ static int str_packsize (lua_State *L) {
case Kstring: /* strings with length count */
case Kzstr: /* zero-terminated string */
luaL_argerror(L, 1, "variable-length format");
break;
/* call never return, but to avoid warnings: *//* FALLTHROUGH */
default: break;
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.c,v 2.110 2015/05/20 16:22:30 roberto Exp roberto $
** $Id: ltable.c,v 2.116 2015/11/03 18:35:21 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -85,7 +85,7 @@ static const Node dummynode_ = {
/*
** Hash for floating-point numbers.
** The main computation should be just
** n = frepx(n, &i); return (n * INT_MAX) + i
** n = frexp(n, &i); return (n * INT_MAX) + i
** but there are some numerical subtleties.
** In a two-complement representation, INT_MAX does not has an exact
** representation as a float, but INT_MIN does; because the absolute
@@ -101,7 +101,7 @@ static int l_hashfloat (lua_Number n) {
lua_Integer ni;
n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN);
if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */
lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL);
lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL));
return 0;
}
else { /* normal case */
@@ -124,14 +124,8 @@ static Node *mainposition (const Table *t, const TValue *key) {
return hashmod(t, l_hashfloat(fltvalue(key)));
case LUA_TSHRSTR:
return hashstr(t, tsvalue(key));
case LUA_TLNGSTR: {
TString *s = tsvalue(key);
if (s->extra == 0) { /* no hash? */
s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash);
s->extra = 1; /* now it has its hash */
}
return hashstr(t, tsvalue(key));
}
case LUA_TLNGSTR:
return hashpow2(t, luaS_hashlongstr(tsvalue(key)));
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));
case LUA_TLIGHTUSERDATA:
@@ -139,6 +133,7 @@ static Node *mainposition (const Table *t, const TValue *key) {
case LUA_TLCF:
return hashpointer(t, fvalue(key));
default:
lua_assert(!ttisdeadkey(key));
return hashpointer(t, gcvalue(key));
}
}
@@ -463,7 +458,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *f = getfreepos(t); /* get a free place */
if (f == NULL) { /* cannot find a free place? */
rehash(L, t, key); /* grow table */
/* whatever called 'newkey' takes care of TM cache and GC barrier */
/* whatever called 'newkey' takes care of TM cache */
return luaH_set(L, t, key); /* insert key into grown table */
}
lua_assert(!isdummy(f));
@@ -501,7 +496,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
*/
const TValue *luaH_getint (Table *t, lua_Integer key) {
/* (1 <= key && key <= t->sizearray) */
if (l_castS2U(key - 1) < t->sizearray)
if (l_castS2U(key) - 1 < t->sizearray)
return &t->array[key - 1];
else {
Node *n = hashint(t, key);
@@ -513,7 +508,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
if (nx == 0) break;
n += nx;
}
};
}
return luaO_nilobject;
}
}
@@ -522,7 +517,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
/*
** search function for short strings
*/
const TValue *luaH_getstr (Table *t, TString *key) {
const TValue *luaH_getshortstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
lua_assert(key->tt == LUA_TSHRSTR);
for (;;) { /* check whether 'key' is somewhere in the chain */
@@ -531,11 +526,41 @@ const TValue *luaH_getstr (Table *t, TString *key) {
return gval(n); /* that's it */
else {
int nx = gnext(n);
if (nx == 0) break;
if (nx == 0)
return luaO_nilobject; /* not found */
n += nx;
}
};
return luaO_nilobject;
}
}
/*
** "Generic" get version. (Not that generic: not valid for integers,
** which may be in array part, nor for floats with integral values.)
*/
static const TValue *getgeneric (Table *t, const TValue *key) {
Node *n = mainposition(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
if (luaV_rawequalobj(gkey(n), key))
return gval(n); /* that's it */
else {
int nx = gnext(n);
if (nx == 0)
return luaO_nilobject; /* not found */
n += nx;
}
}
}
const TValue *luaH_getstr (Table *t, TString *key) {
if (key->tt == LUA_TSHRSTR)
return luaH_getshortstr(t, key);
else { /* for long strings, use generic case */
TValue ko;
setsvalue(cast(lua_State *, NULL), &ko, key);
return getgeneric(t, &ko);
}
}
@@ -544,7 +569,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
*/
const TValue *luaH_get (Table *t, const TValue *key) {
switch (ttype(key)) {
case LUA_TSHRSTR: return luaH_getstr(t, tsvalue(key));
case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
case LUA_TNIL: return luaO_nilobject;
case LUA_TNUMFLT: {
@@ -553,19 +578,8 @@ const TValue *luaH_get (Table *t, const TValue *key) {
return luaH_getint(t, k); /* use specialized version */
/* else... */
} /* FALLTHROUGH */
default: {
Node *n = mainposition(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
if (luaV_rawequalobj(gkey(n), key))
return gval(n); /* that's it */
else {
int nx = gnext(n);
if (nx == 0) break;
n += nx;
}
};
return luaO_nilobject;
}
default:
return getgeneric(t, key);
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltable.h,v 2.19 2014/07/29 16:22:24 roberto Exp roberto $
** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp roberto $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -18,6 +18,10 @@
/* 'const' to avoid wrong writings that can mess up field 'next' */
#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk))
/*
** writable version of 'gkey'; allows updates to individual fields,
** but not to the whole (which has incompatible type)
*/
#define wgkey(n) (&(n)->i_key.nk)
#define invalidateTMcache(t) ((t)->flags = 0)
@@ -31,6 +35,7 @@
LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
TValue *value);
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key);

374
ltablib.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp roberto $
** $Id: ltablib.c,v 1.89 2015/11/24 16:54:32 roberto Exp roberto $
** Library for Table Manipulation
** See Copyright Notice in lua.h
*/
@@ -12,6 +12,7 @@
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include "lua.h"
@@ -19,40 +20,42 @@
#include "lualib.h"
/*
** Structure with table-access functions
** Operations that an object must define to mimic a table
** (some functions only need some of them)
*/
typedef struct {
int (*geti) (lua_State *L, int idx, lua_Integer n);
void (*seti) (lua_State *L, int idx, lua_Integer n);
} TabA;
#define TAB_R 1 /* read */
#define TAB_W 2 /* write */
#define TAB_L 4 /* length */
#define TAB_RW (TAB_R | TAB_W) /* read/write */
/*
** Check that 'arg' has a table and set access functions in 'ta' to raw
** or non-raw according to the presence of corresponding metamethods.
*/
static void checktab (lua_State *L, int arg, TabA *ta) {
ta->geti = NULL; ta->seti = NULL;
if (lua_getmetatable(L, arg)) {
lua_pushliteral(L, "__index"); /* 'index' metamethod */
if (lua_rawget(L, -2) != LUA_TNIL)
ta->geti = lua_geti;
lua_pushliteral(L, "__newindex"); /* 'newindex' metamethod */
if (lua_rawget(L, -3) != LUA_TNIL)
ta->seti = lua_seti;
lua_pop(L, 3); /* pop metatable plus both metamethods */
}
if (ta->geti == NULL || ta->seti == NULL) {
luaL_checktype(L, arg, LUA_TTABLE); /* must be table for raw methods */
if (ta->geti == NULL) ta->geti = lua_rawgeti;
if (ta->seti == NULL) ta->seti = lua_rawseti;
}
#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);
}
#define aux_getn(L,n,ta) (checktab(L, n, ta), luaL_len(L, n))
/*
** Check that 'arg' either is a table or can behave like one (that is,
** has a metatable with the required metamethods)
*/
static void checktab (lua_State *L, int arg, int what) {
if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */
int n = 1; /* number of elements to pop */
if (lua_getmetatable(L, arg) && /* must have metatable */
(!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
(!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
(!(what & TAB_L) || checkfield(L, "__len", ++n))) {
lua_pop(L, n); /* pop metatable and tested metamethods */
}
else
luaL_argerror(L, arg, "table expected"); /* force an error */
}
}
#if defined(LUA_COMPAT_MAXN)
@@ -74,8 +77,7 @@ static int maxn (lua_State *L) {
static int tinsert (lua_State *L) {
TabA ta;
lua_Integer e = aux_getn(L, 1, &ta) + 1; /* first empty element */
lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */
lua_Integer pos; /* where to insert new element */
switch (lua_gettop(L)) {
case 2: { /* called with only 2 arguments */
@@ -87,8 +89,8 @@ static int tinsert (lua_State *L) {
pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
for (i = e; i > pos; i--) { /* move up elements */
(*ta.geti)(L, 1, i - 1);
(*ta.seti)(L, 1, i); /* t[i] = t[i - 1] */
lua_geti(L, 1, i - 1);
lua_seti(L, 1, i); /* t[i] = t[i - 1] */
}
break;
}
@@ -96,57 +98,57 @@ static int tinsert (lua_State *L) {
return luaL_error(L, "wrong number of arguments to 'insert'");
}
}
(*ta.seti)(L, 1, pos); /* t[pos] = v */
lua_seti(L, 1, pos); /* t[pos] = v */
return 0;
}
static int tremove (lua_State *L) {
TabA ta;
lua_Integer size = aux_getn(L, 1, &ta);
lua_Integer size = aux_getn(L, 1, TAB_RW);
lua_Integer pos = luaL_optinteger(L, 2, size);
if (pos != size) /* validate 'pos' if given */
luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
(*ta.geti)(L, 1, pos); /* result = t[pos] */
lua_geti(L, 1, pos); /* result = t[pos] */
for ( ; pos < size; pos++) {
(*ta.geti)(L, 1, pos + 1);
(*ta.seti)(L, 1, pos); /* t[pos] = t[pos + 1] */
lua_geti(L, 1, pos + 1);
lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
}
lua_pushnil(L);
(*ta.seti)(L, 1, pos); /* t[pos] = nil */
lua_seti(L, 1, pos); /* t[pos] = nil */
return 1;
}
/*
** 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) {
TabA ta;
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;
ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL)
? (luaL_checktype(L, 1, LUA_TTABLE), lua_rawgeti)
: lua_geti;
ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL)
? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti)
: lua_seti;
luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
"too many elements to move");
n = e - f + 1; /* number of elements to move */
luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
"destination wrap around");
if (t > f) {
for (i = n - 1; i >= 0; i--) {
(*ta.geti)(L, 1, f + i);
(*ta.seti)(L, tt, t + i);
if (t > e || t <= f || tt != 1) {
for (i = 0; i < n; i++) {
lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i);
}
}
else {
for (i = 0; i < n; i++) {
(*ta.geti)(L, 1, f + i);
(*ta.seti)(L, tt, t + i);
for (i = n - 1; i >= 0; i--) {
lua_geti(L, 1, f + i);
lua_seti(L, tt, t + i);
}
}
}
@@ -155,8 +157,8 @@ static int tmove (lua_State *L) {
}
static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) {
(*ta->geti)(L, 1, i);
static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
lua_geti(L, 1, i);
if (!lua_isstring(L, -1))
luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
luaL_typename(L, -1), i);
@@ -165,21 +167,19 @@ static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) {
static int tconcat (lua_State *L) {
TabA ta;
luaL_Buffer b;
lua_Integer last = aux_getn(L, 1, TAB_R);
size_t lsep;
lua_Integer i, last;
const char *sep = luaL_optlstring(L, 2, "", &lsep);
checktab(L, 1, &ta);
i = luaL_optinteger(L, 3, 1);
last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1));
lua_Integer i = luaL_optinteger(L, 3, 1);
last = luaL_opt(L, luaL_checkinteger, 4, last);
luaL_buffinit(L, &b);
for (; i < last; i++) {
addfield(L, &b, &ta, i);
addfield(L, &b, i);
luaL_addlstring(&b, sep, lsep);
}
if (i == last) /* add last value (if interval was not empty) */
addfield(L, &b, &ta, i);
addfield(L, &b, i);
luaL_pushresult(&b);
return 1;
}
@@ -197,7 +197,7 @@ static int pack (lua_State *L) {
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_rawseti(L, 1, i);
lua_seti(L, 1, i);
lua_pushinteger(L, n);
lua_setfield(L, 1, "n"); /* t.n = number of elements */
return 1; /* return table */
@@ -205,20 +205,17 @@ static int pack (lua_State *L) {
static int unpack (lua_State *L) {
TabA ta;
lua_Integer i, e;
lua_Unsigned n;
checktab(L, 1, &ta);
i = luaL_optinteger(L, 2, 1);
e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
lua_Integer i = luaL_optinteger(L, 2, 1);
lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
if (i > e) return 0; /* empty range */
n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n)))
return luaL_error(L, "too many results to unpack");
do { /* must have at least one element */
(*ta.geti)(L, 1, i); /* push arg[i..e] */
} while (i++ < e);
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;
}
@@ -235,97 +232,190 @@ static int unpack (lua_State *L) {
*/
static void set2 (lua_State *L, TabA *ta, int i, int j) {
(*ta->seti)(L, 1, i);
(*ta->seti)(L, 1, j);
/*
** 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, unsigned int i, unsigned int 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_call(L, 2, 1); /* call function */
res = lua_toboolean(L, -1); /* get result */
lua_pop(L, 1); /* pop result */
return res;
}
else /* a < b? */
return lua_compare(L, a, b, LUA_OPLT);
}
static void auxsort (lua_State *L, TabA *ta, int l, int u) {
while (l < u) { /* for tail recursion */
int i, j;
/* sort elements a[l], a[(l+u)/2] and a[u] */
(*ta->geti)(L, 1, l);
(*ta->geti)(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
set2(L, ta, 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 unsigned int partition (lua_State *L, unsigned int lo,
unsigned int up) {
unsigned int i = lo; /* will be incremented before first use */
unsigned int j = up - 1; /* will be decremented before first use */
/* loop invariant: a[lo .. i] <= P <= a[j .. up] */
for (;;) {
/* next loop: repeat ++i while a[i] < P */
while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */
luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[i] */
}
/* after the loop, a[i] >= P and a[lo .. i - 1] < P */
/* next loop: repeat --j while P < a[j] */
while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
if (j < i) /* j < i but a[j] > P ?? */
luaL_error(L, "invalid order function for sorting");
lua_pop(L, 1); /* remove a[j] */
}
/* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
if (j < i) { /* no elements out of place? */
/* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
lua_pop(L, 1); /* pop a[j] */
/* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
set2(L, up - 1, i);
return i;
}
/* otherwise, swap a[i] - a[j] to restore invariant and repeat */
set2(L, i, j);
}
}
/*
** Choose an element in the middle (2nd-3th quarters) of [lo,up]
** "randomized" by 'rnd'
*/
static unsigned int choosePivot (unsigned int lo, unsigned int up,
unsigned int rnd) {
unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */
unsigned int 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, unsigned int lo, unsigned int up,
unsigned int rnd) {
while (lo < up) { /* loop for tail recursion */
unsigned int p; /* Pivot index */
unsigned int 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;
(*ta->geti)(L, 1, i);
(*ta->geti)(L, 1, l);
if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
set2(L, ta, 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] */
(*ta->geti)(L, 1, u);
if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
set2(L, ta, 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 */
(*ta->geti)(L, 1, i); /* Pivot */
lua_pushvalue(L, -1);
(*ta->geti)(L, 1, u-1);
set2(L, ta, 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 ((*ta->geti)(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 ((*ta->geti)(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, ta, i, j);
}
(*ta->geti)(L, 1, u-1);
(*ta->geti)(L, 1, i);
set2(L, ta, 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, ta, j, i); /* call recursively the smaller one */
} /* repeat the routine for the larger one */
if ((up - lo) / 128u > n) /* partition too imbalanced? */
rnd = l_randomizePivot(); /* try a new randomization */
} /* tail call auxsort(L, lo, up, rnd) */
}
static int sort (lua_State *L) {
TabA ta;
int n = (int)aux_getn(L, 1, &ta);
luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, &ta, 1, n);
lua_Integer n = aux_getn(L, 1, TAB_RW);
if (n > 1) { /* non-trivial interval? */
luaL_argcheck(L, n < INT_MAX, 1, "array too big");
luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */
if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
lua_settop(L, 2); /* make sure there are two arguments */
auxsort(L, 1, (unsigned int)n, 0u);
}
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 2.204 2015/03/13 16:24:50 roberto Exp roberto $
** $Id: ltests.c,v 2.208 2015/09/08 16:55:43 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -313,7 +313,7 @@ static void checkstack (global_State *g, lua_State *L1) {
}
if (L1->stack) { /* complete thread? */
for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++)
checkliveness(g, o); /* entire stack must have valid values */
checkliveness(L1, o); /* entire stack must have valid values */
}
else lua_assert(L1->stacksize == 0);
}
@@ -911,7 +911,7 @@ static int doremote (lua_State *L) {
static int int2fb_aux (lua_State *L) {
int b = luaO_int2fb((unsigned int)luaL_checkinteger(L, 1));
lua_pushinteger(L, b);
lua_pushinteger(L, luaO_fb2int(b));
lua_pushinteger(L, (unsigned int)luaO_fb2int(b));
return 2;
}
@@ -1001,6 +1001,11 @@ static int getnum_aux (lua_State *L, lua_State *L1, const char **pc) {
(*pc)++;
return res;
}
else if (**pc == '*') {
res = lua_gettop(L1);
(*pc)++;
return res;
}
else if (**pc == '-') {
sig = -1;
(*pc)++;
@@ -1350,7 +1355,7 @@ static struct X { int x; } x;
else if EQ("tostring") {
const char *s = lua_tostring(L1, getindex);
const char *s1 = lua_pushstring(L1, s);
lua_assert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
}
else if EQ("type") {
lua_pushstring(L1, luaL_typename(L1, getnum));

View File

@@ -1,5 +1,5 @@
/*
** $Id: ltests.h,v 2.46 2014/12/19 13:33:06 roberto Exp roberto $
** $Id: ltests.h,v 2.48 2015/06/18 14:27:44 roberto Exp roberto $
** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@@ -37,6 +37,15 @@
#define UNUSED(x) (x=0, (void)(x))
/* 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
/* memory-allocator control variables */
typedef struct Memcontrol {
unsigned long numblocks;
@@ -109,5 +118,9 @@ LUA_API void *debug_realloc (void *ud, void *block,
#undef LUAI_USER_ALIGNMENT_T
#define LUAI_USER_ALIGNMENT_T union { char b[sizeof(void*) * 8]; }
#define STRCACHE_N 23
#define STRCACHE_M 5
#endif

19
ltm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 2.33 2014/11/21 12:15:57 roberto Exp roberto $
** $Id: ltm.c,v 2.35 2015/11/02 18:48:07 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@@ -57,7 +57,7 @@ void luaT_init (lua_State *L) {
** tag methods
*/
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
const TValue *tm = luaH_getstr(events, ename);
const TValue *tm = luaH_getshortstr(events, ename);
lua_assert(event <= TM_EQ);
if (ttisnil(tm)) { /* no tag method? */
events->flags |= cast_byte(1u<<event); /* cache this fact */
@@ -79,20 +79,25 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
default:
mt = G(L)->mt[ttnov(o)];
}
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}
void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
const TValue *p2, TValue *p3, int hasres) {
ptrdiff_t result = savestack(L, p3);
setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */
setobj2s(L, L->top++, p1); /* 1st argument */
setobj2s(L, L->top++, p2); /* 2nd argument */
StkId func = L->top;
setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */
setobj2s(L, func + 1, p1); /* 1st argument */
setobj2s(L, func + 2, p2); /* 2nd argument */
L->top += 3;
if (!hasres) /* no result? 'p3' is third argument */
setobj2s(L, L->top++, p3); /* 3rd argument */
/* metamethod may yield only when called from Lua code */
luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
if (isLua(L->ci))
luaD_call(L, func, hasres);
else
luaD_callnoyield(L, func, hasres);
if (hasres) { /* if has result, move it to its place */
p3 = restorestack(L, result);
setobjs2s(L, p3, --L->top);

20
lua.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.224 2015/03/10 14:15:06 roberto Exp roberto $
** $Id: lua.c,v 1.225 2015/03/30 15:42:59 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -324,24 +324,20 @@ static int pushline (lua_State *L, int firstline) {
/*
** Try to compile line on the stack as 'return <line>'; on return, stack
** 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) {
int status;
size_t len; const char *line;
lua_pushliteral(L, "return ");
lua_pushvalue(L, -2); /* duplicate line */
lua_concat(L, 2); /* new line is "return ..." */
line = lua_tolstring(L, -1, &len);
if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) {
lua_remove(L, -3); /* remove original line */
line += sizeof("return")/sizeof(char); /* remove 'return' for history */
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); /* remove result from 'luaL_loadbuffer' and new line */
lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
return status;
}

4
lua.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.327 2015/03/10 14:17:51 roberto Exp roberto $
** $Id: lua.h,v 1.328 2015/06/03 13:03:38 roberto Exp roberto $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -19,7 +19,7 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "3"
#define LUA_VERSION_NUM 503
#define LUA_VERSION_RELEASE "1"
#define LUA_VERSION_RELEASE "2"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE

View File

@@ -1,5 +1,5 @@
/*
** $Id: luaconf.h,v 1.250 2015/04/03 18:41:57 roberto Exp roberto $
** $Id: luaconf.h,v 1.253 2015/06/24 18:23:57 roberto Exp roberto $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -145,7 +145,7 @@
#if !defined(LUA_FLOAT_TYPE)
#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
#endif /* } */
#endif
/* }================================================================== */
@@ -412,9 +412,33 @@
@@ LUA_NUMBER_FMT is the format for writing floats.
@@ lua_number2str converts a float to a string.
@@ l_mathop allows the addition of an 'l' or 'f' to all math operations.
@@ l_floor takes the floor of a float.
@@ lua_str2number converts a decimal numeric string to a number.
*/
/* The following definitions are good for most cases here */
#define l_floor(x) (l_mathop(floor)(x))
#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n))
/*
@@ lua_numbertointeger converts a float number to an integer, or
** returns 0 if float is not within the range of a lua_Integer.
** (The range comparisons are tricky because of rounding. The tests
** here assume a two-complement representation, where MININTEGER always
** has an exact representation as a float; MAXINTEGER may not have one,
** and therefore its conversion to float may have an ill-defined value.)
*/
#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
@@ -468,25 +492,6 @@
#endif /* } */
#define l_floor(x) (l_mathop(floor)(x))
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
/*
@@ lua_numbertointeger converts a float number to an integer, or
** returns 0 if float is not within the range of a lua_Integer.
** (The range comparisons are tricky because of rounding. The tests
** here assume a two-complement representation, where MININTEGER always
** has an exact representation as a float; MAXINTEGER may not have one,
** and therefore its conversion to float may have an ill-defined value.)
*/
#define lua_numbertointeger(n,p) \
((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
(n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
(*(p) = (LUA_INTEGER)(n), 1))
/*
@@ LUA_INTEGER is the integer type used by Lua.
@@ -506,7 +511,7 @@
/* The following definitions are good for most cases here */
#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d"
#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n))
#define lua_integer2str(s,sz,n) l_sprintf((s), sz, LUA_INTEGER_FMT, (n))
#define LUAI_UACINT LUA_INTEGER
@@ -537,6 +542,7 @@
#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 */
@@ -577,6 +583,17 @@
** ===================================================================
*/
/*
@@ 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 an hexadecimal numeric string to a number.
** In C99, 'strtod' does that conversion. Otherwise, you can
@@ -584,7 +601,7 @@
** implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_strx2number(s,p) lua_str2number(s,p)
#define lua_strx2number(s,p) lua_str2number(s,p)
#endif
@@ -595,7 +612,7 @@
** provide its own implementation.
*/
#if !defined(LUA_USE_C89)
#define lua_number2strx(L,b,f,n) sprintf(b,f,n)
#define lua_number2strx(L,b,sz,f,n) l_sprintf(b,sz,f,n)
#endif

View File

@@ -1,5 +1,5 @@
/*
** $Id: lundump.c,v 2.40 2014/06/19 18:27:20 roberto Exp roberto $
** $Id: lundump.c,v 2.43 2015/09/17 15:51:05 roberto Exp roberto $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -32,7 +32,6 @@
typedef struct {
lua_State *L;
ZIO *Z;
Mbuffer *b;
const char *name;
} LoadState;
@@ -92,10 +91,15 @@ static TString *LoadString (LoadState *S) {
LoadVar(S, size);
if (size == 0)
return NULL;
else {
char *s = luaZ_openspace(S->L, S->b, --size);
LoadVector(S, s, size);
return luaS_newlstr(S->L, s, size);
else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */
char buff[LUAI_MAXSHORTLEN];
LoadVector(S, buff, size);
return luaS_newlstr(S->L, buff, size);
}
else { /* long string */
TString *ts = luaS_createlngstrobj(S->L, size);
LoadVector(S, getstr(ts), size); /* load directly in final place */
return ts;
}
}
@@ -251,8 +255,7 @@ static void checkHeader (LoadState *S) {
/*
** load precompiled chunk
*/
LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
const char *name) {
LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
LoadState S;
LClosure *cl;
if (*name == '@' || *name == '=')
@@ -263,11 +266,10 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff,
S.name = name;
S.L = L;
S.Z = Z;
S.b = buff;
checkHeader(&S);
cl = luaF_newLclosure(L, LoadByte(&S));
setclLvalue(L, L->top, cl);
incr_top(L);
luaD_inctop(L);
cl->p = luaF_newproto(L);
LoadFunction(&S, cl->p, NULL);
lua_assert(cl->nupvalues == cl->p->sizeupvalues);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lundump.h,v 1.43 2014/04/15 14:28:20 roberto Exp roberto $
** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp roberto $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -23,8 +23,7 @@
#define LUAC_FORMAT 0 /* this is the official format */
/* load one chunk; from lundump.c */
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff,
const char* name);
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name);
/* dump one chunk; from ldump.c */
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,

217
lvm.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.244 2015/06/02 19:11:24 roberto Exp roberto $
** $Id: lvm.c,v 2.264 2015/11/19 19:16:22 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -153,30 +153,28 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step,
/*
** Main function for table access (invoking metamethods if needed).
** Compute 'val = t[key]'
** Complete a table access: if 't' is a table, 'tm' has its metamethod;
** otherwise, 'tm' is NULL.
*/
void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
const TValue *tm) {
int loop; /* counter to avoid infinite loops */
lua_assert(tm != NULL || !ttistable(t));
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t)) { /* 't' is a table? */
Table *h = hvalue(t);
const TValue *res = luaH_get(h, key); /* do a primitive get */
if (!ttisnil(res) || /* result is not nil? */
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
setobj2s(L, val, res); /* result is the raw get */
return;
}
/* else will try metamethod */
if (tm == NULL) { /* no metamethod (from a table)? */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index"); /* no metamethod */
}
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
luaG_typeerror(L, t, "index"); /* no metamethod */
if (ttisfunction(tm)) { /* metamethod is a function */
luaT_callTM(L, tm, t, key, val, 1);
luaT_callTM(L, tm, t, key, val, 1); /* call it */
return;
}
t = tm; /* else repeat access over 'tm' */
if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */
setobj2s(L, val, tm); /* done */
return;
}
/* else repeat */
}
luaG_runerror(L, "gettable chain too long; possible loop");
}
@@ -186,40 +184,41 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
** Main function for table assignment (invoking metamethods if needed).
** Compute 't[key] = val'
*/
void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval) {
int loop; /* counter to avoid infinite loops */
for (loop = 0; loop < MAXTAGLOOP; loop++) {
const TValue *tm;
if (ttistable(t)) { /* 't' is a table? */
Table *h = hvalue(t);
TValue *oldval = cast(TValue *, luaH_get(h, key));
/* if previous value is not nil, there must be a previous entry
in the table; a metamethod has no relevance */
if (!ttisnil(oldval) ||
/* previous value is nil; must check the metamethod */
((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
if (oldval != NULL) {
lua_assert(ttistable(t) && ttisnil(oldval));
/* must check the metamethod */
if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL &&
/* no metamethod; is there a previous entry in the table? */
(oldval != luaO_nilobject ||
/* no previous entry; must create one. (The next test is
always true; we only need the assignment.) */
(oldval = luaH_newkey(L, h, key), 1)))) {
(oldval = luaH_newkey(L, hvalue(t), key), 1))) {
/* no metamethod and (now) there is an entry with given key */
setobj2t(L, oldval, val); /* assign new value to that entry */
invalidateTMcache(h);
luaC_barrierback(L, h, val);
setobj2t(L, cast(TValue *, oldval), val);
invalidateTMcache(hvalue(t));
luaC_barrierback(L, hvalue(t), val);
return;
}
/* else will try the metamethod */
}
else /* not a table; check metamethod */
else { /* not a table; check metamethod */
if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
luaG_typeerror(L, t, "index");
}
/* try the metamethod */
if (ttisfunction(tm)) {
luaT_callTM(L, tm, t, key, val, 0);
return;
}
t = tm; /* else repeat assignment over 'tm' */
if (luaV_fastset(L, t, key, oldval, luaH_get, val))
return; /* done */
/* else loop */
}
luaG_runerror(L, "settable chain too long; possible loop");
}
@@ -443,6 +442,17 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0)
/* copy strings in stack from top - n up to top - 1 to buffer */
static void copy2buff (StkId top, int n, char *buff) {
size_t tl = 0; /* size already copied */
do {
size_t l = vslen(top - n); /* length of string being copied */
memcpy(buff + tl, svalue(top - n), l * sizeof(char));
tl += l;
} while (--n > 0);
}
/*
** Main operation for concatenation: concat 'total' values in the stack,
** from 'L->top - total' up to 'L->top - 1'.
@@ -462,24 +472,24 @@ void luaV_concat (lua_State *L, int total) {
else {
/* at least two non-empty string values; get as many as possible */
size_t tl = vslen(top - 1);
char *buffer;
int i;
/* collect total length */
for (i = 1; i < total && tostring(L, top-i-1); i++) {
size_t l = vslen(top - i - 1);
TString *ts;
/* collect total length and number of strings */
for (n = 1; n < total && tostring(L, top - n - 1); n++) {
size_t l = vslen(top - n - 1);
if (l >= (MAX_SIZE/sizeof(char)) - tl)
luaG_runerror(L, "string length overflow");
tl += l;
}
buffer = luaZ_openspace(L, &G(L)->buff, tl);
tl = 0;
n = i;
do { /* copy all strings to buffer */
size_t l = vslen(top - i);
memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
tl += l;
} while (--i > 0);
setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */
if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */
char buff[LUAI_MAXSHORTLEN];
copy2buff(top, n, buff); /* copy strings to buffer */
ts = luaS_newlstr(L, buff, tl);
}
else { /* long string; copy strings directly to final result */
ts = luaS_createlngstrobj(L, tl);
copy2buff(top, n, getstr(ts));
}
setsvalue2s(L, top - n, ts); /* create result */
}
total -= n-1; /* got 'n' strings to create 1 new */
L->top -= n-1; /* popped 'n' strings and pushed one */
@@ -700,27 +710,20 @@ void luaV_finishOp (lua_State *L) {
** some macros for common tasks in 'luaV_execute'
*/
#if !defined(luai_runtimecheck)
#define luai_runtimecheck(L, c) /* void */
#endif
#define RA(i) (base+GETARG_A(i))
/* to be used after possible stack reallocation */
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
#define KBx(i) \
(k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
/* execute a jump instruction */
#define dojump(ci,i,e) \
{ int a = GETARG_A(i); \
if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
ci->u.l.savedpc += GETARG_sBx(i) + e; }
/* for test instructions, execute the jump instruction that follows it */
@@ -730,34 +733,49 @@ void luaV_finishOp (lua_State *L) {
#define Protect(x) { {x;}; base = ci->u.l.base; }
#define checkGC(L,c) \
Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \
luaC_step(L); \
L->top = ci->top;}) /* restore top */ \
luai_threadyield(L); )
{ luaC_condGC(L, L->top = (c), /* limit of live values */ \
Protect(L->top = ci->top)); /* restore top */ \
luai_threadyield(L); }
#define vmdispatch(o) switch(o)
#define vmcase(l) case l:
#define vmbreak break
/*
** copy of 'luaV_gettable', but protecting call to potential metamethod
** (which can reallocate the stack)
*/
#define gettableProtected(L,t,k,v) { const TValue *aux; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
else Protect(luaV_finishget(L,t,k,v,aux)); }
/* same for 'luaV_settable' */
#define settableProtected(L,t,k,v) { const TValue *slot; \
if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
Protect(luaV_finishset(L,t,k,v,slot)); }
void luaV_execute (lua_State *L) {
CallInfo *ci = L->ci;
LClosure *cl;
TValue *k;
StkId base;
ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */
newframe: /* reentry point when frame changes (call/return) */
lua_assert(ci == L->ci);
cl = clLvalue(ci->func);
k = cl->p->k;
base = ci->u.l.base;
cl = clLvalue(ci->func); /* local reference to function's closure */
k = cl->p->k; /* local reference to function's constant table */
base = ci->u.l.base; /* local copy of function's base */
/* main loop of interpreter */
for (;;) {
Instruction i = *(ci->u.l.savedpc++);
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))
Protect(luaG_traceexec(L));
}
/* WARNING: several calls may realloc the stack and invalidate 'ra' */
ra = RA(i);
lua_assert(base == ci->u.l.base);
@@ -797,17 +815,22 @@ void luaV_execute (lua_State *L) {
vmbreak;
}
vmcase(OP_GETTABUP) {
int b = GETARG_B(i);
Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
TValue *upval = cl->upvals[GETARG_B(i)]->v;
TValue *rc = RKC(i);
gettableProtected(L, upval, rc, ra);
vmbreak;
}
vmcase(OP_GETTABLE) {
Protect(luaV_gettable(L, RB(i), RKC(i), ra));
StkId rb = RB(i);
TValue *rc = RKC(i);
gettableProtected(L, rb, rc, ra);
vmbreak;
}
vmcase(OP_SETTABUP) {
int a = GETARG_A(i);
Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
TValue *upval = cl->upvals[GETARG_A(i)]->v;
TValue *rb = RKB(i);
TValue *rc = RKC(i);
settableProtected(L, upval, rb, rc);
vmbreak;
}
vmcase(OP_SETUPVAL) {
@@ -817,7 +840,9 @@ void luaV_execute (lua_State *L) {
vmbreak;
}
vmcase(OP_SETTABLE) {
Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
TValue *rb = RKB(i);
TValue *rc = RKC(i);
settableProtected(L, ra, rb, rc);
vmbreak;
}
vmcase(OP_NEWTABLE) {
@@ -831,9 +856,15 @@ void luaV_execute (lua_State *L) {
vmbreak;
}
vmcase(OP_SELF) {
const TValue *aux;
StkId rb = RB(i);
setobjs2s(L, ra+1, rb);
Protect(luaV_gettable(L, rb, RKC(i), ra));
TValue *rc = RKC(i);
TString *key = tsvalue(rc); /* key must be a string */
setobjs2s(L, ra + 1, rb);
if (luaV_fastget(L, rb, key, aux, luaH_getstr)) {
setobj2s(L, ra, aux);
}
else Protect(luaV_finishget(L, rb, rc, ra, aux));
vmbreak;
}
vmcase(OP_ADD) {
@@ -1020,7 +1051,7 @@ void luaV_execute (lua_State *L) {
StkId rb;
L->top = base + c + 1; /* mark the end of concat operands */
Protect(luaV_concat(L, c - b + 1));
ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */
ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */
rb = base + b;
setobjs2s(L, ra, rb);
checkGC(L, (ra >= rb ? ra + 1 : rb));
@@ -1035,7 +1066,7 @@ void luaV_execute (lua_State *L) {
TValue *rb = RKB(i);
TValue *rc = RKC(i);
Protect(
if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
if (luaV_equalobj(L, rb, rc) != GETARG_A(i))
ci->u.l.savedpc++;
else
donextjump(ci);
@@ -1082,12 +1113,12 @@ void luaV_execute (lua_State *L) {
int nresults = GETARG_C(i) - 1;
if (b != 0) L->top = ra+b; /* else previous instruction set top */
if (luaD_precall(L, ra, nresults)) { /* C function? */
if (nresults >= 0) L->top = ci->top; /* adjust results */
base = ci->u.l.base;
if (nresults >= 0)
L->top = ci->top; /* adjust results */
Protect((void)0); /* update 'base' */
}
else { /* Lua function */
ci = L->ci;
ci->callstatus |= CIST_REENTRY;
goto newframe; /* restart luaV_execute over new Lua function */
}
vmbreak;
@@ -1096,8 +1127,9 @@ void luaV_execute (lua_State *L) {
int b = GETARG_B(i);
if (b != 0) L->top = ra+b; /* else previous instruction set top */
lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */
base = ci->u.l.base;
if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */
Protect((void)0); /* update 'base' */
}
else {
/* tail call: put called frame (n) in place of caller one (o) */
CallInfo *nci = L->ci; /* called frame */
@@ -1125,8 +1157,8 @@ void luaV_execute (lua_State *L) {
vmcase(OP_RETURN) {
int b = GETARG_B(i);
if (cl->p->sizep > 0) luaF_close(L, base);
b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
return; /* external invocation: return */
else { /* invocation via reentry: continue execution */
ci = L->ci;
@@ -1139,7 +1171,7 @@ void luaV_execute (lua_State *L) {
vmcase(OP_FORLOOP) {
if (ttisinteger(ra)) { /* integer loop? */
lua_Integer step = ivalue(ra + 2);
lua_Integer idx = ivalue(ra) + step; /* increment index */
lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */
lua_Integer limit = ivalue(ra + 1);
if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
@@ -1171,7 +1203,7 @@ void luaV_execute (lua_State *L) {
/* all values are integer */
lua_Integer initv = (stopnow ? 0 : ivalue(init));
setivalue(plimit, ilimit);
setivalue(init, initv - ivalue(pstep));
setivalue(init, intop(-, initv, ivalue(pstep)));
}
else { /* try making all values floats */
lua_Number ninit; lua_Number nlimit; lua_Number nstep;
@@ -1194,7 +1226,7 @@ void luaV_execute (lua_State *L) {
setobjs2s(L, cb+1, ra+1);
setobjs2s(L, cb, ra);
L->top = cb + 3; /* func. + 2 args (state and index) */
Protect(luaD_call(L, cb, GETARG_C(i), 1));
Protect(luaD_call(L, cb, GETARG_C(i)));
L->top = ci->top;
i = *(ci->u.l.savedpc++); /* go to next instruction */
ra = RA(i);
@@ -1219,11 +1251,10 @@ void luaV_execute (lua_State *L) {
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
c = GETARG_Ax(*ci->u.l.savedpc++);
}
luai_runtimecheck(L, ttistable(ra));
h = hvalue(ra);
last = ((c-1)*LFIELDS_PER_FLUSH) + n;
if (last > h->sizearray) /* needs more space? */
luaH_resizearray(L, h, last); /* pre-allocate it at once */
luaH_resizearray(L, h, last); /* preallocate it at once */
for (; n > 0; n--) {
TValue *val = ra+n;
luaH_setint(L, h, last--, val);
@@ -1243,23 +1274,21 @@ void luaV_execute (lua_State *L) {
vmbreak;
}
vmcase(OP_VARARG) {
int b = GETARG_B(i) - 1;
int b = GETARG_B(i) - 1; /* required results */
int j;
int n = cast_int(base - ci->func) - cl->p->numparams - 1;
if (n < 0) /* less arguments than parameters? */
n = 0; /* no vararg arguments */
if (b < 0) { /* B == 0? */
b = n; /* get all var. arguments */
Protect(luaD_checkstack(L, n));
ra = RA(i); /* previous call may change the stack */
L->top = ra + n;
}
for (j = 0; j < b; j++) {
if (j < n) {
setobjs2s(L, ra + j, base - n + j);
}
else {
setnilvalue(ra + j);
}
}
for (j = 0; j < b && j < n; j++)
setobjs2s(L, ra + j, base - n + j);
for (; j < b; j++) /* complete required results with nil */
setnilvalue(ra + j);
vmbreak;
}
vmcase(OP_EXTRAARG) {

56
lvm.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lvm.h,v 2.34 2014/08/01 17:24:02 roberto Exp roberto $
** $Id: lvm.h,v 2.38 2015/08/03 20:40:26 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -48,15 +48,61 @@
#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)
/*
** fast track for 'gettable': 1 means 'aux' points to resulted value;
** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is
** the raw get function to use.
*/
#define luaV_fastget(L,t,k,aux,f) \
(!ttistable(t) \
? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \
: (aux = f(hvalue(t), k), /* else, do raw access */ \
!ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \
: (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\
aux != NULL ? 0 /* has metamethod? must call it */ \
: (aux = luaO_nilobject, 1)))) /* else, final result is nil */
/*
** standard implementation for 'gettable'
*/
#define luaV_gettable(L,t,k,v) { const TValue *aux; \
if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \
else luaV_finishget(L,t,k,v,aux); }
/*
** Fast track for set table. If 't' is a table and 't[k]' is not nil,
** call GC barrier, do a raw 't[k]=v', and return true; otherwise,
** return false with 'slot' equal to NULL (if 't' is not a table) or
** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro
** returns true, there is no need to 'invalidateTMcache', because the
** call is not creating a new entry.
*/
#define luaV_fastset(L,t,k,slot,f,v) \
(!ttistable(t) \
? (slot = NULL, 0) \
: (slot = f(hvalue(t), k), \
ttisnil(slot) ? 0 \
: (luaC_barrierback(L, hvalue(t), v), \
setobj2t(L, cast(TValue *,slot), v), \
1)))
#define luaV_settable(L,t,k,v) { const TValue *slot; \
if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \
luaV_finishset(L,t,k,v,slot); }
LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
StkId val);
LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
StkId val);
LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *tm);
LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
StkId val, const TValue *oldval);
LUAI_FUNC void luaV_finishOp (lua_State *L);
LUAI_FUNC void luaV_execute (lua_State *L);
LUAI_FUNC void luaV_concat (lua_State *L, int total);

12
lzio.c
View File

@@ -1,5 +1,5 @@
/*
** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp roberto $
** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp roberto $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -66,13 +66,3 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
return 0;
}
/* ------------------------------------------------------------------------ */
char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {
if (n > buff->buffsize) {
if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;
luaZ_resizebuffer(L, buff, n);
}
return buff->buffer;
}

3
lzio.h
View File

@@ -1,5 +1,5 @@
/*
** $Id: lzio.h,v 1.29 2014/12/19 13:45:40 roberto Exp roberto $
** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp roberto $
** Buffered streams
** See Copyright Notice in lua.h
*/
@@ -44,7 +44,6 @@ typedef struct Mbuffer {
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
void *data);
LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */

View File

@@ -8,15 +8,14 @@
CWARNSCPP= \
-pedantic \
-Wextra \
-Waggregate-return \
-Wshadow \
-Wsign-compare \
-Wundef \
-Wwrite-strings \
-Wredundant-decls \
-Wdisabled-optimization \
-Wstrict-aliasing \
# the next warnings generate to much noise, so they are disabled
# -Wdouble-promotion \
# -Wconversion -Wno-sign-conversion \
# -Wsign-conversion \
# -Wconversion \
@@ -32,15 +31,17 @@ CWARNSC= -Wdeclaration-after-statement \
-Wstrict-prototypes \
-Wc++-compat \
-Wold-style-definition \
-Wold-style-declaration \
CWARNS= $(CWARNSCPP) $(CWARNSC)
# -DEXTERNMEMCHECK -DHARDSTACKTESTS -DHARDMEMTESTS -DTRACEMEM='"tempmem"'
# -g -DLUA_USER_H='"ltests.h"'
# -fomit-frame-pointer #-pg -malign-double
# -pg -malign-double
# -DLUA_USE_CTYPE -DLUA_USE_APICHECK
# (in clang, '-ftrapv' for runtime checks of integer overflows)
# -fsanitize=undefined -ftrapv
# TESTS= -DLUA_USER_H='"ltests.h"'
# -mtune=native -fomit-frame-pointer
@@ -54,10 +55,8 @@ MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS= -ldl -lreadline -lhistory -lncurses
CC= gcc
CC= clang-3.6
CFLAGS= -Wall -O2 $(MYCFLAGS)
# CC= ~lhf/sunstudio12/bin/cc
# CFLAGS= -xO5 -v -Xc -native -xstrconst
AR= ar rcu
RANLIB= ranlib
RM= rm -f
@@ -148,16 +147,16 @@ ldump.o: ldump.c lprefix.h lua.h luaconf.h lobject.h llimits.h lstate.h \
ltm.h lzio.h lmem.h lundump.h
lfunc.o: lfunc.c lprefix.h lua.h luaconf.h lfunc.h lobject.h llimits.h \
lgc.h lstate.h ltm.h lzio.h lmem.h
lgc.o: lgc.c lprefix.h lua.h luaconf.h ldebug.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.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 llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldo.h lgc.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 \
@@ -170,25 +169,25 @@ lparser.o: lparser.c lprefix.h lua.h luaconf.h lcode.h llex.h lobject.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 llimits.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.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 llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.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 lstring.h lgc.h ltable.h \
lualib.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
ltm.o: ltm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h
lua.o: lua.c lprefix.h lua.h luaconf.h lauxlib.h lualib.h
lundump.o: lundump.c lprefix.h lua.h luaconf.h ldebug.h llimits.h \
lstate.h lobject.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.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 llimits.h lstate.h \
lobject.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
lvm.o: lvm.c lprefix.h lua.h luaconf.h ldebug.h lstate.h lobject.h \
llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h \
ltable.h lvm.h
lzio.o: lzio.c lprefix.h lua.h luaconf.h llimits.h lmem.h lstate.h \
lobject.h ltm.h lzio.h