diff --git a/ldo.c b/ldo.c index 9d981468..8f49b595 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $ +** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) { } -static void message (lua_State *L, const char *s) { - const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); - if (*luaO_typename(em) == 'f') { - *L->top = *em; - incr_top; - lua_pushstring(L, s); - luaD_call(L, L->top-2, 0); - } -} - - -void luaD_breakrun (lua_State *L, int errcode) { - if (L->errorJmp) { - L->errorJmp->status = errcode; - longjmp(L->errorJmp->b, 1); - } - else { - if (errcode != LUA_ERRMEM) - message(L, "unable to recover; exiting\n"); - exit(EXIT_FAILURE); - } -} - -/* -** Reports an error, and jumps up to the available recovery label -*/ -void lua_error (lua_State *L, const char *s) { - if (s) message(L, s); - luaD_breakrun(L, LUA_ERRRUN); -} - - -static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { - lj->status = 0; - lj->base = L->Cbase; - lj->previous = L->errorJmp; - L->errorJmp = lj; -} - - -static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) { - L->Cbase = lj->base; - L->errorJmp = lj->previous; - return lj->status; -} - - /* ** Execute a protected call. */ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = (struct CallS *)ud; + luaD_call(L, c->func, c->nresults); +} + + int lua_call (lua_State *L, int nargs, int nresults) { StkId func = L->top - (nargs+1); /* function to be called */ - struct lua_longjmp myErrorJmp; - chain_longjmp(L, &myErrorJmp); - if (setjmp(myErrorJmp.b) == 0) { - luaD_call(L, func, nresults); - } - else { /* an error occurred: restore the state */ - L->top = func; /* remove garbage from the stack */ - restore_stack_limit(L); - } - return restore_longjmp(L, &myErrorJmp); + struct CallS c; + int status; + c.func = func; c.nresults = nresults; + status = luaD_runprotected(L, f_call, &c); + if (status != 0) /* an error occurred? */ + L->top = func; /* remove parameters from the stack */ + return status; +} + + +/* +** Execute a protected parser. +*/ +struct ParserS { /* data to `f_parser' */ + ZIO *z; + int bin; +}; + +static void f_parser (lua_State *L, void *ud) { + struct ParserS *p = (struct ParserS *)ud; + Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); + luaV_Lclosure(L, tf, 0); } static int protectedparser (lua_State *L, ZIO *z, int bin) { - struct lua_longjmp myErrorJmp; + struct ParserS p; unsigned long old_blocks; + int status; + p.z = z; p.bin = bin; luaC_checkGC(L); old_blocks = L->nblocks; - chain_longjmp(L, &myErrorJmp); - if (setjmp(myErrorJmp.b) == 0) { - Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z); - luaV_Lclosure(L, tf, 0); - } - else { /* an error occurred: correct error code */ - if (myErrorJmp.status == LUA_ERRRUN) - myErrorJmp.status = LUA_ERRSYNTAX; - } + status = luaD_runprotected(L, f_parser, &p); + if (status == LUA_ERRRUN) /* an error occurred: correct error code */ + status = LUA_ERRSYNTAX; /* add new memory to threshould (as it probably will stay) */ L->GCthreshold += (L->nblocks - old_blocks); - return restore_longjmp(L, &myErrorJmp); /* error code */ + return status; } @@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) { return lua_dobuffer(L, str, strlen(str), str); } + +/* +** {====================================================== +** Error-recover functions (based on long jumps) +** ======================================================= +*/ + +/* chain list of long jump buffers */ +struct lua_longjmp { + jmp_buf b; + struct lua_longjmp *previous; + volatile int status; /* error code */ +}; + + +static void message (lua_State *L, const char *s) { + const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); + if (*luaO_typename(em) == 'f') { + *L->top = *em; + incr_top; + lua_pushstring(L, s); + luaD_call(L, L->top-2, 0); + } +} + + +/* +** Reports an error, and jumps up to the available recovery label +*/ +void lua_error (lua_State *L, const char *s) { + if (s) message(L, s); + luaD_breakrun(L, LUA_ERRRUN); +} + + +void luaD_breakrun (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + longjmp(L->errorJmp->b, 1); + } + else { + if (errcode != LUA_ERRMEM) + message(L, "unable to recover; exiting\n"); + exit(EXIT_FAILURE); + } +} + + +int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { + StkId oldCbase = L->Cbase; + StkId oldtop = L->top; + 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); + else { /* an error occurred: restore the state */ + L->Cbase = oldCbase; + L->top = oldtop; + restore_stack_limit(L); + } + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + diff --git a/ldo.h b/ldo.h index becbf417..da52e496 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $ +** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra); void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); void luaD_call (lua_State *L, StkId func, int nResults); void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); -void luaD_breakrun (lua_State *L, int errcode); void luaD_checkstack (lua_State *L, int n); +void luaD_breakrun (lua_State *L, int errcode); +int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); + #endif diff --git a/lstate.c b/lstate.c index d315e976..71671785 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $ +** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -20,7 +20,7 @@ #ifdef DEBUG -extern lua_State *lua_state; +static lua_State *lua_state = NULL; void luaB_opentests (lua_State *L); #endif @@ -38,8 +38,29 @@ static int errormessage (lua_State *L) { } +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + int stacksize = *(int *)ud; + if (stacksize == 0) + stacksize = DEFAULT_STACK_SIZE; + else + stacksize += LUA_MINSTACK; + L->gt = luaH_new(L, 10); + luaD_init(L, stacksize); + luaS_init(L); + luaX_init(L); + luaT_init(L); + lua_register(L, LUA_ERRORMESSAGE, errormessage); +#ifdef DEBUG + luaB_opentests(L); + if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ +#endif +} + + lua_State *lua_open (int stacksize) { - struct lua_longjmp myErrorJmp; lua_State *L = luaM_new(NULL, lua_State); if (L == NULL) return NULL; /* memory allocation error */ L->stack = NULL; @@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) { L->callhook = NULL; L->linehook = NULL; L->allowhooks = 1; - L->errorJmp = &myErrorJmp; - if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */ - L->gt = luaH_new(L, 10); - luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE : - stacksize+LUA_MINSTACK); - luaS_init(L); - luaX_init(L); - luaT_init(L); - lua_register(L, LUA_ERRORMESSAGE, errormessage); -#ifdef DEBUG - luaB_opentests(L); -#endif - L->GCthreshold = L->nblocks*4; - L->errorJmp = NULL; - return L; - } - else { /* memory allocation error: free partial state */ + L->errorJmp = NULL; + if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) { + /* memory allocation error: free partial state */ lua_close(L); return NULL; } + L->GCthreshold = L->nblocks*4; + return L; } diff --git a/lstate.h b/lstate.h index 66ae964d..8d54e932 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $ +** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -7,8 +7,6 @@ #ifndef lstate_h #define lstate_h -#include - #include "lobject.h" #include "lua.h" #include "luadebug.h" @@ -33,15 +31,7 @@ struct Ref { }; -/* -** chain list of long jumps -*/ -struct lua_longjmp { - jmp_buf b; - struct lua_longjmp *previous; - volatile int status; /* error code */ - StkId base; -}; +struct lua_longjmp; /* defined in ldo.c */ typedef struct stringtable { diff --git a/ltests.c b/ltests.c index fe0ed439..85bfaad8 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $ +** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -422,11 +422,19 @@ static int testC (lua_State *L) { else if EQ("concat") { lua_concat(L, getnum); } - else if EQ("call") { + else if EQ("rawcall") { int narg = getnum; int nres = getnum; lua_rawcall(L, narg, nres); } + else if EQ("call") { + int narg = getnum; + int nres = getnum; + lua_call(L, narg, nres); + } + else if EQ("dostring") { + lua_dostring(L, luaL_check_string(L, getnum)); + } else if EQ("type") { lua_pushstring(L, lua_type(L, getnum)); }