mirror of
https://github.com/lua/lua
synced 2026-09-27 00:28:25 +03:00
Merge branch 'master' of https://github.com/shewitt-au/lua into msdev-build
This commit is contained in:
commit
1a0d4151e8
31 changed files with 331 additions and 95 deletions
11
lapi.c
11
lapi.c
|
|
@ -366,7 +366,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API unsigned (lua_numbertocstring) (lua_State *L, int idx, char *buff) {
|
LUA_API unsigned lua_numbertocstring (lua_State *L, int idx, char *buff) {
|
||||||
const TValue *o = index2value(L, idx);
|
const TValue *o = index2value(L, idx);
|
||||||
if (ttisnumber(o)) {
|
if (ttisnumber(o)) {
|
||||||
unsigned len = luaO_tostringbuff(o, buff);
|
unsigned len = luaO_tostringbuff(o, buff);
|
||||||
|
|
@ -1201,11 +1201,16 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||||
case LUA_GCSTEP: {
|
case LUA_GCSTEP: {
|
||||||
lu_byte oldstp = g->gcstp;
|
lu_byte oldstp = g->gcstp;
|
||||||
l_mem n = cast(l_mem, va_arg(argp, size_t));
|
l_mem n = cast(l_mem, va_arg(argp, size_t));
|
||||||
|
l_mem newdebt;
|
||||||
int work = 0; /* true if GC did some work */
|
int work = 0; /* true if GC did some work */
|
||||||
g->gcstp = 0; /* allow GC to run (other bits must be zero here) */
|
g->gcstp = 0; /* allow GC to run (other bits must be zero here) */
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
n = g->GCdebt; /* force to run one basic step */
|
newdebt = 0; /* force to run one basic step */
|
||||||
luaE_setdebt(g, g->GCdebt - n);
|
else if (g->GCdebt >= n - MAX_LMEM) /* no overflow? */
|
||||||
|
newdebt = g->GCdebt - n;
|
||||||
|
else /* overflow */
|
||||||
|
newdebt = -MAX_LMEM; /* set debt to miminum value */
|
||||||
|
luaE_setdebt(g, newdebt);
|
||||||
luaC_condGC(L, (void)0, work = 1);
|
luaC_condGC(L, (void)0, work = 1);
|
||||||
if (work && g->gcstate == GCSpause) /* end of cycle? */
|
if (work && g->gcstate == GCSpause) /* end of cycle? */
|
||||||
res = 1; /* signal it */
|
res = 1; /* signal it */
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
|
||||||
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
|
LUALIB_API int (luaL_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);
|
||||||
|
|
||||||
LUALIB_API void *luaL_alloc (void *ud, void *ptr, size_t osize,
|
LUALIB_API void *(luaL_alloc) (void *ud, void *ptr, size_t osize,
|
||||||
size_t nsize);
|
size_t nsize);
|
||||||
|
|
||||||
|
|
||||||
/* predefined references */
|
/* predefined references */
|
||||||
|
|
@ -103,7 +103,7 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||||
|
|
||||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||||
|
|
||||||
LUALIB_API unsigned luaL_makeseed (lua_State *L);
|
LUALIB_API unsigned (luaL_makeseed) (lua_State *L);
|
||||||
|
|
||||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||||
|
|
||||||
|
|
|
||||||
9
lcode.c
9
lcode.c
|
|
@ -827,7 +827,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||||
} /* FALLTHROUGH */
|
} /* FALLTHROUGH */
|
||||||
case VLOCAL: { /* already in a register */
|
case VLOCAL: { /* already in a register */
|
||||||
int temp = e->u.var.ridx;
|
int temp = e->u.var.ridx;
|
||||||
e->u.info = temp; /* (can't do a direct assignment; values overlap) */
|
e->u.info = temp; /* (avoid a direct assignment; values overlap) */
|
||||||
e->k = VNONRELOC; /* becomes a non-relocatable value */
|
e->k = VNONRELOC; /* becomes a non-relocatable value */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1365,7 +1365,7 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
||||||
luaK_exp2anyreg(fs, t); /* put it in a register */
|
luaK_exp2anyreg(fs, t); /* put it in a register */
|
||||||
if (t->k == VUPVAL) {
|
if (t->k == VUPVAL) {
|
||||||
lu_byte temp = cast_byte(t->u.info); /* upvalue index */
|
lu_byte temp = cast_byte(t->u.info); /* upvalue index */
|
||||||
t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */
|
t->u.ind.t = temp; /* (avoid a direct assignment; values overlap) */
|
||||||
lua_assert(isKstr(fs, k));
|
lua_assert(isKstr(fs, k));
|
||||||
fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
|
fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
|
||||||
}
|
}
|
||||||
|
|
@ -1373,12 +1373,13 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
||||||
int kreg = luaK_exp2anyreg(fs, k); /* put key in some register */
|
int kreg = luaK_exp2anyreg(fs, k); /* put key in some register */
|
||||||
lu_byte vreg = cast_byte(t->u.var.ridx); /* register with vararg param. */
|
lu_byte vreg = cast_byte(t->u.var.ridx); /* register with vararg param. */
|
||||||
lua_assert(vreg == fs->f->numparams);
|
lua_assert(vreg == fs->f->numparams);
|
||||||
t->u.ind.t = vreg; /* (avoid a direct assignment; values may overlap) */
|
t->u.ind.t = vreg; /* (avoid a direct assignment; values may overlap?) */
|
||||||
fillidxk(t, kreg, VVARGIND); /* 't' represents 'vararg[k]' */
|
fillidxk(t, kreg, VVARGIND); /* 't' represents 'vararg[k]' */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* register index of the table */
|
/* register index of the table */
|
||||||
t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info);
|
lu_byte temp = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info);
|
||||||
|
t->u.ind.t = temp; /* (avoid a direct assignment; values may overlap?) */
|
||||||
if (isKstr(fs, k))
|
if (isKstr(fs, k))
|
||||||
fillidxk(t, k->u.info, VINDEXSTR); /* literal short string */
|
fillidxk(t, k->u.info, VINDEXSTR); /* literal short string */
|
||||||
else if (isCint(k)) /* int. constant in proper range? */
|
else if (isCint(k)) /* int. constant in proper range? */
|
||||||
|
|
|
||||||
20
ldo.c
20
ldo.c
|
|
@ -221,13 +221,21 @@ l_noret luaD_errerr (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether stack has enough space to run a simple function (such
|
** Check whether stacks have enough space to run a simple function (such
|
||||||
** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack and
|
** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack, two
|
||||||
** 2 slots in the C stack.
|
** available CallInfos, and two "slots" in the C stack.
|
||||||
*/
|
*/
|
||||||
int luaD_checkminstack (lua_State *L) {
|
int luaD_checkminstack (lua_State *L) {
|
||||||
return ((stacksize(L) < MAXSTACK - BASIC_STACK_SIZE) &&
|
if (getCcalls(L) >= LUAI_MAXCCALLS - 2)
|
||||||
(getCcalls(L) < LUAI_MAXCCALLS - 2));
|
return 0; /* not enough C-stack slots */
|
||||||
|
if (L->ci->next == NULL && luaE_extendCI(L, 0) == NULL)
|
||||||
|
return 0; /* unable to allocate first ci */
|
||||||
|
if (L->ci->next->next == NULL && luaE_extendCI(L, 0) == NULL)
|
||||||
|
return 0; /* unable to allocate second ci */
|
||||||
|
if (L->stack_last.p - L->top.p >= BASIC_STACK_SIZE)
|
||||||
|
return 1; /* enough (BASIC_STACK_SIZE) free slots in the Lua stack */
|
||||||
|
else /* try to grow stack to a size with enough free slots */
|
||||||
|
return luaD_growstack(L, BASIC_STACK_SIZE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -616,7 +624,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L))
|
#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L, 1))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
4
lgc.c
4
lgc.c
|
|
@ -1293,7 +1293,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
|
||||||
correctgraylists(g);
|
correctgraylists(g);
|
||||||
checkSizes(L, g);
|
checkSizes(L, g);
|
||||||
g->gcstate = GCSpropagate; /* skip restart */
|
g->gcstate = GCSpropagate; /* skip restart */
|
||||||
if (!g->gcemergency && luaD_checkminstack(L))
|
if (g->tobefnz != NULL && !g->gcemergency && luaD_checkminstack(L))
|
||||||
callallpendingfinalizers(L);
|
callallpendingfinalizers(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1672,7 +1672,7 @@ static l_mem singlestep (lua_State *L, int fast) {
|
||||||
GCTM(L); /* call one finalizer */
|
GCTM(L); /* call one finalizer */
|
||||||
stepresult = CWUFIN;
|
stepresult = CWUFIN;
|
||||||
}
|
}
|
||||||
else { /* no more finalizers or emergency mode or no enough stack
|
else { /* no more finalizers or emergency mode or not enough stack
|
||||||
to run finalizers */
|
to run finalizers */
|
||||||
g->gcstate = GCSpause; /* finish collection */
|
g->gcstate = GCSpause; /* finish collection */
|
||||||
stepresult = step2pause;
|
stepresult = step2pause;
|
||||||
|
|
|
||||||
2
llex.c
2
llex.c
|
|
@ -188,7 +188,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source,
|
||||||
so they cannot be collected */
|
so they cannot be collected */
|
||||||
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env string */
|
ls->envn = luaS_newliteral(L, LUA_ENV); /* get env string */
|
||||||
ls->brkn = luaS_newliteral(L, "break"); /* get "break" string */
|
ls->brkn = luaS_newliteral(L, "break"); /* get "break" string */
|
||||||
#if defined(LUA_COMPAT_GLOBAL)
|
#if LUA_COMPAT_GLOBAL
|
||||||
/* compatibility mode: "global" is not a reserved word */
|
/* compatibility mode: "global" is not a reserved word */
|
||||||
ls->glbn = luaS_newliteral(L, "global"); /* get "global" string */
|
ls->glbn = luaS_newliteral(L, "global"); /* get "global" string */
|
||||||
ls->glbn->extra = 0; /* mark it as not reserved */
|
ls->glbn->extra = 0; /* mark it as not reserved */
|
||||||
|
|
|
||||||
12
llimits.h
12
llimits.h
|
|
@ -234,12 +234,12 @@ typedef unsigned long l_uint32;
|
||||||
|
|
||||||
/* floor division (defined as 'floor(a/b)') */
|
/* floor division (defined as 'floor(a/b)') */
|
||||||
#if !defined(luai_numidiv)
|
#if !defined(luai_numidiv)
|
||||||
#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b)))
|
#define luai_numidiv(L,a,b) l_floor(luai_numdiv(L,a,b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* float division */
|
/* float division */
|
||||||
#if !defined(luai_numdiv)
|
#if !defined(luai_numdiv)
|
||||||
#define luai_numdiv(L,a,b) ((a)/(b))
|
#define luai_numdiv(L,a,b) ((void)L, (a)/(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -267,10 +267,10 @@ typedef unsigned long l_uint32;
|
||||||
|
|
||||||
/* the others are quite standard operations */
|
/* the others are quite standard operations */
|
||||||
#if !defined(luai_numadd)
|
#if !defined(luai_numadd)
|
||||||
#define luai_numadd(L,a,b) ((a)+(b))
|
#define luai_numadd(L,a,b) ((void)L, (a)+(b))
|
||||||
#define luai_numsub(L,a,b) ((a)-(b))
|
#define luai_numsub(L,a,b) ((void)L, (a)-(b))
|
||||||
#define luai_nummul(L,a,b) ((a)*(b))
|
#define luai_nummul(L,a,b) ((void)L, (a)*(b))
|
||||||
#define luai_numunm(L,a) (-(a))
|
#define luai_numunm(L,a) ((void)L, -(a))
|
||||||
#define luai_numeq(a,b) ((a)==(b))
|
#define luai_numeq(a,b) ((a)==(b))
|
||||||
#define luai_numlt(a,b) ((a)<(b))
|
#define luai_numlt(a,b) ((a)<(b))
|
||||||
#define luai_numle(a,b) ((a)<=(b))
|
#define luai_numle(a,b) ((a)<=(b))
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||||
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
|
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
|
||||||
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETVARG */
|
,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETVARG */
|
||||||
,opmode(0, 0, 0, 0, 0, iABx) /* OP_ERRNNIL */
|
,opmode(0, 0, 0, 0, 0, iABx) /* OP_ERRNNIL */
|
||||||
,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
|
,opmode(0, 0, 1, 0, 0, iABC) /* OP_VARARGPREP */
|
||||||
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
15
lparser.c
15
lparser.c
|
|
@ -1682,13 +1682,22 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Control whether for-loop control variables are read-only
|
||||||
|
*/
|
||||||
|
#if LUA_COMPAT_LOOPVAR
|
||||||
|
#define LOOPVARKIND VDKREG
|
||||||
|
#else /* by default, these variables are read only */
|
||||||
|
#define LOOPVARKIND RDKCONST
|
||||||
|
#endif
|
||||||
|
|
||||||
static void fornum (LexState *ls, TString *varname, int line) {
|
static void fornum (LexState *ls, TString *varname, int line) {
|
||||||
/* fornum -> NAME = exp,exp[,exp] forbody */
|
/* fornum -> NAME = exp,exp[,exp] forbody */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int base = fs->freereg;
|
int base = fs->freereg;
|
||||||
new_localvarliteral(ls, "(for state)");
|
new_localvarliteral(ls, "(for state)");
|
||||||
new_localvarliteral(ls, "(for state)");
|
new_localvarliteral(ls, "(for state)");
|
||||||
new_varkind(ls, varname, RDKCONST); /* control variable */
|
new_varkind(ls, varname, LOOPVARKIND); /* control variable */
|
||||||
checknext(ls, '=');
|
checknext(ls, '=');
|
||||||
exp1(ls); /* initial value */
|
exp1(ls); /* initial value */
|
||||||
checknext(ls, ',');
|
checknext(ls, ',');
|
||||||
|
|
@ -1715,7 +1724,7 @@ static void forlist (LexState *ls, TString *indexname) {
|
||||||
new_localvarliteral(ls, "(for state)"); /* iterator function */
|
new_localvarliteral(ls, "(for state)"); /* iterator function */
|
||||||
new_localvarliteral(ls, "(for state)"); /* state */
|
new_localvarliteral(ls, "(for state)"); /* state */
|
||||||
new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
|
new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
|
||||||
new_varkind(ls, indexname, RDKCONST); /* control variable */
|
new_varkind(ls, indexname, LOOPVARKIND); /* control variable */
|
||||||
/* other declared variables */
|
/* other declared variables */
|
||||||
while (testnext(ls, ',')) {
|
while (testnext(ls, ',')) {
|
||||||
new_localvar(ls, str_checkname(ls));
|
new_localvar(ls, str_checkname(ls));
|
||||||
|
|
@ -2111,7 +2120,7 @@ static void statement (LexState *ls) {
|
||||||
gotostat(ls, line);
|
gotostat(ls, line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if defined(LUA_COMPAT_GLOBAL)
|
#if LUA_COMPAT_GLOBAL
|
||||||
case TK_NAME: {
|
case TK_NAME: {
|
||||||
/* compatibility code to parse global keyword when "global"
|
/* compatibility code to parse global keyword when "global"
|
||||||
is not reserved */
|
is not reserved */
|
||||||
|
|
|
||||||
17
lstate.c
17
lstate.c
|
|
@ -68,14 +68,19 @@ void luaE_setdebt (global_State *g, l_mem debt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CallInfo *luaE_extendCI (lua_State *L) {
|
CallInfo *luaE_extendCI (lua_State *L, int err) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
lua_assert(L->ci->next == NULL);
|
ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
|
||||||
ci = luaM_new(L, CallInfo);
|
if (l_unlikely(ci == NULL)) { /* allocation failed? */
|
||||||
lua_assert(L->ci->next == NULL);
|
if (err)
|
||||||
L->ci->next = ci;
|
luaM_error(L); /* raise the error */
|
||||||
|
return NULL; /* else only report it */
|
||||||
|
}
|
||||||
|
ci->next = L->ci->next;
|
||||||
ci->previous = L->ci;
|
ci->previous = L->ci;
|
||||||
ci->next = NULL;
|
L->ci->next = ci;
|
||||||
|
if (ci->next)
|
||||||
|
ci->next->previous = ci;
|
||||||
ci->u.l.trap = 0;
|
ci->u.l.trap = 0;
|
||||||
L->nci++;
|
L->nci++;
|
||||||
return ci;
|
return ci;
|
||||||
|
|
|
||||||
2
lstate.h
2
lstate.h
|
|
@ -438,7 +438,7 @@ union GCUnion {
|
||||||
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
|
LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
|
||||||
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
|
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
|
||||||
LUAI_FUNC lu_mem luaE_threadsize (lua_State *L);
|
LUAI_FUNC lu_mem luaE_threadsize (lua_State *L);
|
||||||
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
|
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L, int err);
|
||||||
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
|
||||||
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
LUAI_FUNC void luaE_checkcstack (lua_State *L);
|
||||||
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
LUAI_FUNC void luaE_incCstack (lua_State *L);
|
||||||
|
|
|
||||||
|
|
@ -141,8 +141,8 @@ static int str_rep (lua_State *L) {
|
||||||
const char *s = luaL_checklstring(L, 1, &len);
|
const char *s = luaL_checklstring(L, 1, &len);
|
||||||
lua_Integer n = luaL_checkinteger(L, 2);
|
lua_Integer n = luaL_checkinteger(L, 2);
|
||||||
const char *sep = luaL_optlstring(L, 3, "", &lsep);
|
const char *sep = luaL_optlstring(L, 3, "", &lsep);
|
||||||
if (n <= 0)
|
if (n <= 0 || (len | lsep) == 0)
|
||||||
lua_pushliteral(L, "");
|
lua_pushliteral(L, ""); /* no repetitions or both strings empty */
|
||||||
else if (l_unlikely(len > MAX_SIZE - lsep ||
|
else if (l_unlikely(len > MAX_SIZE - lsep ||
|
||||||
cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n))
|
cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n))
|
||||||
return luaL_error(L, "resulting string too large");
|
return luaL_error(L, "resulting string too large");
|
||||||
|
|
@ -968,7 +968,7 @@ static int str_gsub (lua_State *L) {
|
||||||
reprepstate(&ms); /* (re)prepare state for new match */
|
reprepstate(&ms); /* (re)prepare state for new match */
|
||||||
if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
|
if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
|
||||||
n++;
|
n++;
|
||||||
changed = add_value(&ms, &b, src, e, tr) | changed;
|
changed = add_value(&ms, &b, src, e, tr) || changed;
|
||||||
src = lastmatch = e;
|
src = lastmatch = e;
|
||||||
}
|
}
|
||||||
else if (src < ms.src_end) /* otherwise, skip one character */
|
else if (src < ms.src_end) /* otherwise, skip one character */
|
||||||
|
|
@ -1726,7 +1726,7 @@ static int str_packsize (lua_State *L) {
|
||||||
luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
|
luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
|
||||||
"variable-length format");
|
"variable-length format");
|
||||||
size += ntoalign; /* total space used by option */
|
size += ntoalign; /* total space used by option */
|
||||||
luaL_argcheck(L, totalsize <= LUA_MAXINTEGER - size,
|
luaL_argcheck(L, totalsize <= MAX_SIZE - size,
|
||||||
1, "format result too large");
|
1, "format result too large");
|
||||||
totalsize += size;
|
totalsize += size;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
ltable.c
16
ltable.c
|
|
@ -651,10 +651,9 @@ static void reinserthash (lua_State *L, Table *ot, Table *t) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Exchange the hash part of 't1' and 't2'. (In 'flags', only the
|
** Exchange the hash part of 't1' and 't2'. (In 'flags', only the dummy
|
||||||
** dummy bit must be exchanged: The 'isrealasize' is not related
|
** bit must be exchanged: The metamethod bits do not change during a
|
||||||
** to the hash part, and the metamethod bits do not change during
|
** resize, so the "real" table can keep their values.)
|
||||||
** a resize, so the "real" table can keep their values.)
|
|
||||||
*/
|
*/
|
||||||
static void exchangehashpart (Table *t1, Table *t2) {
|
static void exchangehashpart (Table *t1, Table *t2) {
|
||||||
lu_byte lsizenode = t1->lsizenode;
|
lu_byte lsizenode = t1->lsizenode;
|
||||||
|
|
@ -1156,14 +1155,15 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
||||||
lua_assert(hres != HOK);
|
lua_assert(hres != HOK);
|
||||||
if (hres == HNOTFOUND) {
|
if (hres == HNOTFOUND) {
|
||||||
TValue aux;
|
TValue aux;
|
||||||
|
const TValue *actk = key; /* actual key to insert */
|
||||||
if (l_unlikely(ttisnil(key)))
|
if (l_unlikely(ttisnil(key)))
|
||||||
luaG_runerror(L, "table index is nil");
|
luaG_runerror(L, "table index is nil");
|
||||||
else if (ttisfloat(key)) {
|
else if (ttisfloat(key)) {
|
||||||
lua_Number f = fltvalue(key);
|
lua_Number f = fltvalue(key);
|
||||||
lua_Integer k;
|
lua_Integer k;
|
||||||
if (luaV_flttointeger(f, &k, F2Ieq)) {
|
if (luaV_flttointeger(f, &k, F2Ieq)) { /* is key equal to an integer? */
|
||||||
setivalue(&aux, k); /* key is equal to an integer */
|
setivalue(&aux, k);
|
||||||
key = &aux; /* insert it as an integer */
|
actk = &aux; /* use the integer as the key */
|
||||||
}
|
}
|
||||||
else if (l_unlikely(luai_numisnan(f)))
|
else if (l_unlikely(luai_numisnan(f)))
|
||||||
luaG_runerror(L, "table index is NaN");
|
luaG_runerror(L, "table index is NaN");
|
||||||
|
|
@ -1176,7 +1176,7 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
||||||
L->top.p--;
|
L->top.p--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
luaH_newkey(L, t, key, value);
|
luaH_newkey(L, t, actk, value);
|
||||||
}
|
}
|
||||||
else if (hres > 0) { /* regular Node? */
|
else if (hres > 0) { /* regular Node? */
|
||||||
setobj2t(L, gval(gnode(t, hres - HFIRSTNODE)), value);
|
setobj2t(L, gval(gnode(t, hres - HFIRSTNODE)), value);
|
||||||
|
|
|
||||||
11
ltablib.c
11
ltablib.c
|
|
@ -42,15 +42,17 @@ static int checkfield (lua_State *L, const char *key, int n) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check that 'arg' either is a table or can behave like one (that is,
|
** Check that 'arg' either is a table or can behave like one (that is,
|
||||||
** has a metatable with the required metamethods)
|
** has a metatable with the required metamethods).
|
||||||
*/
|
*/
|
||||||
static void checktab (lua_State *L, int arg, int what) {
|
static void checktab (lua_State *L, int arg, int what) {
|
||||||
if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */
|
int tp = lua_type(L, arg);
|
||||||
|
if (tp != LUA_TTABLE) { /* is it not a table? */
|
||||||
int n = 1; /* number of elements to pop */
|
int n = 1; /* number of elements to pop */
|
||||||
if (lua_getmetatable(L, arg) && /* must have metatable */
|
if (lua_getmetatable(L, arg) && /* must have metatable */
|
||||||
(!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
|
(!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
|
||||||
(!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
|
(!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
|
||||||
(!(what & TAB_L) || checkfield(L, "__len", ++n))) {
|
(!(what & TAB_L) || /* strings don't need '__len' to have a length */
|
||||||
|
tp == LUA_TSTRING || checkfield(L, "__len", ++n))) {
|
||||||
lua_pop(L, n); /* pop metatable and tested metamethods */
|
lua_pop(L, n); /* pop metatable and tested metamethods */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -204,8 +206,9 @@ static int tpack (lua_State *L) {
|
||||||
|
|
||||||
static int tunpack (lua_State *L) {
|
static int tunpack (lua_State *L) {
|
||||||
lua_Unsigned n;
|
lua_Unsigned n;
|
||||||
|
lua_Integer len = aux_getn(L, 1, TAB_R);
|
||||||
lua_Integer i = luaL_optinteger(L, 2, 1);
|
lua_Integer i = luaL_optinteger(L, 2, 1);
|
||||||
lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
|
lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, len);
|
||||||
if (i > e) return 0; /* empty range */
|
if (i > e) return 0; /* empty range */
|
||||||
n = l_castS2U(e) - l_castS2U(i); /* number of elements minus 1 */
|
n = l_castS2U(e) - l_castS2U(i); /* number of elements minus 1 */
|
||||||
if (l_unlikely(n >= (unsigned int)INT_MAX ||
|
if (l_unlikely(n >= (unsigned int)INT_MAX ||
|
||||||
|
|
|
||||||
23
ltests.c
23
ltests.c
|
|
@ -1106,6 +1106,27 @@ static int stacklevel (lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int resetCI (lua_State *L) {
|
||||||
|
CallInfo *ci = L->ci;
|
||||||
|
while (ci->next != NULL) {
|
||||||
|
CallInfo *tofree = ci->next;
|
||||||
|
ci->next = ci->next->next;
|
||||||
|
luaM_free(L, tofree);
|
||||||
|
L->nci--;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int reallocstack (lua_State *L) {
|
||||||
|
int n = cast_int(luaL_checkinteger(L, 1));
|
||||||
|
lua_lock(L);
|
||||||
|
luaD_reallocstack(L, cast_int(L->top.p - L->stack.p) + n, 1);
|
||||||
|
lua_unlock(L);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int table_query (lua_State *L) {
|
static int table_query (lua_State *L) {
|
||||||
const Table *t;
|
const Table *t;
|
||||||
int i = cast_int(luaL_optinteger(L, 2, -1));
|
int i = cast_int(luaL_optinteger(L, 2, -1));
|
||||||
|
|
@ -2182,6 +2203,8 @@ static const struct luaL_Reg tests_funcs[] = {
|
||||||
{"s2d", s2d},
|
{"s2d", s2d},
|
||||||
{"sethook", sethook},
|
{"sethook", sethook},
|
||||||
{"stacklevel", stacklevel},
|
{"stacklevel", stacklevel},
|
||||||
|
{"resetCI", resetCI},
|
||||||
|
{"reallocstack", reallocstack},
|
||||||
{"sizes", get_sizes},
|
{"sizes", get_sizes},
|
||||||
{"testC", testC},
|
{"testC", testC},
|
||||||
{"makeCfunc", makeCfunc},
|
{"makeCfunc", makeCfunc},
|
||||||
|
|
|
||||||
1
ltests.h
1
ltests.h
|
|
@ -14,6 +14,7 @@
|
||||||
/* test Lua with compatibility code */
|
/* test Lua with compatibility code */
|
||||||
#define LUA_COMPAT_MATHLIB
|
#define LUA_COMPAT_MATHLIB
|
||||||
#undef LUA_COMPAT_GLOBAL
|
#undef LUA_COMPAT_GLOBAL
|
||||||
|
#define LUA_COMPAT_GLOBAL 0
|
||||||
|
|
||||||
|
|
||||||
#define LUA_DEBUG
|
#define LUA_DEBUG
|
||||||
|
|
|
||||||
2
ltm.h
2
ltm.h
|
|
@ -49,7 +49,7 @@ typedef enum {
|
||||||
** Mask with 1 in all fast-access methods. A 1 in any of these bits
|
** Mask with 1 in all fast-access methods. A 1 in any of these bits
|
||||||
** in the flag of a (meta)table means the metatable does not have the
|
** in the flag of a (meta)table means the metatable does not have the
|
||||||
** corresponding metamethod field. (Bit 6 of the flag indicates that
|
** corresponding metamethod field. (Bit 6 of the flag indicates that
|
||||||
** the table is using the dummy node; bit 7 is used for 'isrealasize'.)
|
** the table is using the dummy node.)
|
||||||
*/
|
*/
|
||||||
#define maskflags cast_byte(~(~0u << (TM_EQ + 1)))
|
#define maskflags cast_byte(~(~0u << (TM_EQ + 1)))
|
||||||
|
|
||||||
|
|
|
||||||
46
lua.c
46
lua.c
|
|
@ -30,6 +30,12 @@
|
||||||
#define LUA_INIT_VAR "LUA_INIT"
|
#define LUA_INIT_VAR "LUA_INIT"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Name of the environment variable with the name of the readline library */
|
||||||
|
#if !defined(LUA_RLLIB_VAR)
|
||||||
|
#define LUA_RLLIB_VAR "LUA_READLINELIB"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
|
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -374,12 +380,21 @@ static int runargs (lua_State *L, char **argv, int n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *(*l_getenv)(const char *name);
|
||||||
|
|
||||||
|
/* Function to ignore environment variables, used by option -E */
|
||||||
|
static char *no_getenv (const char *name) {
|
||||||
|
UNUSED(name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handle_luainit (lua_State *L) {
|
static int handle_luainit (lua_State *L) {
|
||||||
const char *name = "=" LUA_INITVARVERSION;
|
const char *name = "=" LUA_INITVARVERSION;
|
||||||
const char *init = getenv(name + 1);
|
const char *init = l_getenv(name + 1);
|
||||||
if (init == NULL) {
|
if (init == NULL) {
|
||||||
name = "=" LUA_INIT_VAR;
|
name = "=" LUA_INIT_VAR;
|
||||||
init = getenv(name + 1); /* try alternative name */
|
init = l_getenv(name + 1); /* try alternative name */
|
||||||
}
|
}
|
||||||
if (init == NULL) return LUA_OK;
|
if (init == NULL) return LUA_OK;
|
||||||
else if (init[0] == '@')
|
else if (init[0] == '@')
|
||||||
|
|
@ -498,18 +513,24 @@ static void lua_freeline (char *line) {
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
static void lua_initreadline (lua_State *L) {
|
static void lua_initreadline (lua_State *L) {
|
||||||
void *lib = dlopen(LUA_READLINELIB, RTLD_NOW | RTLD_LOCAL);
|
const char *rllib = l_getenv(LUA_RLLIB_VAR); /* name of readline library */
|
||||||
if (lib == NULL)
|
void *lib; /* library handle */
|
||||||
lua_warning(L, "library '" LUA_READLINELIB "' not found", 0);
|
if (rllib == NULL) /* no environment variable? */
|
||||||
else {
|
rllib = LUA_READLINELIB; /* use default name */
|
||||||
|
lib = dlopen(rllib, RTLD_NOW | RTLD_LOCAL);
|
||||||
|
if (lib != NULL) {
|
||||||
const char **name = cast(const char**, dlsym(lib, "rl_readline_name"));
|
const char **name = cast(const char**, dlsym(lib, "rl_readline_name"));
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
*name = "lua";
|
*name = "lua";
|
||||||
l_readline = cast(l_readlineT, cast_func(dlsym(lib, "readline")));
|
l_readline = cast(l_readlineT, cast_func(dlsym(lib, "readline")));
|
||||||
l_addhist = cast(l_addhistT, cast_func(dlsym(lib, "add_history")));
|
l_addhist = cast(l_addhistT, cast_func(dlsym(lib, "add_history")));
|
||||||
if (l_readline == NULL)
|
if (l_readline != NULL) /* could load readline function? */
|
||||||
lua_warning(L, "unable to load 'readline'", 0);
|
return; /* everything ok */
|
||||||
|
/* else emit a warning */
|
||||||
}
|
}
|
||||||
|
lua_warning(L, "unable to load readline library '", 1);
|
||||||
|
lua_warning(L, rllib, 1);
|
||||||
|
lua_warning(L, "'", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* }{ */
|
#else /* }{ */
|
||||||
|
|
@ -715,17 +736,18 @@ static int pmain (lua_State *L) {
|
||||||
if (args & has_v) /* option '-v'? */
|
if (args & has_v) /* option '-v'? */
|
||||||
print_version();
|
print_version();
|
||||||
if (args & has_E) { /* option '-E'? */
|
if (args & has_E) { /* option '-E'? */
|
||||||
|
l_getenv = &no_getenv; /* program will ignore environment variables */
|
||||||
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
|
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
|
||||||
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
l_getenv = &getenv;
|
||||||
luai_openlibs(L); /* open standard libraries */
|
luai_openlibs(L); /* open standard libraries */
|
||||||
createargtable(L, argv, argc, script); /* create table 'arg' */
|
createargtable(L, argv, argc, script); /* create table 'arg' */
|
||||||
lua_gc(L, LUA_GCRESTART); /* start GC... */
|
lua_gc(L, LUA_GCRESTART); /* start GC... */
|
||||||
lua_gc(L, LUA_GCGEN); /* ...in generational mode */
|
lua_gc(L, LUA_GCGEN); /* ...in generational mode */
|
||||||
if (!(args & has_E)) { /* no option '-E'? */
|
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
|
||||||
if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */
|
return 0; /* error running LUA_INIT */
|
||||||
return 0; /* error running LUA_INIT */
|
|
||||||
}
|
|
||||||
if (!runargs(L, argv, optlim)) /* execute arguments -e, -l, and -W */
|
if (!runargs(L, argv, optlim)) /* execute arguments -e, -l, and -W */
|
||||||
return 0; /* something failed */
|
return 0; /* something failed */
|
||||||
if (script > 0) { /* execute main script (if there is one) */
|
if (script > 0) { /* execute main script (if there is one) */
|
||||||
|
|
|
||||||
6
lua.h
6
lua.h
|
|
@ -13,13 +13,13 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2025 Lua.org, PUC-Rio"
|
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2026 Lua.org, PUC-Rio"
|
||||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
|
||||||
|
|
||||||
|
|
||||||
#define LUA_VERSION_MAJOR_N 5
|
#define LUA_VERSION_MAJOR_N 5
|
||||||
#define LUA_VERSION_MINOR_N 5
|
#define LUA_VERSION_MINOR_N 5
|
||||||
#define LUA_VERSION_RELEASE_N 0
|
#define LUA_VERSION_RELEASE_N 1
|
||||||
|
|
||||||
#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N)
|
#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N)
|
||||||
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N)
|
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N)
|
||||||
|
|
@ -521,7 +521,7 @@ struct lua_Debug {
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Copyright (C) 1994-2025 Lua.org, PUC-Rio.
|
* Copyright (C) 1994-2026 Lua.org, PUC-Rio.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
||||||
46
luaconf.h
46
luaconf.h
|
|
@ -70,15 +70,19 @@
|
||||||
#if defined(LUA_USE_LINUX)
|
#if defined(LUA_USE_LINUX)
|
||||||
#define LUA_USE_POSIX
|
#define LUA_USE_POSIX
|
||||||
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
|
#define LUA_USE_DLOPEN /* needs an extra library: -ldl */
|
||||||
|
#if !defined(LUA_READLINELIB)
|
||||||
#define LUA_READLINELIB "libreadline.so"
|
#define LUA_READLINELIB "libreadline.so"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(LUA_USE_MACOSX)
|
#if defined(LUA_USE_MACOSX)
|
||||||
#define LUA_USE_POSIX
|
#define LUA_USE_POSIX
|
||||||
#define LUA_USE_DLOPEN /* macOS does not need -ldl */
|
#define LUA_USE_DLOPEN /* macOS does not need -ldl */
|
||||||
|
#if !defined(LUA_READLINELIB)
|
||||||
#define LUA_READLINELIB "libedit.dylib"
|
#define LUA_READLINELIB "libedit.dylib"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(LUA_USE_IOS)
|
#if defined(LUA_USE_IOS)
|
||||||
|
|
@ -224,17 +228,17 @@
|
||||||
|
|
||||||
#if !defined(LUA_PATH_DEFAULT)
|
#if !defined(LUA_PATH_DEFAULT)
|
||||||
#define LUA_PATH_DEFAULT \
|
#define LUA_PATH_DEFAULT \
|
||||||
LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
|
LUA_LDIR "?.lua;" LUA_LDIR "?\\init.lua;" \
|
||||||
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \
|
LUA_CDIR "?.lua;" LUA_CDIR "?\\init.lua;" \
|
||||||
LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \
|
LUA_SHRDIR "?.lua;" LUA_SHRDIR "?\\init.lua;" \
|
||||||
".\\?.lua;" ".\\?\\init.lua"
|
".\\?.lua;" ".\\?\\init.lua"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(LUA_CPATH_DEFAULT)
|
#if !defined(LUA_CPATH_DEFAULT)
|
||||||
#define LUA_CPATH_DEFAULT \
|
#define LUA_CPATH_DEFAULT \
|
||||||
LUA_CDIR"?.dll;" \
|
LUA_CDIR "?.dll;" \
|
||||||
LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
|
LUA_CDIR "..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \
|
||||||
LUA_CDIR"loadall.dll;" ".\\?.dll"
|
LUA_CDIR "loadall.dll;" ".\\?.dll"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* }{ */
|
#else /* }{ */
|
||||||
|
|
@ -245,14 +249,14 @@
|
||||||
|
|
||||||
#if !defined(LUA_PATH_DEFAULT)
|
#if !defined(LUA_PATH_DEFAULT)
|
||||||
#define LUA_PATH_DEFAULT \
|
#define LUA_PATH_DEFAULT \
|
||||||
LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \
|
LUA_LDIR "?.lua;" LUA_LDIR "?/init.lua;" \
|
||||||
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \
|
LUA_CDIR "?.lua;" LUA_CDIR "?/init.lua;" \
|
||||||
"./?.lua;" "./?/init.lua"
|
"./?.lua;" "./?/init.lua"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(LUA_CPATH_DEFAULT)
|
#if !defined(LUA_CPATH_DEFAULT)
|
||||||
#define LUA_CPATH_DEFAULT \
|
#define LUA_CPATH_DEFAULT \
|
||||||
LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so"
|
LUA_CDIR "?.so;" LUA_CDIR "loadall.so;" "./?.so"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* } */
|
#endif /* } */
|
||||||
|
|
@ -339,7 +343,18 @@
|
||||||
/*
|
/*
|
||||||
@@ LUA_COMPAT_GLOBAL avoids 'global' being a reserved word
|
@@ LUA_COMPAT_GLOBAL avoids 'global' being a reserved word
|
||||||
*/
|
*/
|
||||||
#define LUA_COMPAT_GLOBAL
|
#if !defined(LUA_COMPAT_GLOBAL)
|
||||||
|
#define LUA_COMPAT_GLOBAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ LUA_COMPAT_LOOPVAR makes for-loop control variables not read-only,
|
||||||
|
** as they were in previous versions.
|
||||||
|
*/
|
||||||
|
#if !defined(LUA_COMPAT_LOOPVAR)
|
||||||
|
#define LUA_COMPAT_LOOPVAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -721,10 +736,17 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
|
@@ LUAI_MAXALIGN defines fields that ensure proper alignment for
|
||||||
** maximum alignment for the other items in that union.
|
** memory areas offered by Lua (e.g., userdata memory).
|
||||||
|
** Add fields to it if you need alignment for non-ISO objects.
|
||||||
*/
|
*/
|
||||||
|
#if defined(LLONG_MAX)
|
||||||
|
/* use ISO C99 stuff */
|
||||||
|
#define LUAI_MAXALIGN long double u; void *s; long long l
|
||||||
|
#else
|
||||||
|
/* use only C89 stuff */
|
||||||
#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l
|
#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l
|
||||||
|
#endif
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ static const char *utf8_decode (const char *s, l_uint32 *val, int strict) {
|
||||||
l_uint32 res = 0; /* final result */
|
l_uint32 res = 0; /* final result */
|
||||||
if (c < 0x80) /* ASCII? */
|
if (c < 0x80) /* ASCII? */
|
||||||
res = c;
|
res = c;
|
||||||
|
else if (c >= 0xfe) /* c >= 1111 1110b ? */
|
||||||
|
return NULL; /* would need six or more continuation bytes */
|
||||||
else {
|
else {
|
||||||
int count = 0; /* to count number of continuation bytes */
|
int count = 0; /* to count number of continuation bytes */
|
||||||
for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
|
for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
|
||||||
|
|
@ -64,8 +66,9 @@ static const char *utf8_decode (const char *s, l_uint32 *val, int strict) {
|
||||||
return NULL; /* invalid byte sequence */
|
return NULL; /* invalid byte sequence */
|
||||||
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
|
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
|
||||||
}
|
}
|
||||||
|
lua_assert(count <= 5);
|
||||||
res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */
|
res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */
|
||||||
if (count > 5 || res > MAXUTF || res < limits[count])
|
if (res > MAXUTF || res < limits[count])
|
||||||
return NULL; /* invalid byte sequence */
|
return NULL; /* invalid byte sequence */
|
||||||
s += count; /* skip continuation bytes read */
|
s += count; /* skip continuation bytes read */
|
||||||
}
|
}
|
||||||
|
|
@ -146,7 +149,7 @@ static int codepoint (lua_State *L) {
|
||||||
static void pushutfchar (lua_State *L, int arg) {
|
static void pushutfchar (lua_State *L, int arg) {
|
||||||
lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg);
|
lua_Unsigned code = (lua_Unsigned)luaL_checkinteger(L, arg);
|
||||||
luaL_argcheck(L, code <= MAXUTF, arg, "value out of range");
|
luaL_argcheck(L, code <= MAXUTF, arg, "value out of range");
|
||||||
lua_pushfstring(L, "%U", (long)code);
|
lua_pushfstring(L, "%U", cast(unsigned long, code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
6
lvm.c
6
lvm.c
|
|
@ -268,9 +268,9 @@ static int forprep (lua_State *L, StkId ra) {
|
||||||
/*
|
/*
|
||||||
** Execute a step of a float numerical for loop, returning
|
** Execute a step of a float numerical for loop, returning
|
||||||
** true iff the loop must continue. (The integer case is
|
** true iff the loop must continue. (The integer case is
|
||||||
** written online with opcode OP_FORLOOP, for performance.)
|
** written inline with opcode OP_FORLOOP, for performance.)
|
||||||
*/
|
*/
|
||||||
static int floatforloop (StkId ra) {
|
static int floatforloop (lua_State *L, StkId ra) {
|
||||||
lua_Number step = fltvalue(s2v(ra + 1));
|
lua_Number step = fltvalue(s2v(ra + 1));
|
||||||
lua_Number limit = fltvalue(s2v(ra));
|
lua_Number limit = fltvalue(s2v(ra));
|
||||||
lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
|
lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */
|
||||||
|
|
@ -1841,7 +1841,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
||||||
pc -= GETARG_Bx(i); /* jump back */
|
pc -= GETARG_Bx(i); /* jump back */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (floatforloop(ra)) /* float loop */
|
else if (floatforloop(L, ra)) /* float loop */
|
||||||
pc -= GETARG_Bx(i); /* jump back */
|
pc -= GETARG_Bx(i); /* jump back */
|
||||||
updatetrap(ci); /* allows a signal to break the loop */
|
updatetrap(ci); /* allows a signal to break the loop */
|
||||||
vmbreak;
|
vmbreak;
|
||||||
|
|
|
||||||
2
makefile
2
makefile
|
|
@ -60,7 +60,7 @@ CWARNS= $(CWARNSCPP) $(CWARNSC) $(CWARNGCC)
|
||||||
# create problems; some are only available in newer gcc versions. To
|
# create problems; some are only available in newer gcc versions. To
|
||||||
# use some of them, we also have to define an environment variable
|
# use some of them, we also have to define an environment variable
|
||||||
# ASAN_OPTIONS="detect_invalid_pointer_pairs=2".
|
# ASAN_OPTIONS="detect_invalid_pointer_pairs=2".
|
||||||
# -fsanitize=undefined
|
# -fsanitize=undefined (you may need to add "-lubsan" to libs)
|
||||||
# -fsanitize=pointer-subtract -fsanitize=address -fsanitize=pointer-compare
|
# -fsanitize=pointer-subtract -fsanitize=address -fsanitize=pointer-compare
|
||||||
# TESTS= -DLUA_USER_H='"ltests.h"' -Og -g
|
# TESTS= -DLUA_USER_H='"ltests.h"' -Og -g
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
|
||||||
<p>
|
<p>
|
||||||
<small>
|
<small>
|
||||||
<a href="http://www.lua.org/copyright.html">Copyright</a>
|
<a href="http://www.lua.org/copyright.html">Copyright</a>
|
||||||
© 2025 Lua.org, PUC-Rio. All rights reserved.
|
© 2026 Lua.org, PUC-Rio. All rights reserved.
|
||||||
</small>
|
</small>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2692,7 +2692,19 @@ which behaves like a nil value.
|
||||||
|
|
||||||
@sect3{constchar|@title{Pointers to Strings}
|
@sect3{constchar|@title{Pointers to Strings}
|
||||||
|
|
||||||
Several functions in the API return pointers (@T{const char*})
|
Several functions in the API accept pointers (@T{const char*})
|
||||||
|
to C strings.
|
||||||
|
Some of there parameters have an associated length (@T{size_t}).
|
||||||
|
Unless stated otherwise,
|
||||||
|
when there is an associated length,
|
||||||
|
the string can contain embedded zeros;
|
||||||
|
moreover, the pointer can be @id{NULL} if the length is zero.
|
||||||
|
When there is no associated length,
|
||||||
|
the pointer must point to a zero-terminated string.
|
||||||
|
In any case, the string contents should remain unchanged
|
||||||
|
until the function returns.
|
||||||
|
|
||||||
|
Several functions in the API also return pointers (@T{const char*})
|
||||||
to Lua strings in the stack.
|
to Lua strings in the stack.
|
||||||
(See @Lid{lua_pushfstring}, @Lid{lua_pushlstring},
|
(See @Lid{lua_pushfstring}, @Lid{lua_pushlstring},
|
||||||
@Lid{lua_pushstring}, and @Lid{lua_tolstring}.
|
@Lid{lua_pushstring}, and @Lid{lua_tolstring}.
|
||||||
|
|
@ -3903,8 +3915,12 @@ like any Lua object.
|
||||||
This function creates and pushes on the stack a new full userdata,
|
This function creates and pushes on the stack a new full userdata,
|
||||||
with @id{nuvalue} associated Lua values, called @id{user values},
|
with @id{nuvalue} associated Lua values, called @id{user values},
|
||||||
plus an associated block of raw memory with @id{size} bytes.
|
plus an associated block of raw memory with @id{size} bytes.
|
||||||
(The user values can be set and read with the functions
|
|
||||||
@Lid{lua_setiuservalue} and @Lid{lua_getiuservalue}.)
|
The user values can be set and read with the functions
|
||||||
|
@Lid{lua_setiuservalue} and @Lid{lua_getiuservalue}.
|
||||||
|
The block of memory is suitably aligned for any @N{ISO C} object.
|
||||||
|
(See macro @id{LUAI_MAXALIGN} in file @id{luaconf.h} for other
|
||||||
|
alignment requirements.)
|
||||||
|
|
||||||
The function returns the address of the block of memory.
|
The function returns the address of the block of memory.
|
||||||
Lua ensures that this address is valid as long as
|
Lua ensures that this address is valid as long as
|
||||||
|
|
@ -9594,12 +9610,18 @@ change between versions.
|
||||||
@item{
|
@item{
|
||||||
The word @Rw{global} is a reserved word.
|
The word @Rw{global} is a reserved word.
|
||||||
Do not use it as a regular name.
|
Do not use it as a regular name.
|
||||||
|
|
||||||
|
The compilation option @id{LUA_COMPAT_GLOBAL} (see @id{luaconf.h})
|
||||||
|
makes @id{global} a regular word.
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
The control variable in @Rw{for} loops is read only.
|
The control variable in @Rw{for} loops is read only.
|
||||||
If you need to change it,
|
If you need to change it,
|
||||||
declare a local variable with the same name in the loop body.
|
declare a local variable with the same name in the loop body.
|
||||||
|
|
||||||
|
The compilation option @id{LUA_COMPAT_LOOPVAR} (see @id{luaconf.h})
|
||||||
|
makes these variables regular (writable).
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
|
|
@ -9725,7 +9747,7 @@ and @bnfNter{LiteralString}, see @See{lexical}.)
|
||||||
@OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody
|
@OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody
|
||||||
@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
|
@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
|
||||||
@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
|
@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
|
||||||
@OrNL @Rw{global} attnamelist
|
@OrNL @Rw{global} attnamelist @bnfopt{@bnfter{=} explist}
|
||||||
@OrNL @Rw{global} @bnfopt{attrib} @bnfter{*}
|
@OrNL @Rw{global} @bnfopt{attrib} @bnfter{*}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -707,4 +707,46 @@ end
|
||||||
|
|
||||||
collectgarbage(oldmode)
|
collectgarbage(oldmode)
|
||||||
|
|
||||||
|
|
||||||
|
if T then
|
||||||
|
print("testing stack issues when calling finalizers")
|
||||||
|
|
||||||
|
local X
|
||||||
|
local obj
|
||||||
|
|
||||||
|
local function initobj ()
|
||||||
|
X = false
|
||||||
|
obj = setmetatable({}, {__gc = function () X = true end})
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loop (n)
|
||||||
|
if n > 0 then loop(n - 1) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- should not try to call finalizer without a CallInfo available
|
||||||
|
initobj()
|
||||||
|
loop(20) -- ensure stack space
|
||||||
|
T.resetCI() -- remove extra CallInfos
|
||||||
|
T.alloccount(0) -- cannot allocate more CallInfos
|
||||||
|
obj = nil
|
||||||
|
collectgarbage() -- will not call finalizer
|
||||||
|
T.alloccount()
|
||||||
|
assert(X == false)
|
||||||
|
collectgarbage() -- now will call finalizer (it was still pending)
|
||||||
|
assert(X == true)
|
||||||
|
|
||||||
|
-- should not try to call finalizer without stack space available
|
||||||
|
initobj()
|
||||||
|
loop(5) -- ensure enough CallInfos
|
||||||
|
T.reallocstack(0) -- remove extra stack slots
|
||||||
|
T.alloccount(0) -- cannot reallocate stack
|
||||||
|
obj = nil
|
||||||
|
collectgarbage() -- will not call finalizer
|
||||||
|
T.alloccount()
|
||||||
|
assert(X == false)
|
||||||
|
collectgarbage() -- now will call finalizer (it was still pending)
|
||||||
|
assert(X == true)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
print('OK')
|
print('OK')
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,9 @@ end
|
||||||
|
|
||||||
RUN('lua -v')
|
RUN('lua -v')
|
||||||
|
|
||||||
|
RUN('lua -v > %s', out)
|
||||||
|
local release = string.match(getoutput(), "Lua (%d+%.%d+%.%d+)")
|
||||||
|
|
||||||
print(string.format("(temporary program file used in these tests: %s)", prog))
|
print(string.format("(temporary program file used in these tests: %s)", prog))
|
||||||
|
|
||||||
-- running stdin as a file
|
-- running stdin as a file
|
||||||
|
|
@ -167,7 +170,9 @@ checkout("10\n11\n")
|
||||||
-- test errors in LUA_INIT
|
-- test errors in LUA_INIT
|
||||||
NoRun('LUA_INIT:1: msg', 'env LUA_INIT="error(\'msg\')" lua')
|
NoRun('LUA_INIT:1: msg', 'env LUA_INIT="error(\'msg\')" lua')
|
||||||
|
|
||||||
-- test option '-E'
|
|
||||||
|
print("testing option '-E'")
|
||||||
|
|
||||||
local defaultpath, defaultCpath
|
local defaultpath, defaultCpath
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
@ -192,6 +197,22 @@ assert(not string.find(defaultpath, "xxx") and
|
||||||
string.find(defaultCpath, "lua"))
|
string.find(defaultCpath, "lua"))
|
||||||
|
|
||||||
|
|
||||||
|
-- (LUA_READLINELIB was introduced in 5.5.1)
|
||||||
|
if release >= "5.5.1" then
|
||||||
|
print"testing readline library name"
|
||||||
|
-- should generate a warning when trying to load inexistent library "xuxu"
|
||||||
|
local env = [[LUA_READLINELIB=xuxu LUA_INIT="warn('@allow')"]]
|
||||||
|
local code = 'echo " " | env %s lua %s -W -i >%s 2>&1'
|
||||||
|
RUN(code, env, "", out) -- run code with no extra options
|
||||||
|
assert(string.find(getoutput(),
|
||||||
|
"warning: unable to load readline library 'xuxu'"))
|
||||||
|
|
||||||
|
RUN(code, env, "-E", out) -- run again with option -E
|
||||||
|
-- no warning when LUA_READLINELIB is to be ignored
|
||||||
|
assert(not string.find(getoutput(), "warning"))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- test replacement of ';;' to default path
|
-- test replacement of ';;' to default path
|
||||||
local function convert (p)
|
local function convert (p)
|
||||||
prepfile("print(package.path)")
|
prepfile("print(package.path)")
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,25 @@ testamem("growing stack", function ()
|
||||||
return foo(100)
|
return foo(100)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
collectgarbage()
|
||||||
|
collectgarbage()
|
||||||
|
global io, T, setmetatable, collectgarbage, print
|
||||||
|
|
||||||
|
local Count = 0
|
||||||
|
testamem("finalizers", function ()
|
||||||
|
local X = false
|
||||||
|
local obj = setmetatable({}, {__gc = function () X = true end})
|
||||||
|
obj = nil
|
||||||
|
T.resetCI() -- remove extra CallInfos
|
||||||
|
T.reallocstack(18) -- remove extra stack slots
|
||||||
|
Count = Count + 1
|
||||||
|
io.stderr:write(Count, "\n")
|
||||||
|
T.trick(io)
|
||||||
|
collectgarbage()
|
||||||
|
return X
|
||||||
|
end)
|
||||||
|
|
||||||
-- }==================================================================
|
-- }==================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,19 @@ assert(a==1 and x==nil)
|
||||||
a,x = unpack({1,2}, 1, 1)
|
a,x = unpack({1,2}, 1, 1)
|
||||||
assert(a==1 and x==nil)
|
assert(a==1 and x==nil)
|
||||||
|
|
||||||
|
|
||||||
|
do -- unpack with non-tables
|
||||||
|
local debug = require"debug"
|
||||||
|
local oldmt = debug.getmetatable(0)
|
||||||
|
local str = "hello"
|
||||||
|
debug.setmetatable(0,
|
||||||
|
{ __len = function () return #str end,
|
||||||
|
__index = function (_, i) return string.sub(str, i, i) end})
|
||||||
|
assert(table.concat({table.unpack(0)}) == str)
|
||||||
|
debug.setmetatable(0, oldmt) -- restore original metatable for numbers
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
do
|
do
|
||||||
local maxi = (1 << 31) - 1 -- maximum value for an int (usually)
|
local maxi = (1 << 31) - 1 -- maximum value for an int (usually)
|
||||||
local mini = -(1 << 31) -- minimum value for an int (usually)
|
local mini = -(1 << 31) -- minimum value for an int (usually)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
-- track collections
|
-- track collections
|
||||||
|
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
-- import list
|
-- import list
|
||||||
local setmetatable, stderr, collectgarbage =
|
local stderr, collectgarbage = io.stderr, collectgarbage
|
||||||
setmetatable, io.stderr, collectgarbage
|
|
||||||
|
-- the debug version of setmetatable does not create any object (such as
|
||||||
|
-- a '__metatable' string), and so it is more appropriate to be used in
|
||||||
|
-- a finalizer
|
||||||
|
local setmetatable = require"debug".setmetatable
|
||||||
|
|
||||||
global none
|
global none
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,10 +238,18 @@ s = "\0 \x7F\z
|
||||||
s = string.gsub(s, " ", "")
|
s = string.gsub(s, " ", "")
|
||||||
check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF})
|
check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF})
|
||||||
|
|
||||||
|
|
||||||
|
-- again, without strictness
|
||||||
|
s = "\xF0\x90\x80\x80 \xF7\xBF\xBF\xBF\z
|
||||||
|
\xF8\x88\x80\x80\x80 \xFB\xBF\xBF\xBF\xBF\z
|
||||||
|
\xFC\x84\x80\x80\x80\x80 \xFD\xBF\xBF\xBF\xBF\xBF"
|
||||||
|
s = string.gsub(s, " ", "")
|
||||||
|
check(s, {0x10000,0x1FFFFF, 0x200000,0x3FFFFFF, 0x4000000,0x7FFFFFFF}, true)
|
||||||
|
|
||||||
do
|
do
|
||||||
-- original UTF-8 values
|
-- original UTF-8 values
|
||||||
local s = "\u{4000000}\u{7FFFFFFF}"
|
local s = "\u{4000000}\u{7FFFFFFF}"
|
||||||
assert(#s == 12)
|
assert(s == "\xFC\x84\x80\x80\x80\x80\xFD\xBF\xBF\xBF\xBF\xBF")
|
||||||
check(s, {0x4000000, 0x7FFFFFFF}, true)
|
check(s, {0x4000000, 0x7FFFFFFF}, true)
|
||||||
|
|
||||||
s = "\u{200000}\u{3FFFFFF}"
|
s = "\u{200000}\u{3FFFFFF}"
|
||||||
|
|
@ -257,6 +265,10 @@ local x = "日本語a-4\0éó"
|
||||||
check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243})
|
check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243})
|
||||||
|
|
||||||
|
|
||||||
|
-- more than 5 continuation bytes
|
||||||
|
assert(not utf8.len("\xff\x8f\x8f\x8f\x8f\x8f\x8f\x8f"))
|
||||||
|
|
||||||
|
|
||||||
-- Supplementary Characters
|
-- Supplementary Characters
|
||||||
check("𣲷𠜎𠱓𡁻𠵼ab𠺢",
|
check("𣲷𠜎𠱓𡁻𠵼ab𠺢",
|
||||||
{0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,})
|
{0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue