From ee4859b3e3db6c1a3223669d15538b3852ca4791 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 22 Apr 2002 11:40:50 -0300 Subject: new way to handle errors (temporary version) --- ldo.c | 107 ++++++++++++++++++++++-------------------------------------------- 1 file changed, 36 insertions(+), 71 deletions(-) (limited to 'ldo.c') diff --git a/ldo.c b/ldo.c index 29276f1b..c89d3a3c 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.170 2002/04/15 19:34:42 roberto Exp roberto $ +** $Id: ldo.c,v 1.171 2002/04/16 17:08:28 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -38,9 +38,11 @@ struct lua_longjmp { jmp_buf b; int allowhooks; /* `allowhook' state when protection was set */ volatile int status; /* error code */ + TObject err; /* function to be called in case of errors */ }; + static void correctstack (lua_State *L, TObject *oldstack) { struct lua_longjmp *lj; CallInfo *ci; @@ -108,11 +110,11 @@ void luaD_growstack (lua_State *L, int n) { static void luaD_growCI (lua_State *L) { L->ci--; if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ - luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ + luaD_error(L, NULL, LUA_ERRERR); /* break run without error message */ else { luaD_reallocCI(L, 2*L->size_ci); if (L->size_ci > LUA_MAXCALLS) - luaD_error(L, "stack overflow"); + luaD_runerror(L, "stack overflow"); } L->ci++; } @@ -278,7 +280,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { firstResult = luaV_execute(L); /* call it */ if (firstResult == NULL) { luaD_poscall(L, 0, L->top); - luaD_error(L, "attempt to `yield' across tag-method/C-call boundary"); + luaD_runerror(L, "attempt to `yield' across tag-method/C-call boundary"); } } luaD_poscall(L, nResults, firstResult); @@ -325,14 +327,17 @@ static void resume (lua_State *L, void *numres) { LUA_API int lua_resume (lua_State *L, lua_State *co) { CallInfo *ci; int numres; + TObject o; int status; lua_lock(L); ci = co->ci; if (ci == co->base_ci) /* no activation record? ?? */ - luaD_error(L, "thread is dead - cannot be resumed"); + luaD_runerror(L, "thread is dead - cannot be resumed"); if (co->errorJmp != NULL) /* ?? */ - luaD_error(L, "thread is active - cannot be resumed"); - status = luaD_runprotected(co, resume, &numres); + luaD_runerror(L, "thread is active - cannot be resumed"); + setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); + luaV_gettable(L, gt(L), &o, &o); + status = luaD_runprotected(co, resume, &o, &numres); if (status == 0) move_results(L, co->top - numres, co->top); lua_unlock(L); @@ -345,7 +350,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { lua_lock(L); ci = L->ci; if (ci_func(ci-1)->c.isC) - luaD_error(L, "cannot `yield' a C function"); + luaD_runerror(L, "cannot `yield' a C function"); ci->yield_results = nresults; lua_unlock(L); return -1; @@ -360,24 +365,23 @@ struct CallS { /* data to `f_call' */ int nresults; }; + static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); luaD_call(L, c->func, c->nresults); } -LUA_API int lua_call (lua_State *L, int nargs, int nresults) { +int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { struct CallS c; int status; - lua_lock(L); c.func = L->top - (nargs+1); /* function to be called */ c.nresults = nresults; - status = luaD_runprotected(L, f_call, &c); + status = luaD_runprotected(L, &f_call, err, &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 */ } - lua_unlock(L); return status; } @@ -400,8 +404,9 @@ static void f_parser (lua_State *L, void *ud) { } -static int protectedparser (lua_State *L, ZIO *z, int bin) { +int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { struct SParser p; + TObject o; lu_mem old_blocks; int status; lua_lock(L); @@ -410,7 +415,9 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { if (G(L)->nblocks/8 >= G(L)->GCthreshold/10) luaC_collectgarbage(L); old_blocks = G(L)->nblocks; - status = luaD_runprotected(L, f_parser, &p); + setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); + luaV_gettable(L, gt(L), &o, &o); + status = luaD_runprotected(L, f_parser, &o, &p); if (status == 0) { /* add new memory to threshold (as it probably will stay) */ lua_assert(G(L)->nblocks >= old_blocks); @@ -423,47 +430,6 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { } -LUA_API int lua_loadfile (lua_State *L, const char *filename) { - ZIO z; - int status; - int bin; /* flag for file mode */ - int nlevel; /* level on the stack of filename */ - FILE *f = (filename == NULL) ? stdin : fopen(filename, "r"); - if (f == NULL) return LUA_ERRFILE; /* unable to open file */ - bin = (ungetc(getc(f), f) == LUA_SIGNATURE[0]); - if (bin && f != stdin) { - fclose(f); - f = fopen(filename, "rb"); /* reopen in binary mode */ - if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ - } - if (filename == NULL) - lua_pushstring(L, "=stdin"); - else { - lua_pushliteral(L, "@"); - lua_pushstring(L, filename); - lua_concat(L, 2); - } - nlevel = lua_gettop(L); - filename = lua_tostring(L, -1); /* filename = `@'..filename */ - luaZ_Fopen(&z, f, filename); - status = protectedparser(L, &z, bin); - if (ferror(f)) status = LUA_ERRFILE; - lua_remove(L, nlevel); /* remove filename */ - if (f != stdin) - fclose(f); - return status; -} - - -LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { - ZIO z; - if (!name) name = "?"; - luaZ_mopen(&z, buff, size, name); - return protectedparser(L, &z, buff[0]==LUA_SIGNATURE[0]); -} - - /* ** {====================================================== @@ -472,16 +438,14 @@ LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size, */ -static void message (lua_State *L, const char *s) { - TObject o, m; - setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); - luaV_gettable(L, gt(L), &o, &m); - if (ttype(&m) == LUA_TFUNCTION) { - setobj(L->top, &m); +static void message (lua_State *L, const char *msg) { + TObject *m = &L->errorJmp->err; + if (ttype(m) == LUA_TFUNCTION) { + setobj(L->top, m); incr_top(L); - setsvalue(L->top, luaS_new(L, s)); + setsvalue(L->top, luaS_new(L, msg)); incr_top(L); - luaD_call(L, L->top-2, 0); + luaD_call(L, L->top - 2, 0); } } @@ -489,15 +453,10 @@ static void message (lua_State *L, const char *s) { /* ** Reports an error, and jumps up to the available recovery label */ -void luaD_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) { +void luaD_error (lua_State *L, const char *s, int errcode) { if (L->errorJmp) { L->errorJmp->status = errcode; + if (s) message(L, s); longjmp(L->errorJmp->b, 1); } else { @@ -507,12 +466,18 @@ void luaD_breakrun (lua_State *L, int errcode) { } -int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { +void luaD_runerror (lua_State *L, const char *s) { + luaD_error(L, s, LUA_ERRRUN); +} + + +int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud) { struct lua_longjmp lj; lj.ci = L->ci; lj.top = L->top; lj.allowhooks = L->allowhooks; lj.status = 0; + lj.err = *err; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; if (setjmp(lj.b) == 0) -- cgit v1.2.3-55-g6feb