mirror of
https://github.com/lua/lua.git
synced 2026-07-26 16:09:07 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7579fc9d7e | ||
|
|
d5bbe95584 | ||
|
|
9130ceb19d | ||
|
|
84938a7d2b | ||
|
|
6ca33260d2 | ||
|
|
b996f8fd1b | ||
|
|
bc4bbcef65 | ||
|
|
40b76de2d7 | ||
|
|
0465c23b3e | ||
|
|
53b41d0cdd | ||
|
|
36c1f6d949 | ||
|
|
0da6d320f7 | ||
|
|
ae23e72601 | ||
|
|
4c5d5063a5 | ||
|
|
3228a97c6a | ||
|
|
0c16a42d61 | ||
|
|
d0bd25d2e7 | ||
|
|
29cf284089 | ||
|
|
c037162a1a | ||
|
|
efddc2309c | ||
|
|
f1bb2773bb | ||
|
|
51269bd783 | ||
|
|
377cbea61b | ||
|
|
36d5d2b284 | ||
|
|
9e501d9855 | ||
|
|
10eb89d114 | ||
|
|
7c40c5edb2 | ||
|
|
b60e2bcd7c | ||
|
|
c6b4848238 | ||
|
|
efbc297545 | ||
|
|
cfcaa9493b | ||
|
|
3360710bd3 | ||
|
|
e992c6a959 | ||
|
|
f5d1e8639b | ||
|
|
2a7cf4f319 | ||
|
|
5cfc725a8b | ||
|
|
45c7ae5b1b | ||
|
|
962f444a75 | ||
|
|
c4e2c91973 | ||
|
|
632a71b24d | ||
|
|
578ae5745c | ||
|
|
a5522f06d2 | ||
|
|
3d03ae5bd6 | ||
|
|
82d721a855 | ||
|
|
104b0fc700 | ||
|
|
8164d09338 |
28
lapi.c
28
lapi.c
@@ -187,7 +187,7 @@ LUA_API void lua_settop (lua_State *L, int idx) {
|
|||||||
api_check(L, idx <= ci->top.p - (func + 1), "new top too large");
|
api_check(L, idx <= ci->top.p - (func + 1), "new top too large");
|
||||||
diff = ((func + 1) + idx) - L->top.p;
|
diff = ((func + 1) + idx) - L->top.p;
|
||||||
for (; diff > 0; diff--)
|
for (; diff > 0; diff--)
|
||||||
setnilvalue(s2v(L->top.p++)); /* clear new slots */
|
setnilvalue2s(L->top.p++); /* clear new slots */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top");
|
api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top");
|
||||||
@@ -210,7 +210,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) {
|
|||||||
api_check(L, (L->ci->callstatus & CIST_TBC) && (L->tbclist.p == level),
|
api_check(L, (L->ci->callstatus & CIST_TBC) && (L->tbclist.p == level),
|
||||||
"no variable to close at given level");
|
"no variable to close at given level");
|
||||||
level = luaF_close(L, level, CLOSEKTOP, 0);
|
level = luaF_close(L, level, CLOSEKTOP, 0);
|
||||||
setnilvalue(s2v(level));
|
setnilvalue2s(level);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
@@ -513,7 +513,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
|||||||
|
|
||||||
LUA_API void lua_pushnil (lua_State *L) {
|
LUA_API void lua_pushnil (lua_State *L) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
}
|
}
|
||||||
@@ -570,7 +570,7 @@ LUA_API const char *lua_pushexternalstring (lua_State *L,
|
|||||||
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
|
LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
else {
|
else {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
ts = luaS_new(L, s);
|
ts = luaS_new(L, s);
|
||||||
@@ -743,7 +743,7 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
|
|||||||
|
|
||||||
static int finishrawget (lua_State *L, lu_byte tag) {
|
static int finishrawget (lua_State *L, lu_byte tag) {
|
||||||
if (tagisempty(tag)) /* avoid copying empty items to the stack */
|
if (tagisempty(tag)) /* avoid copying empty items to the stack */
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return novariant(tag);
|
return novariant(tag);
|
||||||
@@ -836,7 +836,7 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
|
|||||||
o = index2value(L, idx);
|
o = index2value(L, idx);
|
||||||
api_check(L, ttisfulluserdata(o), "full userdata expected");
|
api_check(L, ttisfulluserdata(o), "full userdata expected");
|
||||||
if (n <= 0 || n > uvalue(o)->nuvalue) {
|
if (n <= 0 || n > uvalue(o)->nuvalue) {
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
t = LUA_TNONE;
|
t = LUA_TNONE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1122,6 +1122,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
|
|||||||
ZIO z;
|
ZIO z;
|
||||||
TStatus status;
|
TStatus status;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
|
luaC_checkGC(L);
|
||||||
if (!chunkname) chunkname = "?";
|
if (!chunkname) chunkname = "?";
|
||||||
luaZ_init(L, &z, reader, data);
|
luaZ_init(L, &z, reader, data);
|
||||||
status = luaD_protectedparser(L, &z, chunkname, mode);
|
status = luaD_protectedparser(L, &z, chunkname, mode);
|
||||||
@@ -1201,11 +1202,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 mininum 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 */
|
||||||
@@ -1293,8 +1299,8 @@ LUA_API void lua_toclose (lua_State *L, int idx) {
|
|||||||
|
|
||||||
LUA_API void lua_concat (lua_State *L, int n) {
|
LUA_API void lua_concat (lua_State *L, int n) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
api_checknelems(L, n);
|
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
api_checkpop(L, n);
|
||||||
luaV_concat(L, n);
|
luaV_concat(L, n);
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
}
|
}
|
||||||
@@ -1412,7 +1418,7 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
|
|||||||
TValue *fi;
|
TValue *fi;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
fi = index2value(L, funcindex);
|
fi = index2value(L, funcindex);
|
||||||
api_checknelems(L, 1);
|
api_checkpop(L, 1);
|
||||||
name = aux_upvalue(fi, n, &val, &owner);
|
name = aux_upvalue(fi, n, &val, &owner);
|
||||||
if (name) {
|
if (name) {
|
||||||
L->top.p--;
|
L->top.p--;
|
||||||
|
|||||||
21
lauxlib.c
21
lauxlib.c
@@ -513,12 +513,25 @@ static const luaL_Reg boxmt[] = { /* box metamethods */
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Get/create metatable (MT) for boxes
|
||||||
|
*/
|
||||||
|
static void getBoxMT (lua_State *L) {
|
||||||
|
const char *BOXMT = "_UBOX*"; /* key for the metatable */
|
||||||
|
if (luaL_getmetatable(L, BOXMT) == LUA_TNIL) { /* MT not created yet? */
|
||||||
|
luaL_newlibtable(L, boxmt); /* create it */
|
||||||
|
luaL_setfuncs(L, boxmt, 0); /* initialize it */
|
||||||
|
lua_copy(L, -1, -2); /* change stack from nil,MT to MT,MT */
|
||||||
|
lua_setfield(L, LUA_REGISTRYINDEX, BOXMT); /* store MT in the registry */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void newbox (lua_State *L) {
|
static void newbox (lua_State *L) {
|
||||||
UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
|
UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
|
||||||
box->box = NULL;
|
box->box = NULL;
|
||||||
box->bsize = 0;
|
box->bsize = 0;
|
||||||
if (luaL_newmetatable(L, "_UBOX*")) /* creating metatable? */
|
getBoxMT(L);
|
||||||
luaL_setfuncs(L, boxmt, 0); /* set its metamethods */
|
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +887,7 @@ LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
|
|||||||
|
|
||||||
|
|
||||||
LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
|
LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
|
||||||
return luaL_loadbuffer(L, s, strlen(s), s);
|
return luaL_loadbufferx(L, s, strlen(s), s, "t");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
@@ -1185,7 +1198,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);
|
||||||
|
|
||||||
|
|||||||
35
lbaselib.c
35
lbaselib.c
@@ -340,9 +340,11 @@ static int load_aux (lua_State *L, int status, int envidx) {
|
|||||||
|
|
||||||
|
|
||||||
static const char *getMode (lua_State *L, int idx) {
|
static const char *getMode (lua_State *L, int idx) {
|
||||||
const char *mode = luaL_optstring(L, idx, "bt");
|
const char *mode = luaL_optstring(L, idx, NULL);
|
||||||
if (strchr(mode, 'B') != NULL) /* Lua code cannot use fixed buffers */
|
if (mode != NULL && strchr(mode, 'B') != NULL) {
|
||||||
|
/* Lua code cannot use fixed buffers */
|
||||||
luaL_argerror(L, idx, "invalid mode");
|
luaL_argerror(L, idx, "invalid mode");
|
||||||
|
}
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,33 +366,24 @@ static int luaB_loadfile (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** reserved slot, above all arguments, to hold a copy of the returned
|
** Reader for generic 'load' function.
|
||||||
** string to avoid it being collected while parsed. 'load' has four
|
|
||||||
** optional arguments (chunk, source name, mode, and environment).
|
|
||||||
*/
|
|
||||||
#define RESERVEDSLOT 5
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Reader for generic 'load' function: 'lua_load' uses the
|
|
||||||
** stack for internal stuff, so the reader cannot change the
|
|
||||||
** stack top. Instead, it keeps its resulting string in a
|
|
||||||
** reserved slot inside the stack.
|
|
||||||
*/
|
*/
|
||||||
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
||||||
(void)(ud); /* not used */
|
int *firstcall = cast(int *, ud);
|
||||||
luaL_checkstack(L, 2, "too many nested functions");
|
luaL_checkstack(L, 2, "too many nested functions");
|
||||||
|
if (*firstcall)
|
||||||
|
*firstcall = 0;
|
||||||
|
else
|
||||||
|
lua_pop(L, 1); /* remove previous result */
|
||||||
lua_pushvalue(L, 1); /* get function */
|
lua_pushvalue(L, 1); /* get function */
|
||||||
lua_call(L, 0, 1); /* call it */
|
lua_call(L, 0, 1); /* call it */
|
||||||
if (lua_isnil(L, -1)) {
|
if (lua_isnil(L, -1)) {
|
||||||
lua_pop(L, 1); /* pop result */
|
|
||||||
*size = 0;
|
*size = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (l_unlikely(!lua_isstring(L, -1)))
|
else if (l_unlikely(!lua_isstring(L, -1)))
|
||||||
luaL_error(L, "reader function must return a string");
|
luaL_error(L, "reader function must return a string");
|
||||||
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
|
return lua_tolstring(L, -1, size);
|
||||||
return lua_tolstring(L, RESERVEDSLOT, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -405,10 +398,10 @@ static int luaB_load (lua_State *L) {
|
|||||||
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
||||||
}
|
}
|
||||||
else { /* loading from a reader function */
|
else { /* loading from a reader function */
|
||||||
|
int firstcall = 1; /* userdata for generic_reader */
|
||||||
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
||||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||||
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
|
status = lua_load(L, generic_reader, &firstcall, chunkname, mode);
|
||||||
status = lua_load(L, generic_reader, NULL, chunkname, mode);
|
|
||||||
}
|
}
|
||||||
return load_aux(L, status, env);
|
return load_aux(L, status, env);
|
||||||
}
|
}
|
||||||
@@ -425,7 +418,7 @@ static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
|
|||||||
static int luaB_dofile (lua_State *L) {
|
static int luaB_dofile (lua_State *L) {
|
||||||
const char *fname = luaL_optstring(L, 1, NULL);
|
const char *fname = luaL_optstring(L, 1, NULL);
|
||||||
lua_settop(L, 1);
|
lua_settop(L, 1);
|
||||||
if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK))
|
if (l_unlikely(luaL_loadfilex(L, fname, "bt") != LUA_OK))
|
||||||
return lua_error(L);
|
return lua_error(L);
|
||||||
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
||||||
return dofilecont(L, 0, 0);
|
return dofilecont(L, 0, 0);
|
||||||
|
|||||||
25
lcode.c
25
lcode.c
@@ -663,11 +663,11 @@ static int boolT (FuncState *fs) {
|
|||||||
** Add nil to list of constants and return its index.
|
** Add nil to list of constants and return its index.
|
||||||
*/
|
*/
|
||||||
static int nilK (FuncState *fs) {
|
static int nilK (FuncState *fs) {
|
||||||
TValue k, v;
|
lua_State *L = fs->ls->L;
|
||||||
setnilvalue(&v);
|
TValue k;
|
||||||
/* cannot use nil as key; instead use table itself */
|
/* cannot use nil as key; instead use table itself */
|
||||||
sethvalue(fs->ls->L, &k, fs->kcache);
|
sethvalue(L, &k, fs->kcache);
|
||||||
return k2proto(fs, &k, &v);
|
return k2proto(fs, &k, &G(L)->nilvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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,18 +1365,21 @@ 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 */
|
||||||
}
|
}
|
||||||
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 */
|
||||||
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? */
|
||||||
@@ -1931,8 +1934,6 @@ void luaK_finish (FuncState *fs) {
|
|||||||
p->flag &= cast_byte(~PF_VAHID); /* then it will not use hidden args. */
|
p->flag &= cast_byte(~PF_VAHID); /* then it will not use hidden args. */
|
||||||
for (i = 0; i < fs->pc; i++) {
|
for (i = 0; i < fs->pc; i++) {
|
||||||
Instruction *pc = &p->code[i];
|
Instruction *pc = &p->code[i];
|
||||||
/* avoid "not used" warnings when assert is off (for 'onelua.c') */
|
|
||||||
(void)luaP_isOT; (void)luaP_isIT;
|
|
||||||
lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc));
|
lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc));
|
||||||
switch (GET_OPCODE(*pc)) {
|
switch (GET_OPCODE(*pc)) {
|
||||||
case OP_RETURN0: case OP_RETURN1: {
|
case OP_RETURN0: case OP_RETURN1: {
|
||||||
|
|||||||
2
ldblib.c
2
ldblib.c
@@ -427,7 +427,7 @@ static int db_debug (lua_State *L) {
|
|||||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
|
if (fgets(buffer, sizeof(buffer), stdin) == NULL ||
|
||||||
strcmp(buffer, "cont\n") == 0)
|
strcmp(buffer, "cont\n") == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
|
if (luaL_loadbufferx(L, buffer, strlen(buffer), "=(debug command)", "t") ||
|
||||||
lua_pcall(L, 0, 0, 0))
|
lua_pcall(L, 0, 0, 0))
|
||||||
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
|
lua_writestringerror("%s\n", luaL_tolstring(L, -1, NULL));
|
||||||
lua_settop(L, 0); /* remove eventual returns */
|
lua_settop(L, 0); /* remove eventual returns */
|
||||||
|
|||||||
4
ldebug.c
4
ldebug.c
@@ -291,7 +291,7 @@ static int nextline (const Proto *p, int currentline, int pc) {
|
|||||||
|
|
||||||
static void collectvalidlines (lua_State *L, Closure *f) {
|
static void collectvalidlines (lua_State *L, Closure *f) {
|
||||||
if (!LuaClosure(f)) {
|
if (!LuaClosure(f)) {
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -580,7 +580,7 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
|
|||||||
kname(p, k, name);
|
kname(p, k, name);
|
||||||
return isEnv(p, lastpc, i, 1);
|
return isEnv(p, lastpc, i, 1);
|
||||||
}
|
}
|
||||||
case OP_GETTABLE: {
|
case OP_GETTABLE: case OP_GETVARG: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
rname(p, lastpc, k, name);
|
rname(p, lastpc, k, name);
|
||||||
return isEnv(p, lastpc, i, 0);
|
return isEnv(p, lastpc, i, 0);
|
||||||
|
|||||||
69
ldo.c
69
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
|
||||||
@@ -330,7 +349,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
|||||||
correctstack(L, oldstack); /* change offsets back to pointers */
|
correctstack(L, oldstack); /* change offsets back to pointers */
|
||||||
L->stack_last.p = L->stack.p + newsize;
|
L->stack_last.p = L->stack.p + newsize;
|
||||||
for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++)
|
for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++)
|
||||||
setnilvalue(s2v(newstack + i)); /* erase new segment */
|
setnilvalue2s(newstack + i); /* erase new segment */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,12 +430,6 @@ void luaD_shrinkstack (lua_State *L) {
|
|||||||
luaE_shrinkCI(L); /* shrink CI list */
|
luaE_shrinkCI(L); /* shrink CI list */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaD_inctop (lua_State *L) {
|
|
||||||
L->top.p++;
|
|
||||||
luaD_checkstack(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|
||||||
@@ -535,7 +548,7 @@ l_sinline void genmoveresults (lua_State *L, StkId res, int nres,
|
|||||||
for (i = 0; i < nres; i++) /* move all results to correct place */
|
for (i = 0; i < nres; i++) /* move all results to correct place */
|
||||||
setobjs2s(L, res + i, firstresult + i);
|
setobjs2s(L, res + i, firstresult + i);
|
||||||
for (; i < wanted; i++) /* complete wanted number of results */
|
for (; i < wanted; i++) /* complete wanted number of results */
|
||||||
setnilvalue(s2v(res + i));
|
setnilvalue2s(res + i);
|
||||||
L->top.p = res + wanted; /* top points after the last result */
|
L->top.p = res + wanted; /* top points after the last result */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,7 +568,7 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres,
|
|||||||
return;
|
return;
|
||||||
case 1 + 1: /* one value needed */
|
case 1 + 1: /* one value needed */
|
||||||
if (nres == 0) /* no results? */
|
if (nres == 0) /* no results? */
|
||||||
setnilvalue(s2v(res)); /* adjust with nil */
|
setnilvalue2s(res); /* adjust with nil */
|
||||||
else /* at least one result */
|
else /* at least one result */
|
||||||
setobjs2s(L, res, L->top.p - nres); /* move it to proper place */
|
setobjs2s(L, res, L->top.p - nres); /* move it to proper place */
|
||||||
L->top.p = res + 1;
|
L->top.p = res + 1;
|
||||||
@@ -605,7 +618,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))
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -675,7 +688,7 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
|
|||||||
setobjs2s(L, ci->func.p + i, func + i);
|
setobjs2s(L, ci->func.p + i, func + i);
|
||||||
func = ci->func.p; /* moved-down function */
|
func = ci->func.p; /* moved-down function */
|
||||||
for (; narg1 <= nfixparams; narg1++)
|
for (; narg1 <= nfixparams; narg1++)
|
||||||
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
|
setnilvalue2s(func + narg1); /* complete missing arguments */
|
||||||
ci->top.p = func + 1 + fsize; /* top for new function */
|
ci->top.p = func + 1 + fsize; /* top for new function */
|
||||||
lua_assert(ci->top.p <= L->stack_last.p);
|
lua_assert(ci->top.p <= L->stack_last.p);
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
@@ -722,7 +735,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
|
|||||||
L->ci = ci = prepCallInfo(L, func, status, func + 1 + fsize);
|
L->ci = ci = prepCallInfo(L, func, status, func + 1 + fsize);
|
||||||
ci->u.l.savedpc = p->code; /* starting point */
|
ci->u.l.savedpc = p->code; /* starting point */
|
||||||
for (; narg < nfixparams; narg++)
|
for (; narg < nfixparams; narg++)
|
||||||
setnilvalue(s2v(L->top.p++)); /* complete missing arguments */
|
setnilvalue2s(L->top.p++); /* complete missing arguments */
|
||||||
lua_assert(ci->top.p <= L->stack_last.p);
|
lua_assert(ci->top.p <= L->stack_last.p);
|
||||||
return ci;
|
return ci;
|
||||||
}
|
}
|
||||||
@@ -1109,28 +1122,54 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Before the first call to the reader function, Lua reserves a slot
|
||||||
|
** with a table for anchoring stuff.
|
||||||
|
*/
|
||||||
static void f_parser (lua_State *L, void *ud) {
|
static void f_parser (lua_State *L, void *ud) {
|
||||||
LClosure *cl;
|
LClosure *cl;
|
||||||
struct SParser *p = cast(struct SParser *, ud);
|
struct SParser *p = cast(struct SParser *, ud);
|
||||||
const char *mode = p->mode ? p->mode : "bt";
|
const char *mode = p->mode ? p->mode : "bt";
|
||||||
int c = zgetc(p->z); /* read first character */
|
int c;
|
||||||
|
Table *anchor;
|
||||||
|
ptrdiff_t otop = savestack(L, L->top.p); /* original top */
|
||||||
|
luaD_checkstack(L, 2);
|
||||||
|
anchor = luaH_new(L); /* create the anchor table */
|
||||||
|
sethvalue2s(L, L->top.p++, anchor); /* anchor the anchor table */
|
||||||
|
c = zgetc(p->z); /* read first character */
|
||||||
if (c == LUA_SIGNATURE[0]) {
|
if (c == LUA_SIGNATURE[0]) {
|
||||||
int fixed = 0;
|
int fixed = 0;
|
||||||
if (strchr(mode, 'B') != NULL)
|
if (strchr(mode, 'B') != NULL)
|
||||||
fixed = 1;
|
fixed = 1;
|
||||||
else
|
else
|
||||||
checkmode(L, mode, "binary");
|
checkmode(L, mode, "binary");
|
||||||
cl = luaU_undump(L, p->z, p->name, fixed);
|
cl = luaU_undump(L, p->z, anchor, p->name, fixed);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
checkmode(L, mode, "text");
|
checkmode(L, mode, "text");
|
||||||
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
|
cl = luaY_parser(L, p->z, anchor, &p->buff, &p->dyd, p->name, c);
|
||||||
}
|
}
|
||||||
|
L->top.p = restorestack(L, otop); /* restore stack */
|
||||||
|
setclLvalue2s(L, L->top.p++, cl); /* push closure */
|
||||||
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
|
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
|
||||||
luaF_initupvals(L, cl);
|
luaF_initupvals(L, cl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Anchor an object in a table in the stack. First, anchor the object
|
||||||
|
** temporarily in the stack, as luaH_set may call an emergency GC.
|
||||||
|
** Then, add it in the table with itself as its key.
|
||||||
|
*/
|
||||||
|
void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj) {
|
||||||
|
setgcovalue(L, s2v(L->top.p++), obj); /* temporary anchor in the stack */
|
||||||
|
luaH_set(L, anchor, s2v(L->top.p - 1), s2v(L->top.p - 1));
|
||||||
|
/* Because this is a new key, luaH_set will call the GC barrier, so
|
||||||
|
we don't need to call the barrier again here */
|
||||||
|
L->top.p--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
|
||||||
const char *mode) {
|
const char *mode) {
|
||||||
struct SParser p;
|
struct SParser p;
|
||||||
|
|||||||
3
ldo.h
3
ldo.h
@@ -88,7 +88,8 @@ LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
|
|||||||
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
|
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 int luaD_checkminstack (lua_State *L);
|
||||||
|
LUAI_FUNC void luaD_anchorobj (lua_State *L, Table *anchor, GCObject *obj);
|
||||||
|
|
||||||
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);
|
||||||
|
|||||||
9
lgc.c
9
lgc.c
@@ -709,7 +709,7 @@ static l_mem traversethread (global_State *g, lua_State *th) {
|
|||||||
if (!g->gcemergency)
|
if (!g->gcemergency)
|
||||||
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
luaD_shrinkstack(th); /* do not change stack in emergency cycle */
|
||||||
for (o = th->top.p; o < th->stack_last.p + EXTRA_STACK; o++)
|
for (o = th->top.p; o < th->stack_last.p + EXTRA_STACK; o++)
|
||||||
setnilvalue(s2v(o)); /* clear dead stack slice */
|
setnilvalue2s(o); /* clear dead stack slice */
|
||||||
/* 'remarkupvals' may have removed thread from 'twups' list */
|
/* 'remarkupvals' may have removed thread from 'twups' list */
|
||||||
if (!isintwups(th) && th->openupval != NULL) {
|
if (!isintwups(th) && th->openupval != NULL) {
|
||||||
th->twups = g->twups; /* link it back to the list */
|
th->twups = g->twups; /* link it back to the list */
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
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))
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ static int searcher_Lua (lua_State *L) {
|
|||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
filename = findfile(L, name, "path", LUA_LSUBSEP);
|
filename = findfile(L, name, "path", LUA_LSUBSEP);
|
||||||
if (filename == NULL) return 1; /* module not found in this path */
|
if (filename == NULL) return 1; /* module not found in this path */
|
||||||
return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename);
|
return checkload(L, (luaL_loadfilex(L, filename, "bt") == LUA_OK), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,8 @@ typedef union {
|
|||||||
#define ttisstrictnil(o) checktag((o), LUA_VNIL)
|
#define ttisstrictnil(o) checktag((o), LUA_VNIL)
|
||||||
|
|
||||||
|
|
||||||
#define setnilvalue(obj) settt_(obj, LUA_VNIL)
|
#define setnilvalue(obj) settt_(obj, LUA_VNIL)
|
||||||
|
#define setnilvalue2s(stk) setnilvalue(s2v(stk))
|
||||||
|
|
||||||
|
|
||||||
#define isabstkey(v) checktag((v), LUA_VABSTKEY)
|
#define isabstkey(v) checktag((v), LUA_VABSTKEY)
|
||||||
|
|||||||
25
lopcodes.c
25
lopcodes.c
@@ -104,35 +104,26 @@ 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, 0, 0, 0, iABC) /* OP_VARARGPREP */
|
||||||
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
|
||||||
/*
|
|
||||||
** Check whether instruction sets top for next instruction, that is,
|
|
||||||
** it results in multiple values.
|
|
||||||
*/
|
|
||||||
int luaP_isOT (Instruction i) {
|
|
||||||
OpCode op = GET_OPCODE(i);
|
|
||||||
switch (op) {
|
|
||||||
case OP_TAILCALL: return 1;
|
|
||||||
default:
|
|
||||||
return testOTMode(op) && GETARG_C(i) == 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether instruction uses top from previous instruction, that is,
|
** Check whether instruction uses top. That happens for OP_VARARGPREP
|
||||||
** it accepts multiple results.
|
** and for instructions that use multiple values set by the previous
|
||||||
|
** instruction.
|
||||||
*/
|
*/
|
||||||
int luaP_isIT (Instruction i) {
|
int luaP_isIT (Instruction i) {
|
||||||
OpCode op = GET_OPCODE(i);
|
OpCode op = GET_OPCODE(i);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_SETLIST:
|
case OP_SETLIST:
|
||||||
return testITMode(GET_OPCODE(i)) && GETARG_vB(i) == 0;
|
return GETARG_vB(i) == 0;
|
||||||
|
case OP_VARARGPREP:
|
||||||
|
return 1;
|
||||||
default:
|
default:
|
||||||
return testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0;
|
return testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
15
lopcodes.h
15
lopcodes.h
@@ -417,8 +417,8 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
|||||||
** bits 0-2: op mode
|
** bits 0-2: op mode
|
||||||
** bit 3: instruction set register A
|
** bit 3: instruction set register A
|
||||||
** bit 4: operator is a test (next instruction must be a jump)
|
** bit 4: operator is a test (next instruction must be a jump)
|
||||||
** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0)
|
** bit 5: used by 'luaP_isIT'
|
||||||
** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
|
** bit 6: used by 'luaP_isOT'
|
||||||
** bit 7: instruction is an MM instruction (call a metamethod)
|
** bit 7: instruction is an MM instruction (call a metamethod)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -427,12 +427,17 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
|
|||||||
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7))
|
#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 7))
|
||||||
#define testAMode(m) (luaP_opmodes[m] & (1 << 3))
|
#define testAMode(m) (luaP_opmodes[m] & (1 << 3))
|
||||||
#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
|
#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
|
||||||
#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
|
|
||||||
#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
|
|
||||||
#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
|
#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC int luaP_isOT (Instruction i);
|
/* Check whether instruction sets top for next instruction, that is,
|
||||||
|
** it results in multiple values. Used only for tests.
|
||||||
|
*/
|
||||||
|
#define luaP_isOT(i) \
|
||||||
|
(GET_OPCODE(i) == OP_TAILCALL || \
|
||||||
|
((luaP_opmodes[GET_OPCODE(i)] & (1 << 6)) && GETARG_C(i) == 0))
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC int luaP_isIT (Instruction i);
|
LUAI_FUNC int luaP_isIT (Instruction i);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
32
lparser.c
32
lparser.c
@@ -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] */
|
||||||
@@ -821,8 +821,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
|
|||||||
luaC_objbarrier(L, f, f->source);
|
luaC_objbarrier(L, f, f->source);
|
||||||
f->maxstacksize = 2; /* registers 0/1 are always valid */
|
f->maxstacksize = 2; /* registers 0/1 are always valid */
|
||||||
fs->kcache = luaH_new(L); /* create table for function */
|
fs->kcache = luaH_new(L); /* create table for function */
|
||||||
sethvalue2s(L, L->top.p, fs->kcache); /* anchor it */
|
luaD_anchorobj(L, ls->h, obj2gco(fs->kcache)); /* anchor it */
|
||||||
luaD_inctop(L);
|
|
||||||
enterblock(fs, bl, 0);
|
enterblock(fs, bl, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,6 +830,7 @@ static void close_func (LexState *ls) {
|
|||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Proto *f = fs->f;
|
Proto *f = fs->f;
|
||||||
|
TValue temp;
|
||||||
luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */
|
luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */
|
||||||
leaveblock(fs);
|
leaveblock(fs);
|
||||||
lua_assert(fs->bl == NULL);
|
lua_assert(fs->bl == NULL);
|
||||||
@@ -843,8 +843,10 @@ static void close_func (LexState *ls) {
|
|||||||
luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
|
luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
|
||||||
luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
|
luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
|
||||||
luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
|
luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
|
||||||
|
/* remove kcache table from scanner table ("weigh" its anchor) */
|
||||||
|
sethvalue(L, &temp, fs->kcache); /* key to be set to nil */
|
||||||
|
luaH_set(L, ls->h, &temp, &G(L)->nilvalue);
|
||||||
ls->fs = fs->prev;
|
ls->fs = fs->prev;
|
||||||
L->top.p--; /* pop kcache table */
|
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,6 +1166,7 @@ static void funcargs (LexState *ls, expdesc *f) {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
luaX_syntaxerror(ls, "function arguments expected");
|
luaX_syntaxerror(ls, "function arguments expected");
|
||||||
|
return; /* to avoid warnings */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_assert(f->k == VNONRELOC);
|
lua_assert(f->k == VNONRELOC);
|
||||||
@@ -1611,7 +1614,6 @@ static void repeatstat (LexState *ls, int line) {
|
|||||||
statlist(ls);
|
statlist(ls);
|
||||||
check_match(ls, TK_UNTIL, TK_REPEAT, line);
|
check_match(ls, TK_UNTIL, TK_REPEAT, line);
|
||||||
condexit = cond(ls); /* read condition (inside scope block) */
|
condexit = cond(ls); /* read condition (inside scope block) */
|
||||||
leaveblock(fs); /* finish scope */
|
|
||||||
if (bl2.upval) { /* upvalues? */
|
if (bl2.upval) { /* upvalues? */
|
||||||
int exit = luaK_jump(fs); /* normal exit must jump over fix */
|
int exit = luaK_jump(fs); /* normal exit must jump over fix */
|
||||||
luaK_patchtohere(fs, condexit); /* repetition must close upvalues */
|
luaK_patchtohere(fs, condexit); /* repetition must close upvalues */
|
||||||
@@ -1620,6 +1622,7 @@ static void repeatstat (LexState *ls, int line) {
|
|||||||
luaK_patchtohere(fs, exit); /* normal exit comes to here */
|
luaK_patchtohere(fs, exit); /* normal exit comes to here */
|
||||||
}
|
}
|
||||||
luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
|
luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
|
||||||
|
leaveblock(fs); /* finish scope */
|
||||||
leaveblock(fs); /* finish loop */
|
leaveblock(fs); /* finish loop */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2111,7 +2114,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 */
|
||||||
@@ -2165,16 +2168,14 @@ static void mainfunc (LexState *ls, FuncState *fs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
LClosure *luaY_parser (lua_State *L, ZIO *z, Table *anchor, Mbuffer *buff,
|
||||||
Dyndata *dyd, const char *name, int firstchar) {
|
Dyndata *dyd, const char *name, int firstchar) {
|
||||||
LexState lexstate;
|
LexState lexstate;
|
||||||
FuncState funcstate;
|
FuncState funcstate;
|
||||||
LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */
|
LClosure *cl;
|
||||||
setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */
|
lexstate.h = anchor; /* table for scanner */
|
||||||
luaD_inctop(L);
|
cl = luaF_newLclosure(L, 1); /* create main closure */
|
||||||
lexstate.h = luaH_new(L); /* create table for scanner */
|
luaD_anchorobj(L, anchor, obj2gco(cl)); /* anchor it in scanner table */
|
||||||
sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */
|
|
||||||
luaD_inctop(L);
|
|
||||||
funcstate.f = cl->p = luaF_newproto(L);
|
funcstate.f = cl->p = luaF_newproto(L);
|
||||||
luaC_objbarrier(L, cl, cl->p);
|
luaC_objbarrier(L, cl, cl->p);
|
||||||
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
|
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
|
||||||
@@ -2187,7 +2188,6 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
|||||||
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
|
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
|
||||||
/* all scopes should be correctly finished */
|
/* all scopes should be correctly finished */
|
||||||
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
|
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
|
||||||
L->top.p--; /* remove scanner's table */
|
return cl;
|
||||||
return cl; /* closure is on the stack, too */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,8 +189,9 @@ typedef struct FuncState {
|
|||||||
LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs);
|
LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs);
|
||||||
LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l,
|
LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l,
|
||||||
const char *what);
|
const char *what);
|
||||||
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Table *anchor,
|
||||||
Dyndata *dyd, const char *name, int firstchar);
|
Mbuffer *buff, Dyndata *dyd,
|
||||||
|
const char *name, int firstchar);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
lstate.c
21
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;
|
||||||
@@ -146,7 +151,7 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) {
|
|||||||
static void resetCI (lua_State *L) {
|
static void resetCI (lua_State *L) {
|
||||||
CallInfo *ci = L->ci = &L->base_ci;
|
CallInfo *ci = L->ci = &L->base_ci;
|
||||||
ci->func.p = L->stack.p;
|
ci->func.p = L->stack.p;
|
||||||
setnilvalue(s2v(ci->func.p)); /* 'function' entry for basic 'ci' */
|
setnilvalue2s(ci->func.p); /* 'function' entry for basic 'ci' */
|
||||||
ci->top.p = ci->func.p + 1 + LUA_MINSTACK; /* +1 for 'function' entry */
|
ci->top.p = ci->func.p + 1 + LUA_MINSTACK; /* +1 for 'function' entry */
|
||||||
ci->u.c.k = NULL;
|
ci->u.c.k = NULL;
|
||||||
ci->callstatus = CIST_C;
|
ci->callstatus = CIST_C;
|
||||||
@@ -161,7 +166,7 @@ static void stack_init (lua_State *L1, lua_State *L) {
|
|||||||
L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
|
L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
|
||||||
L1->tbclist.p = L1->stack.p;
|
L1->tbclist.p = L1->stack.p;
|
||||||
for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
|
for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
|
||||||
setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */
|
setnilvalue2s(L1->stack.p + i); /* erase new stack */
|
||||||
L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
|
L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
|
||||||
/* initialize first ci */
|
/* initialize first ci */
|
||||||
resetCI(L1);
|
resetCI(L1);
|
||||||
|
|||||||
42
lstate.h
42
lstate.h
@@ -383,7 +383,7 @@ typedef struct global_State {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Union of all collectable objects (only for conversions)
|
** Union of all collectable objects
|
||||||
** ISO C99, 6.5.2.3 p.5:
|
** ISO C99, 6.5.2.3 p.5:
|
||||||
** "if a union contains several structures that share a common initial
|
** "if a union contains several structures that share a common initial
|
||||||
** sequence [...], and if the union object currently contains one
|
** sequence [...], and if the union object currently contains one
|
||||||
@@ -403,32 +403,32 @@ union GCUnion {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* macros to convert a GCObject into a specific value
|
||||||
** ISO C99, 6.7.2.1 p.14:
|
** ISO C99, 6.3.2.2 p.7:
|
||||||
** "A pointer to a union object, suitably converted, points to each of
|
** "A pointer to an object or incomplete type may be converted to a
|
||||||
** its members [...], and vice versa."
|
** pointer to a different object or incomplete type. If the resulting
|
||||||
|
** pointer is not correctly aligned for the pointed-to type, the
|
||||||
|
** behavior is undefined. Otherwise, when converted back again, the
|
||||||
|
** result shall compare equal to the original pointer."
|
||||||
*/
|
*/
|
||||||
#define cast_u(o) cast(union GCUnion *, (o))
|
#define gco2(v,T,o) check_exp((o)->tt == v, cast(T*, o))
|
||||||
|
#define gco2nv(t,T,o) check_exp(novariant((o)->tt) == t, cast(T*, o))
|
||||||
/* macros to convert a GCObject into a specific value */
|
#define gco2ts(o) gco2nv(LUA_TSTRING, TString, o)
|
||||||
#define gco2ts(o) \
|
#define gco2u(o) gco2(LUA_VUSERDATA, Udata, o)
|
||||||
check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
|
#define gco2lcl(o) (&gco2(LUA_VLCL, Closure, o)->l)
|
||||||
#define gco2u(o) check_exp((o)->tt == LUA_VUSERDATA, &((cast_u(o))->u))
|
#define gco2ccl(o) (&gco2(LUA_VCCL, Closure, o)->c)
|
||||||
#define gco2lcl(o) check_exp((o)->tt == LUA_VLCL, &((cast_u(o))->cl.l))
|
#define gco2cl(o) gco2nv(LUA_TFUNCTION, Closure, o)
|
||||||
#define gco2ccl(o) check_exp((o)->tt == LUA_VCCL, &((cast_u(o))->cl.c))
|
#define gco2t(o) gco2(LUA_VTABLE, Table, o)
|
||||||
#define gco2cl(o) \
|
#define gco2p(o) gco2(LUA_VPROTO, Proto, o)
|
||||||
check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl))
|
#define gco2th(o) gco2(LUA_VTHREAD, lua_State, o)
|
||||||
#define gco2t(o) check_exp((o)->tt == LUA_VTABLE, &((cast_u(o))->h))
|
#define gco2upv(o) gco2(LUA_VUPVAL, UpVal, o)
|
||||||
#define gco2p(o) check_exp((o)->tt == LUA_VPROTO, &((cast_u(o))->p))
|
|
||||||
#define gco2th(o) check_exp((o)->tt == LUA_VTHREAD, &((cast_u(o))->th))
|
|
||||||
#define gco2upv(o) check_exp((o)->tt == LUA_VUPVAL, &((cast_u(o))->upv))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** macro to convert a Lua object into a GCObject
|
** macro to convert a Lua object into a GCObject
|
||||||
*/
|
*/
|
||||||
#define obj2gco(v) \
|
#define obj2gco(v) \
|
||||||
check_exp(novariant((v)->tt) >= LUA_TSTRING, &(cast_u(v)->gc))
|
check_exp(novariant((v)->tt) >= LUA_TSTRING, cast(GCObject*, v))
|
||||||
|
|
||||||
|
|
||||||
/* actual number of total memory allocated */
|
/* actual number of total memory allocated */
|
||||||
@@ -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);
|
||||||
|
|||||||
18
lstrlib.c
18
lstrlib.c
@@ -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");
|
||||||
@@ -757,19 +757,25 @@ static int nospecials (const char *p, size_t l) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Prepare state for matches. These fields are not affected by each match.
|
||||||
|
*/
|
||||||
static void prepstate (MatchState *ms, lua_State *L,
|
static void prepstate (MatchState *ms, lua_State *L,
|
||||||
const char *s, size_t ls, const char *p, size_t lp) {
|
const char *s, size_t ls, const char *p, size_t lp) {
|
||||||
ms->L = L;
|
ms->L = L;
|
||||||
ms->matchdepth = MAXCCALLS;
|
|
||||||
ms->src_init = s;
|
ms->src_init = s;
|
||||||
ms->src_end = s + ls;
|
ms->src_end = s + ls;
|
||||||
ms->p_end = p + lp;
|
ms->p_end = p + lp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** (Re)prepare state for a match, setting fields that change during
|
||||||
|
** each match.
|
||||||
|
*/
|
||||||
static void reprepstate (MatchState *ms) {
|
static void reprepstate (MatchState *ms) {
|
||||||
|
ms->matchdepth = MAXCCALLS;
|
||||||
ms->level = 0;
|
ms->level = 0;
|
||||||
lua_assert(ms->matchdepth == MAXCCALLS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -968,7 +974,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 +1732,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 ||
|
||||||
|
|||||||
31
ltests.c
31
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));
|
||||||
@@ -1124,7 +1145,7 @@ static int table_query (lua_State *L) {
|
|||||||
if (!tagisempty(*getArrTag(t, i)))
|
if (!tagisempty(*getArrTag(t, i)))
|
||||||
arr2obj(t, cast_uint(i), s2v(L->top.p));
|
arr2obj(t, cast_uint(i), s2v(L->top.p));
|
||||||
else
|
else
|
||||||
setnilvalue(s2v(L->top.p));
|
setnilvalue2s(L->top.p);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
}
|
}
|
||||||
@@ -1281,7 +1302,7 @@ static int doonnewstack (lua_State *L) {
|
|||||||
lua_State *L1 = lua_newthread(L);
|
lua_State *L1 = lua_newthread(L);
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *s = luaL_checklstring(L, 1, &l);
|
const char *s = luaL_checklstring(L, 1, &l);
|
||||||
int status = luaL_loadbuffer(L1, s, l, s);
|
int status = luaL_loadbufferx(L1, s, l, s, "t");
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK)
|
||||||
status = lua_pcall(L1, 0, 0, 0);
|
status = lua_pcall(L1, 0, 0, 0);
|
||||||
lua_pushinteger(L, status);
|
lua_pushinteger(L, status);
|
||||||
@@ -1361,7 +1382,7 @@ static int doremote (lua_State *L) {
|
|||||||
const char *code = luaL_checklstring(L, 2, &lcode);
|
const char *code = luaL_checklstring(L, 2, &lcode);
|
||||||
int status;
|
int status;
|
||||||
lua_settop(L1, 0);
|
lua_settop(L1, 0);
|
||||||
status = luaL_loadbuffer(L1, code, lcode, code);
|
status = luaL_loadbufferx(L1, code, lcode, code, "t");
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK)
|
||||||
status = lua_pcall(L1, 0, LUA_MULTRET, 0);
|
status = lua_pcall(L1, 0, LUA_MULTRET, 0);
|
||||||
if (status != LUA_OK) {
|
if (status != LUA_OK) {
|
||||||
@@ -1717,7 +1738,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
|
|||||||
lua_pushinteger(L1, luaL_len(L1, getindex));
|
lua_pushinteger(L1, luaL_len(L1, getindex));
|
||||||
}
|
}
|
||||||
else if EQ("loadfile") {
|
else if EQ("loadfile") {
|
||||||
luaL_loadfile(L1, luaL_checkstring(L1, getnum));
|
luaL_loadfilex(L1, luaL_checkstring(L1, getnum), "t");
|
||||||
}
|
}
|
||||||
else if EQ("loadstring") {
|
else if EQ("loadstring") {
|
||||||
size_t slen;
|
size_t slen;
|
||||||
@@ -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
|
||||||
|
|||||||
10
ltm.c
10
ltm.c
@@ -262,7 +262,7 @@ static void buildhiddenargs (lua_State *L, CallInfo *ci, const Proto *p,
|
|||||||
/* move fixed parameters to after the copied function */
|
/* move fixed parameters to after the copied function */
|
||||||
for (i = 1; i <= nfixparams; i++) {
|
for (i = 1; i <= nfixparams; i++) {
|
||||||
setobjs2s(L, L->top.p++, ci->func.p + i);
|
setobjs2s(L, L->top.p++, ci->func.p + i);
|
||||||
setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
|
setnilvalue2s(ci->func.p + i); /* erase original parameter (for GC) */
|
||||||
}
|
}
|
||||||
ci->func.p += totalargs + 1; /* 'func' now lives after hidden arguments */
|
ci->func.p += totalargs + 1; /* 'func' now lives after hidden arguments */
|
||||||
ci->top.p += totalargs + 1;
|
ci->top.p += totalargs + 1;
|
||||||
@@ -283,7 +283,7 @@ void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
|
|||||||
lua_assert(p->flag & PF_VAHID);
|
lua_assert(p->flag & PF_VAHID);
|
||||||
buildhiddenargs(L, ci, p, totalargs, nfixparams, nextra);
|
buildhiddenargs(L, ci, p, totalargs, nfixparams, nextra);
|
||||||
/* set vararg parameter to nil */
|
/* set vararg parameter to nil */
|
||||||
setnilvalue(s2v(ci->func.p + nfixparams + 1));
|
setnilvalue2s(ci->func.p + nfixparams + 1);
|
||||||
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
|
lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setnilvalue(s2v(ra)); /* else produce nil */
|
setnilvalue2s(ra); /* else produce nil */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -355,10 +355,10 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted,
|
|||||||
for (i = 0; i < touse; i++) {
|
for (i = 0; i < touse; i++) {
|
||||||
lu_byte tag = luaH_getint(h, i + 1, s2v(where + i));
|
lu_byte tag = luaH_getint(h, i + 1, s2v(where + i));
|
||||||
if (tagisempty(tag))
|
if (tagisempty(tag))
|
||||||
setnilvalue(s2v(where + i));
|
setnilvalue2s(where + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < wanted; i++) /* complete required results with nil */
|
for (; i < wanted; i++) /* complete required results with nil */
|
||||||
setnilvalue(s2v(where + i));
|
setnilvalue2s(where + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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)))
|
||||||
|
|
||||||
|
|||||||
69
lua.c
69
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
|
||||||
|
|
||||||
|
|
||||||
@@ -201,12 +207,12 @@ static int dochunk (lua_State *L, int status) {
|
|||||||
|
|
||||||
|
|
||||||
static int dofile (lua_State *L, const char *name) {
|
static int dofile (lua_State *L, const char *name) {
|
||||||
return dochunk(L, luaL_loadfile(L, name));
|
return dochunk(L, luaL_loadfilex(L, name, "bt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int dostring (lua_State *L, const char *s, const char *name) {
|
static int dostring (lua_State *L, const char *s, const char *name) {
|
||||||
return dochunk(L, luaL_loadbuffer(L, s, strlen(s), name));
|
return dochunk(L, luaL_loadbufferx(L, s, strlen(s), name, "t"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,7 +266,7 @@ static int handle_script (lua_State *L, char **argv) {
|
|||||||
const char *fname = argv[0];
|
const char *fname = argv[0];
|
||||||
if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
|
if (strcmp(fname, "-") == 0 && strcmp(argv[-1], "--") != 0)
|
||||||
fname = NULL; /* stdin */
|
fname = NULL; /* stdin */
|
||||||
status = luaL_loadfile(L, fname);
|
status = luaL_loadfilex(L, fname, "bt");
|
||||||
if (status == LUA_OK) {
|
if (status == LUA_OK) {
|
||||||
int n = pushargs(L); /* push arguments to script */
|
int n = pushargs(L); /* push arguments to script */
|
||||||
status = docall(L, n, LUA_MULTRET);
|
status = docall(L, n, LUA_MULTRET);
|
||||||
@@ -349,6 +355,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 */
|
||||||
@@ -373,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] == '@')
|
||||||
@@ -497,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 /* }{ */
|
||||||
@@ -587,11 +609,11 @@ static int pushline (lua_State *L, int firstline) {
|
|||||||
static int addreturn (lua_State *L) {
|
static int addreturn (lua_State *L) {
|
||||||
const char *line = lua_tostring(L, -1); /* original line */
|
const char *line = lua_tostring(L, -1); /* original line */
|
||||||
const char *retline = lua_pushfstring(L, "return %s;", line);
|
const char *retline = lua_pushfstring(L, "return %s;", line);
|
||||||
int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin");
|
int status = luaL_loadbufferx(L, retline, strlen(retline), "=stdin", "t");
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK)
|
||||||
lua_remove(L, -2); /* remove modified line */
|
lua_remove(L, -2); /* remove modified line */
|
||||||
else
|
else
|
||||||
lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */
|
lua_pop(L, 2); /* pop result from 'luaL_loadbufferx' and modified line */
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +640,7 @@ static int multiline (lua_State *L) {
|
|||||||
const char *line = lua_tolstring(L, 1, &len); /* get first line */
|
const char *line = lua_tolstring(L, 1, &len); /* get first line */
|
||||||
checklocal(line);
|
checklocal(line);
|
||||||
for (;;) { /* repeat until gets a complete statement */
|
for (;;) { /* repeat until gets a complete statement */
|
||||||
int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */
|
int status = luaL_loadbufferx(L, line, len, "=stdin", "t"); /* try it */
|
||||||
if (!incomplete(L, status) || !pushline(L, 0))
|
if (!incomplete(L, status) || !pushline(L, 0))
|
||||||
return status; /* should not or cannot try to add continuation line */
|
return status; /* should not or cannot try to add continuation line */
|
||||||
lua_remove(L, -2); /* remove error message (from incomplete line) */
|
lua_remove(L, -2); /* remove error message (from incomplete line) */
|
||||||
@@ -692,7 +714,13 @@ static void doREPL (lua_State *L) {
|
|||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
#if !defined(luai_openlibs)
|
#if !defined(luai_openlibs)
|
||||||
#define luai_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
#if defined(LUA_NODEBUGLIB)
|
||||||
|
/* With this option, code must require the debug library before using it */
|
||||||
|
#define luai_openlibs(L) luaL_openselectedlibs(L, ~LUA_DBLIBK, LUA_DBLIBK)
|
||||||
|
#else
|
||||||
|
/* The default is to open all standard libraries */
|
||||||
|
#define luai_openlibs(L) luaL_openselectedlibs(L, ~0, 0)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -714,18 +742,19 @@ 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 and -l */
|
|
||||||
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)
|
||||||
|
|||||||
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
|
||||||
|
|||||||
39
luaconf.h
39
luaconf.h
@@ -70,14 +70,16 @@
|
|||||||
#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 */
|
||||||
#define LUA_READLINELIB "libedit.dylib"
|
#define LUA_USE_READLINE /* needs an extra library: -lreadline */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -224,17 +226,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 +247,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 +341,9 @@
|
|||||||
/*
|
/*
|
||||||
@@ 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
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -649,7 +653,7 @@
|
|||||||
*/
|
*/
|
||||||
#if !defined(luai_likely)
|
#if !defined(luai_likely)
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(LUA_NOBUILTIN)
|
#if !defined(LUA_NOBUILTIN) && defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
|
#define luai_likely(x) (__builtin_expect(((x) != 0), 1))
|
||||||
#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
#define luai_unlikely(x) (__builtin_expect(((x) != 0), 0))
|
||||||
#else
|
#else
|
||||||
@@ -721,10 +725,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
|
||||||
|
|
||||||
/* }================================================================== */
|
/* }================================================================== */
|
||||||
|
|
||||||
|
|||||||
13
lundump.c
13
lundump.c
@@ -392,7 +392,8 @@ static void checkHeader (LoadState *S) {
|
|||||||
/*
|
/*
|
||||||
** Load precompiled chunk.
|
** Load precompiled chunk.
|
||||||
*/
|
*/
|
||||||
LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
|
LClosure *luaU_undump (lua_State *L, ZIO *Z, Table *anchor, const char *name,
|
||||||
|
int fixed) {
|
||||||
LoadState S;
|
LoadState S;
|
||||||
LClosure *cl;
|
LClosure *cl;
|
||||||
if (*name == '@' || *name == '=')
|
if (*name == '@' || *name == '=')
|
||||||
@@ -405,20 +406,16 @@ LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
|
|||||||
S.fixed = cast_byte(fixed);
|
S.fixed = cast_byte(fixed);
|
||||||
S.offset = 1; /* fist byte was already read */
|
S.offset = 1; /* fist byte was already read */
|
||||||
checkHeader(&S);
|
checkHeader(&S);
|
||||||
cl = luaF_newLclosure(L, loadByte(&S));
|
S.h = anchor;
|
||||||
setclLvalue2s(L, L->top.p, cl);
|
|
||||||
luaD_inctop(L);
|
|
||||||
S.h = luaH_new(L); /* create list of saved strings */
|
|
||||||
S.nstr = 0;
|
S.nstr = 0;
|
||||||
sethvalue2s(L, L->top.p, S.h); /* anchor it */
|
cl = luaF_newLclosure(L, loadByte(&S));
|
||||||
luaD_inctop(L);
|
luaD_anchorobj(L, anchor, obj2gco(cl));
|
||||||
cl->p = luaF_newproto(L);
|
cl->p = luaF_newproto(L);
|
||||||
luaC_objbarrier(L, cl, cl->p);
|
luaC_objbarrier(L, cl, cl->p);
|
||||||
loadFunction(&S, cl->p);
|
loadFunction(&S, cl->p);
|
||||||
if (cl->nupvalues != cl->p->sizeupvalues)
|
if (cl->nupvalues != cl->p->sizeupvalues)
|
||||||
error(&S, "corrupted chunk");
|
error(&S, "corrupted chunk");
|
||||||
luai_verifycode(L, cl->p);
|
luai_verifycode(L, cl->p);
|
||||||
L->top.p--; /* pop table */
|
|
||||||
return cl;
|
return cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
|
|
||||||
/* load one chunk; from lundump.c */
|
/* load one chunk; from lundump.c */
|
||||||
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name,
|
LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Table *anchor,
|
||||||
int fixed);
|
const char* name, int fixed);
|
||||||
|
|
||||||
/* dump one chunk; from ldump.c */
|
/* dump one chunk; from ldump.c */
|
||||||
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
|
LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w,
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
28
lvm.c
28
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 */
|
||||||
@@ -303,7 +303,7 @@ lu_byte luaV_finishget (lua_State *L, const TValue *t, TValue *key,
|
|||||||
else { /* 't' is a table */
|
else { /* 't' is a table */
|
||||||
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
|
tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */
|
||||||
if (tm == NULL) { /* no metamethod? */
|
if (tm == NULL) { /* no metamethod? */
|
||||||
setnilvalue(s2v(val)); /* result is nil */
|
setnilvalue2s(val); /* result is nil */
|
||||||
return LUA_VNIL;
|
return LUA_VNIL;
|
||||||
}
|
}
|
||||||
/* else will try the metamethod */
|
/* else will try the metamethod */
|
||||||
@@ -360,13 +360,19 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||||||
luaT_callTM(L, tm, t, key, val);
|
luaT_callTM(L, tm, t, key, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t = tm; /* else repeat assignment over 'tm' */
|
t = tm; /* else must repeat assignment over 'tm' */
|
||||||
luaV_fastset(t, key, val, hres, luaH_pset);
|
/* do the equivalent to 'luaV_fastset', but saving 'h' */
|
||||||
if (hres == HOK) {
|
if (!ttistable(t))
|
||||||
luaV_finishfastset(L, t, val);
|
hres = HNOTATABLE;
|
||||||
return; /* done */
|
else {
|
||||||
|
Table *h = hvalue(t); /* next call can change the value at 't' */
|
||||||
|
hres = luaH_pset(h, key, val);
|
||||||
|
if (hres == HOK) {
|
||||||
|
luaC_barrierback(L, obj2gco(h), val); /* luaV_finishfastset */
|
||||||
|
return; /* done */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
|
/* else 'return luaV_finishset(L, t, key, val, hres)' (loop) */
|
||||||
}
|
}
|
||||||
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
luaG_runerror(L, "'__newindex' chain too long; possible loop");
|
||||||
}
|
}
|
||||||
@@ -919,7 +925,7 @@ void luaV_finishOp (lua_State *L) {
|
|||||||
** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute'
|
** Macros for arithmetic/bitwise/comparison opcodes in 'luaV_execute'
|
||||||
**
|
**
|
||||||
** All these macros are to be used exclusively inside the main
|
** All these macros are to be used exclusively inside the main
|
||||||
** iterpreter loop (function luaV_execute) and may access directly
|
** interpreter loop (function luaV_execute) and may access directly
|
||||||
** the local variables of that function (L, i, pc, ci, etc.).
|
** the local variables of that function (L, i, pc, ci, etc.).
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
@@ -1841,7 +1847,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;
|
||||||
|
|||||||
11
makefile
11
makefile
@@ -60,10 +60,13 @@ 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
|
|
||||||
|
|
||||||
|
# Test mode: Add test library, turn on asserts, redefine several
|
||||||
|
# constants ("to give some bugs a chance"), track memory use, and add
|
||||||
|
# debug information.
|
||||||
|
# TESTS= -DLUA_USER_H='"ltests.h"' -Og -g
|
||||||
|
|
||||||
LOCAL = $(TESTS) $(CWARNS)
|
LOCAL = $(TESTS) $(CWARNS)
|
||||||
|
|
||||||
@@ -71,13 +74,15 @@ LOCAL = $(TESTS) $(CWARNS)
|
|||||||
# To enable Linux goodies, -DLUA_USE_LINUX
|
# To enable Linux goodies, -DLUA_USE_LINUX
|
||||||
# For C89, "-std=c89 -DLUA_USE_C89"
|
# For C89, "-std=c89 -DLUA_USE_C89"
|
||||||
# Note that Linux/Posix options are not compatible with C89
|
# Note that Linux/Posix options are not compatible with C89
|
||||||
|
# (For 32-bit, add option "-m32" to MYCFLAGS and MYLDFLAGS.)
|
||||||
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX
|
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX
|
||||||
MYLDFLAGS= -Wl,-E
|
MYLDFLAGS= -Wl,-E
|
||||||
MYLIBS= -ldl
|
MYLIBS= -ldl
|
||||||
|
|
||||||
|
|
||||||
CC= gcc
|
CC= gcc
|
||||||
CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common -march=native
|
# (Optionally we can use -march=native -mno-avx512f.)
|
||||||
|
CFLAGS= -Wall -O2 $(MYCFLAGS) -fno-stack-protector -fno-common
|
||||||
AR= ar rc
|
AR= ar rc
|
||||||
RANLIB= ranlib
|
RANLIB= ranlib
|
||||||
RM= rm -f
|
RM= rm -f
|
||||||
|
|||||||
11
manual/2html
11
manual/2html
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env lua5.3
|
#!/usr/bin/env lua
|
||||||
|
|
||||||
|
|
||||||
-- special marks:
|
-- special marks:
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ end
|
|||||||
|
|
||||||
local function compose (f,g)
|
local function compose (f,g)
|
||||||
assert(f and g)
|
assert(f and g)
|
||||||
return function (s) return g(f(s)) end
|
return function (...) return g(f(...)) end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function concat (f, g)
|
local function concat (f, g)
|
||||||
@@ -395,9 +395,10 @@ APIEntry = function (e)
|
|||||||
local apiicmd, ne = string.match(e, "^(.-</span>)(.*)")
|
local apiicmd, ne = string.match(e, "^(.-</span>)(.*)")
|
||||||
--io.stderr:write(e)
|
--io.stderr:write(e)
|
||||||
if not apiicmd then
|
if not apiicmd then
|
||||||
return antipara(Tag.hr() .. Tag.h3(a)) .. Tag.pre(h) .. e
|
return antipara(Tag.hr() .. Tag.h3(a)) .. Tag.pre(h, {class="api"}) .. e
|
||||||
else
|
else
|
||||||
return antipara(Tag.hr() .. Tag.h3(a)) .. apiicmd .. Tag.pre(h) .. ne
|
return antipara(Tag.hr() .. Tag.h3(a)) .. apiicmd ..
|
||||||
|
Tag.pre(h, {class="api"}) .. ne
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|||||||
109
manual/manual.of
109
manual/manual.of
@@ -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,
|
||||||
@@ -1728,7 +1728,7 @@ global X <const>, _G
|
|||||||
X = 1 -- ERROR
|
X = 1 -- ERROR
|
||||||
_ENV.X = 1 -- Ok
|
_ENV.X = 1 -- Ok
|
||||||
_G.print(X) -- Ok
|
_G.print(X) -- Ok
|
||||||
foo() -- 'foo' can freely change any global
|
foo() -- 'foo' can freely change any global
|
||||||
}
|
}
|
||||||
|
|
||||||
A chunk is also a block @see{chunks},
|
A chunk is also a block @see{chunks},
|
||||||
@@ -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.
|
||||||
@@ -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 have parameters
|
||||||
|
that are pointers to C strings (@T{const char*}).
|
||||||
|
Some of these 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}.
|
||||||
@@ -3107,7 +3119,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 +3652,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 +3891,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)}.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -3946,8 +3962,8 @@ this confuses the next call to @Lid{lua_next}.
|
|||||||
|
|
||||||
This function may raise an error if the given key
|
This function may raise an error if the given key
|
||||||
is neither @nil nor present in the table.
|
is neither @nil nor present in the table.
|
||||||
See function @Lid{next} for the caveats of modifying
|
|
||||||
the table during its traversal.
|
See function @Lid{next} for more details about the traversal.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4432,7 +4448,7 @@ Starts and resumes a coroutine in the given thread @id{L}.
|
|||||||
To start a coroutine,
|
To start a coroutine,
|
||||||
you push the main function plus any arguments
|
you push the main function plus any arguments
|
||||||
onto the empty stack of the thread.
|
onto the empty stack of the thread.
|
||||||
then you call @Lid{lua_resume},
|
Then you call @Lid{lua_resume},
|
||||||
with @id{nargs} being the number of arguments.
|
with @id{nargs} being the number of arguments.
|
||||||
The function returns when the coroutine suspends,
|
The function returns when the coroutine suspends,
|
||||||
finishes its execution, or raises an unprotected error.
|
finishes its execution, or raises an unprotected error.
|
||||||
@@ -4612,7 +4628,7 @@ You can resume threads with status @Lid{LUA_OK}
|
|||||||
}
|
}
|
||||||
|
|
||||||
@APIEntry{size_t lua_stringtonumber (lua_State *L, const char *s);|
|
@APIEntry{size_t lua_stringtonumber (lua_State *L, const char *s);|
|
||||||
@apii{0,1,-}
|
@apii{0,0|1,-}
|
||||||
|
|
||||||
Converts the zero-terminated string @id{s} to a number,
|
Converts the zero-terminated string @id{s} to a number,
|
||||||
pushes that number into the stack,
|
pushes that number into the stack,
|
||||||
@@ -4942,7 +4958,7 @@ Lua calls the given @x{continuation function} @id{k} to continue
|
|||||||
the execution of the @N{C function} that yielded @see{continuations}.
|
the execution of the @N{C function} that yielded @see{continuations}.
|
||||||
This continuation function receives the same stack
|
This continuation function receives the same stack
|
||||||
from the previous function,
|
from the previous function,
|
||||||
with the @id{n} results removed and
|
with all the results (@id{nresults}) removed and
|
||||||
replaced by the arguments passed to @Lid{lua_resume}.
|
replaced by the arguments passed to @Lid{lua_resume}.
|
||||||
Moreover,
|
Moreover,
|
||||||
the continuation function receives the value @id{ctx}
|
the continuation function receives the value @id{ctx}
|
||||||
@@ -5032,7 +5048,7 @@ the function was defined in a string where
|
|||||||
}
|
}
|
||||||
|
|
||||||
@item{@id{srclen}|
|
@item{@id{srclen}|
|
||||||
The length of the string @id{source}.
|
the length of the string @id{source}.
|
||||||
}
|
}
|
||||||
|
|
||||||
@item{@id{short_src}|
|
@item{@id{short_src}|
|
||||||
@@ -5196,7 +5212,7 @@ running at the given level;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@item{@Char{S}|
|
@item{@Char{S}|
|
||||||
fills in the fields @id{source}, @id{short_src},
|
fills in the fields @id{source}, @id{srclen}, @id{short_src},
|
||||||
@id{linedefined}, @id{lastlinedefined}, and @id{what};
|
@id{linedefined}, @id{lastlinedefined}, and @id{what};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5372,7 +5388,9 @@ Returns @id{NULL} (and pops nothing)
|
|||||||
when the index is greater than
|
when the index is greater than
|
||||||
the number of active local variables.
|
the number of active local variables.
|
||||||
|
|
||||||
Parameters @id{ar} and @id{n} are as in the function @Lid{lua_getlocal}.
|
Parameters @id{ar} and @id{n} are as in the function @Lid{lua_getlocal},
|
||||||
|
except that @id{ar} cannot be @id{NULL},
|
||||||
|
as @id{lua_setlocal} only operates on activation records.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5439,7 +5457,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 +5601,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 +5622,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).
|
||||||
@@ -6053,6 +6071,14 @@ In both cases,
|
|||||||
the function pushes onto the stack the final value associated
|
the function pushes onto the stack the final value associated
|
||||||
with @id{tname} in the registry.
|
with @id{tname} in the registry.
|
||||||
|
|
||||||
|
Usage note: Beware the use of the return value of this function to
|
||||||
|
conditionally initializes the new metatable
|
||||||
|
(e.g., by adding metamethods to it).
|
||||||
|
If the initialization raises an error,
|
||||||
|
the metatable will not be properly initialized,
|
||||||
|
but a subsequent execution of that code will detect that the
|
||||||
|
metatable already exists and then skip the initialization.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@APIEntry{lua_State *luaL_newstate (void);|
|
@APIEntry{lua_State *luaL_newstate (void);|
|
||||||
@@ -6214,7 +6240,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 +6518,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}
|
||||||
@@ -6816,8 +6842,7 @@ for k,v in pairs(t) do @rep{body} end
|
|||||||
}
|
}
|
||||||
will iterate over all key@En{}value pairs of table @id{t}.
|
will iterate over all key@En{}value pairs of table @id{t}.
|
||||||
|
|
||||||
See function @Lid{next} for the caveats of modifying
|
See function @Lid{next} for more details about the traversal.
|
||||||
the table during its traversal.
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7744,7 +7769,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 +8205,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 +8258,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 +8296,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}.
|
||||||
@@ -9107,6 +9132,7 @@ which automatically removes the file when the program ends.
|
|||||||
|
|
||||||
This library provides
|
This library provides
|
||||||
the functionality of the @link{debugI|debug interface} to Lua programs.
|
the functionality of the @link{debugI|debug interface} to Lua programs.
|
||||||
|
|
||||||
You should exert care when using this library.
|
You should exert care when using this library.
|
||||||
Several of its functions
|
Several of its functions
|
||||||
violate basic assumptions about Lua code
|
violate basic assumptions about Lua code
|
||||||
@@ -9116,6 +9142,8 @@ that userdata metatables cannot be changed by Lua code;
|
|||||||
that Lua programs do not crash)
|
that Lua programs do not crash)
|
||||||
and therefore can compromise otherwise secure code.
|
and therefore can compromise otherwise secure code.
|
||||||
Moreover, some functions in this library may be slow.
|
Moreover, some functions in this library may be slow.
|
||||||
|
It is good practice to always require this library explicitly
|
||||||
|
before using it.
|
||||||
|
|
||||||
All functions in this library are provided
|
All functions in this library are provided
|
||||||
inside the @defid{debug} table.
|
inside the @defid{debug} table.
|
||||||
@@ -9594,6 +9622,9 @@ 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{
|
||||||
@@ -9725,7 +9756,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{*}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -372,6 +372,32 @@ do -- another bug (in 5.4.0)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if T then
|
||||||
|
-- check stack level when calling reader function
|
||||||
|
local function get (str)
|
||||||
|
local pos = 0
|
||||||
|
local level = nil
|
||||||
|
return function ()
|
||||||
|
pos = pos + 1
|
||||||
|
local c = string.sub(str, pos, pos)
|
||||||
|
local newlevel = T.stacklevel()
|
||||||
|
if not level then
|
||||||
|
level = newlevel
|
||||||
|
else
|
||||||
|
assert(level == newlevel)
|
||||||
|
end
|
||||||
|
return #c > 0 and c or nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local str = "local function foo () end; return 121"
|
||||||
|
assert(assert(load(get(str)))() == 121)
|
||||||
|
|
||||||
|
str = string.dump(load(str))
|
||||||
|
assert(assert(load(get(str)))() == 121)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
x = string.dump(load("x = 1; return x"))
|
x = string.dump(load("x = 1; return x"))
|
||||||
a = assert(load(read1(x), nil, "b"))
|
a = assert(load(read1(x), nil, "b"))
|
||||||
assert(a() == 1 and _G.x == 1)
|
assert(a() == 1 and _G.x == 1)
|
||||||
|
|||||||
@@ -159,6 +159,9 @@ assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'"))
|
|||||||
checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
|
checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
|
||||||
checkmessage("aaa=(1)..{}", "a table value")
|
checkmessage("aaa=(1)..{}", "a table value")
|
||||||
|
|
||||||
|
checkmessage("local function foo (...t) return t.xx + 1 end; foo()",
|
||||||
|
"field 'xx'")
|
||||||
|
|
||||||
-- bug in 5.4.6
|
-- bug in 5.4.6
|
||||||
checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
|
checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
|
||||||
|
|
||||||
|
|||||||
@@ -390,6 +390,18 @@ do
|
|||||||
for i=1, 10 do t[i] = 1 end
|
for i=1, 10 do t[i] = 1 end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do -- bug since 5.4
|
||||||
|
local parent = {}
|
||||||
|
parent.__newindex = parent
|
||||||
|
collectgarbage()
|
||||||
|
local child = setmetatable({}, parent)
|
||||||
|
child.__newindex = {x = "hello"}
|
||||||
|
collectgarbage("step")
|
||||||
|
assert(parent.__newindex.x == "hello")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- concat metamethod x numbers (bug in 5.1.1)
|
-- concat metamethod x numbers (bug in 5.1.1)
|
||||||
c = {}
|
c = {}
|
||||||
local x
|
local x
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -1179,6 +1179,25 @@ if rawget(_G, "T") then
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do
|
||||||
|
-- detail in scopes of variables in the loop of 'repeat-until'
|
||||||
|
local res = {}
|
||||||
|
local function foo (a)
|
||||||
|
repeat
|
||||||
|
local x
|
||||||
|
local i <close> = setmetatable({}, {__close = function ()
|
||||||
|
res[#res + 1] = debug.getlocal(2, 2) -- get 'x'
|
||||||
|
res[#res + 1] = debug.getlocal(2, 3) -- get 'i'
|
||||||
|
a = true
|
||||||
|
end})
|
||||||
|
until a
|
||||||
|
end
|
||||||
|
foo(false)
|
||||||
|
-- loop variables still in scope when closing 'i', both when 'repeat'
|
||||||
|
-- repeats and when 'repeat' stops.
|
||||||
|
assert(res[1] == "x" and res[2] == "i" and res[3] == "x" and res[4] == "i")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- to-be-closed variables in generic for loops
|
-- to-be-closed variables in generic for loops
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
-- }==================================================================
|
-- }==================================================================
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -347,6 +347,16 @@ do -- init parameter in gmatch
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
do -- bug since 5.3
|
||||||
|
local N = 20000
|
||||||
|
local iter = string.gmatch(string.rep("a", N), string.rep("a?", N))
|
||||||
|
pcall(iter) -- error for pattern too complex
|
||||||
|
-- calling function again found recursion count ('matchdepth') equal
|
||||||
|
-- to -1, so it did not detect next C-stack overflow
|
||||||
|
pcall(iter)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- tests for `%f' (`frontiers')
|
-- tests for `%f' (`frontiers')
|
||||||
|
|
||||||
assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
|
assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
|
||||||
|
|||||||
@@ -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,})
|
||||||
|
|||||||
Reference in New Issue
Block a user