mirror of https://github.com/rusefi/lua.git
new implementation for error handling
This commit is contained in:
parent
1c0ac3c0f5
commit
4e23699aa6
15
lauxlib.c
15
lauxlib.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lauxlib.c,v 1.77 2002/06/26 19:28:44 roberto Exp roberto $
|
||||
** $Id: lauxlib.c,v 1.78 2002/07/01 19:23:58 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -394,21 +394,20 @@ LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
|
|||
|
||||
static void callalert (lua_State *L, int status) {
|
||||
if (status != 0) {
|
||||
int top;
|
||||
if (status == LUA_ERRRUN)
|
||||
lua_concat(L, 2); /* concat error message and traceback */
|
||||
top = lua_gettop(L);
|
||||
lua_getglobal(L, "_ALERT");
|
||||
lua_insert(L, -2);
|
||||
lua_pcall(L, 1, 0);
|
||||
lua_settop(L, top-1);
|
||||
lua_call(L, 1, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int aux_do (lua_State *L, int status) {
|
||||
if (status == 0) /* parse OK? */
|
||||
if (status == 0) { /* parse OK? */
|
||||
status = lua_pcall(L, 0, LUA_MULTRET); /* call main */
|
||||
if (status != 0)
|
||||
lua_pcallreset(L);
|
||||
}
|
||||
callalert(L, status);
|
||||
return status;
|
||||
}
|
||||
|
|
21
ldblib.c
21
ldblib.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ldblib.c,v 1.63 2002/07/08 20:22:08 roberto Exp roberto $
|
||||
** $Id: ldblib.c,v 1.64 2002/07/17 16:25:13 roberto Exp roberto $
|
||||
** Interface from Lua to its debug API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -194,15 +194,11 @@ static int debug (lua_State *L) {
|
|||
static int errorfb (lua_State *L) {
|
||||
int level = 1; /* skip level 0 (it's this function) */
|
||||
int firstpart = 1; /* still before eventual `...' */
|
||||
int alllevels = 1;
|
||||
const char *msg = lua_tostring(L, 1);
|
||||
lua_Debug ar;
|
||||
lua_settop(L, 0);
|
||||
if (msg) {
|
||||
alllevels = 0;
|
||||
if (!strstr(msg, "stack traceback:\n"))
|
||||
lua_pushliteral(L, "stack traceback:\n");
|
||||
}
|
||||
if (lua_gettop(L) == 0)
|
||||
lua_pushliteral(L, "");
|
||||
else if (!lua_isstring(L, 1)) return 1; /* no string message */
|
||||
lua_pushliteral(L, "stack traceback:\n");
|
||||
while (lua_getstack(L, level++, &ar)) {
|
||||
if (level > LEVELS1 && firstpart) {
|
||||
/* no more than `LEVELS2' more levels? */
|
||||
|
@ -217,7 +213,7 @@ static int errorfb (lua_State *L) {
|
|||
continue;
|
||||
}
|
||||
lua_pushliteral(L, "\t");
|
||||
lua_getinfo(L, "Snlc", &ar);
|
||||
lua_getinfo(L, "Snl", &ar);
|
||||
lua_pushfstring(L, "%s:", ar.short_src);
|
||||
if (ar.currentline > 0)
|
||||
lua_pushfstring(L, "%d:", ar.currentline);
|
||||
|
@ -240,7 +236,6 @@ static int errorfb (lua_State *L) {
|
|||
}
|
||||
lua_pushliteral(L, "\n");
|
||||
lua_concat(L, lua_gettop(L));
|
||||
if (!alllevels && ar.isprotected) break;
|
||||
}
|
||||
lua_concat(L, lua_gettop(L));
|
||||
return 1;
|
||||
|
@ -261,9 +256,9 @@ static const luaL_reg dblib[] = {
|
|||
|
||||
LUALIB_API int lua_dblibopen (lua_State *L) {
|
||||
luaL_opennamedlib(L, LUA_DBLIBNAME, dblib, 0);
|
||||
lua_pushliteral(L, LUA_TRACEBACK);
|
||||
lua_pushliteral(L, "_TRACEBACK");
|
||||
lua_pushcfunction(L, errorfb);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
275
ldo.c
275
ldo.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ldo.c,v 1.187 2002/07/09 18:19:19 roberto Exp roberto $
|
||||
** $Id: ldo.c,v 1.188 2002/07/16 14:26:56 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -29,40 +29,113 @@
|
|||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Error-recovery functions (based on long jumps)
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/* chain list of long jump buffers */
|
||||
struct lua_longjmp {
|
||||
struct lua_longjmp *previous;
|
||||
CallInfo *ci; /* index of call info of active function that set protection */
|
||||
StkId top; /* top stack when protection was set */
|
||||
jmp_buf b;
|
||||
int allowhooks; /* `allowhook' state when protection was set */
|
||||
volatile int status; /* error code */
|
||||
TObject *err; /* error messages (start of `ud') */
|
||||
};
|
||||
|
||||
|
||||
static void pusherrormsg (lua_State *L, int status, TObject *err) {
|
||||
setobj(L->top++, &err[0]);
|
||||
if (status == LUA_ERRRUN)
|
||||
setobj(L->top++, &err[1]);
|
||||
static void seterrorobj (lua_State *L, int errcode) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: {
|
||||
setsvalue(L->top, luaS_new(L, MEMERRMSG));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRERR: {
|
||||
setsvalue(L->top, luaS_new(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRSYNTAX:
|
||||
case LUA_ERRRUN: {
|
||||
return; /* error message already on top */
|
||||
}
|
||||
}
|
||||
L->top++;
|
||||
}
|
||||
|
||||
|
||||
void luaD_throw (lua_State *L, int errcode) {
|
||||
if (errcode == LUA_ERRRUN)
|
||||
luaD_checkstack(L, LUA_MINSTACK); /* ensure stack space to handle error */
|
||||
luaG_saveallpcs(L); /* C stack will disapear */
|
||||
if (L->errorJmp) {
|
||||
L->errorJmp->status = errcode;
|
||||
longjmp(L->errorJmp->b, 1);
|
||||
}
|
||||
else {
|
||||
G(L)->panic(L);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||
struct lua_longjmp lj;
|
||||
lj.status = 0;
|
||||
lj.previous = L->errorJmp; /* chain new error handler */
|
||||
L->errorJmp = &lj;
|
||||
if (setjmp(lj.b) == 0)
|
||||
(*f)(L, ud);
|
||||
L->errorJmp = lj.previous; /* restore old error handler */
|
||||
return lj.status;
|
||||
}
|
||||
|
||||
|
||||
static void restore_stack_limit (lua_State *L) {
|
||||
L->stack_last = L->stack+L->stacksize-1;
|
||||
if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
|
||||
int inuse = (L->ci - L->base_ci);
|
||||
if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
|
||||
luaD_reallocCI(L, LUA_MAXCALLS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaD_resetprotection (lua_State *L) {
|
||||
Protection *p;
|
||||
StkId err = L->top - 1; /* error msg. position (if there is one) */
|
||||
lua_assert(L->number_toreset > 0);
|
||||
p = &L->toreset[--L->number_toreset];
|
||||
L->ci = restoreci(L, p->ci);
|
||||
L->top = restorestack(L, p->top);
|
||||
L->ci->top = L->top + LUA_MINSTACK;
|
||||
setallowhook(L, p->allowhooks);
|
||||
restore_stack_limit(L);
|
||||
setobj(L->top++, err); /* copy error message to corrected top */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** invalidate all pc pointers from stack part that becomes inactive
|
||||
*/
|
||||
static void deactivateinfo (lua_State *L, CallInfo *p_ci) {
|
||||
CallInfo *ci;
|
||||
for (ci = L->ci; ci > p_ci; ci--)
|
||||
ci->pc = NULL;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static void correctstack (lua_State *L, TObject *oldstack) {
|
||||
struct lua_longjmp *lj;
|
||||
CallInfo *ci;
|
||||
UpVal *up;
|
||||
L->top = (L->top - oldstack) + L->stack;
|
||||
for (lj = L->errorJmp; lj != NULL; lj = lj->previous)
|
||||
lj->top = (lj->top - oldstack) + L->stack;
|
||||
for (up = L->openupval; up != NULL; up = up->next)
|
||||
up->v = (up->v - oldstack) + L->stack;
|
||||
for (ci = L->base_ci; ci <= L->ci; ci++) {
|
||||
ci->base = (ci->base - oldstack) + L->stack;
|
||||
ci->top = (ci->top - oldstack) + L->stack;
|
||||
if (isLua(ci) && /* is a Lua function... */
|
||||
!(isLua(ci-1) && /* and next is not a Lua function... */
|
||||
ci->u.l.pc == (ci-1)->u.l.pc)) /* sharing the same C frame? */
|
||||
if (ci->pc && ci->pc != &luaV_callingmark) /* function has a frame? */
|
||||
*ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */
|
||||
}
|
||||
}
|
||||
|
@ -72,35 +145,17 @@ void luaD_reallocstack (lua_State *L, int newsize) {
|
|||
TObject *oldstack = L->stack;
|
||||
luaM_reallocvector(L, L->stack, L->stacksize, newsize, TObject);
|
||||
L->stacksize = newsize;
|
||||
L->stack_last = L->stack+(newsize-EXTRA_STACK)-1;
|
||||
L->stack_last = L->stack+newsize-1-EXTRA_STACK;
|
||||
correctstack(L, oldstack);
|
||||
}
|
||||
|
||||
|
||||
static void correctCI (lua_State *L, CallInfo *oldci) {
|
||||
struct lua_longjmp *lj;
|
||||
for (lj = L->errorJmp; lj != NULL; lj = lj->previous) {
|
||||
lj->ci = (lj->ci - oldci) + L->base_ci;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaD_reallocCI (lua_State *L, int newsize) {
|
||||
CallInfo *oldci = L->base_ci;
|
||||
luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
|
||||
L->size_ci = newsize;
|
||||
L->ci = (L->ci - oldci) + L->base_ci;
|
||||
L->end_ci = L->base_ci + L->size_ci;
|
||||
correctCI(L, oldci);
|
||||
}
|
||||
|
||||
|
||||
static void restore_stack_limit (lua_State *L) {
|
||||
if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */
|
||||
int inuse = (L->ci - L->base_ci);
|
||||
if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */
|
||||
luaD_reallocCI(L, LUA_MAXCALLS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -175,7 +230,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
|
|||
const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL);
|
||||
StkId p;
|
||||
ptrdiff_t funcr = savestack(L, func);
|
||||
if (ttype(tm) != LUA_TFUNCTION)
|
||||
if (!ttisfunction(tm))
|
||||
luaG_typeerror(L, func, "call");
|
||||
/* Open a hole inside the stack at `func' */
|
||||
for (p = L->top; p > func; p--) setobj(p, p-1);
|
||||
|
@ -189,7 +244,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
|
|||
StkId luaD_precall (lua_State *L, StkId func) {
|
||||
LClosure *cl;
|
||||
ptrdiff_t funcr = savestack(L, func);
|
||||
if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */
|
||||
if (!ttisfunction(func)) /* `func' is not a function? */
|
||||
func = tryfuncTM(L, func); /* check the `function' tag method */
|
||||
if (L->ci + 1 == L->end_ci) luaD_growCI(L);
|
||||
cl = &clvalue(func)->l;
|
||||
|
@ -202,7 +257,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
|
|||
ci = ++L->ci; /* now `enter' new function */
|
||||
ci->base = restorestack(L, funcr) + 1;
|
||||
ci->top = ci->base + p->maxstacksize;
|
||||
ci->savedpc = p->code; /* starting point */
|
||||
ci->u.l.savedpc = p->code; /* starting point */
|
||||
while (L->top < ci->top)
|
||||
setnilvalue(L->top++);
|
||||
L->top = ci->top;
|
||||
|
@ -215,7 +270,7 @@ StkId luaD_precall (lua_State *L, StkId func) {
|
|||
ci = ++L->ci; /* now `enter' new function */
|
||||
ci->base = restorestack(L, funcr) + 1;
|
||||
ci->top = L->top + LUA_MINSTACK;
|
||||
ci->savedpc = NULL; /* not a Lua function */
|
||||
ci->pc = NULL; /* not a Lua function */
|
||||
if (L->hookmask & LUA_MASKCALL) {
|
||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||
ci = L->ci; /* previous call may realocate `ci' */
|
||||
|
@ -274,6 +329,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
|
|||
LUA_API void lua_cobegin (lua_State *L, int nargs) {
|
||||
lua_lock(L);
|
||||
luaD_precall(L, L->top - (nargs+1));
|
||||
L->ci->pc = &luaV_callingmark; /* function is not active (yet) */
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
@ -287,28 +343,24 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
|
|||
}
|
||||
|
||||
|
||||
struct ResS {
|
||||
TObject err[2];
|
||||
int numres;
|
||||
};
|
||||
|
||||
static void resume (lua_State *L, void *ud) {
|
||||
StkId firstResult;
|
||||
CallInfo *ci = L->ci;
|
||||
if (!isLua(ci)) { /* not first time? */
|
||||
if (ci->pc == NULL) { /* not first time? */
|
||||
/* finish interrupted execution of `OP_CALL' */
|
||||
int nresults;
|
||||
lua_assert(isLua(ci - 1));
|
||||
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL);
|
||||
nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1;
|
||||
lua_assert((ci - 1)->pc == &luaV_callingmark);
|
||||
lua_assert(GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_CALL ||
|
||||
GET_OPCODE(*((ci-1)->u.l.savedpc - 1)) == OP_TAILCALL);
|
||||
nresults = GETARG_C(*((ci-1)->u.l.savedpc - 1)) - 1;
|
||||
luaD_poscall(L, nresults, L->top); /* complete it */
|
||||
if (nresults >= 0) L->top = L->ci->top;
|
||||
}
|
||||
firstResult = luaV_execute(L);
|
||||
if (firstResult == NULL) /* yield? */
|
||||
cast(struct ResS *, ud)->numres = L->ci->u.c.yield_results;
|
||||
*cast(int *, ud) = L->ci->u.c.yield_results;
|
||||
else { /* return */
|
||||
cast(struct ResS *, ud)->numres = L->top - firstResult;
|
||||
*cast(int *, ud) = L->top - firstResult;
|
||||
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
|
||||
}
|
||||
}
|
||||
|
@ -316,7 +368,7 @@ static void resume (lua_State *L, void *ud) {
|
|||
|
||||
LUA_API int lua_resume (lua_State *L, lua_State *co) {
|
||||
CallInfo *ci;
|
||||
struct ResS ud;
|
||||
int numres;
|
||||
int status;
|
||||
lua_lock(L);
|
||||
ci = co->ci;
|
||||
|
@ -324,11 +376,13 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
|
|||
luaG_runerror(L, "cannot resume dead thread");
|
||||
if (co->errorJmp != NULL) /* ?? */
|
||||
luaG_runerror(L, "cannot resume active thread");
|
||||
status = luaD_runprotected(co, resume, ud.err);
|
||||
status = luaD_rawrunprotected(co, resume, &numres);
|
||||
if (status == 0)
|
||||
move_results(L, co->top - ud.numres, co->top);
|
||||
else
|
||||
pusherrormsg(L, status, ud.err);
|
||||
move_results(L, co->top - numres, co->top);
|
||||
else {
|
||||
setobj(L->top++, co->top - 1); /* move error message to other stack */
|
||||
co->ci = co->base_ci; /* `kill' thread */
|
||||
}
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
@ -338,9 +392,9 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
|
|||
CallInfo *ci;
|
||||
lua_lock(L);
|
||||
ci = L->ci;
|
||||
if (!isLua(ci-1))
|
||||
if ((ci-1)->pc == NULL)
|
||||
luaG_runerror(L, "cannot yield a C function");
|
||||
lua_assert(!isLua(ci));
|
||||
lua_assert(ci->pc == NULL); /* current function is not Lua */
|
||||
ci->u.c.yield_results = nresults;
|
||||
lua_unlock(L);
|
||||
return -1;
|
||||
|
@ -351,7 +405,6 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
|
|||
** Execute a protected call.
|
||||
*/
|
||||
struct CallS { /* data to `f_call' */
|
||||
TObject err[2];
|
||||
StkId func;
|
||||
int nresults;
|
||||
};
|
||||
|
@ -359,6 +412,8 @@ struct CallS { /* data to `f_call' */
|
|||
|
||||
static void f_call (lua_State *L, void *ud) {
|
||||
struct CallS *c = cast(struct CallS *, ud);
|
||||
luaM_growvector(L, L->toreset, L->number_toreset, L->size_toreset,
|
||||
Protection, MAX_INT, "");
|
||||
luaD_call(L, c->func, c->nresults);
|
||||
}
|
||||
|
||||
|
@ -366,13 +421,24 @@ static void f_call (lua_State *L, void *ud) {
|
|||
int luaD_pcall (lua_State *L, int nargs, int nresults) {
|
||||
struct CallS c;
|
||||
int status;
|
||||
int protectionlevel = L->number_toreset;
|
||||
Protection protection;
|
||||
protection.top = savestack(L, L->top);
|
||||
protection.ci = saveci(L, L->ci);
|
||||
protection.allowhooks = allowhook(L);
|
||||
c.func = L->top - (nargs+1); /* function to be called */
|
||||
c.nresults = nresults;
|
||||
status = luaD_runprotected(L, &f_call, c.err);
|
||||
status = luaD_rawrunprotected(L, &f_call, &c);
|
||||
if (status != 0) { /* an error occurred? */
|
||||
L->top -= nargs+1; /* remove parameters and func from the stack */
|
||||
luaF_close(L, L->top); /* close eventual pending closures */
|
||||
pusherrormsg(L, status, c.err);
|
||||
/* remove parameters and func from the stack */
|
||||
protection.top = savestack(L, restorestack(L, protection.top) - (nargs+1));
|
||||
/* close eventual pending closures */
|
||||
luaF_close(L, restorestack(L, protection.top));
|
||||
L->ci->top = L->top + LUA_MINSTACK; /* extra space to handle error */
|
||||
seterrorobj(L, status);
|
||||
deactivateinfo(L, restoreci(L, protection.ci));
|
||||
L->number_toreset = protectionlevel + 1;
|
||||
L->toreset[L->number_toreset - 1] = protection;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -382,7 +448,6 @@ int luaD_pcall (lua_State *L, int nargs, int nresults) {
|
|||
** Execute a protected parser.
|
||||
*/
|
||||
struct SParser { /* data to `f_parser' */
|
||||
TObject err[2];
|
||||
ZIO *z;
|
||||
int bin;
|
||||
};
|
||||
|
@ -401,95 +466,25 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
|
|||
struct SParser p;
|
||||
lu_mem old_blocks;
|
||||
int status;
|
||||
ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */
|
||||
p.z = z; p.bin = bin;
|
||||
/* before parsing, give a (good) chance to GC */
|
||||
if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
|
||||
luaC_collectgarbage(L);
|
||||
old_blocks = G(L)->nblocks;
|
||||
status = luaD_runprotected(L, f_parser, p.err);
|
||||
status = luaD_rawrunprotected(L, f_parser, &p);
|
||||
if (status == 0) {
|
||||
/* add new memory to threshold (as it probably will stay) */
|
||||
lua_assert(G(L)->nblocks >= old_blocks);
|
||||
G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
|
||||
}
|
||||
else
|
||||
pusherrormsg(L, status, p.err);
|
||||
else { /* error */
|
||||
StkId oldtop = restorestack(L, oldtopr);
|
||||
seterrorobj(L, status);
|
||||
setobj(oldtop, L->top - 1); /* copy error message to old top */
|
||||
L->top = oldtop+1;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Error-recovery functions (based on long jumps)
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static void seterrorobj (lua_State *L, int errcode, TObject *m) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: {
|
||||
if (G(L) != NULL && G(L)->GCthreshold > 0) /* state is OK? */
|
||||
setsvalue(&m[0], luaS_new(L, MEMERRMSG));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRERR: {
|
||||
setsvalue(&m[0], luaS_new(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
case LUA_ERRSYNTAX: { /* message is on stack top */
|
||||
setobj(&m[0], L->top - 1);
|
||||
break;
|
||||
}
|
||||
case LUA_ERRRUN: { /* traceback is on stack top */
|
||||
setobj(&m[0], L->top - 2);
|
||||
setobj(&m[1], L->top - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaD_throw (lua_State *L, int errcode) {
|
||||
if (L->errorJmp) {
|
||||
seterrorobj(L, errcode, L->errorJmp->err);
|
||||
L->errorJmp->status = errcode;
|
||||
longjmp(L->errorJmp->b, 1);
|
||||
}
|
||||
else {
|
||||
G(L)->panic(L);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
|
||||
struct lua_longjmp lj;
|
||||
lj.ci = L->ci;
|
||||
lj.top = L->top;
|
||||
lj.allowhooks = allowhook(L);
|
||||
lj.status = 0;
|
||||
lj.err = ud;
|
||||
lj.previous = L->errorJmp; /* chain new error handler */
|
||||
L->errorJmp = &lj;
|
||||
if (setjmp(lj.b) == 0)
|
||||
(*f)(L, ud);
|
||||
else { /* an error occurred */
|
||||
L->ci = lj.ci; /* restore the state */
|
||||
L->top = lj.top;
|
||||
setallowhook(L, lj.allowhooks);
|
||||
restore_stack_limit(L);
|
||||
}
|
||||
L->errorJmp = lj.previous; /* restore old error handler */
|
||||
return lj.status;
|
||||
}
|
||||
|
||||
|
||||
int luaD_isprotected (lua_State *L, CallInfo *ci) {
|
||||
struct lua_longjmp *l;
|
||||
for (l = L->errorJmp; l; l = l->previous)
|
||||
if (l->ci+1 == ci) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
|
11
ldo.h
11
ldo.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ldo.h,v 1.47 2002/06/18 17:10:43 roberto Exp roberto $
|
||||
** $Id: ldo.h,v 1.48 2002/07/08 18:21:33 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -27,10 +27,14 @@
|
|||
#define savestack(L,p) ((char *)(p) - (char *)L->stack)
|
||||
#define restorestack(L,n) ((TObject *)((char *)L->stack + (n)))
|
||||
|
||||
#define saveci(L,p) ((char *)(p) - (char *)L->base_ci)
|
||||
#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n)))
|
||||
|
||||
|
||||
/* type of protected functions, to be ran by `runprotected' */
|
||||
typedef void (*Pfunc) (lua_State *L, void *v);
|
||||
typedef void (*Pfunc) (lua_State *L, void *ud);
|
||||
|
||||
void luaD_resetprotection (lua_State *L);
|
||||
int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
|
||||
void luaD_callhook (lua_State *L, lua_Hookevent event, int line);
|
||||
StkId luaD_precall (lua_State *L, StkId func);
|
||||
|
@ -42,8 +46,7 @@ void luaD_reallocstack (lua_State *L, int newsize);
|
|||
void luaD_growstack (lua_State *L, int n);
|
||||
|
||||
void luaD_throw (lua_State *L, int errcode);
|
||||
int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud);
|
||||
int luaD_isprotected (lua_State *L, CallInfo *ci);
|
||||
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
23
lstate.c
23
lstate.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.c,v 1.98 2002/07/08 18:21:33 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 1.99 2002/07/16 14:26:56 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -35,17 +35,19 @@ static int default_panic (lua_State *L) {
|
|||
|
||||
|
||||
static void stack_init (lua_State *L, lua_State *OL) {
|
||||
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE, TObject);
|
||||
L->stacksize = BASIC_STACK_SIZE;
|
||||
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
||||
L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
|
||||
L->top = L->stack;
|
||||
L->stack_last = L->stack+(BASIC_STACK_SIZE-EXTRA_STACK)-1;
|
||||
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
|
||||
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
|
||||
L->ci = L->base_ci;
|
||||
L->ci->savedpc = NULL;
|
||||
L->ci->pc = NULL; /* not a Lua function */
|
||||
L->ci->base = L->top;
|
||||
L->ci->top = L->top + LUA_MINSTACK;
|
||||
L->size_ci = BASIC_CI_SIZE;
|
||||
L->end_ci = L->base_ci + L->size_ci;
|
||||
L->toreset = luaM_newvector(OL, 2, Protection);
|
||||
L->size_toreset = 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,7 +100,12 @@ static void preinit_state (lua_State *L) {
|
|||
resethookcount(L);
|
||||
L->openupval = NULL;
|
||||
L->size_ci = 0;
|
||||
L->base_ci = NULL;
|
||||
L->base_ci = L->ci = NULL;
|
||||
L->toreset = NULL;
|
||||
L->size_toreset = L->number_toreset = 0;
|
||||
setnilvalue(defaultmeta(L));
|
||||
setnilvalue(gt(L));
|
||||
setnilvalue(registry(L));
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,13 +131,12 @@ LUA_API lua_State *lua_newthread (lua_State *OL) {
|
|||
|
||||
LUA_API lua_State *lua_open (void) {
|
||||
lua_State *L;
|
||||
TObject dummy[2];
|
||||
L = luaM_new(NULL, lua_State);
|
||||
if (L) { /* allocation OK? */
|
||||
preinit_state(L);
|
||||
L->l_G = NULL;
|
||||
L->next = L->previous = L;
|
||||
if (luaD_runprotected(L, f_luaopen, dummy) != 0) {
|
||||
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
||||
/* memory allocation error: free partial state */
|
||||
close_state(L);
|
||||
L = NULL;
|
||||
|
@ -147,6 +153,7 @@ void luaE_closethread (lua_State *OL, lua_State *L) {
|
|||
L->previous->next = L->next;
|
||||
L->next->previous = L->previous;
|
||||
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
|
||||
luaM_freearray(OL, L->toreset, L->size_toreset, Protection);
|
||||
luaM_freearray(OL, L->stack, L->stacksize, TObject);
|
||||
luaM_freelem(OL, L);
|
||||
}
|
||||
|
|
31
lstate.h
31
lstate.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.h,v 1.88 2002/07/08 20:22:08 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 1.89 2002/07/16 14:26:56 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ struct lua_longjmp; /* defined in ldo.c */
|
|||
#define registry(L) (L->globs + 2)
|
||||
|
||||
|
||||
/* space to handle TM calls and other temporary overflows */
|
||||
/* extra stack space to handle TM calls and some other extras */
|
||||
#define EXTRA_STACK 5
|
||||
|
||||
|
||||
|
@ -88,10 +88,10 @@ typedef struct stringtable {
|
|||
typedef struct CallInfo {
|
||||
StkId base; /* base for called function */
|
||||
StkId top; /* top for this function */
|
||||
const Instruction *savedpc; /* NULL means not a Lua function */
|
||||
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
|
||||
union {
|
||||
struct { /* for Lua functions */
|
||||
const Instruction **pc; /* points to `pc' variable in `luaV_execute' */
|
||||
const Instruction *savedpc;
|
||||
StkId *pb; /* points to `base' variable in `luaV_execute' */
|
||||
} l;
|
||||
struct { /* for C functions */
|
||||
|
@ -101,7 +101,15 @@ typedef struct CallInfo {
|
|||
} CallInfo;
|
||||
|
||||
|
||||
#define isLua(ci) ((ci)->savedpc != NULL)
|
||||
/*
|
||||
** informations about a `protection' (error recovery points)
|
||||
*/
|
||||
typedef struct Protection {
|
||||
ptrdiff_t ci;
|
||||
ptrdiff_t top;
|
||||
int allowhooks;
|
||||
} Protection;
|
||||
|
||||
|
||||
#define ci_func(ci) (clvalue((ci)->base - 1))
|
||||
|
||||
|
@ -133,22 +141,25 @@ typedef struct global_State {
|
|||
struct lua_State {
|
||||
LUA_USERSTATE
|
||||
StkId top; /* first free slot in the stack */
|
||||
global_State *l_G;
|
||||
CallInfo *ci; /* call info for current function */
|
||||
StkId stack_last; /* last free slot in the stack */
|
||||
StkId stack; /* stack base */
|
||||
int stacksize;
|
||||
CallInfo *end_ci; /* points after end of ci array*/
|
||||
CallInfo *base_ci; /* array of CallInfo's */
|
||||
global_State *l_G;
|
||||
int size_ci; /* size of array `base_ci' */
|
||||
int hookmask;
|
||||
ls_count hookcount;
|
||||
lua_Hook hook;
|
||||
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
|
||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||
UpVal *openupval; /* list of open upvalues in this stack */
|
||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||
Protection *toreset; /* array of pending pcall resets */
|
||||
int number_toreset;
|
||||
int size_toreset;
|
||||
lua_State *next; /* circular double linked list of states */
|
||||
lua_State *previous;
|
||||
int stacksize;
|
||||
int size_ci; /* size of array `base_ci' */
|
||||
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: luadebug.h,v 1.29 2002/07/08 18:21:33 roberto Exp roberto $
|
||||
** $Id: luadebug.h,v 1.30 2002/07/08 20:22:08 roberto Exp $
|
||||
** Debugging API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -46,7 +46,6 @@ struct lua_Debug {
|
|||
const char *what; /* (S) `Lua' function, `C' function, Lua `main' */
|
||||
const char *source; /* (S) */
|
||||
int currentline; /* (l) */
|
||||
int isprotected; /* (c) function was called in protected mode */
|
||||
int nups; /* (u) number of upvalues */
|
||||
int linedefined; /* (S) */
|
||||
char short_src[LUA_IDSIZE]; /* (S) */
|
||||
|
|
150
lvm.c
150
lvm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.c,v 1.247 2002/07/16 14:26:56 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 1.248 2002/07/17 16:25:13 roberto Exp $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -24,6 +24,9 @@
|
|||
#include "lvm.h"
|
||||
|
||||
|
||||
Instruction const *luaV_callingmark = NULL;
|
||||
|
||||
|
||||
/* function to convert a lua_Number to a string */
|
||||
#ifndef lua_number2str
|
||||
#include <stdio.h>
|
||||
|
@ -46,8 +49,8 @@ static void luaV_checkGC (lua_State *L, StkId top) {
|
|||
|
||||
const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
|
||||
lua_Number num;
|
||||
if (ttype(obj) == LUA_TNUMBER) return obj;
|
||||
if (ttype(obj) == LUA_TSTRING && luaO_str2d(svalue(obj), &num)) {
|
||||
if (ttisnumber(obj)) return obj;
|
||||
if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
|
||||
setnvalue(n, num);
|
||||
return n;
|
||||
}
|
||||
|
@ -57,7 +60,7 @@ const TObject *luaV_tonumber (const TObject *obj, TObject *n) {
|
|||
|
||||
|
||||
int luaV_tostring (lua_State *L, TObject *obj) {
|
||||
if (ttype(obj) != LUA_TNUMBER)
|
||||
if (!ttisnumber(obj))
|
||||
return 0;
|
||||
else {
|
||||
char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */
|
||||
|
@ -80,16 +83,16 @@ static void traceexec (lua_State *L) {
|
|||
if (mask & LUA_MASKLINE) {
|
||||
CallInfo *ci = L->ci;
|
||||
Proto *p = ci_func(ci)->l.p;
|
||||
int newline = getline(p, pcRel(*ci->u.l.pc, p));
|
||||
if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */
|
||||
ci->savedpc = *ci->u.l.pc; /* initialize `savedpc' */
|
||||
int newline = getline(p, pcRel(*ci->pc, p));
|
||||
if (pcRel(*ci->pc, p) == 0) /* tracing may be starting now? */
|
||||
ci->u.l.savedpc = *ci->pc; /* initialize `savedpc' */
|
||||
/* calls linehook when enters a new line or jumps back (loop) */
|
||||
if (*ci->u.l.pc <= ci->savedpc ||
|
||||
newline != getline(p, pcRel(ci->savedpc, p))) {
|
||||
if (*ci->pc <= ci->u.l.savedpc ||
|
||||
newline != getline(p, pcRel(ci->u.l.savedpc, p))) {
|
||||
luaD_callhook(L, LUA_HOOKLINE, newline);
|
||||
ci = L->ci; /* previous call may reallocate `ci' */
|
||||
}
|
||||
ci->savedpc = *ci->u.l.pc;
|
||||
ci->u.l.savedpc = *ci->pc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +126,7 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
|
|||
TObject *key, int loop) {
|
||||
const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);
|
||||
if (tm == NULL) return &luaO_nilobject; /* no TM */
|
||||
if (ttype(tm) == LUA_TFUNCTION) {
|
||||
if (ttisfunction(tm)) {
|
||||
callTMres(L, tm, t, key);
|
||||
return L->top;
|
||||
}
|
||||
|
@ -133,9 +136,9 @@ static const TObject *luaV_index (lua_State *L, const TObject *t,
|
|||
static const TObject *luaV_getnotable (lua_State *L, const TObject *t,
|
||||
TObject *key, int loop) {
|
||||
const TObject *tm = luaT_gettmbyobj(L, t, TM_GETTABLE);
|
||||
if (ttype(tm) == LUA_TNIL)
|
||||
if (ttisnil(tm))
|
||||
luaG_typeerror(L, t, "index");
|
||||
if (ttype(tm) == LUA_TFUNCTION) {
|
||||
if (ttisfunction(tm)) {
|
||||
callTMres(L, tm, t, key);
|
||||
return L->top;
|
||||
}
|
||||
|
@ -152,10 +155,10 @@ const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,
|
|||
int loop) {
|
||||
if (loop > MAXTAGLOOP)
|
||||
luaG_runerror(L, "loop in gettable");
|
||||
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
||||
if (ttistable(t)) { /* `t' is a table? */
|
||||
Table *h = hvalue(t);
|
||||
const TObject *v = luaH_get(h, key); /* do a primitive get */
|
||||
if (ttype(v) != LUA_TNIL) return v;
|
||||
if (!ttisnil(v)) return v;
|
||||
else return luaV_index(L, t, key, loop+1);
|
||||
}
|
||||
else return luaV_getnotable(L, t, key, loop+1);
|
||||
|
@ -169,19 +172,19 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {
|
|||
const TObject *tm;
|
||||
int loop = 0;
|
||||
do {
|
||||
if (ttype(t) == LUA_TTABLE) { /* `t' is a table? */
|
||||
if (ttistable(t)) { /* `t' is a table? */
|
||||
Table *h = hvalue(t);
|
||||
TObject *oldval = luaH_set(L, h, key); /* do a primitive set */
|
||||
if (ttype(oldval) != LUA_TNIL || /* result is no nil? */
|
||||
if (!ttisnil(oldval) || /* result is no nil? */
|
||||
(tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
|
||||
setobj(oldval, val);
|
||||
return;
|
||||
}
|
||||
/* else will try the tag method */
|
||||
}
|
||||
else if (ttype(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)) == LUA_TNIL)
|
||||
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_SETTABLE)))
|
||||
luaG_typeerror(L, t, "index");
|
||||
if (ttype(tm) == LUA_TFUNCTION) {
|
||||
if (ttisfunction(tm)) {
|
||||
callTM(L, tm, t, key, val);
|
||||
return;
|
||||
}
|
||||
|
@ -195,9 +198,9 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
|
|||
TObject *res, TMS event) {
|
||||
ptrdiff_t result = savestack(L, res);
|
||||
const TObject *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */
|
||||
if (ttype(tm) == LUA_TNIL)
|
||||
if (ttisnil(tm))
|
||||
tm = luaT_gettmbyobj(L, p2, event); /* try second operand */
|
||||
if (ttype(tm) != LUA_TFUNCTION) return 0;
|
||||
if (!ttisfunction(tm)) return 0;
|
||||
callTMres(L, tm, p1, p2);
|
||||
res = restorestack(L, result); /* previous call may change stack */
|
||||
setobj(res, L->top);
|
||||
|
@ -230,9 +233,9 @@ static int luaV_strcmp (const TString *ls, const TString *rs) {
|
|||
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
|
||||
if (ttype(l) != ttype(r))
|
||||
return luaG_ordererror(L, l, r);
|
||||
else if (ttype(l) == LUA_TNUMBER)
|
||||
else if (ttisnumber(l))
|
||||
return nvalue(l) < nvalue(r);
|
||||
else if (ttype(l) == LUA_TSTRING)
|
||||
else if (ttisstring(l))
|
||||
return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;
|
||||
else if (call_binTM(L, l, r, L->top, TM_LT))
|
||||
return !l_isfalse(L->top);
|
||||
|
@ -243,9 +246,9 @@ int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {
|
|||
static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {
|
||||
if (ttype(l) != ttype(r))
|
||||
return luaG_ordererror(L, l, r);
|
||||
else if (ttype(l) == LUA_TNUMBER)
|
||||
else if (ttisnumber(l))
|
||||
return nvalue(l) <= nvalue(r);
|
||||
else if (ttype(l) == LUA_TSTRING)
|
||||
else if (ttisstring(l))
|
||||
return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;
|
||||
else if (call_binTM(L, l, r, L->top, TM_LE)) /* first try `le' */
|
||||
return !l_isfalse(L->top);
|
||||
|
@ -330,7 +333,7 @@ static void Arith (lua_State *L, StkId ra, StkId rb, StkId rc, TMS op) {
|
|||
const TObject *f = luaH_getstr(hvalue(registry(L)),
|
||||
G(L)->tmname[TM_POW]);
|
||||
ptrdiff_t res = savestack(L, ra);
|
||||
if (ttype(f) != LUA_TFUNCTION)
|
||||
if (!ttisfunction(f))
|
||||
luaG_runerror(L, "`pow' (for `^' operator) is not a function");
|
||||
callTMres(L, f, b, c);
|
||||
ra = restorestack(L, res); /* previous call may change stack */
|
||||
|
@ -370,9 +373,9 @@ StkId luaV_execute (lua_State *L) {
|
|||
TObject *k;
|
||||
const Instruction *pc;
|
||||
callentry: /* entry point when calling new functions */
|
||||
L->ci->u.l.pc = &pc;
|
||||
L->ci->u.l.pb = &base;
|
||||
pc = L->ci->savedpc;
|
||||
L->ci->pc = &pc;
|
||||
pc = L->ci->u.l.savedpc;
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||
retentry: /* entry point when returning to old functions */
|
||||
|
@ -382,11 +385,10 @@ StkId luaV_execute (lua_State *L) {
|
|||
/* main loop of interpreter */
|
||||
for (;;) {
|
||||
const Instruction i = *pc++;
|
||||
StkId ra;
|
||||
const StkId ra = RA(i);
|
||||
if (L->hookmask >= LUA_MASKLINE &&
|
||||
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE))
|
||||
traceexec(L);
|
||||
ra = RA(i);
|
||||
traceexec(L);
|
||||
lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
|
||||
lua_assert(L->top == L->ci->top ||
|
||||
GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||
|
||||
|
@ -420,9 +422,9 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_GETGLOBAL: {
|
||||
StkId rb = KBx(i);
|
||||
const TObject *v;
|
||||
lua_assert(ttype(rb) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE);
|
||||
lua_assert(ttisstring(rb) && ttistable(&cl->g));
|
||||
v = luaH_getstr(hvalue(&cl->g), tsvalue(rb));
|
||||
if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, &cl->g, rb, 0));
|
||||
break;
|
||||
|
@ -430,9 +432,9 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_GETTABLE: {
|
||||
StkId rb = RB(i);
|
||||
TObject *rc = RKC(i);
|
||||
if (ttype(rb) == LUA_TTABLE) {
|
||||
if (ttistable(rb)) {
|
||||
const TObject *v = luaH_get(hvalue(rb), rc);
|
||||
if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, rb, rc, 0));
|
||||
}
|
||||
|
@ -441,7 +443,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
break;
|
||||
}
|
||||
case OP_SETGLOBAL: {
|
||||
lua_assert(ttype(KBx(i)) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE);
|
||||
lua_assert(ttisstring(KBx(i)) && ttistable(&cl->g));
|
||||
luaV_settable(L, &cl->g, KBx(i), ra);
|
||||
break;
|
||||
}
|
||||
|
@ -464,11 +466,11 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_SELF: {
|
||||
StkId rb = RB(i);
|
||||
TObject *rc = RKC(i);
|
||||
runtime_check(L, ttype(rc) == LUA_TSTRING);
|
||||
runtime_check(L, ttisstring(rc));
|
||||
setobj(ra+1, rb);
|
||||
if (ttype(rb) == LUA_TTABLE) {
|
||||
if (ttistable(rb)) {
|
||||
const TObject *v = luaH_getstr(hvalue(rb), tsvalue(rc));
|
||||
if (ttype(v) != LUA_TNIL) { setobj(ra, v); }
|
||||
if (!ttisnil(v)) { setobj(ra, v); }
|
||||
else
|
||||
setobj(RA(i), luaV_index(L, rb, rc, 0));
|
||||
}
|
||||
|
@ -479,7 +481,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_ADD: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) + nvalue(rc));
|
||||
}
|
||||
else
|
||||
|
@ -489,7 +491,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_SUB: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) - nvalue(rc));
|
||||
}
|
||||
else
|
||||
|
@ -499,7 +501,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_MUL: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) * nvalue(rc));
|
||||
}
|
||||
else
|
||||
|
@ -509,7 +511,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
case OP_DIV: {
|
||||
StkId rb = RB(i);
|
||||
StkId rc = RKC(i);
|
||||
if (ttype(rb) == LUA_TNUMBER && ttype(rc) == LUA_TNUMBER) {
|
||||
if (ttisnumber(rb) && ttisnumber(rc)) {
|
||||
setnvalue(ra, nvalue(rb) / nvalue(rc));
|
||||
}
|
||||
else
|
||||
|
@ -584,7 +586,8 @@ StkId luaV_execute (lua_State *L) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OP_CALL: {
|
||||
case OP_CALL:
|
||||
case OP_TAILCALL: {
|
||||
StkId firstResult;
|
||||
int b = GETARG_B(i);
|
||||
int nresults;
|
||||
|
@ -593,46 +596,47 @@ StkId luaV_execute (lua_State *L) {
|
|||
firstResult = luaD_precall(L, ra);
|
||||
if (firstResult) {
|
||||
if (firstResult > L->top) { /* yield? */
|
||||
(L->ci-1)->savedpc = pc;
|
||||
(L->ci - 1)->u.l.savedpc = pc;
|
||||
(L->ci - 1)->pc = &luaV_callingmark;
|
||||
return NULL;
|
||||
}
|
||||
/* it was a C function (`precall' called it); adjust results */
|
||||
luaD_poscall(L, nresults, firstResult);
|
||||
if (nresults >= 0) L->top = L->ci->top;
|
||||
}
|
||||
else { /* it is a Lua function: `call' it */
|
||||
(L->ci-1)->savedpc = pc;
|
||||
else { /* it is a Lua function */
|
||||
if (GET_OPCODE(i) == OP_CALL) { /* regular call? */
|
||||
(L->ci-1)->u.l.savedpc = pc; /* save `pc' to return later */
|
||||
(L->ci-1)->pc = &luaV_callingmark; /* function is calling */
|
||||
}
|
||||
else { /* tail call: put new frame in place of previous one */
|
||||
int aux;
|
||||
StkId ra1 = RA(i); /* `luaD_precall' may change the stack */
|
||||
if (L->openupval) luaF_close(L, base);
|
||||
for (aux = 0; ra1+aux < L->top; aux++) /* move frame down */
|
||||
setobj(base+aux-1, ra1+aux);
|
||||
(L->ci - 1)->top = L->top = base+aux; /* correct top */
|
||||
(L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc;
|
||||
L->ci--; /* remove previous frame */
|
||||
}
|
||||
goto callentry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_TAILCALL: {
|
||||
int b = GETARG_B(i);
|
||||
if (L->openupval) luaF_close(L, base);
|
||||
if (b != 0) L->top = ra+b; /* else previous instruction set top */
|
||||
luaD_poscall(L, LUA_MULTRET, ra); /* move down function and args. */
|
||||
ra = luaD_precall(L, base-1);
|
||||
if (ra == NULL) goto callentry; /* it is a Lua function */
|
||||
else if (ra > L->top) return NULL; /* yield??? */
|
||||
else goto ret;
|
||||
}
|
||||
case OP_RETURN: {
|
||||
int b;
|
||||
if (L->openupval) luaF_close(L, base);
|
||||
b = GETARG_B(i);
|
||||
CallInfo *ci = L->ci - 1;
|
||||
int b = GETARG_B(i);
|
||||
if (b != 0) L->top = ra+b-1;
|
||||
lua_assert(L->ci->u.l.pc == &pc);
|
||||
}
|
||||
ret: {
|
||||
CallInfo *ci;
|
||||
ci = L->ci - 1;
|
||||
lua_assert(L->ci->pc == &pc);
|
||||
if (L->openupval) luaF_close(L, base);
|
||||
/* previous function was running `here'? */
|
||||
if (!isLua(ci) || ci->u.l.pc != &pc)
|
||||
if (ci->pc != &luaV_callingmark)
|
||||
return ra; /* no: return */
|
||||
else { /* yes: continue its execution */
|
||||
else { /* yes: continue its execution (go through) */
|
||||
int nresults;
|
||||
lua_assert(ttype(ci->base-1) == LUA_TFUNCTION);
|
||||
pc = ci->savedpc;
|
||||
lua_assert(ttisfunction(ci->base-1));
|
||||
ci->pc = &pc; /* function is active again */
|
||||
pc = ci->u.l.savedpc;
|
||||
lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL);
|
||||
nresults = GETARG_C(*(pc-1)) - 1;
|
||||
luaD_poscall(L, nresults, ra);
|
||||
|
@ -644,7 +648,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
lua_Number step, index, limit;
|
||||
const TObject *plimit = ra+1;
|
||||
const TObject *pstep = ra+2;
|
||||
if (ttype(ra) != LUA_TNUMBER)
|
||||
if (!ttisnumber(ra))
|
||||
luaG_runerror(L, "`for' initial value must be a number");
|
||||
if (!tonumber(plimit, ra+1))
|
||||
luaG_runerror(L, "`for' limit must be a number");
|
||||
|
@ -666,12 +670,12 @@ StkId luaV_execute (lua_State *L) {
|
|||
L->top = ra+5;
|
||||
luaD_call(L, ra+2, GETARG_C(i) + 1);
|
||||
L->top = L->ci->top;
|
||||
if (ttype(ra+2) == LUA_TNIL) pc++; /* skip jump (break loop) */
|
||||
if (ttisnil(ra+2)) pc++; /* skip jump (break loop) */
|
||||
else dojump(pc, GETARG_sBx(*pc) + 1); /* else jump back */
|
||||
break;
|
||||
}
|
||||
case OP_TFORPREP: { /* for compatibility only */
|
||||
if (ttype(ra) == LUA_TTABLE) {
|
||||
if (ttistable(ra)) {
|
||||
setobj(ra+1, ra);
|
||||
setobj(ra, luaH_getstr(hvalue(gt(L)), luaS_new(L, "next")));
|
||||
}
|
||||
|
@ -683,7 +687,7 @@ StkId luaV_execute (lua_State *L) {
|
|||
int bc;
|
||||
int n;
|
||||
Table *h;
|
||||
runtime_check(L, ttype(ra) == LUA_TTABLE);
|
||||
runtime_check(L, ttistable(ra));
|
||||
h = hvalue(ra);
|
||||
bc = GETARG_Bx(i);
|
||||
if (GET_OPCODE(i) == OP_SETLIST)
|
||||
|
|
9
lvm.h
9
lvm.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.h,v 1.43 2002/06/24 13:08:45 roberto Exp roberto $
|
||||
** $Id: lvm.h,v 1.44 2002/07/05 18:27:39 roberto Exp $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -22,6 +22,13 @@
|
|||
(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
|
||||
|
||||
|
||||
/*
|
||||
** dummy addrees, to mark Lua functions calling other Lua functions (and
|
||||
** therefore without a valid `pc'
|
||||
*/
|
||||
extern Instruction const *luaV_callingmark;
|
||||
|
||||
|
||||
int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
|
||||
int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2);
|
||||
const TObject *luaV_tonumber (const TObject *obj, TObject *n);
|
||||
|
|
Loading…
Reference in New Issue