Merge branch 'master' into nextversion

This commit is contained in:
Roberto Ierusalimschy 2023-06-22 11:41:48 -03:00
commit ab6a949522
33 changed files with 308 additions and 208 deletions

104
lcode.c
View File

@ -415,7 +415,7 @@ int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
/*
** Format and emit an 'iAsBx' instruction.
*/
int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
unsigned int b = bc + OFFSET_sBx;
lua_assert(getOpMode(o) == iAsBx);
lua_assert(a <= MAXARG_A && b <= MAXARG_Bx);
@ -671,7 +671,7 @@ static int fitsBx (lua_Integer i) {
void luaK_int (FuncState *fs, int reg, lua_Integer i) {
if (fitsBx(i))
luaK_codeAsBx(fs, OP_LOADI, reg, cast_int(i));
codeAsBx(fs, OP_LOADI, reg, cast_int(i));
else
luaK_codek(fs, reg, luaK_intK(fs, i));
}
@ -680,7 +680,7 @@ void luaK_int (FuncState *fs, int reg, lua_Integer i) {
static void luaK_float (FuncState *fs, int reg, lua_Number f) {
lua_Integer fi;
if (luaV_flttointeger(f, &fi, F2Ieq) && fitsBx(fi))
luaK_codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
codeAsBx(fs, OP_LOADF, reg, cast_int(fi));
else
luaK_codek(fs, reg, luaK_numberK(fs, f));
}
@ -1025,7 +1025,7 @@ static int luaK_exp2K (FuncState *fs, expdesc *e) {
** in the range of R/K indices).
** Returns 1 iff expression is K.
*/
int luaK_exp2RK (FuncState *fs, expdesc *e) {
static int exp2RK (FuncState *fs, expdesc *e) {
if (luaK_exp2K(fs, e))
return 1;
else { /* not a constant in the right range: put it in a register */
@ -1037,7 +1037,7 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
static void codeABRK (FuncState *fs, OpCode o, int a, int b,
expdesc *ec) {
int k = luaK_exp2RK(fs, ec);
int k = exp2RK(fs, ec);
luaK_codeABCk(fs, o, a, b, ec->u.info, k);
}
@ -1215,7 +1215,7 @@ static void codenot (FuncState *fs, expdesc *e) {
/*
** Check whether expression 'e' is a small literal string
** Check whether expression 'e' is a short literal string
*/
static int isKstr (FuncState *fs, expdesc *e) {
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
@ -1225,7 +1225,7 @@ static int isKstr (FuncState *fs, expdesc *e) {
/*
** Check whether expression 'e' is a literal integer.
*/
int luaK_isKint (expdesc *e) {
static int isKint (expdesc *e) {
return (e->k == VKINT && !hasjumps(e));
}
@ -1235,7 +1235,7 @@ int luaK_isKint (expdesc *e) {
** proper range to fit in register C
*/
static int isCint (expdesc *e) {
return luaK_isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
return isKint(e) && (l_castS2U(e->u.ival) <= l_castS2U(MAXARG_C));
}
@ -1244,7 +1244,7 @@ static int isCint (expdesc *e) {
** proper range to fit in register sC
*/
static int isSCint (expdesc *e) {
return luaK_isKint(e) && fitsC(e->u.ival);
return isKint(e) && fitsC(e->u.ival);
}
@ -1283,15 +1283,16 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
luaK_exp2anyreg(fs, t); /* put it in a register */
if (t->k == VUPVAL) {
lua_assert(isKstr(fs, k));
t->u.ind.t = t->u.info; /* upvalue index */
t->u.ind.idx = k->u.info; /* literal string */
t->u.ind.idx = k->u.info; /* literal short string */
t->k = VINDEXUP;
}
else {
/* register index of the table */
t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info;
if (isKstr(fs, k)) {
t->u.ind.idx = k->u.info; /* literal string */
t->u.ind.idx = k->u.info; /* literal short string */
t->k = VINDEXSTR;
}
else if (isCint(k)) {
@ -1351,6 +1352,35 @@ static int constfolding (FuncState *fs, int op, expdesc *e1,
}
/*
** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP)
*/
l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) {
lua_assert(baser <= opr &&
((baser == OPR_ADD && opr <= OPR_SHR) ||
(baser == OPR_LT && opr <= OPR_LE)));
return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base));
}
/*
** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP)
*/
l_sinline OpCode unopr2op (UnOpr opr) {
return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) +
cast_int(OP_UNM));
}
/*
** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM)
*/
l_sinline TMS binopr2TM (BinOpr opr) {
lua_assert(OPR_ADD <= opr && opr <= OPR_SHR);
return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD));
}
/*
** Emit code for unary expressions that "produce values"
** (everything but 'not').
@ -1389,15 +1419,15 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2,
** Emit code for binary expressions that "produce values" over
** two registers.
*/
static void codebinexpval (FuncState *fs, OpCode op,
static void codebinexpval (FuncState *fs, BinOpr opr,
expdesc *e1, expdesc *e2, int line) {
OpCode op = binopr2op(opr, OPR_ADD, OP_ADD);
int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */
/* 'e1' must be already in a register or it is a constant */
lua_assert((VNIL <= e1->k && e1->k <= VKSTR) ||
e1->k == VNONRELOC || e1->k == VRELOC);
lua_assert(OP_ADD <= op && op <= OP_SHR);
finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN,
cast(TMS, (op - OP_ADD) + TM_ADD));
finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr));
}
@ -1418,9 +1448,9 @@ static void codebini (FuncState *fs, OpCode op,
*/
static void codebinK (FuncState *fs, BinOpr opr,
expdesc *e1, expdesc *e2, int flip, int line) {
TMS event = cast(TMS, opr + TM_ADD);
TMS event = binopr2TM(opr);
int v2 = e2->u.info; /* K index */
OpCode op = cast(OpCode, opr + OP_ADDK);
OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK);
finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event);
}
@ -1430,7 +1460,7 @@ static void codebinK (FuncState *fs, BinOpr opr,
*/
static int finishbinexpneg (FuncState *fs, expdesc *e1, expdesc *e2,
OpCode op, int line, TMS event) {
if (!luaK_isKint(e2))
if (!isKint(e2))
return 0; /* not an integer constant */
else {
lua_Integer i2 = e2->u.ival;
@ -1457,10 +1487,9 @@ static void swapexps (expdesc *e1, expdesc *e2) {
*/
static void codebinNoK (FuncState *fs, BinOpr opr,
expdesc *e1, expdesc *e2, int flip, int line) {
OpCode op = cast(OpCode, opr + OP_ADD);
if (flip)
swapexps(e1, e2); /* back to original order */
codebinexpval(fs, op, e1, e2, line); /* use standard operators */
codebinexpval(fs, opr, e1, e2, line); /* use standard operators */
}
@ -1490,7 +1519,7 @@ static void codecommutative (FuncState *fs, BinOpr op,
flip = 1;
}
if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */
codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD);
codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD);
else
codearith(fs, op, e1, e2, flip, line);
}
@ -1518,25 +1547,27 @@ static void codebitwise (FuncState *fs, BinOpr opr,
** Emit code for order comparisons. When using an immediate operand,
** 'isfloat' tells whether the original value was a float.
*/
static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {
static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
int r1, r2;
int im;
int isfloat = 0;
OpCode op;
if (isSCnumber(e2, &im, &isfloat)) {
/* use immediate operand */
r1 = luaK_exp2anyreg(fs, e1);
r2 = im;
op = cast(OpCode, (op - OP_LT) + OP_LTI);
op = binopr2op(opr, OPR_LT, OP_LTI);
}
else if (isSCnumber(e1, &im, &isfloat)) {
/* transform (A < B) to (B > A) and (A <= B) to (B >= A) */
r1 = luaK_exp2anyreg(fs, e2);
r2 = im;
op = (op == OP_LT) ? OP_GTI : OP_GEI;
op = binopr2op(opr, OPR_LT, OP_GTI);
}
else { /* regular case, compare two registers */
r1 = luaK_exp2anyreg(fs, e1);
r2 = luaK_exp2anyreg(fs, e2);
op = binopr2op(opr, OPR_LT, OP_LT);
}
freeexps(fs, e1, e2);
e1->u.info = condjump(fs, op, r1, r2, isfloat, 1);
@ -1562,7 +1593,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
op = OP_EQI;
r2 = im; /* immediate operand */
}
else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */
else if (exp2RK(fs, e2)) { /* 2nd expression is constant? */
op = OP_EQK;
r2 = e2->u.info; /* constant index */
}
@ -1579,16 +1610,16 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
/*
** Apply prefix operation 'op' to expression 'e'.
*/
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) {
static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};
luaK_dischargevars(fs, e);
switch (op) {
switch (opr) {
case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */
if (constfolding(fs, op + LUA_OPUNM, e, &ef))
if (constfolding(fs, opr + LUA_OPUNM, e, &ef))
break;
/* else */ /* FALLTHROUGH */
case OPR_LEN:
codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
codeunexpval(fs, unopr2op(opr), e, line);
break;
case OPR_NOT: codenot(fs, e); break;
default: lua_assert(0);
@ -1628,7 +1659,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
}
case OPR_EQ: case OPR_NE: {
if (!tonumeral(v, NULL))
luaK_exp2RK(fs, v);
exp2RK(fs, v);
/* else keep numeral, which may be an immediate operand */
break;
}
@ -1718,30 +1749,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr,
/* coded as (r1 >> -I) */;
}
else /* regular case (two registers) */
codebinexpval(fs, OP_SHL, e1, e2, line);
codebinexpval(fs, opr, e1, e2, line);
break;
}
case OPR_SHR: {
if (isSCint(e2))
codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */
else /* regular case (two registers) */
codebinexpval(fs, OP_SHR, e1, e2, line);
codebinexpval(fs, opr, e1, e2, line);
break;
}
case OPR_EQ: case OPR_NE: {
codeeq(fs, opr, e1, e2);
break;
}
case OPR_LT: case OPR_LE: {
OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ);
codeorder(fs, op, e1, e2);
break;
}
case OPR_GT: case OPR_GE: {
/* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */
OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ);
swapexps(e1, e2);
codeorder(fs, op, e1, e2);
opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT);
} /* FALLTHROUGH */
case OPR_LT: case OPR_LE: {
codeorder(fs, opr, e1, e2);
break;
}
default: lua_assert(0);

View File

@ -61,10 +61,8 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
int B, int C, int k);
LUAI_FUNC int luaK_isKint (expdesc *e);
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
@ -76,7 +74,6 @@ LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);
LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);
LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);
LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);

View File

@ -76,7 +76,7 @@ static int luaB_auxwrap (lua_State *L) {
if (l_unlikely(r < 0)) { /* error? */
int stat = lua_status(co);
if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
stat = lua_resetthread(co, L); /* close its tbc variables */
stat = lua_closethread(co, L); /* close its tbc variables */
lua_assert(stat != LUA_OK);
lua_xmove(co, L, 1); /* move error message to the caller */
}
@ -172,7 +172,7 @@ static int luaB_close (lua_State *L) {
int status = auxstatus(L, co);
switch (status) {
case COS_DEAD: case COS_YIELD: {
status = lua_resetthread(co, L);
status = lua_closethread(co, L);
if (status == LUA_OK) {
lua_pushboolean(L, 1);
return 1;

View File

@ -656,18 +656,19 @@ static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
/*
** Check whether pointer 'o' points to some value in the stack
** frame of the current function. Because 'o' may not point to a
** value in this stack, we cannot compare it with the region
** boundaries (undefined behaviour in ISO C).
** Check whether pointer 'o' points to some value in the stack frame of
** the current function and, if so, returns its index. Because 'o' may
** not point to a value in this stack, we cannot compare it with the
** region boundaries (undefined behavior in ISO C).
*/
static int isinstack (CallInfo *ci, const TValue *o) {
StkId pos;
for (pos = ci->func.p + 1; pos < ci->top.p; pos++) {
if (o == s2v(pos))
return 1;
static int instack (CallInfo *ci, const TValue *o) {
int pos;
StkId base = ci->func.p + 1;
for (pos = 0; base + pos < ci->top.p; pos++) {
if (o == s2v(base + pos))
return pos;
}
return 0; /* not found */
return -1; /* not found */
}
@ -708,9 +709,11 @@ static const char *varinfo (lua_State *L, const TValue *o) {
const char *kind = NULL;
if (isLua(ci)) {
kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */
if (!kind && isinstack(ci, o)) /* no? try a register */
kind = getobjname(ci_func(ci)->p, currentpc(ci),
cast_int(cast(StkId, o) - (ci->func.p + 1)), &name);
if (!kind) { /* not an upvalue? */
int reg = instack(ci, o); /* try a register */
if (reg >= 0) /* is 'o' a register? */
kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name);
}
}
return formatvarinfo(L, kind, name);
}
@ -845,7 +848,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
if (p->lineinfo == NULL) /* no debug information? */
return 0;
if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
int delta = 0; /* line diference */
int delta = 0; /* line difference */
int pc = oldpc;
for (;;) {
int lineinfo = p->lineinfo[++pc];

20
ldo.c
View File

@ -299,17 +299,13 @@ static int stackinuse (lua_State *L) {
*/
void luaD_shrinkstack (lua_State *L) {
int inuse = stackinuse(L);
int nsize = inuse * 2; /* proposed new size */
int max = inuse * 3; /* maximum "reasonable" size */
if (max > LUAI_MAXSTACK) {
max = LUAI_MAXSTACK; /* respect stack limit */
if (nsize > LUAI_MAXSTACK)
nsize = LUAI_MAXSTACK;
}
int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3;
/* if thread is currently not handling a stack overflow and its
size is larger than maximum "reasonable" size, shrink it */
if (inuse <= LUAI_MAXSTACK && stacksize(L) > max)
if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) {
int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2;
luaD_reallocstack(L, nsize, 0); /* ok if that fails */
}
else /* don't change stack */
condmovestack(L,{},{}); /* (change only for debugging) */
luaE_shrinkCI(L); /* shrink CI list */
@ -413,7 +409,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
** stack, below original 'func', so that 'luaD_precall' can call it. Raise
** an error if there is no '__call' metafield.
*/
StkId luaD_tryfuncTM (lua_State *L, StkId func) {
static StkId tryfuncTM (lua_State *L, StkId func) {
const TValue *tm;
StkId p;
checkstackp(L, 1, func); /* space for metamethod */
@ -572,7 +568,7 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
return -1;
}
default: { /* not a function */
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
func = tryfuncTM(L, func); /* try to get '__call' metamethod */
/* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */
narg1++;
goto retry; /* try again */
@ -613,7 +609,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
return ci;
}
default: { /* not a function */
func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
func = tryfuncTM(L, func); /* try to get '__call' metamethod */
/* return luaD_precall(L, func, nresults); */
goto retry; /* try again with metamethod */
}
@ -629,7 +625,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
** check the stack before doing anything else. 'luaD_precall' already
** does that.
*/
l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) {
l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) {
CallInfo *ci;
L->nCcalls += inc;
if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) {

1
ldo.h
View File

@ -59,7 +59,6 @@ LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);
LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults);
LUAI_FUNC StkId luaD_tryfuncTM (lua_State *L, StkId func);
LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef);

View File

@ -10,6 +10,7 @@
#include "lprefix.h"
#include <limits.h>
#include <stddef.h>
#include "lua.h"
@ -59,8 +60,11 @@ static void dumpByte (DumpState *D, int y) {
}
/* dumpInt Buff Size */
#define DIBS ((sizeof(size_t) * 8 / 7) + 1)
/*
** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6"
** rounds up the division.)
*/
#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7)
static void dumpSize (DumpState *D, size_t x) {
lu_byte buff[DIBS];

2
llex.c
View File

@ -128,7 +128,7 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
** ensuring there is only one copy of each unique string. The table
** here is used as a set: the string enters as the key, while its value
** is irrelevant. We use the string itself as the value only because it
** is a TValue readly available. Later, the code generation can change
** is a TValue readily available. Later, the code generation can change
** this value.
*/
TString *luaX_newstring (LexState *ls, const char *str, size_t l) {

View File

@ -81,7 +81,7 @@ typedef signed char ls_byte;
#if defined(UINTPTR_MAX) /* even in C99 this type is optional */
#define L_P2I uintptr_t
#else /* no 'intptr'? */
#define L_P2I uintmax_t /* use the largerst available integer */
#define L_P2I uintmax_t /* use the largest available integer */
#endif
#else /* C89 option */
#define L_P2I size_t

View File

@ -24,15 +24,6 @@
#include "lualib.h"
/*
** LUA_IGMARK is a mark to ignore all before it when building the
** luaopen_ function name.
*/
#if !defined (LUA_IGMARK)
#define LUA_IGMARK "-"
#endif
/*
** LUA_CSUBSEP is the character that replaces dots in submodule names
** when searching for a C loader.

View File

@ -21,7 +21,7 @@ iABC C(8) | B(8) |k| A(8) | Op(7) |
iABx Bx(17) | A(8) | Op(7) |
iAsBx sBx (signed)(17) | A(8) | Op(7) |
iAx Ax(25) | Op(7) |
isJ sJ(25) | Op(7) |
isJ sJ (signed)(25) | Op(7) |
A signed argument is represented in excess K: the represented value is
the written unsigned value minus K, where K is half the maximum for the
@ -210,15 +210,15 @@ OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */
OP_GETUPVAL,/* A B R[A] := UpValue[B] */
OP_SETUPVAL,/* A B UpValue[B] := R[A] */
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:string] */
OP_GETTABUP,/* A B C R[A] := UpValue[B][K[C]:shortstring] */
OP_GETTABLE,/* A B C R[A] := R[B][R[C]] */
OP_GETI,/* A B C R[A] := R[B][C] */
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:string] */
OP_GETFIELD,/* A B C R[A] := R[B][K[C]:shortstring] */
OP_SETTABUP,/* A B C UpValue[A][K[B]:string] := RK(C) */
OP_SETTABUP,/* A B C UpValue[A][K[B]:shortstring] := RK(C) */
OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */
OP_SETI,/* A B C R[A][B] := RK(C) */
OP_SETFIELD,/* A B C R[A][K[B]:string] := RK(C) */
OP_SETFIELD,/* A B C R[A][K[B]:shortstring] := RK(C) */
OP_NEWTABLE,/* A B C k R[A] := {} */

View File

@ -30,23 +30,14 @@
*/
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
/* options for ANSI C 89 (only 1-char options) */
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
/* options for ISO C 99 and POSIX */
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
/* options for Windows */
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
#if defined(LUA_USE_WINDOWS)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
#elif defined(LUA_USE_C89)
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */
#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%"
#else /* C99 specification */
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
#endif
#endif /* } */

View File

@ -529,12 +529,12 @@ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) {
/*
** Solves the goto at index 'g' to given 'label' and removes it
** from the list of pending goto's.
** from the list of pending gotos.
** If it jumps into the scope of some variable, raises an error.
*/
static void solvegoto (LexState *ls, int g, Labeldesc *label) {
int i;
Labellist *gl = &ls->dyd->gt; /* list of goto's */
Labellist *gl = &ls->dyd->gt; /* list of gotos */
Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */
lua_assert(eqstr(gt->name, label->name));
if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */
@ -588,7 +588,7 @@ static int newgotoentry (LexState *ls, TString *name, int line, int pc) {
/*
** Solves forward jumps. Check whether new label 'lb' matches any
** pending gotos in current block and solves them. Return true
** if any of the goto's need to close upvalues.
** if any of the gotos need to close upvalues.
*/
static int solvegotos (LexState *ls, Labeldesc *lb) {
Labellist *gl = &ls->dyd->gt;
@ -609,7 +609,7 @@ static int solvegotos (LexState *ls, Labeldesc *lb) {
/*
** Create a new label with the given 'name' at the given 'line'.
** 'last' tells whether label is the last non-op statement in its
** block. Solves all pending goto's to this new label and adds
** block. Solves all pending gotos to this new label and adds
** a close instruction if necessary.
** Returns true iff it added a close instruction.
*/

View File

@ -88,7 +88,7 @@ CallInfo *luaE_extendCI (lua_State *L) {
/*
** free all CallInfo structures not in use by a thread
*/
void luaE_freeCI (lua_State *L) {
static void freeCI (lua_State *L) {
CallInfo *ci = L->ci;
CallInfo *next = ci->next;
ci->next = NULL;
@ -173,7 +173,7 @@ static void freestack (lua_State *L) {
if (L->stack.p == NULL)
return; /* stack not completely built yet */
L->ci = &L->base_ci; /* free the entire 'ci' list */
luaE_freeCI(L);
freeCI(L);
lua_assert(L->nci == 0);
luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */
}
@ -309,7 +309,7 @@ int luaE_resetthread (lua_State *L, int status) {
}
LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
LUA_API int lua_closethread (lua_State *L, lua_State *from) {
int status;
lua_lock(L);
L->nCcalls = (from) ? getCcalls(from) : 0;

View File

@ -399,7 +399,6 @@ union GCUnion {
LUAI_FUNC void luaE_setdebt (global_State *g, l_obj debt);
LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
LUAI_FUNC void luaE_freeCI (lua_State *L);
LUAI_FUNC void luaE_shrinkCI (lua_State *L);
LUAI_FUNC void luaE_checkcstack (lua_State *L);
LUAI_FUNC void luaE_incCstack (lua_State *L);

View File

@ -571,7 +571,7 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
static const char *match (MatchState *ms, const char *s, const char *p) {
if (l_unlikely(ms->matchdepth-- == 0))
luaL_error(ms->L, "pattern too complex");
init: /* using goto's to optimize tail recursion */
init: /* using goto to optimize tail recursion */
if (p != ms->p_end) { /* end of pattern? */
switch (*p) {
case '(': { /* start capture */

View File

@ -278,9 +278,11 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) {
size |= (size >> 2);
size |= (size >> 4);
size |= (size >> 8);
#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */
size |= (size >> 16);
#if (UINT_MAX >> 30) > 3
size |= (size >> 32); /* unsigned int has more than 32 bits */
#endif
#endif
size++;
lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size);
@ -710,7 +712,8 @@ static Node *getfreepos (Table *t) {
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
static void luaH_newkey (lua_State *L, Table *t, const TValue *key,
TValue *value) {
Node *mp;
TValue aux;
if (l_unlikely(ttisnil(key)))

View File

@ -51,8 +51,6 @@ LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key,
TValue *value);
LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key,
TValue *value);
LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key,

View File

@ -1526,7 +1526,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
lua_newthread(L1);
}
else if EQ("resetthread") {
lua_pushinteger(L1, lua_resetthread(L1, L));
lua_pushinteger(L1, lua_resetthread(L1)); /* deprecated */
}
else if EQ("newuserdata") {
lua_newuserdata(L1, getnum);

5
ltm.h
View File

@ -9,7 +9,6 @@
#include "lobject.h"
#include "lstate.h"
/*
@ -96,8 +95,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
int inv, int isfloat, TMS event);
LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
CallInfo *ci, const Proto *p);
LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci,
struct CallInfo *ci, const Proto *p);
LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
StkId where, int wanted);

14
lua.c
View File

@ -210,12 +210,17 @@ static int dostring (lua_State *L, const char *s, const char *name) {
/*
** Receives 'globname[=modname]' and runs 'globname = require(modname)'.
** If there is no explicit modname and globname contains a '-', cut
** the sufix after '-' (the "version") to make the global name.
*/
static int dolibrary (lua_State *L, char *globname) {
int status;
char *suffix = NULL;
char *modname = strchr(globname, '=');
if (modname == NULL) /* no explicit name? */
if (modname == NULL) { /* no explicit name? */
modname = globname; /* module name is equal to global name */
suffix = strchr(modname, *LUA_IGMARK); /* look for a suffix mark */
}
else {
*modname = '\0'; /* global name ends here */
modname++; /* module name starts after the '=' */
@ -223,8 +228,11 @@ static int dolibrary (lua_State *L, char *globname) {
lua_getglobal(L, "require");
lua_pushstring(L, modname);
status = docall(L, 1, 1); /* call 'require(modname)' */
if (status == LUA_OK)
if (status == LUA_OK) {
if (suffix != NULL) /* is there a suffix mark? */
*suffix = '\0'; /* remove sufix from global name */
lua_setglobal(L, globname); /* globname = require(modname) */
}
return report(L, status);
}
@ -670,7 +678,7 @@ int main (int argc, char **argv) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
lua_gc(L, LUA_GCSTOP); /* stop GC while buidling state */
lua_gc(L, LUA_GCSTOP); /* stop GC while building state */
lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */
lua_pushinteger(L, argc); /* 1st argument */
lua_pushlightuserdata(L, argv); /* 2nd argument */

44
lua.h
View File

@ -1,7 +1,7 @@
/*
** $Id: lua.h $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** Lua.org, PUC-Rio, Brazil (www.lua.org)
** See Copyright Notice at the end of this file
*/
@ -13,22 +13,21 @@
#include <stddef.h>
#include "luaconf.h"
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "5"
#define LUA_VERSION_RELEASE "0"
#define LUA_VERSION_NUM 505
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio"
#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
#define LUA_VERSION_MAJOR_N 5
#define LUA_VERSION_MINOR_N 5
#define LUA_VERSION_RELEASE_N 0
#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)
#include "luaconf.h"
/* mark for precompiled code ('<esc>Lua') */
#define LUA_SIGNATURE "\x1bLua"
@ -164,7 +163,7 @@ LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud,
unsigned int seed);
LUA_API void (lua_close) (lua_State *L);
LUA_API lua_State *(lua_newthread) (lua_State *L);
LUA_API int (lua_resetthread) (lua_State *L, lua_State *from);
LUA_API int (lua_closethread) (lua_State *L, lua_State *from);
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
@ -426,6 +425,8 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx);
#define LUA_NUMTAGS LUA_NUMTYPES
#define lua_resetthread(L) lua_closethread(L,NULL)
/* }============================================================== */
/*
@ -496,8 +497,19 @@ struct lua_Debug {
/* }====================================================================== */
#define LUAI_TOSTRAUX(x) #x
#define LUAI_TOSTR(x) LUAI_TOSTRAUX(x)
#define LUA_VERSION_MAJOR LUAI_TOSTR(LUA_VERSION_MAJOR_N)
#define LUA_VERSION_MINOR LUAI_TOSTR(LUA_VERSION_MINOR_N)
#define LUA_VERSION_RELEASE LUAI_TOSTR(LUA_VERSION_RELEASE_N)
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
/******************************************************************************
* Copyright (C) 1994-2022 Lua.org, PUC-Rio.
* Copyright (C) 1994-2023 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the

View File

@ -257,6 +257,15 @@
#endif
/*
** LUA_IGMARK is a mark to ignore all after it when building the
** module name (e.g., used to build the luaopen_ function name).
** Typically, the sufix after the mark is the module version,
** as in "mod-v1.2.so".
*/
#define LUA_IGMARK "-"
/* }================================================================== */

View File

@ -261,6 +261,8 @@ static void loadDebug (LoadState *S, Proto *f) {
f->locvars[i].endpc = loadInt(S);
}
n = loadInt(S);
if (n != 0) /* does it have debug information? */
n = f->sizeupvalues; /* must be this many */
for (i = 0; i < n; i++)
f->upvalues[i].name = loadStringN(S, f);
}

50
lvm.c
View File

@ -367,30 +367,32 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
/*
** Compare two strings 'ls' x 'rs', returning an integer less-equal-
** -greater than zero if 'ls' is less-equal-greater than 'rs'.
** Compare two strings 'ts1' x 'ts2', returning an integer less-equal-
** -greater than zero if 'ts1' is less-equal-greater than 'ts2'.
** The code is a little tricky because it allows '\0' in the strings
** and it uses 'strcoll' (to respect locales) for each segments
** of the strings.
** and it uses 'strcoll' (to respect locales) for each segment
** of the strings. Note that segments can compare equal but still
** have different lengths.
*/
static int l_strcmp (const TString *ls, const TString *rs) {
const char *l = getstr(ls);
size_t ll = tsslen(ls);
const char *r = getstr(rs);
size_t lr = tsslen(rs);
static int l_strcmp (const TString *ts1, const TString *ts2) {
const char *s1 = getstr(ts1);
size_t rl1 = tsslen(ts1); /* real length */
const char *s2 = getstr(ts2);
size_t rl2 = tsslen(ts2);
for (;;) { /* for each segment */
int temp = strcoll(l, r);
int temp = strcoll(s1, s2);
if (temp != 0) /* not equal? */
return temp; /* done */
else { /* strings are equal up to a '\0' */
size_t len = strlen(l); /* index of first '\0' in both strings */
if (len == lr) /* 'rs' is finished? */
return (len == ll) ? 0 : 1; /* check 'ls' */
else if (len == ll) /* 'ls' is finished? */
return -1; /* 'ls' is less than 'rs' ('rs' is not finished) */
/* both strings longer than 'len'; go on comparing after the '\0' */
len++;
l += len; ll -= len; r += len; lr -= len;
size_t zl1 = strlen(s1); /* index of first '\0' in 's1' */
size_t zl2 = strlen(s2); /* index of first '\0' in 's2' */
if (zl2 == rl2) /* 's2' is finished? */
return (zl1 == rl1) ? 0 : 1; /* check 's1' */
else if (zl1 == rl1) /* 's1' is finished? */
return -1; /* 's1' is less than 's2' ('s2' is not finished) */
/* both strings longer than 'zl'; go on comparing after the '\0' */
zl1++; zl2++;
s1 += zl1; rl1 -= zl1; s2 += zl2; rl2 -= zl2;
}
}
}
@ -1254,7 +1256,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
TValue *upval = cl->upvals[GETARG_B(i)]->v.p;
TValue *rc = KC(i);
TString *key = tsvalue(rc); /* key must be a string */
TString *key = tsvalue(rc); /* key must be a short string */
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
setobj2s(L, ra, slot);
}
@ -1297,7 +1299,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
TValue *rb = vRB(i);
TValue *rc = KC(i);
TString *key = tsvalue(rc); /* key must be a string */
TString *key = tsvalue(rc); /* key must be a short string */
if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) {
setobj2s(L, ra, slot);
}
@ -1310,7 +1312,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *upval = cl->upvals[GETARG_A(i)]->v.p;
TValue *rb = KB(i);
TValue *rc = RKC(i);
TString *key = tsvalue(rb); /* key must be a string */
TString *key = tsvalue(rb); /* key must be a short string */
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
luaV_finishfastset(L, upval, slot, rc);
}
@ -1353,7 +1355,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
TValue *rb = KB(i);
TValue *rc = RKC(i);
TString *key = tsvalue(rb); /* key must be a string */
TString *key = tsvalue(rb); /* key must be a short string */
if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
luaV_finishfastset(L, s2v(ra), slot, rc);
}
@ -1411,6 +1413,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak;
}
vmcase(OP_MODK) {
savestate(L, ci); /* in case of division by 0 */
op_arithK(L, luaV_mod, luaV_modf);
vmbreak;
}
@ -1423,6 +1426,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak;
}
vmcase(OP_IDIVK) {
savestate(L, ci); /* in case of division by 0 */
op_arithK(L, luaV_idiv, luai_numidiv);
vmbreak;
}
@ -1471,6 +1475,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak;
}
vmcase(OP_MOD) {
savestate(L, ci); /* in case of division by 0 */
op_arith(L, luaV_mod, luaV_modf);
vmbreak;
}
@ -1483,6 +1488,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak;
}
vmcase(OP_IDIV) { /* floor division */
savestate(L, ci); /* in case of division by 0 */
op_arith(L, luaV_idiv, luai_numidiv);
vmbreak;
}

View File

@ -8,7 +8,6 @@ CWARNSCPP= \
-Wfatal-errors \
-Wextra \
-Wshadow \
-Wsign-compare \
-Wundef \
-Wwrite-strings \
-Wredundant-decls \
@ -60,7 +59,7 @@ CWARNS= $(CWARNSCPP) $(CWARNSC) $(CWARNGCC)
# The following options help detect "undefined behavior"s that seldom
# create problems; some are only available in newer gcc versions. To
# use some of them, we also have to define an enrivonment variable
# use some of them, we also have to define an environment variable
# ASAN_OPTIONS="detect_invalid_pointer_pairs=2".
# -fsanitize=undefined
# -fsanitize=pointer-subtract -fsanitize=address -fsanitize=pointer-compare

View File

@ -30,7 +30,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
<p>
<small>
<a href="http://www.lua.org/copyright.html">Copyright</a>
&copy; 2022 Lua.org, PUC-Rio. All rights reserved.
&copy; 2023 Lua.org, PUC-Rio. All rights reserved.
</small>
<hr>

View File

@ -20,7 +20,7 @@ making it ideal for configuration, scripting,
and rapid prototyping.
Lua is implemented as a library, written in @emphx{clean C},
the common subset of C and C++.
the common subset of @N{standard C} and C++.
The Lua distribution includes a host program called @id{lua},
which uses the Lua library to offer a complete,
standalone Lua interpreter,
@ -3161,6 +3161,27 @@ when called through this function.
}
@APIEntry{int lua_closethread (lua_State *L, lua_State *from);|
@apii{0,?,-}
Resets a thread, cleaning its call stack and closing all pending
to-be-closed variables.
Returns a status code:
@Lid{LUA_OK} for no errors in the thread
(either the original error that stopped the thread or
errors in closing methods),
or an error status otherwise.
In case of error,
leaves the error object on the top of the stack.
The parameter @id{from} represents the coroutine that is resetting @id{L}.
If there is no such coroutine,
this parameter can be @id{NULL}.
(This function was introduced in @N{release 5.4.6}.)
}
@APIEntry{int lua_compare (lua_State *L, int index1, int index2, int op);|
@apii{0,0,e}
@ -4157,23 +4178,12 @@ and then pops the top element.
}
@APIEntry{int lua_resetthread (lua_State *L, lua_State *from);|
@APIEntry{int lua_resetthread (lua_State *L);|
@apii{0,?,-}
Resets a thread, cleaning its call stack and closing all pending
to-be-closed variables.
Returns a status code:
@Lid{LUA_OK} for no errors in the thread
(either the original error that stopped the thread or
errors in closing methods),
or an error status otherwise.
In case of error,
leaves the error object on the top of the stack.
The parameter @id{from} represents the coroutine that is resetting @id{L}.
If there is no such coroutine,
this parameter can be @id{NULL}.
(This parameter was introduced in @N{release 5.4.5}.)
This function is deprecated;
it is equivalent to @Lid{lua_closethread} with
@id{from} being @id{NULL}.
}
@ -5787,7 +5797,7 @@ with @id{tname} in the registry.
Creates a new Lua state.
It calls @Lid{lua_newstate} with an
allocator based on the @N{standard C} allocation functions
allocator based on the @N{ISO C} allocation functions
and then sets a warning function and a panic function @see{C-error}
that print messages to the standard error output.
@ -6905,10 +6915,10 @@ including if necessary a path and an extension.
@id{funcname} must be the exact name exported by the @N{C library}
(which may depend on the @N{C compiler} and linker used).
This function is not supported by @N{ISO C}.
As such, it is only available on some platforms
(Windows, Linux, Mac OS X, Solaris, BSD,
plus other Unix systems that support the @id{dlfcn} standard).
This functionality is not supported by @N{ISO C}.
As such, @id{loadlib} is only available on some platforms:
Linux, Windows, Mac OS X, Solaris, BSD,
plus other Unix systems that support the @id{dlfcn} standard.
This function is inherently insecure,
as it allows Lua to call any function in any readable dynamic

View File

@ -1,5 +1,14 @@
/*
* one.c -- Lua core, libraries, and interpreter in a single file
** Lua core, libraries, and interpreter in a single file.
** Compiling just this file generates a complete Lua stand-alone
** program:
**
** $ gcc -O2 -std=c99 -o lua onelua.c -lm
**
** or
**
** $ gcc -O2 -std=c89 -DLUA_USE_C89 -o lua onelua.c -lm
**
*/
/* default is to build the full interpreter */
@ -11,8 +20,12 @@
#endif
#endif
/* choose suitable platform-specific features */
/* some of these may need extra libraries such as -ldl -lreadline -lncurses */
/*
** Choose suitable platform-specific features. Default is no
** platform-specific features. Some of these options may need extra
** libraries such as -ldl -lreadline -lncurses
*/
#if 0
#define LUA_USE_LINUX
#define LUA_USE_MACOSX
@ -20,6 +33,7 @@
#define LUA_ANSI
#endif
/* no need to change anything below this line ----------------------------- */
#include "lprefix.h"

View File

@ -342,6 +342,20 @@ do -- another bug (in 5.4.0)
end
do -- another bug (since 5.2)
-- corrupted binary dump: list of upvalue names is larger than number
-- of upvalues, overflowing the array of upvalues.
local code =
"\x1b\x4c\x75\x61\x55\x00\x19\x93\x0d\x0a\x1a\x0a\x04\x08\x08\x78\x56\z
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x77\x40\x00\x86\x40\z
\x74\x65\x6d\x70\x81\x81\x01\x00\x02\x82\x48\x00\x02\x00\xc7\x00\x01\z
\x00\x80\x80\x80\x82\x00\x00\x80\x81\x82\x78\x80\x82\x81\x86\x40\x74\z
\x65\x6d\x70"
assert(load(code)) -- segfaults in previous versions
end
x = string.dump(load("x = 1; return x"))
a = assert(load(read1(x), nil, "b"))
assert(a() == 1 and _G.x == 1)

View File

@ -928,7 +928,7 @@ do
local cl = countlines(rest)
-- at most 10 lines in first part, 11 in second, plus '...'
assert(cl <= 10 + 11 + 1)
local brk = string.find(rest, "%.%.%.")
local brk = string.find(rest, "%.%.%.\t%(skip")
if brk then -- does message have '...'?
local rest1 = string.sub(rest, 1, brk)
local rest2 = string.sub(rest, brk, #rest)

View File

@ -444,6 +444,14 @@ if not b then
end
end]], 5)
-- bug in 5.4.0
lineerror([[
local a = 0
local b = 1
local c = b % a
]], 3)
do
-- Force a negative estimate for base line. Error in instruction 2
-- (after VARARGPREP, GETGLOBAL), with first absolute line information

View File

@ -27,17 +27,19 @@ do
end
print("progname: "..progname)
local prepfile = function (s, p)
p = p or prog
io.output(p)
io.write(s)
assert(io.close())
local prepfile = function (s, mod, p)
mod = mod and "wb" or "w" -- mod true means binary files
p = p or prog -- file to write the program
local f = io.open(p, mod)
f:write(s)
assert(f:close())
end
local function getoutput ()
io.input(out)
local t = io.read("a")
io.input():close()
local f = io.open(out)
local t = f:read("a")
f:close()
assert(os.remove(out))
return t
end
@ -65,10 +67,11 @@ local function RUN (p, ...)
assert(os.execute(s))
end
local function NoRun (msg, p, ...)
p = string.gsub(p, "lua", '"'..progname..'"', 1)
local s = string.format(p, ...)
s = string.format("%s 2> %s", s, out) -- will send error to 'out'
s = string.format("%s >%s 2>&1", s, out) -- send output and error to 'out'
assert(not os.execute(s))
assert(string.find(getoutput(), msg, 1, true)) -- check error message
end
@ -108,17 +111,17 @@ RUN('lua %s > %s', prog, out)
checkout("3\n")
-- bad BOMs
prepfile("\xEF")
NoRun("unexpected symbol", 'lua %s > %s', prog, out)
prepfile("\xEF", true)
NoRun("unexpected symbol", 'lua %s', prog)
prepfile("\xEF\xBB")
NoRun("unexpected symbol", 'lua %s > %s', prog, out)
prepfile("\xEF\xBB", true)
NoRun("unexpected symbol", 'lua %s', prog)
prepfile("\xEFprint(3)")
NoRun("unexpected symbol", 'lua %s > %s', prog, out)
prepfile("\xEFprint(3)", true)
NoRun("unexpected symbol", 'lua %s', prog)
prepfile("\xEF\xBBprint(3)")
NoRun("unexpected symbol", 'lua %s > %s', prog, out)
prepfile("\xEF\xBBprint(3)", true)
NoRun("unexpected symbol", 'lua %s', prog)
-- test option '-'
@ -213,7 +216,7 @@ convert("a;b;;c")
-- test -l over multiple libraries
prepfile("print(1); a=2; return {x=15}")
prepfile(("print(a); print(_G['%s'].x)"):format(prog), otherprog)
prepfile(("print(a); print(_G['%s'].x)"):format(prog), false, otherprog)
RUN('env LUA_PATH="?;;" lua -l %s -l%s -lstring -l io %s > %s', prog, otherprog, otherprog, out)
checkout("1\n2\n15\n2\n15\n")
@ -222,6 +225,13 @@ prepfile("print(str.upper'alo alo', m.max(10, 20))")
RUN("lua -l 'str=string' '-lm=math' -e 'print(m.sin(0))' %s > %s", prog, out)
checkout("0.0\nALO ALO\t20\n")
-- test module names with version sufix ("libs/lib2-v2")
RUN("env LUA_CPATH='./libs/?.so' lua -l lib2-v2 -e 'print(lib2.id())' > %s",
out)
checkout("true\n")
-- test 'arg' table
local a = [[
assert(#arg == 3 and arg[1] == 'a' and
@ -237,7 +247,7 @@ RUN('lua "-e " -- %s a b c', prog) -- "-e " runs an empty command
-- test 'arg' availability in libraries
prepfile"assert(arg)"
prepfile("assert(arg)", otherprog)
prepfile("assert(arg)", false, otherprog)
RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog)
-- test messing up the 'arg' table
@ -413,7 +423,7 @@ prepfile[[#comment in 1st line without \n at the end]]
RUN('lua %s', prog)
-- first-line comment with binary file
prepfile("#comment\n" .. string.dump(load("print(3)")))
prepfile("#comment\n" .. string.dump(load("print(3)")), true)
RUN('lua %s > %s', prog, out)
checkout('3\n')