From ee4859b3e3db6c1a3223669d15538b3852ca4791 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 22 Apr 2002 11:40:50 -0300 Subject: [PATCH] new way to handle errors (temporary version) --- lapi.c | 92 ++++++++++++++++++++++++++++++++++++++++------- ldblib.c | 4 +-- ldo.c | 107 +++++++++++++++++++------------------------------------ ldo.h | 14 +++++--- lua.c | 10 +++--- 5 files changed, 133 insertions(+), 94 deletions(-) diff --git a/lapi.c b/lapi.c index 72f38c93..4eeada6c 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.183 2002/04/05 18:54:31 roberto Exp roberto $ +** $Id: lapi.c,v 1.184 2002/04/16 17:08:28 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -19,6 +19,7 @@ #include "lstring.h" #include "ltable.h" #include "ltm.h" +#include "lundump.h" #include "lvm.h" @@ -528,22 +529,48 @@ LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) { } -LUA_API int lua_dofile (lua_State *L, const char *filename) { +LUA_API int lua_call (lua_State *L, int nargs, int nresults) { int status; - status = lua_loadfile(L, filename); - if (status == 0) /* parse OK? */ - status = lua_call(L, 0, LUA_MULTRET); /* call main */ + int errpos = lua_gettop(L) - nargs; + lua_getglobal(L, "_ERRORMESSAGE"); + lua_insert(L, errpos); /* put below function and args */ + status = lua_pcall(L, nargs, nresults, errpos); + lua_remove(L, errpos); return status; } +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf) { + int status; + const TObject *err; + lua_lock(L); + err = (errf == 0) ? &luaO_nilobject : luaA_index(L, errf); + status = luaD_pcall(L, nargs, nresults, err); + lua_unlock(L); + return status; +} + + +static int aux_do (lua_State *L, int status) { + if (status == 0) { /* parse OK? */ + int err = lua_gettop(L); + lua_getglobal(L, "_ERRORMESSAGE"); + lua_insert(L, err); + status = lua_pcall(L, 0, LUA_MULTRET, err); /* call main */ + lua_remove(L, err); /* remove error function */ + } + return status; +} + + +LUA_API int lua_dofile (lua_State *L, const char *filename) { + return aux_do(L, lua_loadfile(L, filename)); +} + + LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) { - int status; - status = lua_loadbuffer(L, buff, size, name); - if (status == 0) /* parse OK? */ - status = lua_call(L, 0, LUA_MULTRET); /* call main */ - return status; + return aux_do(L, lua_loadbuffer(L, buff, size, name)); } @@ -552,6 +579,47 @@ LUA_API int lua_dostring (lua_State *L, const char *str) { } +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 = luaD_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 luaD_protectedparser(L, &z, buff[0]==LUA_SIGNATURE[0]); +} + + /* ** Garbage-collection functions @@ -595,7 +663,7 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { LUA_API void lua_error (lua_State *L, const char *s) { lua_lock(L); - luaD_error(L, s); + luaD_runerror(L, s); lua_unlock(L); } @@ -662,7 +730,7 @@ LUA_API void lua_concat (lua_State *L, int n) { L->top -= (n-1); luaC_checkGC(L); } - else if (n == 0) { /* push null string */ + else if (n == 0) { /* push empty string */ setsvalue(L->top, luaS_newlstr(L, NULL, 0)); api_incr_top(L); } diff --git a/ldblib.c b/ldblib.c index dec973e6..c38cf419 100644 --- a/ldblib.c +++ b/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.46 2002/04/02 20:41:59 roberto Exp roberto $ +** $Id: ldblib.c,v 1.47 2002/04/09 19:48:08 roberto Exp roberto $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -265,7 +265,7 @@ static const luaL_reg dblib[] = { LUALIB_API int lua_dblibopen (lua_State *L) { luaL_opennamedlib(L, "dbg", dblib, 0); - lua_register(L, LUA_ERRORMESSAGE, errorfb); + lua_register(L, "_ERRORMESSAGE", errorfb); return 0; } 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) diff --git a/ldo.h b/ldo.h index 2eb5f43b..5464e544 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.41 2002/03/20 12:52:32 roberto Exp roberto $ +** $Id: ldo.h,v 1.42 2002/03/25 17:47:14 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -10,6 +10,7 @@ #include "lobject.h" #include "lstate.h" +#include "lzio.h" /* @@ -27,17 +28,22 @@ #define restorestack(L,n) ((TObject *)((char *)L->stack + (n))) +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *v); + +int luaD_protectedparser (lua_State *L, ZIO *z, int bin); void luaD_lineHook (lua_State *L, int line); StkId luaD_precall (lua_State *L, StkId func); void luaD_call (lua_State *L, StkId func, int nResults); +int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err); void luaD_poscall (lua_State *L, int wanted, StkId firstResult); void luaD_reallocCI (lua_State *L, int newsize); void luaD_reallocstack (lua_State *L, int newsize); void luaD_growstack (lua_State *L, int n); -void luaD_error (lua_State *L, const char *s); -void luaD_breakrun (lua_State *L, int errcode); -int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); +void luaD_error (lua_State *L, const char *s, int errcode); +void luaD_runerror (lua_State *L, const char *s); +int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud); #endif diff --git a/lua.c b/lua.c index 03cfbb9d..fbeaf239 100644 --- a/lua.c +++ b/lua.c @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.81 2002/04/05 18:54:31 roberto Exp roberto $ +** $Id: lua.c,v 1.82 2002/04/09 20:19:06 roberto Exp roberto $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -200,16 +200,16 @@ static int trap_eof (lua_State *l) { static int load_string (void) { - lua_getglobal(L, LUA_ERRORMESSAGE); + lua_getglobal(L, "_ERRORMESSAGE"); lua_pushvalue(L, 1); - lua_setglobal(L, LUA_ERRORMESSAGE); + lua_setglobal(L, "_ERRORMESSAGE"); incomplete = 0; for (;;) { /* repeat until gets a complete line */ int result; char *buffer = readline(get_prompt(incomplete)); if (buffer == NULL) { /* input end? */ lua_settop(L, 2); - lua_setglobal(L, LUA_ERRORMESSAGE); + lua_setglobal(L, "_ERRORMESSAGE"); return 0; } if (!incomplete && buffer[0] == '=') { @@ -225,7 +225,7 @@ static int load_string (void) { lua_remove(L, 3); if (result == 0) { lua_insert(L, 2); /* swap compiled chunk with old _ERRORMESSAGE */ - lua_setglobal(L, LUA_ERRORMESSAGE); /* restore old _ERRORMESSAGE */ + lua_setglobal(L, "_ERRORMESSAGE"); /* restore old _ERRORMESSAGE */ return 1; } else