mirror of
https://github.com/lua/lua.git
synced 2026-01-28 10:24:37 +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);
|
||||
if (ttisnumber(o)) {
|
||||
unsigned len = luaO_tostringbuff(o, buff);
|
||||
@ -1201,11 +1201,16 @@ LUA_API int lua_gc (lua_State *L, int what, ...) {
|
||||
case LUA_GCSTEP: {
|
||||
lu_byte oldstp = g->gcstp;
|
||||
l_mem n = cast(l_mem, va_arg(argp, size_t));
|
||||
l_mem newdebt;
|
||||
int work = 0; /* true if GC did some work */
|
||||
g->gcstp = 0; /* allow GC to run (other bits must be zero here) */
|
||||
if (n <= 0)
|
||||
n = g->GCdebt; /* force to run one basic step */
|
||||
luaE_setdebt(g, g->GCdebt - n);
|
||||
newdebt = 0; /* force to run one basic step */
|
||||
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);
|
||||
if (work && g->gcstate == GCSpause) /* end of cycle? */
|
||||
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));
|
||||
if (l_likely(L)) {
|
||||
lua_atpanic(L, &panic);
|
||||
lua_setwarnf(L, warnfoff, L); /* default is warnings off */
|
||||
lua_setwarnf(L, warnfon, 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_execresult) (lua_State *L, int stat);
|
||||
|
||||
LUALIB_API void *luaL_alloc (void *ud, void *ptr, size_t osize,
|
||||
size_t nsize);
|
||||
LUALIB_API void *(luaL_alloc) (void *ud, void *ptr, size_t osize,
|
||||
size_t nsize);
|
||||
|
||||
|
||||
/* 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 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);
|
||||
|
||||
|
||||
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 */
|
||||
}
|
||||
else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */
|
||||
lua_assert(t->u.ind.t == fs->f->numparams);
|
||||
t->u.ind.t = cast_byte(t->u.var.ridx);
|
||||
fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* 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. */
|
||||
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 {
|
||||
/* 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
|
||||
** 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 void luaD_shrinkstack (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_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);
|
||||
checkSizes(L, g);
|
||||
g->gcstate = GCSpropagate; /* skip restart */
|
||||
if (!g->gcemergency)
|
||||
if (g->tobefnz != NULL && !g->gcemergency && luaD_checkminstack(L))
|
||||
callallpendingfinalizers(L);
|
||||
}
|
||||
|
||||
@ -1667,12 +1667,13 @@ static l_mem singlestep (lua_State *L, int fast) {
|
||||
break;
|
||||
}
|
||||
case GCScallfin: { /* call finalizers */
|
||||
if (g->tobefnz && !g->gcemergency) {
|
||||
if (g->tobefnz && !g->gcemergency && luaD_checkminstack(L)) {
|
||||
g->gcstopem = 0; /* ok collections during finalizers */
|
||||
GCTM(L); /* call one finalizer */
|
||||
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 */
|
||||
stepresult = step2pause;
|
||||
}
|
||||
|
||||
@ -505,8 +505,8 @@ static void buildglobal (LexState *ls, TString *varname, expdesc *var) {
|
||||
init_exp(var, VGLOBAL, -1); /* global by default */
|
||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||
if (var->k == VGLOBAL)
|
||||
luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
|
||||
getstr(varname));
|
||||
luaK_semerror(ls, "%s is global when accessing variable '%s'",
|
||||
LUA_ENV, getstr(varname));
|
||||
luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
|
||||
codestring(&key, varname); /* key is variable name */
|
||||
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;
|
||||
lua_assert(L->ci->next == NULL);
|
||||
ci = luaM_new(L, CallInfo);
|
||||
lua_assert(L->ci->next == NULL);
|
||||
L->ci->next = ci;
|
||||
ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
|
||||
if (l_unlikely(ci == NULL)) { /* allocation failed? */
|
||||
if (err)
|
||||
luaM_error(L); /* raise the error */
|
||||
return NULL; /* else only report it */
|
||||
}
|
||||
ci->next = L->ci->next;
|
||||
ci->previous = L->ci;
|
||||
ci->next = NULL;
|
||||
L->ci->next = ci;
|
||||
if (ci->next)
|
||||
ci->next->previous = ci;
|
||||
ci->u.l.trap = 0;
|
||||
L->nci++;
|
||||
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_freethread (lua_State *L, lua_State *L1);
|
||||
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_checkcstack (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);
|
||||
lua_Integer n = luaL_checkinteger(L, 2);
|
||||
const char *sep = luaL_optlstring(L, 3, "", &lsep);
|
||||
if (n <= 0)
|
||||
lua_pushliteral(L, "");
|
||||
if (n <= 0 || (len | lsep) == 0)
|
||||
lua_pushliteral(L, ""); /* no repetitions or both strings empty */
|
||||
else if (l_unlikely(len > MAX_SIZE - lsep ||
|
||||
cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n))
|
||||
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 */
|
||||
if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
|
||||
n++;
|
||||
changed = add_value(&ms, &b, src, e, tr) | changed;
|
||||
changed = add_value(&ms, &b, src, e, tr) || changed;
|
||||
src = lastmatch = e;
|
||||
}
|
||||
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,
|
||||
"variable-length format");
|
||||
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");
|
||||
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
|
||||
** dummy bit must be exchanged: The 'isrealasize' is not related
|
||||
** to the hash part, and the metamethod bits do not change during
|
||||
** a resize, so the "real" table can keep their values.)
|
||||
** Exchange the hash part of 't1' and 't2'. (In 'flags', only the dummy
|
||||
** bit must be exchanged: The metamethod bits do not change during a
|
||||
** resize, so the "real" table can keep their values.)
|
||||
*/
|
||||
static void exchangehashpart (Table *t1, Table *t2) {
|
||||
lu_byte lsizenode = t1->lsizenode;
|
||||
@ -1156,14 +1155,15 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
||||
lua_assert(hres != HOK);
|
||||
if (hres == HNOTFOUND) {
|
||||
TValue aux;
|
||||
const TValue *actk = key; /* actual key to insert */
|
||||
if (l_unlikely(ttisnil(key)))
|
||||
luaG_runerror(L, "table index is nil");
|
||||
else if (ttisfloat(key)) {
|
||||
lua_Number f = fltvalue(key);
|
||||
lua_Integer k;
|
||||
if (luaV_flttointeger(f, &k, F2Ieq)) {
|
||||
setivalue(&aux, k); /* key is equal to an integer */
|
||||
key = &aux; /* insert it as an integer */
|
||||
if (luaV_flttointeger(f, &k, F2Ieq)) { /* is key equal to an integer? */
|
||||
setivalue(&aux, k);
|
||||
actk = &aux; /* use the integer as the key */
|
||||
}
|
||||
else if (l_unlikely(luai_numisnan(f)))
|
||||
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--;
|
||||
return;
|
||||
}
|
||||
luaH_newkey(L, t, key, value);
|
||||
luaH_newkey(L, t, actk, value);
|
||||
}
|
||||
else if (hres > 0) { /* regular Node? */
|
||||
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) {
|
||||
const Table *t;
|
||||
int i = cast_int(luaL_optinteger(L, 2, -1));
|
||||
@ -2182,6 +2203,8 @@ static const struct luaL_Reg tests_funcs[] = {
|
||||
{"s2d", s2d},
|
||||
{"sethook", sethook},
|
||||
{"stacklevel", stacklevel},
|
||||
{"resetCI", resetCI},
|
||||
{"reallocstack", reallocstack},
|
||||
{"sizes", get_sizes},
|
||||
{"testC", testC},
|
||||
{"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
|
||||
** in the flag of a (meta)table means the metatable does not have the
|
||||
** 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)))
|
||||
|
||||
|
||||
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) {
|
||||
int i;
|
||||
lua_warning(L, "@off", 0); /* by default, Lua stand-alone has warnings off */
|
||||
for (i = 1; i < n; i++) {
|
||||
int option = argv[i][1];
|
||||
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 */
|
||||
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 */
|
||||
if (script > 0) { /* execute main script (if there is one) */
|
||||
if (handle_script(L, argv + script) != LUA_OK)
|
||||
|
||||
@ -107,7 +107,7 @@ for small machines and embedded systems.
|
||||
|
||||
Unless stated otherwise,
|
||||
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,
|
||||
the actual result is the unique representable integer
|
||||
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.
|
||||
|
||||
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).
|
||||
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.
|
||||
(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),
|
||||
so it is not a sequence, too.
|
||||
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{
|
||||
|
||||
@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,
|
||||
for instance @T{{e1, e2, e3}} @see{tableconstructor}.}
|
||||
for instance @T{{e1,e2,e3}} @see{tableconstructor}.}
|
||||
|
||||
@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,
|
||||
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,
|
||||
which is similar to a multiple assignment.}
|
||||
|
||||
@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,
|
||||
@ -2501,7 +2501,7 @@ we recommend assigning the vararg expression
|
||||
to a single variable and using that variable
|
||||
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
|
||||
@Q{the n-th result} and there is no such result,
|
||||
it uses a @nil.
|
||||
@ -3107,7 +3107,7 @@ void *luaL_alloc (void *ud, void *ptr, size_t osize,
|
||||
}
|
||||
Note that @N{ISO C} ensures
|
||||
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.
|
||||
|
||||
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}
|
||||
(usually a 32-bit two-complement integer).
|
||||
(usually a 32-bit two's complement integer).
|
||||
(See @id{LUA_INT_TYPE} in @id{luaconf.h}.)
|
||||
|
||||
Lua also defines the constants
|
||||
@ -3879,7 +3879,7 @@ is a seed for the hashing of strings.
|
||||
@apii{0,1,m}
|
||||
|
||||
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.
|
||||
|
||||
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_}.
|
||||
|
||||
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{Then initialize it with a call @T{luaL_buffinit(L, &b)}.}
|
||||
@item{Then initialize it with a call @T{luaL_buffinit(L,&b)}.}
|
||||
|
||||
@item{
|
||||
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{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{
|
||||
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
|
||||
copied into that space (which may be less than or
|
||||
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}.
|
||||
|
||||
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.
|
||||
|
||||
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,
|
||||
the host can select which libraries to open,
|
||||
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}
|
||||
|
||||
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,
|
||||
the call @T{string.sub(s,1,j)} returns a prefix of @id{s}
|
||||
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}
|
||||
with length @id{i}.
|
||||
|
||||
@ -8180,7 +8180,7 @@ the function returns @fail.
|
||||
A negative @id{n} gets characters before position @id{i}.
|
||||
The default for @id{i} is 1 when @id{n} is non-negative
|
||||
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.
|
||||
|
||||
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},
|
||||
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},
|
||||
so that a call @T{table.insert(t,x)} inserts @id{x} at the end
|
||||
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.
|
||||
When @id{pos} is an integer between 1 and @T{#list},
|
||||
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]};
|
||||
The index @id{pos} can also be 0 when @T{#list} is 0,
|
||||
or @T{#list + 1}.
|
||||
|
||||
@ -707,4 +707,46 @@ end
|
||||
|
||||
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')
|
||||
|
||||
@ -282,6 +282,25 @@ testamem("growing stack", function ()
|
||||
return foo(100)
|
||||
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
|
||||
|
||||
|
||||
local M = {}
|
||||
|
||||
-- import list
|
||||
local setmetatable, stderr, collectgarbage =
|
||||
setmetatable, io.stderr, collectgarbage
|
||||
local stderr, collectgarbage = 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
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user