mirror of
https://gitlab.com/Syping/luaengineapp.git
synced 2024-12-22 11:55:29 +01:00
Lua 5.4.2 runtime
This commit is contained in:
parent
ddc4ab91c4
commit
406905b359
33 changed files with 424 additions and 435 deletions
|
@ -4,7 +4,7 @@
|
||||||
!define COMP_NAME "Syping"
|
!define COMP_NAME "Syping"
|
||||||
!define WEB_SITE "https://luaengine.syping.de/"
|
!define WEB_SITE "https://luaengine.syping.de/"
|
||||||
!define VERSION "0.1.0.0"
|
!define VERSION "0.1.0.0"
|
||||||
!define COPYRIGHT "Copyright © 2018-2020 Syping"
|
!define COPYRIGHT "Copyright © 2018-2021 Syping"
|
||||||
!define DESCRIPTION "LuaEngine Runtime and Compiler"
|
!define DESCRIPTION "LuaEngine Runtime and Compiler"
|
||||||
!define INSTALLER_NAME "luaengine_setup.exe"
|
!define INSTALLER_NAME "luaengine_setup.exe"
|
||||||
!define MAIN_APP_RUNTIME "luaengine.exe"
|
!define MAIN_APP_RUNTIME "luaengine.exe"
|
||||||
|
|
|
@ -55,6 +55,6 @@ win32 {
|
||||||
RC_ICONS = ../../res/lua.ico
|
RC_ICONS = ../../res/lua.ico
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine Runtime"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine Runtime"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "luaengine"
|
QMAKE_TARGET_PRODUCT = "luaengine"
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,6 @@ win32 {
|
||||||
RC_ICONS = ../../res/lua.ico
|
RC_ICONS = ../../res/lua.ico
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine Compiler"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine Compiler"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "luaenginec"
|
QMAKE_TARGET_PRODUCT = "luaenginec"
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,6 @@ win32 {
|
||||||
RC_ICONS = ../../res/lua.ico
|
RC_ICONS = ../../res/lua.ico
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine CLI Runtime"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine CLI Runtime"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "luaenginecli"
|
QMAKE_TARGET_PRODUCT = "luaenginecli"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
|
||||||
|
|
||||||
|
|
||||||
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
|
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
|
||||||
|
static const UpVal *const nullup = NULL;
|
||||||
LClosure *f;
|
LClosure *f;
|
||||||
TValue *fi = index2value(L, fidx);
|
TValue *fi = index2value(L, fidx);
|
||||||
api_check(L, ttisLclosure(fi), "Lua function expected");
|
api_check(L, ttisLclosure(fi), "Lua function expected");
|
||||||
f = clLvalue(fi);
|
f = clLvalue(fi);
|
||||||
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
|
|
||||||
if (pf) *pf = f;
|
if (pf) *pf = f;
|
||||||
return &f->upvals[n - 1]; /* get its upvalue pointer */
|
if (1 <= n && n <= f->p->sizeupvalues)
|
||||||
|
return &f->upvals[n - 1]; /* get its upvalue pointer */
|
||||||
|
else
|
||||||
|
return (UpVal**)&nullup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1401,11 +1404,14 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
|
||||||
}
|
}
|
||||||
case LUA_VCCL: { /* C closure */
|
case LUA_VCCL: { /* C closure */
|
||||||
CClosure *f = clCvalue(fi);
|
CClosure *f = clCvalue(fi);
|
||||||
api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
|
if (1 <= n && n <= f->nupvalues)
|
||||||
return &f->upvalue[n - 1];
|
return &f->upvalue[n - 1];
|
||||||
}
|
/* else */
|
||||||
|
} /* FALLTHROUGH */
|
||||||
|
case LUA_VLCF:
|
||||||
|
return NULL; /* light C functions have no upvalues */
|
||||||
default: {
|
default: {
|
||||||
api_check(L, 0, "closure expected");
|
api_check(L, 0, "function expected");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1417,6 +1423,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
|
||||||
LClosure *f1;
|
LClosure *f1;
|
||||||
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
|
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
|
||||||
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
|
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
|
||||||
|
api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index");
|
||||||
*up1 = *up2;
|
*up1 = *up2;
|
||||||
luaC_objbarrier(L, f1, *up1);
|
luaC_objbarrier(L, f1, *up1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
|
||||||
|
|
||||||
|
|
||||||
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
|
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
|
||||||
const char *what = "exit"; /* type of termination */
|
|
||||||
if (stat != 0 && errno != 0) /* error with an 'errno'? */
|
if (stat != 0 && errno != 0) /* error with an 'errno'? */
|
||||||
return luaL_fileresult(L, 0, NULL);
|
return luaL_fileresult(L, 0, NULL);
|
||||||
else {
|
else {
|
||||||
|
const char *what = "exit"; /* type of termination */
|
||||||
l_inspectstat(stat, what); /* interpret result */
|
l_inspectstat(stat, what); /* interpret result */
|
||||||
if (*what == 'e' && stat == 0) /* successful termination? */
|
if (*what == 'e' && stat == 0) /* successful termination? */
|
||||||
lua_pushboolean(L, 1);
|
lua_pushboolean(L, 1);
|
||||||
|
@ -1006,43 +1006,67 @@ static int panic (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Emit a warning. '*warnstate' means:
|
** Warning functions:
|
||||||
** 0 - warning system is off;
|
** warnfoff: warning system is off
|
||||||
** 1 - ready to start a new message;
|
** warnfon: ready to start a new message
|
||||||
** 2 - previous message is to be continued.
|
** warnfcont: previous message is to be continued
|
||||||
*/
|
*/
|
||||||
static void warnf (void *ud, const char *message, int tocont) {
|
static void warnfoff (void *ud, const char *message, int tocont);
|
||||||
int *warnstate = (int *)ud;
|
static void warnfon (void *ud, const char *message, int tocont);
|
||||||
if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
|
static void warnfcont (void *ud, const char *message, int tocont);
|
||||||
if (strcmp(message, "@off") == 0)
|
|
||||||
*warnstate = 0;
|
|
||||||
else if (strcmp(message, "@on") == 0)
|
/*
|
||||||
*warnstate = 1;
|
** Check whether message is a control message. If so, execute the
|
||||||
return;
|
** control or ignore it if unknown.
|
||||||
|
*/
|
||||||
|
static int checkcontrol (lua_State *L, const char *message, int tocont) {
|
||||||
|
if (tocont || *(message++) != '@') /* not a control message? */
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
if (strcmp(message, "off") == 0)
|
||||||
|
lua_setwarnf(L, warnfoff, L); /* turn warnings off */
|
||||||
|
else if (strcmp(message, "on") == 0)
|
||||||
|
lua_setwarnf(L, warnfon, L); /* turn warnings on */
|
||||||
|
return 1; /* it was a control message */
|
||||||
}
|
}
|
||||||
else if (*warnstate == 0) /* warnings off? */
|
}
|
||||||
return;
|
|
||||||
if (*warnstate == 1) /* previous message was the last? */
|
|
||||||
lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
|
static void warnfoff (void *ud, const char *message, int tocont) {
|
||||||
|
checkcontrol((lua_State *)ud, message, tocont);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Writes the message and handle 'tocont', finishing the message
|
||||||
|
** if needed and setting the next warn function.
|
||||||
|
*/
|
||||||
|
static void warnfcont (void *ud, const char *message, int tocont) {
|
||||||
|
lua_State *L = (lua_State *)ud;
|
||||||
lua_writestringerror("%s", message); /* write message */
|
lua_writestringerror("%s", message); /* write message */
|
||||||
if (tocont) /* not the last part? */
|
if (tocont) /* not the last part? */
|
||||||
*warnstate = 2; /* to be continued */
|
lua_setwarnf(L, warnfcont, L); /* to be continued */
|
||||||
else { /* last part */
|
else { /* last part */
|
||||||
lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
|
lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
|
||||||
*warnstate = 1; /* ready to start a new message */
|
lua_setwarnf(L, warnfon, L); /* next call is a new message */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void warnfon (void *ud, const char *message, int tocont) {
|
||||||
|
if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */
|
||||||
|
return; /* nothing else to be done */
|
||||||
|
lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
|
||||||
|
warnfcont(ud, message, tocont); /* finish processing */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUALIB_API lua_State *luaL_newstate (void) {
|
LUALIB_API lua_State *luaL_newstate (void) {
|
||||||
lua_State *L = lua_newstate(l_alloc, NULL);
|
lua_State *L = lua_newstate(l_alloc, NULL);
|
||||||
if (L) {
|
if (L) {
|
||||||
int *warnstate; /* space for warning state */
|
|
||||||
lua_atpanic(L, &panic);
|
lua_atpanic(L, &panic);
|
||||||
warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0);
|
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
|
||||||
luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
|
|
||||||
*warnstate = 0; /* default is warnings off */
|
|
||||||
lua_setwarnf(L, warnf, warnstate);
|
|
||||||
}
|
}
|
||||||
return L;
|
return L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -753,7 +753,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Ensure that expression 'e' is not a variable (nor a constant).
|
** Ensure that expression 'e' is not a variable (nor a <const>).
|
||||||
** (Expression still may have jump lists.)
|
** (Expression still may have jump lists.)
|
||||||
*/
|
*/
|
||||||
void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||||
|
@ -805,8 +805,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Ensures expression value is in register 'reg' (and therefore
|
** Ensure expression value is in register 'reg', making 'e' a
|
||||||
** 'e' will become a non-relocatable expression).
|
** non-relocatable expression.
|
||||||
** (Expression still may have jump lists.)
|
** (Expression still may have jump lists.)
|
||||||
*/
|
*/
|
||||||
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
||||||
|
@ -860,7 +860,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Ensures expression value is in any register.
|
** Ensure expression value is in a register, making 'e' a
|
||||||
|
** non-relocatable expression.
|
||||||
** (Expression still may have jump lists.)
|
** (Expression still may have jump lists.)
|
||||||
*/
|
*/
|
||||||
static void discharge2anyreg (FuncState *fs, expdesc *e) {
|
static void discharge2anyreg (FuncState *fs, expdesc *e) {
|
||||||
|
@ -946,8 +947,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
|
||||||
exp2reg(fs, e, e->u.info); /* put final result in it */
|
exp2reg(fs, e, e->u.info); /* put final result in it */
|
||||||
return e->u.info;
|
return e->u.info;
|
||||||
}
|
}
|
||||||
|
/* else expression has jumps and cannot change its register
|
||||||
|
to hold the jump values, because it is a local variable.
|
||||||
|
Go through to the default case. */
|
||||||
}
|
}
|
||||||
luaK_exp2nextreg(fs, e); /* otherwise, use next available register */
|
luaK_exp2nextreg(fs, e); /* default: use next available register */
|
||||||
return e->u.info;
|
return e->u.info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) {
|
||||||
** Check whether a given upvalue from a given closure exists and
|
** Check whether a given upvalue from a given closure exists and
|
||||||
** returns its index
|
** returns its index
|
||||||
*/
|
*/
|
||||||
static int checkupval (lua_State *L, int argf, int argnup) {
|
static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) {
|
||||||
|
void *id;
|
||||||
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
|
int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */
|
||||||
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
|
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
|
||||||
luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
|
id = lua_upvalueid(L, argf, nup);
|
||||||
"invalid upvalue index");
|
if (pnup) {
|
||||||
return nup;
|
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
|
||||||
|
*pnup = nup;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int db_upvalueid (lua_State *L) {
|
static int db_upvalueid (lua_State *L) {
|
||||||
int n = checkupval(L, 1, 2);
|
void *id = checkupval(L, 1, 2, NULL);
|
||||||
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
|
if (id != NULL)
|
||||||
|
lua_pushlightuserdata(L, id);
|
||||||
|
else
|
||||||
|
luaL_pushfail(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int db_upvaluejoin (lua_State *L) {
|
static int db_upvaluejoin (lua_State *L) {
|
||||||
int n1 = checkupval(L, 1, 2);
|
int n1, n2;
|
||||||
int n2 = checkupval(L, 3, 4);
|
checkupval(L, 1, 2, &n1);
|
||||||
|
checkupval(L, 3, 4, &n2);
|
||||||
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
|
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
|
||||||
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
|
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
|
||||||
lua_upvaluejoin(L, 1, n1, 3, n2);
|
lua_upvaluejoin(L, 1, n1, 3, n2);
|
||||||
|
@ -440,10 +448,7 @@ static int db_traceback (lua_State *L) {
|
||||||
static int db_setcstacklimit (lua_State *L) {
|
static int db_setcstacklimit (lua_State *L) {
|
||||||
int limit = (int)luaL_checkinteger(L, 1);
|
int limit = (int)luaL_checkinteger(L, 1);
|
||||||
int res = lua_setcstacklimit(L, limit);
|
int res = lua_setcstacklimit(L, limit);
|
||||||
if (res == 0)
|
lua_pushinteger(L, res);
|
||||||
lua_pushboolean(L, 0);
|
|
||||||
else
|
|
||||||
lua_pushinteger(L, res);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,7 @@ l_noret luaD_throw (lua_State *L, int errcode) {
|
||||||
|
|
||||||
|
|
||||||
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||||
global_State *g = G(L);
|
l_uint32 oldnCcalls = L->nCcalls;
|
||||||
l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci);
|
|
||||||
struct lua_longjmp lj;
|
struct lua_longjmp lj;
|
||||||
lj.status = LUA_OK;
|
lj.status = LUA_OK;
|
||||||
lj.previous = L->errorJmp; /* chain new error handler */
|
lj.previous = L->errorJmp; /* chain new error handler */
|
||||||
|
@ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||||
(*f)(L, ud);
|
(*f)(L, ud);
|
||||||
);
|
);
|
||||||
L->errorJmp = lj.previous; /* restore old error handler */
|
L->errorJmp = lj.previous; /* restore old error handler */
|
||||||
L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci;
|
L->nCcalls = oldnCcalls;
|
||||||
return lj.status;
|
return lj.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,21 +182,20 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
|
||||||
|
|
||||||
|
|
||||||
int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
||||||
int lim = L->stacksize;
|
int lim = stacksize(L);
|
||||||
StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue);
|
StkId newstack = luaM_reallocvector(L, L->stack,
|
||||||
|
lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue);
|
||||||
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
||||||
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
|
|
||||||
if (unlikely(newstack == NULL)) { /* reallocation failed? */
|
if (unlikely(newstack == NULL)) { /* reallocation failed? */
|
||||||
if (raiseerror)
|
if (raiseerror)
|
||||||
luaM_error(L);
|
luaM_error(L);
|
||||||
else return 0; /* do not raise an error */
|
else return 0; /* do not raise an error */
|
||||||
}
|
}
|
||||||
for (; lim < newsize; lim++)
|
for (; lim < newsize; lim++)
|
||||||
setnilvalue(s2v(newstack + lim)); /* erase new segment */
|
setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* erase new segment */
|
||||||
correctstack(L, L->stack, newstack);
|
correctstack(L, L->stack, newstack);
|
||||||
L->stack = newstack;
|
L->stack = newstack;
|
||||||
L->stacksize = newsize;
|
L->stack_last = L->stack + newsize;
|
||||||
L->stack_last = L->stack + newsize - EXTRA_STACK;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,51 +205,73 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
||||||
** is true, raises any error; otherwise, return 0 in case of errors.
|
** is true, raises any error; otherwise, return 0 in case of errors.
|
||||||
*/
|
*/
|
||||||
int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
int luaD_growstack (lua_State *L, int n, int raiseerror) {
|
||||||
int size = L->stacksize;
|
int size = stacksize(L);
|
||||||
int newsize = 2 * size; /* tentative new size */
|
if (unlikely(size > LUAI_MAXSTACK)) {
|
||||||
if (unlikely(size > LUAI_MAXSTACK)) { /* need more space after extra size? */
|
/* if stack is larger than maximum, thread is already using the
|
||||||
|
extra space reserved for errors, that is, thread is handling
|
||||||
|
a stack error; cannot grow further than that. */
|
||||||
|
lua_assert(stacksize(L) == ERRORSTACKSIZE);
|
||||||
if (raiseerror)
|
if (raiseerror)
|
||||||
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
|
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
|
||||||
else return 0;
|
return 0; /* if not 'raiseerror', just signal it */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
|
int newsize = 2 * size; /* tentative new size */
|
||||||
|
int needed = cast_int(L->top - L->stack) + n;
|
||||||
if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */
|
if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */
|
||||||
newsize = LUAI_MAXSTACK;
|
newsize = LUAI_MAXSTACK;
|
||||||
if (newsize < needed) /* but must respect what was asked for */
|
if (newsize < needed) /* but must respect what was asked for */
|
||||||
newsize = needed;
|
newsize = needed;
|
||||||
if (unlikely(newsize > LUAI_MAXSTACK)) { /* stack overflow? */
|
if (likely(newsize <= LUAI_MAXSTACK))
|
||||||
|
return luaD_reallocstack(L, newsize, raiseerror);
|
||||||
|
else { /* stack overflow */
|
||||||
/* add extra size to be able to handle the error message */
|
/* add extra size to be able to handle the error message */
|
||||||
luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
|
luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
|
||||||
if (raiseerror)
|
if (raiseerror)
|
||||||
luaG_runerror(L, "stack overflow");
|
luaG_runerror(L, "stack overflow");
|
||||||
else return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} /* else no errors */
|
}
|
||||||
return luaD_reallocstack(L, newsize, raiseerror);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int stackinuse (lua_State *L) {
|
static int stackinuse (lua_State *L) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
|
int res;
|
||||||
StkId lim = L->top;
|
StkId lim = L->top;
|
||||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||||
if (lim < ci->top) lim = ci->top;
|
if (lim < ci->top) lim = ci->top;
|
||||||
}
|
}
|
||||||
lua_assert(lim <= L->stack_last);
|
lua_assert(lim <= L->stack_last);
|
||||||
return cast_int(lim - L->stack) + 1; /* part of stack in use */
|
res = cast_int(lim - L->stack) + 1; /* part of stack in use */
|
||||||
|
if (res < LUA_MINSTACK)
|
||||||
|
res = LUA_MINSTACK; /* ensure a minimum size */
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If stack size is more than 3 times the current use, reduce that size
|
||||||
|
** to twice the current use. (So, the final stack size is at most 2/3 the
|
||||||
|
** previous size, and half of its entries are empty.)
|
||||||
|
** As a particular case, if stack was handling a stack overflow and now
|
||||||
|
** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than
|
||||||
|
** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack
|
||||||
|
** will be reduced to a "regular" size.
|
||||||
|
*/
|
||||||
void luaD_shrinkstack (lua_State *L) {
|
void luaD_shrinkstack (lua_State *L) {
|
||||||
int inuse = stackinuse(L);
|
int inuse = stackinuse(L);
|
||||||
int goodsize = inuse + BASIC_STACK_SIZE;
|
int nsize = inuse * 2; /* proposed new size */
|
||||||
if (goodsize > LUAI_MAXSTACK)
|
int max = inuse * 3; /* maximum "reasonable" size */
|
||||||
goodsize = LUAI_MAXSTACK; /* respect stack limit */
|
if (max > LUAI_MAXSTACK) {
|
||||||
|
max = LUAI_MAXSTACK; /* respect stack limit */
|
||||||
|
if (nsize > LUAI_MAXSTACK)
|
||||||
|
nsize = LUAI_MAXSTACK;
|
||||||
|
}
|
||||||
/* if thread is currently not handling a stack overflow and its
|
/* if thread is currently not handling a stack overflow and its
|
||||||
good size is smaller than current size, shrink its stack */
|
size is larger than maximum "reasonable" size, shrink it */
|
||||||
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize)
|
if (inuse <= LUAI_MAXSTACK && stacksize(L) > max)
|
||||||
luaD_reallocstack(L, goodsize, 0); /* ok if that fails */
|
luaD_reallocstack(L, nsize, 0); /* ok if that fails */
|
||||||
else /* don't change stack */
|
else /* don't change stack */
|
||||||
condmovestack(L,{},{}); /* (change only for debugging) */
|
condmovestack(L,{},{}); /* (change only for debugging) */
|
||||||
luaE_shrinkCI(L); /* shrink CI list */
|
luaE_shrinkCI(L); /* shrink CI list */
|
||||||
|
@ -348,7 +368,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether 'func' has a '__call' metafield. If so, put it in the
|
** Check whether 'func' has a '__call' metafield. If so, put it in the
|
||||||
** stack, below original 'func', so that 'luaD_call' can call it. Raise
|
** stack, below original 'func', so that 'luaD_precall' can call it. Raise
|
||||||
** an error if there is no '__call' metafield.
|
** an error if there is no '__call' metafield.
|
||||||
*/
|
*/
|
||||||
void luaD_tryfuncTM (lua_State *L, StkId func) {
|
void luaD_tryfuncTM (lua_State *L, StkId func) {
|
||||||
|
@ -449,12 +469,14 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Call a function (C or Lua). The function to be called is at *func.
|
** Prepares the call to a function (C or Lua). For C functions, also do
|
||||||
** The arguments are on the stack, right after the function.
|
** the call. The function to be called is at '*func'. The arguments
|
||||||
** When returns, all the results are on the stack, starting at the original
|
** are on the stack, right after the function. Returns the CallInfo
|
||||||
** function position.
|
** to be executed, if it was a Lua function. Otherwise (a C function)
|
||||||
|
** returns NULL, with all the results on the stack, starting at the
|
||||||
|
** original function position.
|
||||||
*/
|
*/
|
||||||
void luaD_call (lua_State *L, StkId func, int nresults) {
|
CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||||
lua_CFunction f;
|
lua_CFunction f;
|
||||||
retry:
|
retry:
|
||||||
switch (ttypetag(s2v(func))) {
|
switch (ttypetag(s2v(func))) {
|
||||||
|
@ -482,7 +504,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, n);
|
api_checknelems(L, n);
|
||||||
luaD_poscall(L, ci, n);
|
luaD_poscall(L, ci, n);
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
case LUA_VLCL: { /* Lua function */
|
case LUA_VLCL: { /* Lua function */
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
|
@ -494,15 +516,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
|
||||||
L->ci = ci = next_ci(L);
|
L->ci = ci = next_ci(L);
|
||||||
ci->nresults = nresults;
|
ci->nresults = nresults;
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
ci->callstatus = 0;
|
|
||||||
ci->top = func + 1 + fsize;
|
ci->top = func + 1 + fsize;
|
||||||
ci->func = func;
|
ci->func = func;
|
||||||
L->ci = ci;
|
L->ci = ci;
|
||||||
for (; narg < nfixparams; narg++)
|
for (; narg < nfixparams; narg++)
|
||||||
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
setnilvalue(s2v(L->top++)); /* complete missing arguments */
|
||||||
lua_assert(ci->top <= L->stack_last);
|
lua_assert(ci->top <= L->stack_last);
|
||||||
luaV_execute(L, ci); /* run the function */
|
return ci;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
default: { /* not a function */
|
default: { /* not a function */
|
||||||
checkstackGCp(L, 1, func); /* space for metamethod */
|
checkstackGCp(L, 1, func); /* space for metamethod */
|
||||||
|
@ -513,17 +533,37 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Call a function (C or Lua) through C. 'inc' can be 1 (increment
|
||||||
|
** number of recursive invocations in the C stack) or nyci (the same
|
||||||
|
** plus increment number of non-yieldable calls).
|
||||||
|
*/
|
||||||
|
static void ccall (lua_State *L, StkId func, int nResults, int inc) {
|
||||||
|
CallInfo *ci;
|
||||||
|
L->nCcalls += inc;
|
||||||
|
if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
|
luaE_checkcstack(L);
|
||||||
|
if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
|
||||||
|
ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
|
||||||
|
luaV_execute(L, ci); /* call it */
|
||||||
|
}
|
||||||
|
L->nCcalls -= inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** External interface for 'ccall'
|
||||||
|
*/
|
||||||
|
void luaD_call (lua_State *L, StkId func, int nResults) {
|
||||||
|
ccall(L, func, nResults, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Similar to 'luaD_call', but does not allow yields during the call.
|
** Similar to 'luaD_call', but does not allow yields during the call.
|
||||||
*/
|
*/
|
||||||
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
|
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
|
||||||
incXCcalls(L);
|
ccall(L, func, nResults, nyci);
|
||||||
if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */
|
|
||||||
luaE_exitCcall(L); /* to compensate decrement in next call */
|
|
||||||
luaE_enterCcall(L); /* check properly */
|
|
||||||
}
|
|
||||||
luaD_call(L, func, nResults);
|
|
||||||
decXCcalls(L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -601,12 +641,12 @@ static int recover (lua_State *L, int status) {
|
||||||
if (ci == NULL) return 0; /* no recovery point */
|
if (ci == NULL) return 0; /* no recovery point */
|
||||||
/* "finish" luaD_pcall */
|
/* "finish" luaD_pcall */
|
||||||
oldtop = restorestack(L, ci->u2.funcidx);
|
oldtop = restorestack(L, ci->u2.funcidx);
|
||||||
luaF_close(L, oldtop, status); /* may change the stack */
|
|
||||||
oldtop = restorestack(L, ci->u2.funcidx);
|
|
||||||
luaD_seterrorobj(L, status, oldtop);
|
|
||||||
L->ci = ci;
|
L->ci = ci;
|
||||||
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
|
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
|
||||||
luaD_shrinkstack(L);
|
status = luaF_close(L, oldtop, status); /* may change the stack */
|
||||||
|
oldtop = restorestack(L, ci->u2.funcidx);
|
||||||
|
luaD_seterrorobj(L, status, oldtop);
|
||||||
|
luaD_shrinkstack(L); /* restore stack size in case of overflow */
|
||||||
L->errfunc = ci->u.c.old_errfunc;
|
L->errfunc = ci->u.c.old_errfunc;
|
||||||
return 1; /* continue running the coroutine */
|
return 1; /* continue running the coroutine */
|
||||||
}
|
}
|
||||||
|
@ -637,12 +677,12 @@ static void resume (lua_State *L, void *ud) {
|
||||||
int n = *(cast(int*, ud)); /* number of arguments */
|
int n = *(cast(int*, ud)); /* number of arguments */
|
||||||
StkId firstArg = L->top - n; /* first argument */
|
StkId firstArg = L->top - n; /* first argument */
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
if (L->status == LUA_OK) { /* starting a coroutine? */
|
if (L->status == LUA_OK) /* starting a coroutine? */
|
||||||
luaD_call(L, firstArg - 1, LUA_MULTRET);
|
ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */
|
||||||
}
|
|
||||||
else { /* resuming from previous yield */
|
else { /* resuming from previous yield */
|
||||||
lua_assert(L->status == LUA_YIELD);
|
lua_assert(L->status == LUA_YIELD);
|
||||||
L->status = LUA_OK; /* mark that it is running (again) */
|
L->status = LUA_OK; /* mark that it is running (again) */
|
||||||
|
luaE_incCstack(L); /* control the C stack */
|
||||||
if (isLua(ci)) /* yielded inside a hook? */
|
if (isLua(ci)) /* yielded inside a hook? */
|
||||||
luaV_execute(L, ci); /* just continue running Lua code */
|
luaV_execute(L, ci); /* just continue running Lua code */
|
||||||
else { /* 'common' yield */
|
else { /* 'common' yield */
|
||||||
|
@ -670,12 +710,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
|
||||||
}
|
}
|
||||||
else if (L->status != LUA_YIELD) /* ended with errors? */
|
else if (L->status != LUA_YIELD) /* ended with errors? */
|
||||||
return resume_error(L, "cannot resume dead coroutine", nargs);
|
return resume_error(L, "cannot resume dead coroutine", nargs);
|
||||||
if (from == NULL)
|
L->nCcalls = (from) ? getCcalls(from) : 0;
|
||||||
L->nCcalls = CSTACKTHREAD;
|
|
||||||
else /* correct 'nCcalls' for this thread */
|
|
||||||
L->nCcalls = getCcalls(from) - L->nci - CSTACKCF;
|
|
||||||
if (L->nCcalls <= CSTACKERR)
|
|
||||||
return resume_error(L, "C stack overflow", nargs);
|
|
||||||
luai_userstateresume(L, nargs);
|
luai_userstateresume(L, nargs);
|
||||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||||
|
@ -754,7 +789,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
status = luaF_close(L, oldtop, status);
|
status = luaF_close(L, oldtop, status);
|
||||||
oldtop = restorestack(L, old_top); /* previous call may change stack */
|
oldtop = restorestack(L, old_top); /* previous call may change stack */
|
||||||
luaD_seterrorobj(L, status, oldtop);
|
luaD_seterrorobj(L, status, oldtop);
|
||||||
luaD_shrinkstack(L);
|
luaD_shrinkstack(L); /* restore stack size in case of overflow */
|
||||||
}
|
}
|
||||||
L->errfunc = old_errfunc;
|
L->errfunc = old_errfunc;
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -59,6 +59,7 @@ LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
|
||||||
int fTransfer, int nTransfer);
|
int fTransfer, int nTransfer);
|
||||||
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
|
||||||
LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
|
||||||
|
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
|
||||||
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
|
||||||
|
|
|
@ -53,7 +53,7 @@ void luaF_initupvals (lua_State *L, LClosure *cl) {
|
||||||
uv->v = &uv->u.value; /* make it closed */
|
uv->v = &uv->u.value; /* make it closed */
|
||||||
setnilvalue(uv->v);
|
setnilvalue(uv->v);
|
||||||
cl->upvals[i] = uv;
|
cl->upvals[i] = uv;
|
||||||
luaC_objbarrier(L, cl, o);
|
luaC_objbarrier(L, cl, uv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,18 +161,17 @@ static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Clear keys for empty entries in tables. If entry is empty
|
** Clear keys for empty entries in tables. If entry is empty, mark its
|
||||||
** and its key is not marked, mark its entry as dead. This allows the
|
** entry as dead. This allows the collection of the key, but keeps its
|
||||||
** collection of the key, but keeps its entry in the table (its removal
|
** entry in the table: its removal could break a chain and could break
|
||||||
** could break a chain). The main feature of a dead key is that it must
|
** a table traversal. Other places never manipulate dead keys, because
|
||||||
** be different from any other value, to do not disturb searches.
|
** its associated empty value is enough to signal that the entry is
|
||||||
** Other places never manipulate dead keys, because its associated empty
|
** logically empty.
|
||||||
** value is enough to signal that the entry is logically empty.
|
|
||||||
*/
|
*/
|
||||||
static void clearkey (Node *n) {
|
static void clearkey (Node *n) {
|
||||||
lua_assert(isempty(gval(n)));
|
lua_assert(isempty(gval(n)));
|
||||||
if (keyiswhite(n))
|
if (keyiscollectable(n))
|
||||||
setdeadkey(n); /* unused and unmarked key; remove it */
|
setdeadkey(n); /* unused key; remove it */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -301,7 +300,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
||||||
if (upisopen(uv))
|
if (upisopen(uv))
|
||||||
set2gray(uv); /* open upvalues are kept gray */
|
set2gray(uv); /* open upvalues are kept gray */
|
||||||
else
|
else
|
||||||
set2black(o); /* closed upvalues are visited here */
|
set2black(uv); /* closed upvalues are visited here */
|
||||||
markvalue(g, uv->v); /* mark its content */
|
markvalue(g, uv->v); /* mark its content */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +308,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
||||||
Udata *u = gco2u(o);
|
Udata *u = gco2u(o);
|
||||||
if (u->nuvalue == 0) { /* no user values? */
|
if (u->nuvalue == 0) { /* no user values? */
|
||||||
markobjectN(g, u->metatable); /* mark its metatable */
|
markobjectN(g, u->metatable); /* mark its metatable */
|
||||||
set2black(o); /* nothing else to mark */
|
set2black(u); /* nothing else to mark */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else... */
|
/* else... */
|
||||||
|
@ -633,9 +632,8 @@ static int traversethread (global_State *g, lua_State *th) {
|
||||||
for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
|
for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
|
||||||
markobject(g, uv); /* open upvalues cannot be collected */
|
markobject(g, uv); /* open upvalues cannot be collected */
|
||||||
if (g->gcstate == GCSatomic) { /* final traversal? */
|
if (g->gcstate == GCSatomic) { /* final traversal? */
|
||||||
StkId lim = th->stack + th->stacksize; /* real end of stack */
|
for (; o < th->stack_last + EXTRA_STACK; o++)
|
||||||
for (; o < lim; o++) /* clear not-marked stack slice */
|
setnilvalue(s2v(o)); /* clear dead stack slice */
|
||||||
setnilvalue(s2v(o));
|
|
||||||
/* 'remarkupvals' may have removed thread from 'twups' list */
|
/* 'remarkupvals' may have removed thread from 'twups' list */
|
||||||
if (!isintwups(th) && th->openupval != NULL) {
|
if (!isintwups(th) && th->openupval != NULL) {
|
||||||
th->twups = g->twups; /* link it back to the list */
|
th->twups = g->twups; /* link it back to the list */
|
||||||
|
@ -644,7 +642,7 @@ static int traversethread (global_State *g, lua_State *th) {
|
||||||
}
|
}
|
||||||
else if (!g->gcemergency)
|
else if (!g->gcemergency)
|
||||||
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
||||||
return 1 + th->stacksize;
|
return 1 + stacksize(th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -771,12 +769,16 @@ static void freeobj (lua_State *L, GCObject *o) {
|
||||||
case LUA_VUPVAL:
|
case LUA_VUPVAL:
|
||||||
freeupval(L, gco2upv(o));
|
freeupval(L, gco2upv(o));
|
||||||
break;
|
break;
|
||||||
case LUA_VLCL:
|
case LUA_VLCL: {
|
||||||
luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
|
LClosure *cl = gco2lcl(o);
|
||||||
|
luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
|
||||||
break;
|
break;
|
||||||
case LUA_VCCL:
|
}
|
||||||
luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
|
case LUA_VCCL: {
|
||||||
|
CClosure *cl = gco2ccl(o);
|
||||||
|
luaM_freemem(L, cl, sizeCclosure(cl->nupvalues));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case LUA_VTABLE:
|
case LUA_VTABLE:
|
||||||
luaH_free(L, gco2t(o));
|
luaH_free(L, gco2t(o));
|
||||||
break;
|
break;
|
||||||
|
@ -788,13 +790,17 @@ static void freeobj (lua_State *L, GCObject *o) {
|
||||||
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
|
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_VSHRSTR:
|
case LUA_VSHRSTR: {
|
||||||
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
|
TString *ts = gco2ts(o);
|
||||||
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
|
luaS_remove(L, ts); /* remove it from hash table */
|
||||||
|
luaM_freemem(L, ts, sizelstring(ts->shrlen));
|
||||||
break;
|
break;
|
||||||
case LUA_VLNGSTR:
|
}
|
||||||
luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
|
case LUA_VLNGSTR: {
|
||||||
|
TString *ts = gco2ts(o);
|
||||||
|
luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,9 +254,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
|
** read a sequence '[=*[' or ']=*]', leaving the last bracket. If
|
||||||
** If sequence is well formed, return its number of '='s + 2; otherwise,
|
** sequence is well formed, return its number of '='s + 2; otherwise,
|
||||||
** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
|
** return 1 if it is a single bracket (no '='s and no 2nd bracket);
|
||||||
|
** otherwise (an unfinished '[==...') return 0.
|
||||||
*/
|
*/
|
||||||
static size_t skip_sep (LexState *ls) {
|
static size_t skip_sep (LexState *ls) {
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
@ -481,34 +482,34 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
||||||
}
|
}
|
||||||
case '=': {
|
case '=': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, '=')) return TK_EQ;
|
if (check_next1(ls, '=')) return TK_EQ; /* '==' */
|
||||||
else return '=';
|
else return '=';
|
||||||
}
|
}
|
||||||
case '<': {
|
case '<': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, '=')) return TK_LE;
|
if (check_next1(ls, '=')) return TK_LE; /* '<=' */
|
||||||
else if (check_next1(ls, '<')) return TK_SHL;
|
else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */
|
||||||
else return '<';
|
else return '<';
|
||||||
}
|
}
|
||||||
case '>': {
|
case '>': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, '=')) return TK_GE;
|
if (check_next1(ls, '=')) return TK_GE; /* '>=' */
|
||||||
else if (check_next1(ls, '>')) return TK_SHR;
|
else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */
|
||||||
else return '>';
|
else return '>';
|
||||||
}
|
}
|
||||||
case '/': {
|
case '/': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, '/')) return TK_IDIV;
|
if (check_next1(ls, '/')) return TK_IDIV; /* '//' */
|
||||||
else return '/';
|
else return '/';
|
||||||
}
|
}
|
||||||
case '~': {
|
case '~': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, '=')) return TK_NE;
|
if (check_next1(ls, '=')) return TK_NE; /* '~=' */
|
||||||
else return '~';
|
else return '~';
|
||||||
}
|
}
|
||||||
case ':': {
|
case ':': {
|
||||||
next(ls);
|
next(ls);
|
||||||
if (check_next1(ls, ':')) return TK_DBCOLON;
|
if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */
|
||||||
else return ':';
|
else return ':';
|
||||||
}
|
}
|
||||||
case '"': case '\'': { /* short literal strings */
|
case '"': case '\'': { /* short literal strings */
|
||||||
|
@ -547,7 +548,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
||||||
return TK_NAME;
|
return TK_NAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* single-char tokens (+ - / ...) */
|
else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */
|
||||||
int c = ls->current;
|
int c = ls->current;
|
||||||
next(ls);
|
next(ls);
|
||||||
return c;
|
return c;
|
||||||
|
|
|
@ -234,6 +234,17 @@ typedef l_uint32 Instruction;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Maximum depth for nested C calls, syntactical nested non-terminals,
|
||||||
|
** and other features implemented through recursion in C. (Value must
|
||||||
|
** fit in a 16-bit unsigned integer. It must also be compatible with
|
||||||
|
** the size of the C stack.)
|
||||||
|
*/
|
||||||
|
#if !defined(LUAI_MAXCCALLS)
|
||||||
|
#define LUAI_MAXCCALLS 200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** macros that are executed whenever program enters the Lua core
|
** macros that are executed whenever program enters the Lua core
|
||||||
** ('lua_lock') and leaves the core ('lua_unlock')
|
** ('lua_lock') and leaves the core ('lua_unlock')
|
||||||
|
@ -315,7 +326,8 @@ typedef l_uint32 Instruction;
|
||||||
|
|
||||||
/* exponentiation */
|
/* exponentiation */
|
||||||
#if !defined(luai_numpow)
|
#if !defined(luai_numpow)
|
||||||
#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
|
#define luai_numpow(L,a,b) \
|
||||||
|
((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* the others are quite standard operations */
|
/* the others are quite standard operations */
|
||||||
|
@ -344,7 +356,7 @@ typedef l_uint32 Instruction;
|
||||||
#else
|
#else
|
||||||
/* realloc stack keeping its size */
|
/* realloc stack keeping its size */
|
||||||
#define condmovestack(L,pre,pos) \
|
#define condmovestack(L,pre,pos) \
|
||||||
{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_, 0); pos; }
|
{ int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HARDMEMTESTS)
|
#if !defined(HARDMEMTESTS)
|
||||||
|
|
|
@ -258,7 +258,7 @@ static const char *l_str2d (const char *s, lua_Number *result) {
|
||||||
if (endptr == NULL) { /* failed? may be a different locale */
|
if (endptr == NULL) { /* failed? may be a different locale */
|
||||||
char buff[L_MAXLENNUM + 1];
|
char buff[L_MAXLENNUM + 1];
|
||||||
const char *pdot = strchr(s, '.');
|
const char *pdot = strchr(s, '.');
|
||||||
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
|
if (pdot == NULL || strlen(s) > L_MAXLENNUM)
|
||||||
return NULL; /* string too long or no dot; fail */
|
return NULL; /* string too long or no dot; fail */
|
||||||
strcpy(buff, s); /* copy string to buffer */
|
strcpy(buff, s); /* copy string to buffer */
|
||||||
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
|
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
|
||||||
|
|
|
@ -21,10 +21,12 @@
|
||||||
*/
|
*/
|
||||||
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
|
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
|
||||||
#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */
|
#define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */
|
||||||
|
#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** number of all possible types (including LUA_TNONE)
|
** number of all possible types (including LUA_TNONE but excluding DEADKEY)
|
||||||
*/
|
*/
|
||||||
#define LUA_TOTALTYPES (LUA_TPROTO + 2)
|
#define LUA_TOTALTYPES (LUA_TPROTO + 2)
|
||||||
|
|
||||||
|
@ -555,7 +557,7 @@ typedef struct Proto {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {==================================================================
|
** {==================================================================
|
||||||
** Closures
|
** Functions
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -743,13 +745,13 @@ typedef struct Table {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Use a "nil table" to mark dead keys in a table. Those keys serve
|
** Dead keys in tables have the tag DEADKEY but keep their original
|
||||||
** to keep space for removed entries, which may still be part of
|
** gcvalue. This distinguishes them from regular keys but allows them to
|
||||||
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
|
** be found when searched in a special way. ('next' needs that to find
|
||||||
** set, so these values are considered not collectable and are different
|
** keys removed from a table during a traversal.)
|
||||||
** from any valid value.
|
|
||||||
*/
|
*/
|
||||||
#define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL)
|
#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
|
||||||
|
#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,7 @@ OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
|
||||||
OP_UNM,/* A B R[A] := -R[B] */
|
OP_UNM,/* A B R[A] := -R[B] */
|
||||||
OP_BNOT,/* A B R[A] := ~R[B] */
|
OP_BNOT,/* A B R[A] := ~R[B] */
|
||||||
OP_NOT,/* A B R[A] := not R[B] */
|
OP_NOT,/* A B R[A] := not R[B] */
|
||||||
OP_LEN,/* A B R[A] := length of R[B] */
|
OP_LEN,/* A B R[A] := #R[B] (length operator) */
|
||||||
|
|
||||||
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
|
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
|
||||||
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
|
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
|
||||||
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
|
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
|
||||||
|
|
||||||
OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */
|
OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
|
||||||
|
|
||||||
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
||||||
|
|
||||||
|
|
|
@ -489,12 +489,10 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
#define enterlevel(ls) luaE_incCstack(ls->L)
|
||||||
** Macros to limit the maximum recursion depth while parsing
|
|
||||||
*/
|
|
||||||
#define enterlevel(ls) luaE_enterCcall((ls)->L)
|
|
||||||
|
|
||||||
#define leavelevel(ls) luaE_exitCcall((ls)->L)
|
|
||||||
|
#define leavelevel(ls) ((ls)->L->nCcalls--)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -947,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) {
|
||||||
|
|
||||||
|
|
||||||
static void parlist (LexState *ls) {
|
static void parlist (LexState *ls) {
|
||||||
/* parlist -> [ param { ',' param } ] */
|
/* parlist -> [ {NAME ','} (NAME | '...') ] */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Proto *f = fs->f;
|
Proto *f = fs->f;
|
||||||
int nparams = 0;
|
int nparams = 0;
|
||||||
|
@ -955,12 +953,12 @@ static void parlist (LexState *ls) {
|
||||||
if (ls->t.token != ')') { /* is 'parlist' not empty? */
|
if (ls->t.token != ')') { /* is 'parlist' not empty? */
|
||||||
do {
|
do {
|
||||||
switch (ls->t.token) {
|
switch (ls->t.token) {
|
||||||
case TK_NAME: { /* param -> NAME */
|
case TK_NAME: {
|
||||||
new_localvar(ls, str_checkname(ls));
|
new_localvar(ls, str_checkname(ls));
|
||||||
nparams++;
|
nparams++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK_DOTS: { /* param -> '...' */
|
case TK_DOTS: {
|
||||||
luaX_next(ls);
|
luaX_next(ls);
|
||||||
isvararg = 1;
|
isvararg = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1625,59 +1623,21 @@ static void forstat (LexState *ls, int line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Check whether next instruction is a single jump (a 'break', a 'goto'
|
|
||||||
** to a forward label, or a 'goto' to a backward label with no variable
|
|
||||||
** to close). If so, set the name of the 'label' it is jumping to
|
|
||||||
** ("break" for a 'break') or to where it is jumping to ('target') and
|
|
||||||
** return true. If not a single jump, leave input unchanged, to be
|
|
||||||
** handled as a regular statement.
|
|
||||||
*/
|
|
||||||
static int issinglejump (LexState *ls, TString **label, int *target) {
|
|
||||||
if (testnext(ls, TK_BREAK)) { /* a break? */
|
|
||||||
*label = luaS_newliteral(ls->L, "break");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME)
|
|
||||||
return 0; /* not a valid goto */
|
|
||||||
else {
|
|
||||||
TString *lname = ls->lookahead.seminfo.ts; /* label's id */
|
|
||||||
Labeldesc *lb = findlabel(ls, lname);
|
|
||||||
if (lb) { /* a backward jump? */
|
|
||||||
/* does it need to close variables? */
|
|
||||||
if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar))
|
|
||||||
return 0; /* not a single jump; cannot optimize */
|
|
||||||
*target = lb->pc;
|
|
||||||
}
|
|
||||||
else /* jump forward */
|
|
||||||
*label = lname;
|
|
||||||
luaX_next(ls); /* skip goto */
|
|
||||||
luaX_next(ls); /* skip name */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_then_block (LexState *ls, int *escapelist) {
|
static void test_then_block (LexState *ls, int *escapelist) {
|
||||||
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
||||||
BlockCnt bl;
|
BlockCnt bl;
|
||||||
int line;
|
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
TString *jlb = NULL;
|
|
||||||
int target = NO_JUMP;
|
|
||||||
expdesc v;
|
expdesc v;
|
||||||
int jf; /* instruction to skip 'then' code (if condition is false) */
|
int jf; /* instruction to skip 'then' code (if condition is false) */
|
||||||
luaX_next(ls); /* skip IF or ELSEIF */
|
luaX_next(ls); /* skip IF or ELSEIF */
|
||||||
expr(ls, &v); /* read condition */
|
expr(ls, &v); /* read condition */
|
||||||
checknext(ls, TK_THEN);
|
checknext(ls, TK_THEN);
|
||||||
line = ls->linenumber;
|
if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
|
||||||
if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */
|
int line = ls->linenumber;
|
||||||
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
|
luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */
|
||||||
|
luaX_next(ls); /* skip 'break' */
|
||||||
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
|
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
|
||||||
if (jlb != NULL) /* forward jump? */
|
newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
|
||||||
newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
|
|
||||||
else /* backward jump */
|
|
||||||
luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
|
|
||||||
while (testnext(ls, ';')) {} /* skip semicolons */
|
while (testnext(ls, ';')) {} /* skip semicolons */
|
||||||
if (block_follow(ls, 0)) { /* jump is the entire block? */
|
if (block_follow(ls, 0)) { /* jump is the entire block? */
|
||||||
leaveblock(fs);
|
leaveblock(fs);
|
||||||
|
@ -1686,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
|
||||||
else /* must skip over 'then' part if condition is false */
|
else /* must skip over 'then' part if condition is false */
|
||||||
jf = luaK_jump(fs);
|
jf = luaK_jump(fs);
|
||||||
}
|
}
|
||||||
else { /* regular case (not a jump) */
|
else { /* regular case (not a break) */
|
||||||
luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
|
luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
|
||||||
enterblock(fs, &bl, 0);
|
enterblock(fs, &bl, 0);
|
||||||
jf = v.f;
|
jf = v.f;
|
||||||
|
@ -1754,7 +1714,7 @@ static void checktoclose (LexState *ls, int level) {
|
||||||
|
|
||||||
|
|
||||||
static void localstat (LexState *ls) {
|
static void localstat (LexState *ls) {
|
||||||
/* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */
|
/* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int toclose = -1; /* index of to-be-closed variable (if any) */
|
int toclose = -1; /* index of to-be-closed variable (if any) */
|
||||||
Vardesc *var; /* last variable */
|
Vardesc *var; /* last variable */
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/* kinds of variables/expressions */
|
/* kinds of variables/expressions */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VVOID, /* when 'expdesc' describes the last expression a list,
|
VVOID, /* when 'expdesc' describes the last expression of a list,
|
||||||
this kind means an empty list (so, no expression) */
|
this kind means an empty list (so, no expression) */
|
||||||
VNIL, /* constant nil */
|
VNIL, /* constant nil */
|
||||||
VTRUE, /* constant true */
|
VTRUE, /* constant true */
|
||||||
|
@ -38,7 +38,8 @@ typedef enum {
|
||||||
VLOCAL, /* local variable; var.sidx = stack index (local register);
|
VLOCAL, /* local variable; var.sidx = stack index (local register);
|
||||||
var.vidx = relative index in 'actvar.arr' */
|
var.vidx = relative index in 'actvar.arr' */
|
||||||
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
||||||
VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */
|
VCONST, /* compile-time <const> variable;
|
||||||
|
info = absolute index in 'actvar.arr' */
|
||||||
VINDEXED, /* indexed variable;
|
VINDEXED, /* indexed variable;
|
||||||
ind.t = table register;
|
ind.t = table register;
|
||||||
ind.idx = key's R index */
|
ind.idx = key's R index */
|
||||||
|
|
|
@ -76,7 +76,7 @@ static unsigned int luai_makeseed (lua_State *L) {
|
||||||
addbuff(buff, p, &h); /* local variable */
|
addbuff(buff, p, &h); /* local variable */
|
||||||
addbuff(buff, p, &lua_newstate); /* public function */
|
addbuff(buff, p, &lua_newstate); /* public function */
|
||||||
lua_assert(p == sizeof(buff));
|
lua_assert(p == sizeof(buff));
|
||||||
return luaS_hash(buff, p, h, 1);
|
return luaS_hash(buff, p, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -97,66 +97,14 @@ void luaE_setdebt (global_State *g, l_mem debt) {
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
|
LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
|
||||||
global_State *g = G(L);
|
UNUSED(L); UNUSED(limit);
|
||||||
int ccalls;
|
return LUAI_MAXCCALLS; /* warning?? */
|
||||||
luaE_freeCI(L); /* release unused CIs */
|
|
||||||
ccalls = getCcalls(L);
|
|
||||||
if (limit >= 40000)
|
|
||||||
return 0; /* out of bounds */
|
|
||||||
limit += CSTACKERR;
|
|
||||||
if (L != g-> mainthread)
|
|
||||||
return 0; /* only main thread can change the C stack */
|
|
||||||
else if (ccalls <= CSTACKERR)
|
|
||||||
return 0; /* handling overflow */
|
|
||||||
else {
|
|
||||||
int diff = limit - g->Cstacklimit;
|
|
||||||
if (ccalls + diff <= CSTACKERR)
|
|
||||||
return 0; /* new limit would cause an overflow */
|
|
||||||
g->Cstacklimit = limit; /* set new limit */
|
|
||||||
L->nCcalls += diff; /* correct 'nCcalls' */
|
|
||||||
return limit - diff - CSTACKERR; /* success; return previous limit */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Decrement count of "C calls" and check for overflows. In case of
|
|
||||||
** a stack overflow, check appropriate error ("regular" overflow or
|
|
||||||
** overflow while handling stack overflow). If 'nCcalls' is smaller
|
|
||||||
** than CSTACKERR but larger than CSTACKMARK, it means it has just
|
|
||||||
** entered the "overflow zone", so the function raises an overflow
|
|
||||||
** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is
|
|
||||||
** already handling an overflow) but larger than CSTACKERRMARK, does
|
|
||||||
** not report an error (to allow message handling to work). Otherwise,
|
|
||||||
** report a stack overflow while handling a stack overflow (probably
|
|
||||||
** caused by a repeating error in the message handling function).
|
|
||||||
*/
|
|
||||||
|
|
||||||
void luaE_enterCcall (lua_State *L) {
|
|
||||||
int ncalls = getCcalls(L);
|
|
||||||
L->nCcalls--;
|
|
||||||
if (ncalls <= CSTACKERR) { /* possible overflow? */
|
|
||||||
luaE_freeCI(L); /* release unused CIs */
|
|
||||||
ncalls = getCcalls(L); /* update call count */
|
|
||||||
if (ncalls <= CSTACKERR) { /* still overflow? */
|
|
||||||
if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */
|
|
||||||
luaD_throw(L, LUA_ERRERR); /* error while handling stack error */
|
|
||||||
else if (ncalls >= CSTACKMARK) {
|
|
||||||
/* not in error-handling zone; raise the error now */
|
|
||||||
L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */
|
|
||||||
luaG_runerror(L, "C stack overflow");
|
|
||||||
}
|
|
||||||
/* else stack is in the error-handling zone;
|
|
||||||
allow message handler to work */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CallInfo *luaE_extendCI (lua_State *L) {
|
CallInfo *luaE_extendCI (lua_State *L) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
lua_assert(L->ci->next == NULL);
|
lua_assert(L->ci->next == NULL);
|
||||||
luaE_enterCcall(L);
|
|
||||||
ci = luaM_new(L, CallInfo);
|
ci = luaM_new(L, CallInfo);
|
||||||
lua_assert(L->ci->next == NULL);
|
lua_assert(L->ci->next == NULL);
|
||||||
L->ci->next = ci;
|
L->ci->next = ci;
|
||||||
|
@ -175,13 +123,11 @@ void luaE_freeCI (lua_State *L) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
CallInfo *next = ci->next;
|
CallInfo *next = ci->next;
|
||||||
ci->next = NULL;
|
ci->next = NULL;
|
||||||
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
|
|
||||||
while ((ci = next) != NULL) {
|
while ((ci = next) != NULL) {
|
||||||
next = ci->next;
|
next = ci->next;
|
||||||
luaM_free(L, ci);
|
luaM_free(L, ci);
|
||||||
L->nci--;
|
L->nci--;
|
||||||
}
|
}
|
||||||
L->nCcalls -= L->nci; /* adjust result */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,7 +140,6 @@ void luaE_shrinkCI (lua_State *L) {
|
||||||
CallInfo *next;
|
CallInfo *next;
|
||||||
if (ci == NULL)
|
if (ci == NULL)
|
||||||
return; /* no extra elements */
|
return; /* no extra elements */
|
||||||
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
|
|
||||||
while ((next = ci->next) != NULL) { /* two extra elements? */
|
while ((next = ci->next) != NULL) { /* two extra elements? */
|
||||||
CallInfo *next2 = next->next; /* next's next */
|
CallInfo *next2 = next->next; /* next's next */
|
||||||
ci->next = next2; /* remove next from the list */
|
ci->next = next2; /* remove next from the list */
|
||||||
|
@ -207,19 +152,39 @@ void luaE_shrinkCI (lua_State *L) {
|
||||||
ci = next2; /* continue */
|
ci = next2; /* continue */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
L->nCcalls -= L->nci; /* adjust result */
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS.
|
||||||
|
** If equal, raises an overflow error. If value is larger than
|
||||||
|
** LUAI_MAXCCALLS (which means it is handling an overflow) but
|
||||||
|
** not much larger, does not report an error (to allow overflow
|
||||||
|
** handling to work).
|
||||||
|
*/
|
||||||
|
void luaE_checkcstack (lua_State *L) {
|
||||||
|
if (getCcalls(L) == LUAI_MAXCCALLS)
|
||||||
|
luaG_runerror(L, "C stack overflow");
|
||||||
|
else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
|
||||||
|
luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LUAI_FUNC void luaE_incCstack (lua_State *L) {
|
||||||
|
L->nCcalls++;
|
||||||
|
if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
|
||||||
|
luaE_checkcstack(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void stack_init (lua_State *L1, lua_State *L) {
|
static void stack_init (lua_State *L1, lua_State *L) {
|
||||||
int i; CallInfo *ci;
|
int i; CallInfo *ci;
|
||||||
/* initialize stack array */
|
/* initialize stack array */
|
||||||
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue);
|
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
|
||||||
L1->stacksize = BASIC_STACK_SIZE;
|
for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
|
||||||
for (i = 0; i < BASIC_STACK_SIZE; i++)
|
|
||||||
setnilvalue(s2v(L1->stack + i)); /* erase new stack */
|
setnilvalue(s2v(L1->stack + i)); /* erase new stack */
|
||||||
L1->top = L1->stack;
|
L1->top = L1->stack;
|
||||||
L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
|
L1->stack_last = L1->stack + BASIC_STACK_SIZE;
|
||||||
/* initialize first ci */
|
/* initialize first ci */
|
||||||
ci = &L1->base_ci;
|
ci = &L1->base_ci;
|
||||||
ci->next = ci->previous = NULL;
|
ci->next = ci->previous = NULL;
|
||||||
|
@ -240,7 +205,7 @@ static void freestack (lua_State *L) {
|
||||||
L->ci = &L->base_ci; /* free the entire 'ci' list */
|
L->ci = &L->base_ci; /* free the entire 'ci' list */
|
||||||
luaE_freeCI(L);
|
luaE_freeCI(L);
|
||||||
lua_assert(L->nci == 0);
|
lua_assert(L->nci == 0);
|
||||||
luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
|
luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -290,7 +255,6 @@ static void preinit_thread (lua_State *L, global_State *g) {
|
||||||
L->stack = NULL;
|
L->stack = NULL;
|
||||||
L->ci = NULL;
|
L->ci = NULL;
|
||||||
L->nci = 0;
|
L->nci = 0;
|
||||||
L->stacksize = 0;
|
|
||||||
L->twups = L; /* thread has no upvalues */
|
L->twups = L; /* thread has no upvalues */
|
||||||
L->errorJmp = NULL;
|
L->errorJmp = NULL;
|
||||||
L->hook = NULL;
|
L->hook = NULL;
|
||||||
|
@ -335,7 +299,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
|
||||||
setthvalue2s(L, L->top, L1);
|
setthvalue2s(L, L->top, L1);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
preinit_thread(L1, g);
|
preinit_thread(L1, g);
|
||||||
L1->nCcalls = getCcalls(L);
|
L1->nCcalls = 0;
|
||||||
L1->hookmask = L->hookmask;
|
L1->hookmask = L->hookmask;
|
||||||
L1->basehookcount = L->basehookcount;
|
L1->basehookcount = L->basehookcount;
|
||||||
L1->hook = L->hook;
|
L1->hook = L->hook;
|
||||||
|
@ -396,7 +360,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||||
preinit_thread(L, g);
|
preinit_thread(L, g);
|
||||||
g->allgc = obj2gco(L); /* by now, only object is the main thread */
|
g->allgc = obj2gco(L); /* by now, only object is the main thread */
|
||||||
L->next = NULL;
|
L->next = NULL;
|
||||||
g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR;
|
L->nCcalls = 0;
|
||||||
incnny(L); /* main thread is always non yieldable */
|
incnny(L); /* main thread is always non yieldable */
|
||||||
g->frealloc = f;
|
g->frealloc = f;
|
||||||
g->ud = ud;
|
g->ud = ud;
|
||||||
|
|
|
@ -87,49 +87,13 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
|
** About 'nCcalls': This count has two parts: the lower 16 bits counts
|
||||||
** how many "C calls" it still can do in the C stack, to avoid C-stack
|
** the number of recursive invocations in the C stack; the higher
|
||||||
** overflow. This count is very rough approximation; it considers only
|
** 16 bits counts the number of non-yieldable calls in the stack.
|
||||||
** recursive functions inside the interpreter, as non-recursive calls
|
** (They are together so that we can change and save both with one
|
||||||
** can be considered using a fixed (although unknown) amount of stack
|
** instruction.)
|
||||||
** space.
|
|
||||||
**
|
|
||||||
** The count has two parts: the lower part is the count itself; the
|
|
||||||
** higher part counts the number of non-yieldable calls in the stack.
|
|
||||||
** (They are together so that we can change both with one instruction.)
|
|
||||||
**
|
|
||||||
** Because calls to external C functions can use an unknown amount
|
|
||||||
** of space (e.g., functions using an auxiliary buffer), calls
|
|
||||||
** to these functions add more than one to the count (see CSTACKCF).
|
|
||||||
**
|
|
||||||
** The proper count excludes the number of CallInfo structures allocated
|
|
||||||
** by Lua, as a kind of "potential" calls. So, when Lua calls a function
|
|
||||||
** (and "consumes" one CallInfo), it needs neither to decrement nor to
|
|
||||||
** check 'nCcalls', as its use of C stack is already accounted for.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* number of "C stack slots" used by an external C function */
|
|
||||||
#define CSTACKCF 10
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** The C-stack size is sliced in the following zones:
|
|
||||||
** - larger than CSTACKERR: normal stack;
|
|
||||||
** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow;
|
|
||||||
** - [CSTACKCF, CSTACKERRMARK]: error-handling zone;
|
|
||||||
** - below CSTACKERRMARK: buffer zone to signal overflow during overflow;
|
|
||||||
** (Because the counter can be decremented CSTACKCF at once, we need
|
|
||||||
** the so called "buffer zones", with at least that size, to properly
|
|
||||||
** detect a change from one zone to the next.)
|
|
||||||
*/
|
|
||||||
#define CSTACKERR (8 * CSTACKCF)
|
|
||||||
#define CSTACKMARK (CSTACKERR - (CSTACKCF + 2))
|
|
||||||
#define CSTACKERRMARK (CSTACKCF + 2)
|
|
||||||
|
|
||||||
|
|
||||||
/* initial limit for the C-stack of threads */
|
|
||||||
#define CSTACKTHREAD (2 * CSTACKERR)
|
|
||||||
|
|
||||||
|
|
||||||
/* true if this thread does not have non-yieldable calls in the stack */
|
/* true if this thread does not have non-yieldable calls in the stack */
|
||||||
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
|
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
|
||||||
|
@ -144,13 +108,8 @@
|
||||||
/* Decrement the number of non-yieldable calls */
|
/* Decrement the number of non-yieldable calls */
|
||||||
#define decnny(L) ((L)->nCcalls -= 0x10000)
|
#define decnny(L) ((L)->nCcalls -= 0x10000)
|
||||||
|
|
||||||
/* Increment the number of non-yieldable calls and decrement nCcalls */
|
/* Non-yieldable call increment */
|
||||||
#define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF)
|
#define nyci (0x10000 | 1)
|
||||||
|
|
||||||
/* Decrement the number of non-yieldable calls and increment nCcalls */
|
|
||||||
#define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,12 +127,20 @@ struct lua_longjmp; /* defined in ldo.c */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* extra stack space to handle TM calls and some other extras */
|
/*
|
||||||
|
** Extra stack space to handle TM calls and some other extras. This
|
||||||
|
** space is not included in 'stack_last'. It is used only to avoid stack
|
||||||
|
** checks, either because the element will be promptly popped or because
|
||||||
|
** there will be a stack check soon after the push. Function frames
|
||||||
|
** never use this extra space, so it does not need to be kept clean.
|
||||||
|
*/
|
||||||
#define EXTRA_STACK 5
|
#define EXTRA_STACK 5
|
||||||
|
|
||||||
|
|
||||||
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
|
#define BASIC_STACK_SIZE (2*LUA_MINSTACK)
|
||||||
|
|
||||||
|
#define stacksize(th) cast_int((th)->stack_last - (th)->stack)
|
||||||
|
|
||||||
|
|
||||||
/* kinds of Garbage Collection */
|
/* kinds of Garbage Collection */
|
||||||
#define KGC_INC 0 /* incremental gc */
|
#define KGC_INC 0 /* incremental gc */
|
||||||
|
@ -224,14 +191,15 @@ typedef struct CallInfo {
|
||||||
*/
|
*/
|
||||||
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
|
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
|
||||||
#define CIST_C (1<<1) /* call is running a C function */
|
#define CIST_C (1<<1) /* call is running a C function */
|
||||||
#define CIST_HOOKED (1<<2) /* call is running a debug hook */
|
#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
|
||||||
#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */
|
#define CIST_HOOKED (1<<3) /* call is running a debug hook */
|
||||||
#define CIST_TAIL (1<<4) /* call was tail called */
|
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
|
||||||
#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */
|
#define CIST_TAIL (1<<5) /* call was tail called */
|
||||||
#define CIST_FIN (1<<6) /* call is running a finalizer */
|
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
|
||||||
#define CIST_TRAN (1<<7) /* 'ci' has transfer information */
|
#define CIST_FIN (1<<7) /* call is running a finalizer */
|
||||||
|
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
|
||||||
#if defined(LUA_COMPAT_LT_LE)
|
#if defined(LUA_COMPAT_LT_LE)
|
||||||
#define CIST_LEQ (1<<8) /* using __lt for __le */
|
#define CIST_LEQ (1<<9) /* using __lt for __le */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* active function is a Lua function */
|
/* active function is a Lua function */
|
||||||
|
@ -296,7 +264,6 @@ typedef struct global_State {
|
||||||
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
|
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
|
||||||
lua_WarnFunction warnf; /* warning function */
|
lua_WarnFunction warnf; /* warning function */
|
||||||
void *ud_warn; /* auxiliary data to 'warnf' */
|
void *ud_warn; /* auxiliary data to 'warnf' */
|
||||||
unsigned int Cstacklimit; /* current limit for the C stack */
|
|
||||||
} global_State;
|
} global_State;
|
||||||
|
|
||||||
|
|
||||||
|
@ -311,7 +278,7 @@ struct lua_State {
|
||||||
StkId top; /* first free slot in the stack */
|
StkId top; /* first free slot in the stack */
|
||||||
global_State *l_G;
|
global_State *l_G;
|
||||||
CallInfo *ci; /* call info for current function */
|
CallInfo *ci; /* call info for current function */
|
||||||
StkId stack_last; /* last free slot in the stack */
|
StkId stack_last; /* end of stack (last element + 1) */
|
||||||
StkId stack; /* stack base */
|
StkId stack; /* stack base */
|
||||||
UpVal *openupval; /* list of open upvalues in this stack */
|
UpVal *openupval; /* list of open upvalues in this stack */
|
||||||
GCObject *gclist;
|
GCObject *gclist;
|
||||||
|
@ -320,9 +287,8 @@ struct lua_State {
|
||||||
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
|
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
|
||||||
volatile lua_Hook hook;
|
volatile lua_Hook hook;
|
||||||
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
||||||
l_uint32 nCcalls; /* number of allowed nested C calls - 'nci' */
|
l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */
|
||||||
int oldpc; /* last pc traced */
|
int oldpc; /* last pc traced */
|
||||||
int stacksize;
|
|
||||||
int basehookcount;
|
int basehookcount;
|
||||||
int hookcount;
|
int hookcount;
|
||||||
volatile l_signalT hookmask;
|
volatile l_signalT hookmask;
|
||||||
|
@ -389,12 +355,11 @@ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
|
||||||
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
|
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_freeCI (lua_State *L);
|
LUAI_FUNC void luaE_freeCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_enterCcall (lua_State *L);
|
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
||||||
|
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
||||||
LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
|
LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
|
||||||
LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
|
LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
|
||||||
|
|
||||||
|
|
||||||
#define luaE_exitCcall(L) ((L)->nCcalls++)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -22,16 +22,6 @@
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to
|
|
||||||
** compute its hash
|
|
||||||
*/
|
|
||||||
#if !defined(LUAI_HASHLIMIT)
|
|
||||||
#define LUAI_HASHLIMIT 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Maximum size for string table.
|
** Maximum size for string table.
|
||||||
*/
|
*/
|
||||||
|
@ -50,10 +40,9 @@ int luaS_eqlngstr (TString *a, TString *b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed,
|
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
|
||||||
size_t step) {
|
|
||||||
unsigned int h = seed ^ cast_uint(l);
|
unsigned int h = seed ^ cast_uint(l);
|
||||||
for (; l >= step; l -= step)
|
for (; l > 0; l--)
|
||||||
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
|
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -63,8 +52,7 @@ unsigned int luaS_hashlongstr (TString *ts) {
|
||||||
lua_assert(ts->tt == LUA_VLNGSTR);
|
lua_assert(ts->tt == LUA_VLNGSTR);
|
||||||
if (ts->extra == 0) { /* no hash? */
|
if (ts->extra == 0) { /* no hash? */
|
||||||
size_t len = ts->u.lnglen;
|
size_t len = ts->u.lnglen;
|
||||||
size_t step = (len >> LUAI_HASHLIMIT) + 1;
|
ts->hash = luaS_hash(getstr(ts), len, ts->hash);
|
||||||
ts->hash = luaS_hash(getstr(ts), len, ts->hash, step);
|
|
||||||
ts->extra = 1; /* now it has its hash */
|
ts->extra = 1; /* now it has its hash */
|
||||||
}
|
}
|
||||||
return ts->hash;
|
return ts->hash;
|
||||||
|
@ -201,7 +189,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
stringtable *tb = &g->strt;
|
stringtable *tb = &g->strt;
|
||||||
unsigned int h = luaS_hash(str, l, g->seed, 1);
|
unsigned int h = luaS_hash(str, l, g->seed);
|
||||||
TString **list = &tb->hash[lmod(h, tb->size)];
|
TString **list = &tb->hash[lmod(h, tb->size)];
|
||||||
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
|
||||||
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
|
||||||
|
|
|
@ -41,8 +41,7 @@
|
||||||
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
|
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l,
|
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
|
||||||
unsigned int seed, size_t step);
|
|
||||||
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
|
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
|
||||||
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
|
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
|
||||||
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
||||||
|
|
|
@ -1365,7 +1365,6 @@ typedef union Ftypes {
|
||||||
float f;
|
float f;
|
||||||
double d;
|
double d;
|
||||||
lua_Number n;
|
lua_Number n;
|
||||||
char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
|
|
||||||
} Ftypes;
|
} Ftypes;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1535,12 +1534,10 @@ static void packint (luaL_Buffer *b, lua_Unsigned n,
|
||||||
** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
|
** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
|
||||||
** given 'islittle' is different from native endianness.
|
** given 'islittle' is different from native endianness.
|
||||||
*/
|
*/
|
||||||
static void copywithendian (volatile char *dest, volatile const char *src,
|
static void copywithendian (char *dest, const char *src,
|
||||||
int size, int islittle) {
|
int size, int islittle) {
|
||||||
if (islittle == nativeendian.little) {
|
if (islittle == nativeendian.little)
|
||||||
while (size-- != 0)
|
memcpy(dest, src, size);
|
||||||
*(dest++) = *(src++);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
dest += size - 1;
|
dest += size - 1;
|
||||||
while (size-- != 0)
|
while (size-- != 0)
|
||||||
|
@ -1584,14 +1581,14 @@ static int str_pack (lua_State *L) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kfloat: { /* floating-point options */
|
case Kfloat: { /* floating-point options */
|
||||||
volatile Ftypes u;
|
Ftypes u;
|
||||||
char *buff = luaL_prepbuffsize(&b, size);
|
char *buff = luaL_prepbuffsize(&b, size);
|
||||||
lua_Number n = luaL_checknumber(L, arg); /* get argument */
|
lua_Number n = luaL_checknumber(L, arg); /* get argument */
|
||||||
if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
|
if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
|
||||||
else if (size == sizeof(u.d)) u.d = (double)n;
|
else if (size == sizeof(u.d)) u.d = (double)n;
|
||||||
else u.n = n;
|
else u.n = n;
|
||||||
/* move 'u' to final result, correcting endianness if needed */
|
/* move 'u' to final result, correcting endianness if needed */
|
||||||
copywithendian(buff, u.buff, size, h.islittle);
|
copywithendian(buff, (char *)&u, size, h.islittle);
|
||||||
luaL_addsize(&b, size);
|
luaL_addsize(&b, size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1717,9 +1714,9 @@ static int str_unpack (lua_State *L) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kfloat: {
|
case Kfloat: {
|
||||||
volatile Ftypes u;
|
Ftypes u;
|
||||||
lua_Number num;
|
lua_Number num;
|
||||||
copywithendian(u.buff, data + pos, size, h.islittle);
|
copywithendian((char *)&u, data + pos, size, h.islittle);
|
||||||
if (size == sizeof(u.f)) num = (lua_Number)u.f;
|
if (size == sizeof(u.f)) num = (lua_Number)u.f;
|
||||||
else if (size == sizeof(u.d)) num = (lua_Number)u.d;
|
else if (size == sizeof(u.d)) num = (lua_Number)u.d;
|
||||||
else num = u.n;
|
else num = u.n;
|
||||||
|
@ -1738,7 +1735,7 @@ static int str_unpack (lua_State *L) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Kzstr: {
|
case Kzstr: {
|
||||||
size_t len = (int)strlen(data + pos);
|
size_t len = strlen(data + pos);
|
||||||
luaL_argcheck(L, pos + len < ld, 2,
|
luaL_argcheck(L, pos + len < ld, 2,
|
||||||
"unfinished string for format 'z'");
|
"unfinished string for format 'z'");
|
||||||
lua_pushlstring(L, data + pos, len);
|
lua_pushlstring(L, data + pos, len);
|
||||||
|
|
|
@ -166,17 +166,30 @@ static Node *mainpositionTV (const Table *t, const TValue *key) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether key 'k1' is equal to the key in node 'n2'.
|
** Check whether key 'k1' is equal to the key in node 'n2'. This
|
||||||
** This equality is raw, so there are no metamethods. Floats
|
** equality is raw, so there are no metamethods. Floats with integer
|
||||||
** with integer values have been normalized, so integers cannot
|
** values have been normalized, so integers cannot be equal to
|
||||||
** be equal to floats. It is assumed that 'eqshrstr' is simply
|
** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
|
||||||
** pointer equality, so that short strings are handled in the
|
** that short strings are handled in the default case.
|
||||||
** default case.
|
** A true 'deadok' means to accept dead keys as equal to their original
|
||||||
|
** values. All dead keys are compared in the default case, by pointer
|
||||||
|
** identity. (Only collectable objects can produce dead keys.) Note that
|
||||||
|
** dead long strings are also compared by identity.
|
||||||
|
** Once a key is dead, its corresponding value may be collected, and
|
||||||
|
** then another value can be created with the same address. If this
|
||||||
|
** other value is given to 'next', 'equalkey' will signal a false
|
||||||
|
** positive. In a regular traversal, this situation should never happen,
|
||||||
|
** as all keys given to 'next' came from the table itself, and therefore
|
||||||
|
** could not have been collected. Outside a regular traversal, we
|
||||||
|
** have garbage in, garbage out. What is relevant is that this false
|
||||||
|
** positive does not break anything. (In particular, 'next' will return
|
||||||
|
** some other valid item on the table or nil.)
|
||||||
*/
|
*/
|
||||||
static int equalkey (const TValue *k1, const Node *n2) {
|
static int equalkey (const TValue *k1, const Node *n2, int deadok) {
|
||||||
if (rawtt(k1) != keytt(n2)) /* not the same variants? */
|
if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */
|
||||||
|
!(deadok && keyisdead(n2) && iscollectable(k1)))
|
||||||
return 0; /* cannot be same key */
|
return 0; /* cannot be same key */
|
||||||
switch (ttypetag(k1)) {
|
switch (keytt(n2)) {
|
||||||
case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
|
case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
|
||||||
return 1;
|
return 1;
|
||||||
case LUA_VNUMINT:
|
case LUA_VNUMINT:
|
||||||
|
@ -187,7 +200,7 @@ static int equalkey (const TValue *k1, const Node *n2) {
|
||||||
return pvalue(k1) == pvalueraw(keyval(n2));
|
return pvalue(k1) == pvalueraw(keyval(n2));
|
||||||
case LUA_VLCF:
|
case LUA_VLCF:
|
||||||
return fvalue(k1) == fvalueraw(keyval(n2));
|
return fvalue(k1) == fvalueraw(keyval(n2));
|
||||||
case LUA_VLNGSTR:
|
case ctb(LUA_VLNGSTR):
|
||||||
return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
|
return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
|
||||||
default:
|
default:
|
||||||
return gcvalue(k1) == gcvalueraw(keyval(n2));
|
return gcvalue(k1) == gcvalueraw(keyval(n2));
|
||||||
|
@ -251,11 +264,12 @@ static unsigned int setlimittosize (Table *t) {
|
||||||
/*
|
/*
|
||||||
** "Generic" get version. (Not that generic: not valid for integers,
|
** "Generic" get version. (Not that generic: not valid for integers,
|
||||||
** which may be in array part, nor for floats with integral values.)
|
** which may be in array part, nor for floats with integral values.)
|
||||||
|
** See explanation about 'deadok' in function 'equalkey'.
|
||||||
*/
|
*/
|
||||||
static const TValue *getgeneric (Table *t, const TValue *key) {
|
static const TValue *getgeneric (Table *t, const TValue *key, int deadok) {
|
||||||
Node *n = mainpositionTV(t, key);
|
Node *n = mainpositionTV(t, key);
|
||||||
for (;;) { /* check whether 'key' is somewhere in the chain */
|
for (;;) { /* check whether 'key' is somewhere in the chain */
|
||||||
if (equalkey(key, n))
|
if (equalkey(key, n, deadok))
|
||||||
return gval(n); /* that's it */
|
return gval(n); /* that's it */
|
||||||
else {
|
else {
|
||||||
int nx = gnext(n);
|
int nx = gnext(n);
|
||||||
|
@ -292,7 +306,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key,
|
||||||
if (i - 1u < asize) /* is 'key' inside array part? */
|
if (i - 1u < asize) /* is 'key' inside array part? */
|
||||||
return i; /* yes; that's the index */
|
return i; /* yes; that's the index */
|
||||||
else {
|
else {
|
||||||
const TValue *n = getgeneric(t, key);
|
const TValue *n = getgeneric(t, key, 1);
|
||||||
if (unlikely(isabstkey(n)))
|
if (unlikely(isabstkey(n)))
|
||||||
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
|
||||||
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
|
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
|
||||||
|
@ -730,7 +744,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
|
||||||
else { /* for long strings, use generic case */
|
else { /* for long strings, use generic case */
|
||||||
TValue ko;
|
TValue ko;
|
||||||
setsvalue(cast(lua_State *, NULL), &ko, key);
|
setsvalue(cast(lua_State *, NULL), &ko, key);
|
||||||
return getgeneric(t, &ko);
|
return getgeneric(t, &ko, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,7 +764,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
|
||||||
/* else... */
|
/* else... */
|
||||||
} /* FALLTHROUGH */
|
} /* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
return getgeneric(t, key);
|
return getgeneric(t, key, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#define LUA_VERSION_MAJOR "5"
|
#define LUA_VERSION_MAJOR "5"
|
||||||
#define LUA_VERSION_MINOR "4"
|
#define LUA_VERSION_MINOR "4"
|
||||||
#define LUA_VERSION_RELEASE "1"
|
#define LUA_VERSION_RELEASE "2"
|
||||||
|
|
||||||
#define LUA_VERSION_NUM 504
|
#define LUA_VERSION_NUM 504
|
||||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
|
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
|
||||||
|
|
|
@ -36,21 +36,6 @@
|
||||||
** =====================================================================
|
** =====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
@@ LUAI_MAXCSTACK defines the maximum depth for nested calls and
|
|
||||||
** also limits the maximum depth of other recursive algorithms in
|
|
||||||
** the implementation, such as syntactic analysis. A value too
|
|
||||||
** large may allow the interpreter to crash (C-stack overflow).
|
|
||||||
** The default value seems ok for regular machines, but may be
|
|
||||||
** too high for restricted hardware.
|
|
||||||
** The test file 'cstack.lua' may help finding a good limit.
|
|
||||||
** (It will crash with a limit too high.)
|
|
||||||
*/
|
|
||||||
#if !defined(LUAI_MAXCSTACK)
|
|
||||||
#define LUAI_MAXCSTACK 2000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
|
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
|
||||||
** Define it if you want Lua to avoid the use of a few C99 features
|
** Define it if you want Lua to avoid the use of a few C99 features
|
||||||
|
|
|
@ -229,7 +229,7 @@ static int forprep (lua_State *L, StkId ra) {
|
||||||
count /= l_castS2U(-(step + 1)) + 1u;
|
count /= l_castS2U(-(step + 1)) + 1u;
|
||||||
}
|
}
|
||||||
/* store the counter in place of the limit (which won't be
|
/* store the counter in place of the limit (which won't be
|
||||||
needed anymore */
|
needed anymore) */
|
||||||
setivalue(plimit, l_castU2S(count));
|
setivalue(plimit, l_castU2S(count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) {
|
||||||
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Protect code that will finish the loop (returns) or can only raise
|
** Protect code that can only raise errors. (That is, it cannnot change
|
||||||
** errors. (That is, it will not return to the interpreter main loop
|
** the stack or hooks.)
|
||||||
** after changing the stack or hooks.)
|
|
||||||
*/
|
*/
|
||||||
#define halfProtect(exp) (savestate(L,ci), (exp))
|
#define halfProtect(exp) (savestate(L,ci), (exp))
|
||||||
|
|
||||||
/* idem, but without changing the stack */
|
|
||||||
#define halfProtectNT(exp) (savepc(L), (exp))
|
|
||||||
|
|
||||||
/* 'c' is the limit of live values in the stack */
|
/* 'c' is the limit of live values in the stack */
|
||||||
#define checkGC(L,c) \
|
#define checkGC(L,c) \
|
||||||
{ luaC_condGC(L, (savepc(L), L->top = (c)), \
|
{ luaC_condGC(L, (savepc(L), L->top = (c)), \
|
||||||
|
@ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
#if LUA_USE_JUMPTABLE
|
#if LUA_USE_JUMPTABLE
|
||||||
#include "ljumptab.h"
|
#include "ljumptab.h"
|
||||||
#endif
|
#endif
|
||||||
tailcall:
|
startfunc:
|
||||||
trap = L->hookmask;
|
trap = L->hookmask;
|
||||||
|
returning: /* trap already set */
|
||||||
cl = clLvalue(s2v(ci->func));
|
cl = clLvalue(s2v(ci->func));
|
||||||
k = cl->p->k;
|
k = cl->p->k;
|
||||||
pc = ci->u.l.savedpc;
|
pc = ci->u.l.savedpc;
|
||||||
if (trap) {
|
if (trap) {
|
||||||
if (cl->p->is_vararg)
|
if (pc == cl->p->code) { /* first instruction (not resuming)? */
|
||||||
trap = 0; /* hooks will start after VARARGPREP instruction */
|
if (cl->p->is_vararg)
|
||||||
else if (pc == cl->p->code) /* first instruction (not resuming)? */
|
trap = 0; /* hooks will start after VARARGPREP instruction */
|
||||||
luaD_hookcall(L, ci);
|
else /* check 'call' hook */
|
||||||
ci->u.l.trap = 1; /* there may be other hooks */
|
luaD_hookcall(L, ci);
|
||||||
|
}
|
||||||
|
ci->u.l.trap = 1; /* assume trap is on, for now */
|
||||||
}
|
}
|
||||||
base = ci->func + 1;
|
base = ci->func + 1;
|
||||||
/* main loop of interpreter */
|
/* main loop of interpreter */
|
||||||
|
@ -1151,7 +1150,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
StkId ra; /* instruction's A register */
|
StkId ra; /* instruction's A register */
|
||||||
vmfetch();
|
vmfetch();
|
||||||
lua_assert(base == ci->func + 1);
|
lua_assert(base == ci->func + 1);
|
||||||
lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
|
lua_assert(base <= L->top && L->top < L->stack_last);
|
||||||
/* invalidate top for instructions not expecting it */
|
/* invalidate top for instructions not expecting it */
|
||||||
lua_assert(isIT(i) || (cast_void(L->top = base), 1));
|
lua_assert(isIT(i) || (cast_void(L->top = base), 1));
|
||||||
vmdispatch (GET_OPCODE(i)) {
|
vmdispatch (GET_OPCODE(i)) {
|
||||||
|
@ -1606,24 +1605,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_CALL) {
|
vmcase(OP_CALL) {
|
||||||
|
CallInfo *newci;
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
int nresults = GETARG_C(i) - 1;
|
int nresults = GETARG_C(i) - 1;
|
||||||
if (b != 0) /* fixed number of arguments? */
|
if (b != 0) /* fixed number of arguments? */
|
||||||
L->top = ra + b; /* top signals number of arguments */
|
L->top = ra + b; /* top signals number of arguments */
|
||||||
/* else previous instruction set top */
|
/* else previous instruction set top */
|
||||||
ProtectNT(luaD_call(L, ra, nresults));
|
savepc(L); /* in case of errors */
|
||||||
|
if ((newci = luaD_precall(L, ra, nresults)) == NULL)
|
||||||
|
updatetrap(ci); /* C call; nothing else to be done */
|
||||||
|
else { /* Lua call: run function in this same C frame */
|
||||||
|
ci = newci;
|
||||||
|
ci->callstatus = 0; /* call re-uses 'luaV_execute' */
|
||||||
|
goto startfunc;
|
||||||
|
}
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_TAILCALL) {
|
vmcase(OP_TAILCALL) {
|
||||||
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
int b = GETARG_B(i); /* number of arguments + 1 (function) */
|
||||||
int nparams1 = GETARG_C(i);
|
int nparams1 = GETARG_C(i);
|
||||||
/* delat is virtual 'func' - real 'func' (vararg functions) */
|
/* delta is virtual 'func' - real 'func' (vararg functions) */
|
||||||
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0;
|
||||||
if (b != 0)
|
if (b != 0)
|
||||||
L->top = ra + b;
|
L->top = ra + b;
|
||||||
else /* previous instruction set top */
|
else /* previous instruction set top */
|
||||||
b = cast_int(L->top - ra);
|
b = cast_int(L->top - ra);
|
||||||
savepc(ci); /* some calls here can raise errors */
|
savepc(ci); /* several calls here can raise errors */
|
||||||
if (TESTARG_k(i)) {
|
if (TESTARG_k(i)) {
|
||||||
/* close upvalues from current call; the compiler ensures
|
/* close upvalues from current call; the compiler ensures
|
||||||
that there are no to-be-closed variables here, so this
|
that there are no to-be-closed variables here, so this
|
||||||
|
@ -1637,16 +1644,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
checkstackGCp(L, 1, ra);
|
checkstackGCp(L, 1, ra);
|
||||||
}
|
}
|
||||||
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
if (!ttisLclosure(s2v(ra))) { /* C function? */
|
||||||
luaD_call(L, ra, LUA_MULTRET); /* call it */
|
luaD_precall(L, ra, LUA_MULTRET); /* call it */
|
||||||
updatetrap(ci);
|
updatetrap(ci);
|
||||||
updatestack(ci); /* stack may have been relocated */
|
updatestack(ci); /* stack may have been relocated */
|
||||||
ci->func -= delta;
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
luaD_poscall(L, ci, cast_int(L->top - ra));
|
luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
|
||||||
return;
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret; /* caller returns after the tail call */
|
||||||
}
|
}
|
||||||
ci->func -= delta;
|
ci->func -= delta; /* restore 'func' (if vararg) */
|
||||||
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
|
||||||
goto tailcall;
|
goto startfunc; /* execute the callee */
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN) {
|
vmcase(OP_RETURN) {
|
||||||
int n = GETARG_B(i) - 1; /* number of results */
|
int n = GETARG_B(i) - 1; /* number of results */
|
||||||
|
@ -1665,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
ci->func -= ci->u.l.nextraargs + nparams1;
|
ci->func -= ci->u.l.nextraargs + nparams1;
|
||||||
L->top = ra + n; /* set call for 'luaD_poscall' */
|
L->top = ra + n; /* set call for 'luaD_poscall' */
|
||||||
luaD_poscall(L, ci, n);
|
luaD_poscall(L, ci, n);
|
||||||
return;
|
updatetrap(ci); /* 'luaD_poscall' can change hooks */
|
||||||
|
goto ret;
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN0) {
|
vmcase(OP_RETURN0) {
|
||||||
if (L->hookmask) {
|
if (L->hookmask) {
|
||||||
L->top = ra;
|
L->top = ra;
|
||||||
halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */
|
savepc(ci);
|
||||||
|
luaD_poscall(L, ci, 0); /* no hurry... */
|
||||||
|
trap = 1;
|
||||||
}
|
}
|
||||||
else { /* do the 'poscall' here */
|
else { /* do the 'poscall' here */
|
||||||
int nres = ci->nresults;
|
int nres = ci->nresults;
|
||||||
|
@ -1679,12 +1690,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
while (nres-- > 0)
|
while (nres-- > 0)
|
||||||
setnilvalue(s2v(L->top++)); /* all results are nil */
|
setnilvalue(s2v(L->top++)); /* all results are nil */
|
||||||
}
|
}
|
||||||
return;
|
goto ret;
|
||||||
}
|
}
|
||||||
vmcase(OP_RETURN1) {
|
vmcase(OP_RETURN1) {
|
||||||
if (L->hookmask) {
|
if (L->hookmask) {
|
||||||
L->top = ra + 1;
|
L->top = ra + 1;
|
||||||
halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */
|
savepc(ci);
|
||||||
|
luaD_poscall(L, ci, 1); /* no hurry... */
|
||||||
|
trap = 1;
|
||||||
}
|
}
|
||||||
else { /* do the 'poscall' here */
|
else { /* do the 'poscall' here */
|
||||||
int nres = ci->nresults;
|
int nres = ci->nresults;
|
||||||
|
@ -1698,7 +1711,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
setnilvalue(s2v(L->top++));
|
setnilvalue(s2v(L->top++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
ret: /* return from a Lua function */
|
||||||
|
if (ci->callstatus & CIST_FRESH)
|
||||||
|
return; /* end this frame */
|
||||||
|
else {
|
||||||
|
ci = ci->previous;
|
||||||
|
goto returning; /* continue running caller in this frame */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vmcase(OP_FORLOOP) {
|
vmcase(OP_FORLOOP) {
|
||||||
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
|
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
|
||||||
|
|
|
@ -54,6 +54,6 @@ win32 {
|
||||||
RC_LANG = 0x0
|
RC_LANG = 0x0
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine Library"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine Library"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "LuaEngine"
|
QMAKE_TARGET_PRODUCT = "LuaEngine"
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,6 @@ win32 {
|
||||||
RC_LANG = 0x0
|
RC_LANG = 0x0
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine Gui Library"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine Gui Library"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2018-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "LuaEngineGui"
|
QMAKE_TARGET_PRODUCT = "LuaEngineGui"
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,6 @@ win32 {
|
||||||
RC_LANG = 0x0
|
RC_LANG = 0x0
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine I/O Library"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine I/O Library"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "LuaEngineIO"
|
QMAKE_TARGET_PRODUCT = "LuaEngineIO"
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,6 @@ win32 {
|
||||||
RC_LANG = 0x0
|
RC_LANG = 0x0
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine Network Library"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine Network Library"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "LuaEngineNetwork"
|
QMAKE_TARGET_PRODUCT = "LuaEngineNetwork"
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,6 @@ win32 {
|
||||||
RC_LANG = 0x0
|
RC_LANG = 0x0
|
||||||
QMAKE_TARGET_COMPANY = "Syping"
|
QMAKE_TARGET_COMPANY = "Syping"
|
||||||
QMAKE_TARGET_DESCRIPTION = "LuaEngine OS Library"
|
QMAKE_TARGET_DESCRIPTION = "LuaEngine OS Library"
|
||||||
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2020 Syping"
|
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2019-2021 Syping"
|
||||||
QMAKE_TARGET_PRODUCT = "LuaEngineOS"
|
QMAKE_TARGET_PRODUCT = "LuaEngineOS"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue