Project

Profile

Help

HostedRedmine.com has moved to the Planio platform. All logins and passwords remained the same. All users will be able to login and use Redmine just as before. *Read more...*

Feature #905343 ยป 0039-Update-included-lua-to-version-5.4.2.patch

Marko Lindqvist, 2020-12-11 03:49 PM

View differences:

dependencies/lua-5.4/README
This is Lua 5.4.1, released on 30 Sep 2020.
This is Lua 5.4.2, released on 13 Nov 2020.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
dependencies/lua-5.4/Version
Sources here are from lua-5.4.1
(http://www.lua.org/ftp/lua-5.4.1.tar.gz)
Sources here are from lua-5.4.2
(http://www.lua.org/ftp/lua-5.4.2.tar.gz)
Not entire lua distribution directory hierarchy is included here, and
some files needed for Freeciv usage have been added.
dependencies/lua-5.4/doc/readme.html
<OL>
<LI>
Open a terminal window and move to
the top-level directory, which is named <TT>lua-5.4.1</TT>.
the top-level directory, which is named <TT>lua-5.4.2</TT>.
The <TT>Makefile</TT> there controls both the build process and the installation process.
<P>
<LI>
......
<P CLASS="footer">
Last update:
Wed Sep 30 09:55:45 UTC 2020
Tue Nov 10 20:55:28 UTC 2020
</P>
<!--
Last change: revised for Lua 5.4.1
Last change: revised for Lua 5.4.2
-->
</BODY>
dependencies/lua-5.4/freeciv_lua.patch
diff -Nurd lua-5.4/src/ldo.c lua-5.4/src/ldo.c
--- lua-5.4/src/ldo.c 2019-06-03 01:39:43.783391056 +0300
+++ lua-5.4/src/ldo.c 2019-06-03 00:43:05.506220924 +0300
--- lua-5.4/src/ldo.c 2020-12-11 16:39:32.993735065 +0200
+++ lua-5.4/src/ldo.c 2020-12-11 16:38:20.605260988 +0200
@@ -60,7 +60,7 @@
try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; }
#define luai_jmpbuf int /* dummy variable */
......
/* in POSIX, try _longjmp/_setjmp (more efficient) */
#define LUAI_THROW(L,c) _longjmp((c)->b, 1)
diff -Nurd lua-5.4/src/liolib.c lua-5.4/src/liolib.c
--- lua-5.4/src/liolib.c 2019-06-03 01:39:48.875376031 +0300
+++ lua-5.4/src/liolib.c 2019-06-03 00:43:05.506220924 +0300
@@ -54,7 +54,7 @@
--- lua-5.4/src/liolib.c 2020-12-11 16:39:32.993735065 +0200
+++ lua-5.4/src/liolib.c 2020-11-06 15:53:04.296997133 +0200
@@ -60,7 +60,7 @@
#if !defined(l_popen) /* { */
......
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
#define l_pclose(L,file) (pclose(file))
@@ -103,7 +103,7 @@
@@ -109,7 +109,7 @@
#if !defined(l_fseek) /* { */
......
#include <sys/types.h>
diff -Nurd lua-5.4/src/loslib.c lua-5.4/src/loslib.c
--- lua-5.4/src/loslib.c 2019-06-03 01:42:16.566920512 +0300
+++ lua-5.4/src/loslib.c 2019-06-03 00:43:05.510220908 +0300
@@ -80,7 +80,7 @@
--- lua-5.4/src/loslib.c 2020-12-11 16:39:32.997735091 +0200
+++ lua-5.4/src/loslib.c 2020-11-06 15:53:04.296997133 +0200
@@ -83,7 +83,7 @@
** where it uses gmtime_r/localtime_r
*/
......
#define l_gmtime(t,r) gmtime_r(t,r)
#define l_localtime(t,r) localtime_r(t,r)
@@ -107,7 +107,7 @@
@@ -110,7 +110,7 @@
*/
#if !defined(lua_tmpnam) /* { */
......
#include <unistd.h>
diff -Nurd lua-5.4/src/lstrlib.c lua-5.4/src/lstrlib.c
--- lua-5.4/src/lstrlib.c 2020-12-11 16:39:18.297637204 +0200
+++ lua-5.4/src/lstrlib.c 2020-12-11 16:40:05.433953802 +0200
@@ -1716,6 +1716,7 @@
case Kfloat: {
Ftypes u;
lua_Number num;
+ u.n = 0; /* Silence compiler warning */
copywithendian((char *)&u, data + pos, size, h.islittle);
if (size == sizeof(u.f)) num = (lua_Number)u.f;
else if (size == sizeof(u.d)) num = (lua_Number)u.d;
diff -Nurd lua-5.4/src/luaconf.h lua-5.4/src/luaconf.h
--- lua-5.4/src/luaconf.h 2019-06-03 01:38:58.559522248 +0300
+++ lua-5.4/src/luaconf.h 2019-06-03 01:41:15.431113421 +0300
--- lua-5.4/src/luaconf.h 2020-12-11 16:39:32.997735091 +0200
+++ lua-5.4/src/luaconf.h 2020-12-11 16:38:22.269271653 +0200
@@ -11,6 +11,7 @@
#include <limits.h>
#include <stddef.h>
dependencies/lua-5.4/src/lapi.c
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
static const UpVal *const nullup = NULL;
LClosure *f;
TValue *fi = index2value(L, fidx);
api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi);
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
if (pf) *pf = f;
return &f->upvals[n - 1]; /* get its upvalue pointer */
if (1 <= n && n <= f->p->sizeupvalues)
return &f->upvals[n - 1]; /* get its upvalue pointer */
else
return (UpVal**)&nullup;
}
......
}
case LUA_VCCL: { /* C closure */
CClosure *f = clCvalue(fi);
api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
return &f->upvalue[n - 1];
}
if (1 <= n && n <= f->nupvalues)
return &f->upvalue[n - 1];
/* else */
} /* FALLTHROUGH */
case LUA_VLCF:
return NULL; /* light C functions have no upvalues */
default: {
api_check(L, 0, "closure expected");
api_check(L, 0, "function expected");
return NULL;
}
}
......
LClosure *f1;
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index");
*up1 = *up2;
luaC_objbarrier(L, f1, *up1);
}
dependencies/lua-5.4/src/lauxlib.c
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'? */
return luaL_fileresult(L, 0, NULL);
else {
const char *what = "exit"; /* type of termination */
l_inspectstat(stat, what); /* interpret result */
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
......
/*
** Emit a warning. '*warnstate' means:
** 0 - warning system is off;
** 1 - ready to start a new message;
** 2 - previous message is to be continued.
** Warning functions:
** warnfoff: warning system is off
** warnfon: ready to start a new message
** warnfcont: previous message is to be continued
*/
static void warnf (void *ud, const char *message, int tocont) {
int *warnstate = (int *)ud;
if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
if (strcmp(message, "@off") == 0)
*warnstate = 0;
else if (strcmp(message, "@on") == 0)
*warnstate = 1;
return;
static void warnfoff (void *ud, const char *message, int tocont);
static void warnfon (void *ud, const char *message, int tocont);
static void warnfcont (void *ud, const char *message, int tocont);
/*
** Check whether message is a control message. If so, execute the
** 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 */
if (tocont) /* not the last part? */
*warnstate = 2; /* to be continued */
lua_setwarnf(L, warnfcont, L); /* to be continued */
else { /* last part */
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) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (L) {
int *warnstate; /* space for warning state */
lua_atpanic(L, &panic);
warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0);
luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
*warnstate = 0; /* default is warnings off */
lua_setwarnf(L, warnf, warnstate);
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
}
return L;
}
dependencies/lua-5.4/src/lcode.c
/*
** 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.)
*/
void luaK_dischargevars (FuncState *fs, expdesc *e) {
......
/*
** Ensures expression value is in register 'reg' (and therefore
** 'e' will become a non-relocatable expression).
** Ensure expression value is in register 'reg', making 'e' a
** non-relocatable expression.
** (Expression still may have jump lists.)
*/
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.)
*/
static void discharge2anyreg (FuncState *fs, expdesc *e) {
......
exp2reg(fs, e, e->u.info); /* put final result in it */
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;
}
dependencies/lua-5.4/src/ldblib.c
** Check whether a given upvalue from a given closure exists and
** 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 */
luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */
luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup,
"invalid upvalue index");
return nup;
id = lua_upvalueid(L, argf, nup);
if (pnup) {
luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index");
*pnup = nup;
}
return id;
}
static int db_upvalueid (lua_State *L) {
int n = checkupval(L, 1, 2);
lua_pushlightuserdata(L, lua_upvalueid(L, 1, n));
void *id = checkupval(L, 1, 2, NULL);
if (id != NULL)
lua_pushlightuserdata(L, id);
else
luaL_pushfail(L);
return 1;
}
static int db_upvaluejoin (lua_State *L) {
int n1 = checkupval(L, 1, 2);
int n2 = checkupval(L, 3, 4);
int n1, n2;
checkupval(L, 1, 2, &n1);
checkupval(L, 3, 4, &n2);
luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected");
luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected");
lua_upvaluejoin(L, 1, n1, 3, n2);
......
static int db_setcstacklimit (lua_State *L) {
int limit = (int)luaL_checkinteger(L, 1);
int res = lua_setcstacklimit(L, limit);
if (res == 0)
lua_pushboolean(L, 0);
else
lua_pushinteger(L, res);
lua_pushinteger(L, res);
return 1;
}
dependencies/lua-5.4/src/ldo.c
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
global_State *g = G(L);
l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci);
l_uint32 oldnCcalls = L->nCcalls;
struct lua_longjmp lj;
lj.status = LUA_OK;
lj.previous = L->errorJmp; /* chain new error handler */
......
(*f)(L, ud);
);
L->errorJmp = lj.previous; /* restore old error handler */
L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci;
L->nCcalls = oldnCcalls;
return lj.status;
}
......
int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
int lim = L->stacksize;
StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue);
int lim = stacksize(L);
StkId newstack = luaM_reallocvector(L, L->stack,
lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue);
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 (raiseerror)
luaM_error(L);
else return 0; /* do not raise an error */
}
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);
L->stack = newstack;
L->stacksize = newsize;
L->stack_last = L->stack + newsize - EXTRA_STACK;
L->stack_last = L->stack + newsize;
return 1;
}
......
** is true, raises any error; otherwise, return 0 in case of errors.
*/
int luaD_growstack (lua_State *L, int n, int raiseerror) {
int size = L->stacksize;
int newsize = 2 * size; /* tentative new size */
if (unlikely(size > LUAI_MAXSTACK)) { /* need more space after extra size? */
int size = stacksize(L);
if (unlikely(size > LUAI_MAXSTACK)) {
/* 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)
luaD_throw(L, LUA_ERRERR); /* error inside message handler */
else return 0;
return 0; /* if not 'raiseerror', just signal it */
}
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 */
newsize = LUAI_MAXSTACK;
if (newsize < needed) /* but must respect what was asked for */
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 */
luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
if (raiseerror)
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) {
CallInfo *ci;
int res;
StkId lim = L->top;
for (ci = L->ci; ci != NULL; ci = ci->previous) {
if (lim < ci->top) lim = ci->top;
}
lua_assert(lim <= L->stack_last);
return cast_int(lim - L->stack) + 1; /* part of stack in use */
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) {
int inuse = stackinuse(L);
int goodsize = inuse + BASIC_STACK_SIZE;
if (goodsize > LUAI_MAXSTACK)
goodsize = LUAI_MAXSTACK; /* respect stack limit */
int nsize = inuse * 2; /* proposed new size */
int max = inuse * 3; /* maximum "reasonable" size */
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
good size is smaller than current size, shrink its stack */
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize)
luaD_reallocstack(L, goodsize, 0); /* ok if that fails */
size is larger than maximum "reasonable" size, shrink it */
if (inuse <= LUAI_MAXSTACK && stacksize(L) > max)
luaD_reallocstack(L, nsize, 0); /* ok if that fails */
else /* don't change stack */
condmovestack(L,{},{}); /* (change only for debugging) */
luaE_shrinkCI(L); /* shrink CI list */
......
/*
** 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.
*/
void luaD_tryfuncTM (lua_State *L, StkId func) {
......
/*
** Call a function (C or Lua). The function to be called is at *func.
** The arguments are on the stack, right after the function.
** When returns, all the results are on the stack, starting at the original
** function position.
** Prepares the call to a function (C or Lua). For C functions, also do
** the call. The function to be called is at '*func'. The arguments
** are on the stack, right after the function. Returns the CallInfo
** 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;
retry:
switch (ttypetag(s2v(func))) {
......
lua_lock(L);
api_checknelems(L, n);
luaD_poscall(L, ci, n);
break;
return NULL;
}
case LUA_VLCL: { /* Lua function */
CallInfo *ci;
......
L->ci = ci = next_ci(L);
ci->nresults = nresults;
ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = 0;
ci->top = func + 1 + fsize;
ci->func = func;
L->ci = ci;
for (; narg < nfixparams; narg++)
setnilvalue(s2v(L->top++)); /* complete missing arguments */
lua_assert(ci->top <= L->stack_last);
luaV_execute(L, ci); /* run the function */
break;
return ci;
}
default: { /* not a function */
checkstackGCp(L, 1, func); /* space for metamethod */
......
}
/*
** 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.
*/
void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
incXCcalls(L);
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);
ccall(L, func, nResults, nyci);
}
......
if (ci == NULL) return 0; /* no recovery point */
/* "finish" luaD_pcall */
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->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;
return 1; /* continue running the coroutine */
}
......
int n = *(cast(int*, ud)); /* number of arguments */
StkId firstArg = L->top - n; /* first argument */
CallInfo *ci = L->ci;
if (L->status == LUA_OK) { /* starting a coroutine? */
luaD_call(L, firstArg - 1, LUA_MULTRET);
}
if (L->status == LUA_OK) /* starting a coroutine? */
ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */
else { /* resuming from previous yield */
lua_assert(L->status == LUA_YIELD);
L->status = LUA_OK; /* mark that it is running (again) */
luaE_incCstack(L); /* control the C stack */
if (isLua(ci)) /* yielded inside a hook? */
luaV_execute(L, ci); /* just continue running Lua code */
else { /* 'common' yield */
......
}
else if (L->status != LUA_YIELD) /* ended with errors? */
return resume_error(L, "cannot resume dead coroutine", nargs);
if (from == NULL)
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);
L->nCcalls = (from) ? getCcalls(from) : 0;
luai_userstateresume(L, nargs);
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, &nargs);
......
status = luaF_close(L, oldtop, status);
oldtop = restorestack(L, old_top); /* previous call may change stack */
luaD_seterrorobj(L, status, oldtop);
luaD_shrinkstack(L);
luaD_shrinkstack(L); /* restore stack size in case of overflow */
}
L->errfunc = old_errfunc;
return status;
dependencies/lua-5.4/src/ldo.h
int fTransfer, int nTransfer);
LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
dependencies/lua-5.4/src/lfunc.c
uv->v = &uv->u.value; /* make it closed */
setnilvalue(uv->v);
cl->upvals[i] = uv;
luaC_objbarrier(L, cl, o);
luaC_objbarrier(L, cl, uv);
}
}
dependencies/lua-5.4/src/lgc.c
/*
** Clear keys for empty entries in tables. If entry is empty
** and its key is not marked, mark its entry as dead. This allows the
** collection of the key, but keeps its entry in the table (its removal
** could break a chain). The main feature of a dead key is that it must
** be different from any other value, to do not disturb searches.
** Other places never manipulate dead keys, because its associated empty
** value is enough to signal that the entry is logically empty.
** Clear keys for empty entries in tables. If entry is empty, mark its
** entry as dead. This allows the collection of the key, but keeps its
** entry in the table: its removal could break a chain and could break
** a table traversal. Other places never manipulate dead keys, because
** its associated empty value is enough to signal that the entry is
** logically empty.
*/
static void clearkey (Node *n) {
lua_assert(isempty(gval(n)));
if (keyiswhite(n))
setdeadkey(n); /* unused and unmarked key; remove it */
if (keyiscollectable(n))
setdeadkey(n); /* unused key; remove it */
}
......
if (upisopen(uv))
set2gray(uv); /* open upvalues are kept gray */
else
set2black(o); /* closed upvalues are visited here */
set2black(uv); /* closed upvalues are visited here */
markvalue(g, uv->v); /* mark its content */
break;
}
......
Udata *u = gco2u(o);
if (u->nuvalue == 0) { /* no user values? */
markobjectN(g, u->metatable); /* mark its metatable */
set2black(o); /* nothing else to mark */
set2black(u); /* nothing else to mark */
break;
}
/* else... */
......
for (uv = th->openupval; uv != NULL; uv = uv->u.open.next)
markobject(g, uv); /* open upvalues cannot be collected */
if (g->gcstate == GCSatomic) { /* final traversal? */
StkId lim = th->stack + th->stacksize; /* real end of stack */
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(s2v(o));
for (; o < th->stack_last + EXTRA_STACK; o++)
setnilvalue(s2v(o)); /* clear dead stack slice */
/* 'remarkupvals' may have removed thread from 'twups' list */
if (!isintwups(th) && th->openupval != NULL) {
th->twups = g->twups; /* link it back to the list */
......
}
else if (!g->gcemergency)
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
return 1 + th->stacksize;
return 1 + stacksize(th);
}
......
case LUA_VUPVAL:
freeupval(L, gco2upv(o));
break;
case LUA_VLCL:
luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
case LUA_VLCL: {
LClosure *cl = gco2lcl(o);
luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
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;
}
case LUA_VTABLE:
luaH_free(L, gco2t(o));
break;
......
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
break;
}
case LUA_VSHRSTR:
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
case LUA_VSHRSTR: {
TString *ts = gco2ts(o);
luaS_remove(L, ts); /* remove it from hash table */
luaM_freemem(L, ts, sizelstring(ts->shrlen));
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;
}
default: lua_assert(0);
}
}
dependencies/lua-5.4/src/llex.c
/*
** reads a sequence '[=*[' or ']=*]', leaving the last bracket.
** If sequence is well formed, return its number of '='s + 2; otherwise,
** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...').
** read a sequence '[=*[' or ']=*]', leaving the last bracket. If
** sequence is well formed, return its number of '='s + 2; otherwise,
** return 1 if it is a single bracket (no '='s and no 2nd bracket);
** otherwise (an unfinished '[==...') return 0.
*/
static size_t skip_sep (LexState *ls) {
size_t count = 0;
......
}
case '=': {
next(ls);
if (check_next1(ls, '=')) return TK_EQ;
if (check_next1(ls, '=')) return TK_EQ; /* '==' */
else return '=';
}
case '<': {
next(ls);
if (check_next1(ls, '=')) return TK_LE;
else if (check_next1(ls, '<')) return TK_SHL;
if (check_next1(ls, '=')) return TK_LE; /* '<=' */
else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */
else return '<';
}
case '>': {
next(ls);
if (check_next1(ls, '=')) return TK_GE;
else if (check_next1(ls, '>')) return TK_SHR;
if (check_next1(ls, '=')) return TK_GE; /* '>=' */
else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */
else return '>';
}
case '/': {
next(ls);
if (check_next1(ls, '/')) return TK_IDIV;
if (check_next1(ls, '/')) return TK_IDIV; /* '//' */
else return '/';
}
case '~': {
next(ls);
if (check_next1(ls, '=')) return TK_NE;
if (check_next1(ls, '=')) return TK_NE; /* '~=' */
else return '~';
}
case ':': {
next(ls);
if (check_next1(ls, ':')) return TK_DBCOLON;
if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */
else return ':';
}
case '"': case '\'': { /* short literal strings */
......
return TK_NAME;
}
}
else { /* single-char tokens (+ - / ...) */
else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */
int c = ls->current;
next(ls);
return c;
dependencies/lua-5.4/src/llimits.h
#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
** ('lua_lock') and leaves the core ('lua_unlock')
......
/* exponentiation */
#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
/* the others are quite standard operations */
......
#else
/* realloc stack keeping its size */
#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
#if !defined(HARDMEMTESTS)
dependencies/lua-5.4/src/lobject.c
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
const char *pdot = strchr(s, '.');
if (strlen(s) > L_MAXLENNUM || pdot == NULL)
if (pdot == NULL || strlen(s) > L_MAXLENNUM)
return NULL; /* string too long or no dot; fail */
strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
dependencies/lua-5.4/src/lobject.h
*/
#define LUA_TUPVAL LUA_NUMTYPES /* upvalues */
#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)
......
/*
** {==================================================================
** Closures
** Functions
** ===================================================================
*/
......
/*
** Use a "nil table" to mark dead keys in a table. Those keys serve
** to keep space for removed entries, which may still be part of
** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE
** set, so these values are considered not collectable and are different
** from any valid value.
** Dead keys in tables have the tag DEADKEY but keep their original
** gcvalue. This distinguishes them from regular keys but allows them to
** be found when searched in a special way. ('next' needs that to find
** keys removed from a table during a traversal.)
*/
#define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL)
#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY)
#define keyisdead(node) (keytt(node) == LUA_TDEADKEY)
/* }================================================================== */
dependencies/lua-5.4/src/lopcodes.h
OP_UNM,/* A B R[A] := -R[B] */
OP_BNOT,/* A B R[A] := ~R[B] */
OP_NOT,/* A B R[A] := not R[B] */
OP_LEN,/* A B R[A] := length of R[B] */
OP_LEN,/* A B R[A] := #R[B] (length operator) */
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
......
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */
OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
dependencies/lua-5.4/src/lparser.c
}
/*
** Macros to limit the maximum recursion depth while parsing
*/
#define enterlevel(ls) luaE_enterCcall((ls)->L)
#define enterlevel(ls) luaE_incCstack(ls->L)
#define leavelevel(ls) luaE_exitCcall((ls)->L)
#define leavelevel(ls) ((ls)->L->nCcalls--)
/*
......
static void parlist (LexState *ls) {
/* parlist -> [ param { ',' param } ] */
/* parlist -> [ {NAME ','} (NAME | '...') ] */
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
......
if (ls->t.token != ')') { /* is 'parlist' not empty? */
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME */
case TK_NAME: {
new_localvar(ls, str_checkname(ls));
nparams++;
break;
}
case TK_DOTS: { /* param -> '...' */
case TK_DOTS: {
luaX_next(ls);
isvararg = 1;
break;
......
}
/*
** 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) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
BlockCnt bl;
int line;
FuncState *fs = ls->fs;
TString *jlb = NULL;
int target = NO_JUMP;
expdesc v;
int jf; /* instruction to skip 'then' code (if condition is false) */
luaX_next(ls); /* skip IF or ELSEIF */
expr(ls, &v); /* read condition */
checknext(ls, TK_THEN);
line = ls->linenumber;
if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
int line = ls->linenumber;
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' */
if (jlb != NULL) /* forward jump? */
newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
else /* backward jump */
luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
while (testnext(ls, ';')) {} /* skip semicolons */
if (block_follow(ls, 0)) { /* jump is the entire block? */
leaveblock(fs);
......
else /* must skip over 'then' part if condition is false */
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 */
enterblock(fs, &bl, 0);
jf = v.f;
......
static void localstat (LexState *ls) {
/* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */
/* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
FuncState *fs = ls->fs;
int toclose = -1; /* index of to-be-closed variable (if any) */
Vardesc *var; /* last variable */
dependencies/lua-5.4/src/lparser.h
/* kinds of variables/expressions */
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) */
VNIL, /* constant nil */
VTRUE, /* constant true */
......
VLOCAL, /* local variable; var.sidx = stack index (local register);
var.vidx = relative index in 'actvar.arr' */
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */
VCONST, /* compile-time <const> variable;
info = absolute index in 'actvar.arr' */
VINDEXED, /* indexed variable;
ind.t = table register;
ind.idx = key's R index */
dependencies/lua-5.4/src/lstate.c
addbuff(buff, p, &h); /* local variable */
addbuff(buff, p, &lua_newstate); /* public function */
lua_assert(p == sizeof(buff));
return luaS_hash(buff, p, h, 1);
return luaS_hash(buff, p, h);
}
#endif
......
LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
global_State *g = G(L);
int ccalls;
luaE_freeCI(L); /* release unused CIs */
ccalls = getCcalls(L);
if (limit >= 40000)
return 0; /* out of bounds */
limit += CSTACKERR;
if (L != g-> mainthread)
return 0; /* only main thread can change the C stack */
else if (ccalls <= CSTACKERR)
return 0; /* handling overflow */
else {
int diff = limit - g->Cstacklimit;
if (ccalls + diff <= CSTACKERR)
return 0; /* new limit would cause an overflow */
g->Cstacklimit = limit; /* set new limit */
L->nCcalls += diff; /* correct 'nCcalls' */
return limit - diff - CSTACKERR; /* success; return previous limit */
}
}
/*
** 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 */
}
}
UNUSED(L); UNUSED(limit);
return LUAI_MAXCCALLS; /* warning?? */
}
CallInfo *luaE_extendCI (lua_State *L) {
CallInfo *ci;
lua_assert(L->ci->next == NULL);
luaE_enterCcall(L);
ci = luaM_new(L, CallInfo);
lua_assert(L->ci->next == NULL);
L->ci->next = ci;
......
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
ci->next = NULL;
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
while ((ci = next) != NULL) {
next = ci->next;
luaM_free(L, ci);
L->nci--;
}
L->nCcalls -= L->nci; /* adjust result */
}
......
CallInfo *next;
if (ci == NULL)
return; /* no extra elements */
L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
while ((next = ci->next) != NULL) { /* two extra elements? */
CallInfo *next2 = next->next; /* next's next */
ci->next = next2; /* remove next from the list */
......
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) {
int i; CallInfo *ci;
/* initialize stack array */
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue);
L1->stacksize = BASIC_STACK_SIZE;
for (i = 0; i < BASIC_STACK_SIZE; i++)
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
setnilvalue(s2v(L1->stack + i)); /* erase new 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 */
ci = &L1->base_ci;
ci->next = ci->previous = NULL;
......
L->ci = &L->base_ci; /* free the entire 'ci' list */
luaE_freeCI(L);
lua_assert(L->nci == 0);
luaM_freearray(L, L->stack, L->stacksize); /* free stack array */
luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */
}
......
L->stack = NULL;
L->ci = NULL;
L->nci = 0;
L->stacksize = 0;
L->twups = L; /* thread has no upvalues */
L->errorJmp = NULL;
L->hook = NULL;
......
setthvalue2s(L, L->top, L1);
api_incr_top(L);
preinit_thread(L1, g);
L1->nCcalls = getCcalls(L);
L1->nCcalls = 0;
L1->hookmask = L->hookmask;
L1->basehookcount = L->basehookcount;
L1->hook = L->hook;
......
preinit_thread(L, g);
g->allgc = obj2gco(L); /* by now, only object is the main thread */
L->next = NULL;
g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR;
L->nCcalls = 0;
incnny(L); /* main thread is always non yieldable */
g->frealloc = f;
g->ud = ud;
dependencies/lua-5.4/src/lstate.h
/*
** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
** how many "C calls" it still can do in the C stack, to avoid C-stack
** overflow. This count is very rough approximation; it considers only
** recursive functions inside the interpreter, as non-recursive calls
** can be considered using a fixed (although unknown) amount of stack
** space.
**
** The count has two parts: the lower part is the count itself; the
** higher part counts the number of non-yieldable calls in the stack.
** (They are together so that we can change both with one instruction.)
**
** Because calls to external C functions can use an unknown amount
** of space (e.g., functions using an auxiliary buffer), calls
** to these functions add more than one to the count (see CSTACKCF).
**
** The proper count excludes the number of CallInfo structures allocated
** by Lua, as a kind of "potential" calls. So, when Lua calls a function
** (and "consumes" one CallInfo), it needs neither to decrement nor to
** check 'nCcalls', as its use of C stack is already accounted for.
** About 'nCcalls': This count has two parts: the lower 16 bits counts
** the number of recursive invocations in the C stack; the higher
** 16 bits counts the number of non-yieldable calls in the stack.
** (They are together so that we can change and save both with one
** instruction.)
*/
/* number of "C stack slots" used by an external C function */
#define CSTACKCF 10
/*
** The C-stack size is sliced in the following zones:
** - larger than CSTACKERR: normal stack;
** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow;
** - [CSTACKCF, CSTACKERRMARK]: error-handling zone;
** - below CSTACKERRMARK: buffer zone to signal overflow during overflow;
** (Because the counter can be decremented CSTACKCF at once, we need
** the so called "buffer zones", with at least that size, to properly
** detect a change from one zone to the next.)
*/
#define CSTACKERR (8 * CSTACKCF)
#define CSTACKMARK (CSTACKERR - (CSTACKCF + 2))
#define CSTACKERRMARK (CSTACKCF + 2)
/* initial limit for the C-stack of threads */
#define CSTACKTHREAD (2 * CSTACKERR)
/* true if this thread does not have non-yieldable calls in the stack */
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
......
/* Decrement the number of non-yieldable calls */
#define decnny(L) ((L)->nCcalls -= 0x10000)
/* Increment the number of non-yieldable calls and decrement nCcalls */
#define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF)
/* Decrement the number of non-yieldable calls and increment nCcalls */
#define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF)
/* Non-yieldable call increment */
#define nyci (0x10000 | 1)
......
#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 BASIC_STACK_SIZE (2*LUA_MINSTACK)
#define stacksize(th) cast_int((th)->stack_last - (th)->stack)
/* kinds of Garbage Collection */
#define KGC_INC 0 /* incremental gc */
......
*/
#define CIST_OAH (1<<0) /* original value of 'allowhook' */
#define CIST_C (1<<1) /* call is running a C function */
#define CIST_HOOKED (1<<2) /* call is running a debug hook */
#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */
#define CIST_TAIL (1<<4) /* call was tail called */
#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */
#define CIST_FIN (1<<6) /* call is running a finalizer */
#define CIST_TRAN (1<<7) /* 'ci' has transfer information */
#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
#define CIST_HOOKED (1<<3) /* call is running a debug hook */
#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */
#define CIST_TAIL (1<<5) /* call was tail called */
#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
#define CIST_FIN (1<<7) /* call is running a finalizer */
#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
#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
/* active function is a Lua function */
......
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
lua_WarnFunction warnf; /* warning function */
void *ud_warn; /* auxiliary data to 'warnf' */
unsigned int Cstacklimit; /* current limit for the C stack */
} global_State;
......
StkId top; /* first free slot in the stack */
global_State *l_G;
CallInfo *ci; /* call info for current function */
StkId stack_last; /* last free slot in the stack */
StkId stack_last; /* end of stack (last element + 1) */
StkId stack; /* stack base */
UpVal *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
......
CallInfo base_ci; /* CallInfo for first level (C calling Lua) */
volatile lua_Hook hook;
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 stacksize;
int basehookcount;
int hookcount;
volatile l_signalT hookmask;
......
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
LUAI_FUNC void luaE_enterCcall (lua_State *L);
LUAI_FUNC void luaE_checkcstack (lua_State *L);
LUAI_FUNC void luaE_incCstack (lua_State *L);
LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where);
#define luaE_exitCcall(L) ((L)->nCcalls++)
#endif
dependencies/lua-5.4/src/lstring.c
#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.
*/
......
}
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed,
size_t step) {
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
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]));
return h;
}
......
lua_assert(ts->tt == LUA_VLNGSTR);
if (ts->extra == 0) { /* no hash? */
size_t len = ts->u.lnglen;
size_t step = (len >> LUAI_HASHLIMIT) + 1;
ts->hash = luaS_hash(getstr(ts), len, ts->hash, step);
ts->hash = luaS_hash(getstr(ts), len, ts->hash);
ts->extra = 1; /* now it has its hash */
}
return ts->hash;
......
TString *ts;
global_State *g = G(L);
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)];
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
dependencies/lua-5.4/src/lstring.h
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l,
unsigned int seed, size_t step);
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
dependencies/lua-5.4/src/lstrlib.c
float f;
double d;
lua_Number n;
char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
} Ftypes;
......
** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
** 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) {
if (islittle == nativeendian.little) {
while (size-- != 0)
*(dest++) = *(src++);
}
if (islittle == nativeendian.little)
memcpy(dest, src, size);
else {
dest += size - 1;
while (size-- != 0)
......
break;
}
case Kfloat: { /* floating-point options */
volatile Ftypes u;
Ftypes u;
char *buff = luaL_prepbuffsize(&b, size);
lua_Number n = luaL_checknumber(L, arg); /* get argument */
if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
else if (size == sizeof(u.d)) u.d = (double)n;
else u.n = n;
/* 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);
break;
}
......
break;
}
case Kfloat: {
volatile Ftypes u;
Ftypes u;
lua_Number num;
copywithendian(u.buff, data + pos, size, h.islittle);
u.n = 0; /* Silence compiler warning */
copywithendian((char *)&u, data + pos, size, h.islittle);
if (size == sizeof(u.f)) num = (lua_Number)u.f;
else if (size == sizeof(u.d)) num = (lua_Number)u.d;
else num = u.n;
......
break;
}
case Kzstr: {
size_t len = (int)strlen(data + pos);
size_t len = strlen(data + pos);
luaL_argcheck(L, pos + len < ld, 2,
"unfinished string for format 'z'");
lua_pushlstring(L, data + pos, len);
dependencies/lua-5.4/src/ltable.c
/*
** Check whether key 'k1' is equal to the key in node 'n2'.
** This equality is raw, so there are no metamethods. Floats
** with integer values have been normalized, so integers cannot
** be equal to floats. It is assumed that 'eqshrstr' is simply
** pointer equality, so that short strings are handled in the
** default case.
*/
static int equalkey (const TValue *k1, const Node *n2) {
if (rawtt(k1) != keytt(n2)) /* not the same variants? */
** Check whether key 'k1' is equal to the key in node 'n2'. This
** equality is raw, so there are no metamethods. Floats with integer
** values have been normalized, so integers cannot be equal to
** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
** that short strings are handled in the 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, int deadok) {
if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */
!(deadok && keyisdead(n2) && iscollectable(k1)))
return 0; /* cannot be same key */
switch (ttypetag(k1)) {
switch (keytt(n2)) {
case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
return 1;
case LUA_VNUMINT:
......
return pvalue(k1) == pvalueraw(keyval(n2));
case LUA_VLCF:
return fvalue(k1) == fvalueraw(keyval(n2));
case LUA_VLNGSTR:
case ctb(LUA_VLNGSTR):
return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
default:
return gcvalue(k1) == gcvalueraw(keyval(n2));
......
/*
** "Generic" get version. (Not that generic: not valid for integers,
** 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);
for (;;) { /* check whether 'key' is somewhere in the chain */
if (equalkey(key, n))
if (equalkey(key, n, deadok))
return gval(n); /* that's it */
else {
int nx = gnext(n);
......
if (i - 1u < asize) /* is 'key' inside array part? */
return i; /* yes; that's the index */
else {
const TValue *n = getgeneric(t, key);
const TValue *n = getgeneric(t, key, 1);
if (unlikely(isabstkey(n)))
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
......
else { /* for long strings, use generic case */
TValue ko;
setsvalue(cast(lua_State *, NULL), &ko, key);
return getgeneric(t, &ko);
return getgeneric(t, &ko, 0);
}
}
......
/* else... */
} /* FALLTHROUGH */
default:
return getgeneric(t, key);
return getgeneric(t, key, 0);
}
}
dependencies/lua-5.4/src/lua.h
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "4"
#define LUA_VERSION_RELEASE "1"
#define LUA_VERSION_RELEASE "2"
#define LUA_VERSION_NUM 504
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
dependencies/lua-5.4/src/luaconf.h
** =====================================================================
*/
/*
@@ LUAI_MAXCSTACK defines the maximum depth for nested calls and
** also limits the maximum depth of other recursive algorithms in
** the implementation, such as syntactic analysis. A value too
** large may allow the interpreter to crash (C-stack overflow).
** The default value seems ok for regular machines, but may be
** too high for restricted hardware.
** The test file 'cstack.lua' may help finding a good limit.
** (It will crash with a limit too high.)
*/
#if !defined(LUAI_MAXCSTACK)
#define LUAI_MAXCSTACK 2000
#endif
/*
@@ LUA_USE_C89 controls the use of non-ISO-C89 features.
** Define it if you want Lua to avoid the use of a few C99 features
dependencies/lua-5.4/src/lvm.c
count /= l_castS2U(-(step + 1)) + 1u;
}
/* store the counter in place of the limit (which won't be
needed anymore */
needed anymore) */
setivalue(plimit, l_castU2S(count));
}
}
......
#define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci))
/*
** Protect code that will finish the loop (returns) or can only raise
** errors. (That is, it will not return to the interpreter main loop
** after changing the stack or hooks.)
** Protect code that can only raise errors. (That is, it cannnot change
** the stack or hooks.)
*/
#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 */
#define checkGC(L,c) \
{ luaC_condGC(L, (savepc(L), L->top = (c)), \
......
#if LUA_USE_JUMPTABLE
#include "ljumptab.h"
#endif
tailcall:
startfunc:
trap = L->hookmask;
returning: /* trap already set */
cl = clLvalue(s2v(ci->func));
k = cl->p->k;
pc = ci->u.l.savedpc;
if (trap) {
if (cl->p->is_vararg)
trap = 0; /* hooks will start after VARARGPREP instruction */
else if (pc == cl->p->code) /* first instruction (not resuming)? */
luaD_hookcall(L, ci);
ci->u.l.trap = 1; /* there may be other hooks */
if (pc == cl->p->code) { /* first instruction (not resuming)? */
if (cl->p->is_vararg)
trap = 0; /* hooks will start after VARARGPREP instruction */
else /* check 'call' hook */
luaD_hookcall(L, ci);
}
ci->u.l.trap = 1; /* assume trap is on, for now */
}
base = ci->func + 1;
/* main loop of interpreter */
......
StkId ra; /* instruction's A register */
vmfetch();
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 */
lua_assert(isIT(i) || (cast_void(L->top = base), 1));
vmdispatch (GET_OPCODE(i)) {
......
vmbreak;
}
vmcase(OP_CALL) {
CallInfo *newci;
int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1;
if (b != 0) /* fixed number of arguments? */
L->top = ra + b; /* top signals number of arguments */
/* 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;
}
vmcase(OP_TAILCALL) {
int b = GETARG_B(i); /* number of arguments + 1 (function) */
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;
if (b != 0)
L->top = ra + b;
else /* previous instruction set top */
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)) {
/* close upvalues from current call; the compiler ensures
that there are no to-be-closed variables here, so this
......
checkstackGCp(L, 1, ra);
}
if (!ttisLclosure(s2v(ra))) { /* C function? */
luaD_call(L, ra, LUA_MULTRET); /* call it */
luaD_precall(L, ra, LUA_MULTRET); /* call it */
updatetrap(ci);
updatestack(ci); /* stack may have been relocated */
ci->func -= delta;
luaD_poscall(L, ci, cast_int(L->top - ra));
return;
ci->func -= delta; /* restore 'func' (if vararg) */
luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */
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 */
goto tailcall;
goto startfunc; /* execute the callee */
}
vmcase(OP_RETURN) {
int n = GETARG_B(i) - 1; /* number of results */
......
ci->func -= ci->u.l.nextraargs + nparams1;
L->top = ra + n; /* set call for 'luaD_poscall' */
luaD_poscall(L, ci, n);
return;
updatetrap(ci); /* 'luaD_poscall' can change hooks */
goto ret;
}
vmcase(OP_RETURN0) {
if (L->hookmask) {
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 */
int nres = ci->nresults;
......
while (nres-- > 0)
setnilvalue(s2v(L->top++)); /* all results are nil */
}
return;
goto ret;
}
vmcase(OP_RETURN1) {
if (L->hookmask) {
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 */
int nres = ci->nresults;
......
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) {
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
    (1-1/1)