mirror of
https://github.com/lua/lua.git
synced 2026-01-28 02:15:05 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a7cf4f319 | ||
|
|
5cfc725a8b | ||
|
|
45c7ae5b1b | ||
|
|
962f444a75 | ||
|
|
c4e2c91973 | ||
|
|
632a71b24d | ||
|
|
578ae5745c | ||
|
|
a5522f06d2 | ||
|
|
3d03ae5bd6 | ||
|
|
82d721a855 | ||
|
|
104b0fc700 | ||
|
|
8164d09338 |
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 */
|
||||||
|
|||||||
@ -1185,7 +1185,7 @@ LUALIB_API lua_State *(luaL_newstate) (void) {
|
|||||||
lua_State *L = lua_newstate(luaL_alloc, NULL, luaL_makeseed(NULL));
|
lua_State *L = lua_newstate(luaL_alloc, NULL, luaL_makeseed(NULL));
|
||||||
if (l_likely(L)) {
|
if (l_likely(L)) {
|
||||||
lua_atpanic(L, &panic);
|
lua_atpanic(L, &panic);
|
||||||
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
|
lua_setwarnf(L, warnfon, L);
|
||||||
}
|
}
|
||||||
return L;
|
return L;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
8
lcode.c
8
lcode.c
@ -1370,9 +1370,11 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
|||||||
fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
|
fillidxk(t, k->u.info, VINDEXUP); /* literal short string */
|
||||||
}
|
}
|
||||||
else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */
|
else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */
|
||||||
lua_assert(t->u.ind.t == fs->f->numparams);
|
int kreg = luaK_exp2anyreg(fs, k); /* put key in some register */
|
||||||
t->u.ind.t = cast_byte(t->u.var.ridx);
|
lu_byte vreg = cast_byte(t->u.var.ridx); /* register with vararg param. */
|
||||||
fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* register */
|
lua_assert(vreg == fs->f->numparams);
|
||||||
|
t->u.ind.t = vreg; /* (avoid a direct assignment; values may overlap) */
|
||||||
|
fillidxk(t, kreg, VVARGIND); /* 't' represents 'vararg[k]' */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* register index of the table */
|
/* register index of the table */
|
||||||
|
|||||||
21
ldo.c
21
ldo.c
@ -220,6 +220,25 @@ l_noret luaD_errerr (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether stacks have enough space to run a simple function (such
|
||||||
|
** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack, two
|
||||||
|
** available CallInfos, and two "slots" in the C stack.
|
||||||
|
*/
|
||||||
|
int luaD_checkminstack (lua_State *L) {
|
||||||
|
if (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** In ISO C, any pointer use after the pointer has been deallocated is
|
** In ISO C, any pointer use after the pointer has been deallocated is
|
||||||
** undefined behavior. So, before a stack reallocation, all pointers
|
** undefined behavior. So, before a stack reallocation, all pointers
|
||||||
@ -605,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))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
1
ldo.h
1
ldo.h
@ -89,6 +89,7 @@ LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
|
|||||||
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
|
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
|
||||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||||
LUAI_FUNC void luaD_inctop (lua_State *L);
|
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||||
|
LUAI_FUNC int luaD_checkminstack (lua_State *L);
|
||||||
|
|
||||||
LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode);
|
LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode);
|
||||||
LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode);
|
LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode);
|
||||||
|
|||||||
7
lgc.c
7
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)
|
if (g->tobefnz != NULL && !g->gcemergency && luaD_checkminstack(L))
|
||||||
callallpendingfinalizers(L);
|
callallpendingfinalizers(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1667,12 +1667,13 @@ static l_mem singlestep (lua_State *L, int fast) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GCScallfin: { /* call finalizers */
|
case GCScallfin: { /* call finalizers */
|
||||||
if (g->tobefnz && !g->gcemergency) {
|
if (g->tobefnz && !g->gcemergency && luaD_checkminstack(L)) {
|
||||||
g->gcstopem = 0; /* ok collections during finalizers */
|
g->gcstopem = 0; /* ok collections during finalizers */
|
||||||
GCTM(L); /* call one finalizer */
|
GCTM(L); /* call one finalizer */
|
||||||
stepresult = CWUFIN;
|
stepresult = CWUFIN;
|
||||||
}
|
}
|
||||||
else { /* emergency mode or no more finalizers */
|
else { /* no more finalizers or emergency mode or not enough stack
|
||||||
|
to run finalizers */
|
||||||
g->gcstate = GCSpause; /* finish collection */
|
g->gcstate = GCSpause; /* finish collection */
|
||||||
stepresult = step2pause;
|
stepresult = step2pause;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -505,8 +505,8 @@ static void buildglobal (LexState *ls, TString *varname, expdesc *var) {
|
|||||||
init_exp(var, VGLOBAL, -1); /* global by default */
|
init_exp(var, VGLOBAL, -1); /* global by default */
|
||||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||||
if (var->k == VGLOBAL)
|
if (var->k == VGLOBAL)
|
||||||
luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
|
luaK_semerror(ls, "%s is global when accessing variable '%s'",
|
||||||
getstr(varname));
|
LUA_ENV, getstr(varname));
|
||||||
luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
|
luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
|
||||||
codestring(&key, varname); /* key is variable name */
|
codestring(&key, varname); /* key is variable name */
|
||||||
luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */
|
luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */
|
||||||
|
|||||||
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);
|
||||||
|
|||||||
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},
|
||||||
|
|||||||
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)))
|
||||||
|
|
||||||
|
|||||||
3
lua.c
3
lua.c
@ -349,6 +349,7 @@ static int collectargs (char **argv, int *first) {
|
|||||||
*/
|
*/
|
||||||
static int runargs (lua_State *L, char **argv, int n) {
|
static int runargs (lua_State *L, char **argv, int n) {
|
||||||
int i;
|
int i;
|
||||||
|
lua_warning(L, "@off", 0); /* by default, Lua stand-alone has warnings off */
|
||||||
for (i = 1; i < n; i++) {
|
for (i = 1; i < n; i++) {
|
||||||
int option = argv[i][1];
|
int option = argv[i][1];
|
||||||
lua_assert(argv[i][0] == '-'); /* already checked */
|
lua_assert(argv[i][0] == '-'); /* already checked */
|
||||||
@ -725,7 +726,7 @@ static int pmain (lua_State *L) {
|
|||||||
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 and -l */
|
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) */
|
||||||
if (handle_script(L, argv + script) != LUA_OK)
|
if (handle_script(L, argv + script) != LUA_OK)
|
||||||
|
|||||||
@ -107,7 +107,7 @@ for small machines and embedded systems.
|
|||||||
|
|
||||||
Unless stated otherwise,
|
Unless stated otherwise,
|
||||||
any overflow when manipulating integer values @def{wrap around},
|
any overflow when manipulating integer values @def{wrap around},
|
||||||
according to the usual rules of two-complement arithmetic.
|
according to the usual rules of two's complement arithmetic.
|
||||||
(In other words,
|
(In other words,
|
||||||
the actual result is the unique representable integer
|
the actual result is the unique representable integer
|
||||||
that is equal modulo @M{2@sp{n}} to the mathematical result,
|
that is equal modulo @M{2@sp{n}} to the mathematical result,
|
||||||
@ -2091,12 +2091,12 @@ Note that keys that are not positive integers
|
|||||||
do not interfere with borders.
|
do not interfere with borders.
|
||||||
|
|
||||||
A table with exactly one border is called a @def{sequence}.
|
A table with exactly one border is called a @def{sequence}.
|
||||||
For instance, the table @T{{10, 20, 30, 40, 50}} is a sequence,
|
For instance, the table @T{{10,20,30,40,50}} is a sequence,
|
||||||
as it has only one border (5).
|
as it has only one border (5).
|
||||||
The table @T{{10, 20, 30, nil, 50}} has two borders (3 and 5),
|
The table @T{{10,20,30,nil,50}} has two borders (3 and 5),
|
||||||
and therefore it is not a sequence.
|
and therefore it is not a sequence.
|
||||||
(The @nil at index 4 is called a @emphx{hole}.)
|
(The @nil at index 4 is called a @emphx{hole}.)
|
||||||
The table @T{{nil, 20, 30, nil, nil, 60, nil}}
|
The table @T{{nil,20,30,nil,nil,60,nil}}
|
||||||
has three borders (0, 3, and 6),
|
has three borders (0, 3, and 6),
|
||||||
so it is not a sequence, too.
|
so it is not a sequence, too.
|
||||||
The table @T{{}} is a sequence with border 0.
|
The table @T{{}} is a sequence with border 0.
|
||||||
@ -2449,22 +2449,22 @@ These are the places where Lua expects a list of expressions:
|
|||||||
@description{
|
@description{
|
||||||
|
|
||||||
@item{A @rw{return} statement,
|
@item{A @rw{return} statement,
|
||||||
for instance @T{return e1, e2, e3} @see{control}.}
|
for instance @T{return e1,e2,e3} @see{control}.}
|
||||||
|
|
||||||
@item{A table constructor,
|
@item{A table constructor,
|
||||||
for instance @T{{e1, e2, e3}} @see{tableconstructor}.}
|
for instance @T{{e1,e2,e3}} @see{tableconstructor}.}
|
||||||
|
|
||||||
@item{The arguments of a function call,
|
@item{The arguments of a function call,
|
||||||
for instance @T{foo(e1, e2, e3)} @see{functioncall}.}
|
for instance @T{foo(e1,e2,e3)} @see{functioncall}.}
|
||||||
|
|
||||||
@item{A multiple assignment,
|
@item{A multiple assignment,
|
||||||
for instance @T{a , b, c = e1, e2, e3} @see{assignment}.}
|
for instance @T{a,b,c = e1,e2,e3} @see{assignment}.}
|
||||||
|
|
||||||
@item{A local or global declaration,
|
@item{A local or global declaration,
|
||||||
which is similar to a multiple assignment.}
|
which is similar to a multiple assignment.}
|
||||||
|
|
||||||
@item{The initial values in a generic @rw{for} loop,
|
@item{The initial values in a generic @rw{for} loop,
|
||||||
for instance @T{for k in e1, e2, e3 do ... end} @see{for}.}
|
for instance @T{for k in e1,e2,e3 do ... end} @see{for}.}
|
||||||
|
|
||||||
}
|
}
|
||||||
In the last four cases,
|
In the last four cases,
|
||||||
@ -2501,7 +2501,7 @@ we recommend assigning the vararg expression
|
|||||||
to a single variable and using that variable
|
to a single variable and using that variable
|
||||||
in its place.
|
in its place.
|
||||||
|
|
||||||
Here are some examples of uses of mutlres expressions.
|
Here are some examples of uses of multires expressions.
|
||||||
In all cases, when the construction needs
|
In all cases, when the construction needs
|
||||||
@Q{the n-th result} and there is no such result,
|
@Q{the n-th result} and there is no such result,
|
||||||
it uses a @nil.
|
it uses a @nil.
|
||||||
@ -3107,7 +3107,7 @@ void *luaL_alloc (void *ud, void *ptr, size_t osize,
|
|||||||
}
|
}
|
||||||
Note that @N{ISO C} ensures
|
Note that @N{ISO C} ensures
|
||||||
that @T{free(NULL)} has no effect and that
|
that @T{free(NULL)} has no effect and that
|
||||||
@T{realloc(NULL, size)} is equivalent to @T{malloc(size)}.
|
@T{realloc(NULL,size)} is equivalent to @T{malloc(size)}.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3640,9 +3640,9 @@ because a pseudo-index is not an actual stack position.
|
|||||||
The type of integers in Lua.
|
The type of integers in Lua.
|
||||||
|
|
||||||
By default this type is @id{long long},
|
By default this type is @id{long long},
|
||||||
(usually a 64-bit two-complement integer),
|
(usually a 64-bit two's complement integer),
|
||||||
but that can be changed to @id{long} or @id{int}
|
but that can be changed to @id{long} or @id{int}
|
||||||
(usually a 32-bit two-complement integer).
|
(usually a 32-bit two's complement integer).
|
||||||
(See @id{LUA_INT_TYPE} in @id{luaconf.h}.)
|
(See @id{LUA_INT_TYPE} in @id{luaconf.h}.)
|
||||||
|
|
||||||
Lua also defines the constants
|
Lua also defines the constants
|
||||||
@ -3879,7 +3879,7 @@ is a seed for the hashing of strings.
|
|||||||
@apii{0,1,m}
|
@apii{0,1,m}
|
||||||
|
|
||||||
Creates a new empty table and pushes it onto the stack.
|
Creates a new empty table and pushes it onto the stack.
|
||||||
It is equivalent to @T{lua_createtable(L, 0, 0)}.
|
It is equivalent to @T{lua_createtable(L,0,0)}.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5439,7 +5439,7 @@ the auxiliary library provides higher-level functions for some
|
|||||||
common tasks.
|
common tasks.
|
||||||
|
|
||||||
All functions and types from the auxiliary library
|
All functions and types from the auxiliary library
|
||||||
are defined in header file @id{lauxlib.h} and
|
are defined in the header file @id{lauxlib.h} and
|
||||||
have a prefix @id{luaL_}.
|
have a prefix @id{luaL_}.
|
||||||
|
|
||||||
All functions in the auxiliary library are built on
|
All functions in the auxiliary library are built on
|
||||||
@ -5583,7 +5583,7 @@ Its pattern of use is as follows:
|
|||||||
|
|
||||||
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
|
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
|
||||||
|
|
||||||
@item{Then initialize it with a call @T{luaL_buffinit(L, &b)}.}
|
@item{Then initialize it with a call @T{luaL_buffinit(L,&b)}.}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
Then add string pieces to the buffer calling any of
|
Then add string pieces to the buffer calling any of
|
||||||
@ -5604,12 +5604,12 @@ you can use the buffer like this:
|
|||||||
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
|
@item{First declare a variable @id{b} of type @Lid{luaL_Buffer}.}
|
||||||
|
|
||||||
@item{Then initialize it and preallocate a space of
|
@item{Then initialize it and preallocate a space of
|
||||||
size @id{sz} with a call @T{luaL_buffinitsize(L, &b, sz)}.}
|
size @id{sz} with a call @T{luaL_buffinitsize(L,&b,sz)}.}
|
||||||
|
|
||||||
@item{Then produce the string into that space.}
|
@item{Then produce the string into that space.}
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
Finish by calling @T{luaL_pushresultsize(&b, sz)},
|
Finish by calling @T{luaL_pushresultsize(&b,sz)},
|
||||||
where @id{sz} is the total size of the resulting string
|
where @id{sz} is the total size of the resulting string
|
||||||
copied into that space (which may be less than or
|
copied into that space (which may be less than or
|
||||||
equal to the preallocated size).
|
equal to the preallocated size).
|
||||||
@ -6214,7 +6214,7 @@ You should not manually set integer keys in the table
|
|||||||
after the first use of @Lid{luaL_ref}.
|
after the first use of @Lid{luaL_ref}.
|
||||||
|
|
||||||
You can retrieve an object referred by the reference @id{r}
|
You can retrieve an object referred by the reference @id{r}
|
||||||
by calling @T{lua_rawgeti(L, t, r)} or @T{lua_geti(L, t, r)}.
|
by calling @T{lua_rawgeti(L,t,r)} or @T{lua_geti(L,t,r)}.
|
||||||
The function @Lid{luaL_unref} frees a reference.
|
The function @Lid{luaL_unref} frees a reference.
|
||||||
|
|
||||||
If the object on the top of the stack is @nil,
|
If the object on the top of the stack is @nil,
|
||||||
@ -6492,7 +6492,7 @@ the host program can call the function @Lid{luaL_openlibs}.
|
|||||||
Alternatively,
|
Alternatively,
|
||||||
the host can select which libraries to open,
|
the host can select which libraries to open,
|
||||||
by using @Lid{luaL_openselectedlibs}.
|
by using @Lid{luaL_openselectedlibs}.
|
||||||
Both functions are defined in the header file @id{lualib.h}.
|
Both functions are declared in the header file @id{lualib.h}.
|
||||||
@index{lualib.h}
|
@index{lualib.h}
|
||||||
|
|
||||||
The stand-alone interpreter @id{lua} @see{lua-sa}
|
The stand-alone interpreter @id{lua} @see{lua-sa}
|
||||||
@ -7744,7 +7744,7 @@ If @id{j} is absent, then it is assumed to be equal to @num{-1}
|
|||||||
In particular,
|
In particular,
|
||||||
the call @T{string.sub(s,1,j)} returns a prefix of @id{s}
|
the call @T{string.sub(s,1,j)} returns a prefix of @id{s}
|
||||||
with length @id{j},
|
with length @id{j},
|
||||||
and @T{string.sub(s, -i)} (for a positive @id{i})
|
and @T{string.sub(s,-i)} (for a positive @id{i})
|
||||||
returns a suffix of @id{s}
|
returns a suffix of @id{s}
|
||||||
with length @id{i}.
|
with length @id{i}.
|
||||||
|
|
||||||
@ -8180,7 +8180,7 @@ the function returns @fail.
|
|||||||
A negative @id{n} gets characters before position @id{i}.
|
A negative @id{n} gets characters before position @id{i}.
|
||||||
The default for @id{i} is 1 when @id{n} is non-negative
|
The default for @id{i} is 1 when @id{n} is non-negative
|
||||||
and @T{#s + 1} otherwise,
|
and @T{#s + 1} otherwise,
|
||||||
so that @T{utf8.offset(s, -n)} gets the offset of the
|
so that @T{utf8.offset(s,-n)} gets the offset of the
|
||||||
@id{n}-th character from the end of the string.
|
@id{n}-th character from the end of the string.
|
||||||
|
|
||||||
As a special case,
|
As a special case,
|
||||||
@ -8233,7 +8233,7 @@ the table will have; its default is zero.
|
|||||||
|
|
||||||
Inserts element @id{value} at position @id{pos} in @id{list},
|
Inserts element @id{value} at position @id{pos} in @id{list},
|
||||||
shifting up the elements
|
shifting up the elements
|
||||||
@T{list[pos], list[pos+1], @Cdots, list[#list]}.
|
@T{list[pos],list[pos+1],@Cdots,list[#list]}.
|
||||||
The default value for @id{pos} is @T{#list+1},
|
The default value for @id{pos} is @T{#list+1},
|
||||||
so that a call @T{table.insert(t,x)} inserts @id{x} at the end
|
so that a call @T{table.insert(t,x)} inserts @id{x} at the end
|
||||||
of the list @id{t}.
|
of the list @id{t}.
|
||||||
@ -8271,7 +8271,7 @@ Removes from @id{list} the element at position @id{pos},
|
|||||||
returning the value of the removed element.
|
returning the value of the removed element.
|
||||||
When @id{pos} is an integer between 1 and @T{#list},
|
When @id{pos} is an integer between 1 and @T{#list},
|
||||||
it shifts down the elements
|
it shifts down the elements
|
||||||
@T{list[pos+1], list[pos+2], @Cdots, list[#list]}
|
@T{list[pos+1],list[pos+2],@Cdots,list[#list]}
|
||||||
and erases element @T{list[#list]};
|
and erases element @T{list[#list]};
|
||||||
The index @id{pos} can also be 0 when @T{#list} is 0,
|
The index @id{pos} can also be 0 when @T{#list} is 0,
|
||||||
or @T{#list + 1}.
|
or @T{#list + 1}.
|
||||||
|
|||||||
@ -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')
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
-- }==================================================================
|
-- }==================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user