From 1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 18 Jun 2002 12:19:27 -0300 Subject: [PATCH] new protocol for error handling --- lapi.c | 12 +++---- lauxlib.c | 49 +++++++++-------------------- lauxlib.h | 6 ++-- lbaselib.c | 54 ++++++++++++++------------------ ldebug.c | 51 ++++++++++++++++++++++-------- ldebug.h | 3 +- ldo.c | 91 +++++++++++++++++++++++++----------------------------- ldo.h | 7 ++--- llex.c | 4 +-- lmem.c | 4 +-- lstate.c | 10 +++--- ltests.c | 37 +++++++++++++++++++--- lua.h | 14 +++++---- 13 files changed, 181 insertions(+), 161 deletions(-) diff --git a/lapi.c b/lapi.c index d2600972..0d27a7e8 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.198 2002/06/13 13:39:55 roberto Exp roberto $ +** $Id: lapi.c,v 1.199 2002/06/13 13:44:50 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -565,12 +565,10 @@ LUA_API void lua_upcall (lua_State *L, int nargs, int nresults) { } -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf) { +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults) { int status; - const TObject *err; lua_lock(L); - err = (errf == 0) ? &luaO_nilobject : luaA_index(L, errf); - status = luaD_pcall(L, nargs, nresults, err); + status = luaD_pcall(L, nargs, nresults); lua_unlock(L); return status; } @@ -631,10 +629,10 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { */ -LUA_API int lua_errorobj (lua_State *L) { +LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); - luaD_errorobj(L, L->top - 1, LUA_ERRRUN); + luaG_errormsg(L, 0); lua_unlock(L); return 0; /* to avoid warnings */ } diff --git a/lauxlib.c b/lauxlib.c index 51561746..81150cd4 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.73 2002/06/05 16:59:37 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.74 2002/06/13 13:44:50 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -40,13 +40,13 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { if (strcmp(ar.namewhat, "method") == 0) { narg--; /* do not count `self' */ if (narg == 0) /* error is in the self argument itself? */ - return luaL_verror(L, + return luaL_error(L, "calling %s on bad self (perhaps using `:' instead of `.')", ar.name); } if (ar.name == NULL) ar.name = "?"; - return luaL_verror(L, "bad argument #%d to `%s' (%s)", + return luaL_error(L, "bad argument #%d to `%s' (%s)", narg, ar.name, extramsg); } @@ -63,19 +63,12 @@ static void tag_error (lua_State *L, int narg, int tag) { } -LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...) { - lua_Debug ar; - const char *msg; +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); - msg = lua_pushvfstring(L, fmt, argp); + lua_pushvfstring(L, fmt, argp); va_end(argp); - if (lua_getstack(L, 1, &ar)) { /* check calling function */ - lua_getinfo(L, "Snl", &ar); - if (ar.currentline > 0) - lua_pushfstring(L, "%s:%d: %s", ar.short_src, ar.currentline, msg); - } - return lua_errorobj(L); + return lua_error(L); } /* }====================================================== */ @@ -92,7 +85,7 @@ LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) { if (!lua_checkstack(L, space)) - luaL_verror(L, "stack overflow (%s)", mes); + luaL_error(L, "stack overflow (%s)", mes); } @@ -397,35 +390,21 @@ 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 = lua_gettop(L); + 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, 0); + lua_pcall(L, 1, 0); lua_settop(L, top-1); } } -LUALIB_API int lua_call (lua_State *L, int nargs, int nresults) { - int status; - 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); - callalert(L, status); - 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 */ - } + if (status == 0) /* parse OK? */ + status = lua_pcall(L, 0, LUA_MULTRET); /* call main */ callalert(L, status); return status; } diff --git a/lauxlib.h b/lauxlib.h index 227e77a6..63db2f94 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.47 2002/05/16 18:39:46 roberto Exp roberto $ +** $Id: lauxlib.h,v 1.48 2002/06/03 20:11:41 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -44,7 +44,8 @@ LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *msg); LUALIB_API void luaL_check_type (lua_State *L, int narg, int t); LUALIB_API void luaL_check_any (lua_State *L, int narg); -LUALIB_API int luaL_verror (lua_State *L, const char *fmt, ...); +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...); + LUALIB_API int luaL_findstring (const char *name, const char *const list[]); @@ -117,7 +118,6 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B); #define luaL_checktype luaL_check_type #define luaL_checkany luaL_check_any -LUALIB_API int lua_call (lua_State *L, int nargs, int nresults); LUALIB_API int lua_dofile (lua_State *L, const char *filename); LUALIB_API int lua_dostring (lua_State *L, const char *str); LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, diff --git a/lbaselib.c b/lbaselib.c index 13739a92..14843ace 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.80 2002/06/13 13:39:55 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.81 2002/06/13 13:44:50 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ static int luaB_print (lua_State *L) { lua_upcall(L, 1, 1); s = lua_tostring(L, -1); /* get result */ if (s == NULL) - return luaL_verror(L, "`tostring' must return a string to `print'"); + return luaL_error(L, "`tostring' must return a string to `print'"); if (i>1) fputs("\t", stdout); fputs(s, stdout); lua_pop(L, 1); /* pop result */ @@ -76,8 +76,8 @@ static int luaB_tonumber (lua_State *L) { static int luaB_error (lua_State *L) { - lua_settop(L, 1); - return lua_errorobj(L); + luaL_check_any(L, 1); + return lua_error(L); } @@ -193,9 +193,10 @@ static int luaB_nexti (lua_State *L) { static int passresults (lua_State *L, int status) { if (status == 0) return 1; else { + int numres = (status == LUA_ERRRUN) ? 3 : 2; lua_pushnil(L); - lua_insert(L, -2); - return 2; + lua_insert(L, -numres); + return numres; } } @@ -217,7 +218,7 @@ static int luaB_loadfile (lua_State *L) { static int luaB_assert (lua_State *L) { luaL_check_any(L, 1); if (!lua_toboolean(L, 1)) - return luaL_verror(L, "%s", luaL_opt_string(L, 2, "assertion failed!")); + return luaL_error(L, "%s", luaL_opt_string(L, 2, "assertion failed!")); lua_settop(L, 1); return 1; } @@ -234,25 +235,10 @@ static int luaB_unpack (lua_State *L) { } -static int luaB_xpcall (lua_State *L) { - int status; - luaL_check_any(L, 1); - luaL_check_any(L, 2); - status = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET, 1); - if (status != 0) - return passresults(L, status); - else { - lua_pushboolean(L, 1); - lua_replace(L, 1); - return lua_gettop(L); /* return `true' + all results */ - } -} - - static int luaB_pcall (lua_State *L) { int status; luaL_check_any(L, 1); - status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET); if (status != 0) return passresults(L, status); else { @@ -362,7 +348,7 @@ static int luaB_require (lua_State *L) { lua_pushvalue(L, 1); lua_setglobal(L, "_REQUIREDNAME"); lua_getglobal(L, REQTAB); - if (!lua_istable(L, 2)) return luaL_verror(L, REQTAB " is not a table"); + if (!lua_istable(L, 2)) return luaL_error(L, REQTAB " is not a table"); path = getpath(L); lua_pushvalue(L, 1); /* check package's name in book-keeping table */ lua_gettable(L, 2); @@ -385,11 +371,11 @@ static int luaB_require (lua_State *L) { return 0; } case LUA_ERRFILE: { /* file not found */ - return luaL_verror(L, "could not load package `%s' from path `%s'", + return luaL_error(L, "could not load package `%s' from path `%s'", lua_tostring(L, 1), getpath(L)); } default: { - return luaL_verror(L, "error loading package\n%s", lua_tostring(L, -1)); + return luaL_error(L, "error loading package\n%s", lua_tostring(L, -1)); } } } @@ -413,7 +399,6 @@ static const luaL_reg base_funcs[] = { {"rawget", luaB_rawget}, {"rawset", luaB_rawset}, {"pcall", luaB_pcall}, - {"xpcall", luaB_xpcall}, {"collectgarbage", luaB_collectgarbage}, {"gcinfo", luaB_gcinfo}, {"loadfile", luaB_loadfile}, @@ -432,9 +417,18 @@ static const luaL_reg base_funcs[] = { static int luaB_resume (lua_State *L) { lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1)); + int status; lua_settop(L, 0); - if (lua_resume(L, co) != 0) - return lua_errorobj(L); + status = lua_resume(L, co); + if (status != 0) { + if (status == LUA_ERRRUN) { + if (lua_isstring(L, -1) && lua_isstring(L, -2)) + lua_concat(L, 2); + else + lua_pop(L, 1); + } + return lua_error(L); + } return lua_gettop(L); } @@ -455,7 +449,7 @@ static int luaB_coroutine (lua_State *L) { luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected"); NL = lua_newthread(L); - if (NL == NULL) return luaL_verror(L, "unable to create new thread"); + if (NL == NULL) return luaL_error(L, "unable to create new thread"); /* move function and arguments from L to NL */ for (i=0; i +#include #include "lua.h" @@ -510,18 +511,42 @@ void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) { } -void luaG_runerror (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - if (isLmark(L->ci)) { - char buff[LUA_IDSIZE]; - int line = currentline(L, L->ci); - luaO_chunkid(buff, getstr(getluaproto(L->ci)->source), LUA_IDSIZE); - msg = luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +static void addinfo (lua_State *L, int internal) { + CallInfo *ci = (internal) ? L->ci : L->ci - 1; + const char *msg = svalue(L->top - 1); + if (strchr(msg, '\n')) return; /* message already `formatted' */ + if (!isLmark(ci)) { /* no Lua code? */ + luaO_pushfstring(L, "%s\n", msg); /* no extra info */ + } + else { /* add file:line information */ + char buff[LUA_IDSIZE]; + int line = currentline(L, ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s\n", buff, line, msg); } - luaD_error(L, msg, LUA_ERRRUN); +} + + +void luaG_errormsg (lua_State *L, int internal) { + const TObject *errfunc; + if (ttype(L->top - 1) == LUA_TSTRING) + addinfo(L, internal); + errfunc = luaH_getstr(hvalue(registry(L)), luaS_new(L, LUA_TRACEBACK)); + if (ttype(errfunc) != LUA_TNIL) { /* is there an error function? */ + setobj(L->top, errfunc); /* push function */ + setobj(L->top + 1, L->top - 1); /* push error message */ + L->top += 2; + luaD_call(L, L->top - 2, 1); /* call error function? */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaO_pushvfstring(L, fmt, argp); + va_end(argp); + luaG_errormsg(L, 1); } diff --git a/ldebug.h b/ldebug.h index ef0a046f..cb168743 100644 --- a/ldebug.h +++ b/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 1.20 2002/05/02 13:06:20 roberto Exp roberto $ +** $Id: ldebug.h,v 1.21 2002/05/15 18:57:44 roberto Exp roberto $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -21,6 +21,7 @@ void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2); void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); void luaG_runerror (lua_State *L, const char *fmt, ...); +void luaG_errormsg (lua_State *L, int internal); int luaG_checkcode (const Proto *pt); diff --git a/ldo.c b/ldo.c index e6eba7d1..c47fdac2 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.178 2002/06/03 17:46:34 roberto Exp roberto $ +** $Id: ldo.c,v 1.179 2002/06/03 20:12:50 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -37,10 +37,16 @@ struct lua_longjmp { jmp_buf b; int allowhooks; /* `allowhook' state when protection was set */ volatile int status; /* error code */ - TObject *err; /* error function -> message (start of `ud') */ + 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 correctstack (lua_State *L, TObject *oldstack) { struct lua_longjmp *lj; @@ -109,7 +115,7 @@ 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_error(L, "error in error handling", LUA_ERRERR); + luaD_throw(L, LUA_ERRERR); else { luaD_reallocCI(L, 2*L->size_ci); if (L->size_ci > LUA_MAXCALLS) @@ -302,7 +308,7 @@ static void move_results (lua_State *L, TObject *from, TObject *to) { struct ResS { - TObject err; + TObject err[2]; int numres; }; @@ -337,17 +343,11 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) { luaG_runerror(L, "thread is dead - cannot be resumed"); if (co->errorJmp != NULL) /* ?? */ luaG_runerror(L, "thread is active - cannot be resumed"); - if (L->errorJmp) { - setobj(&ud.err, L->errorJmp->err); - } - else - setnilvalue(&ud.err); - status = luaD_runprotected(co, resume, &ud.err); + status = luaD_runprotected(co, resume, ud.err); if (status == 0) move_results(L, co->top - ud.numres, co->top); - else { - setobj(L->top++, &ud.err); -} + else + pusherrormsg(L, status, ud.err); lua_unlock(L); return status; } @@ -369,7 +369,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { ** Execute a protected call. */ struct CallS { /* data to `f_call' */ - TObject err; /* error field... */ + TObject err[2]; StkId func; int nresults; }; @@ -381,17 +381,16 @@ static void f_call (lua_State *L, void *ud) { } -int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { +int luaD_pcall (lua_State *L, int nargs, int nresults) { struct CallS c; int status; c.func = L->top - (nargs+1); /* function to be called */ c.nresults = nresults; - c.err = *err; - status = luaD_runprotected(L, &f_call, &c.err); + status = luaD_runprotected(L, &f_call, c.err); 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 */ - setobj(L->top++, &c.err); + pusherrormsg(L, status, c.err); } return status; } @@ -401,7 +400,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { ** Execute a protected parser. */ struct SParser { /* data to `f_parser' */ - TObject err; /* error field... */ + TObject err[2]; ZIO *z; int bin; }; @@ -425,15 +424,14 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold) luaC_collectgarbage(L); old_blocks = G(L)->nblocks; - setnilvalue(&p.err); - status = luaD_runprotected(L, f_parser, &p.err); + status = luaD_runprotected(L, f_parser, p.err); 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 - setobj(L->top++, &p.err); + pusherrormsg(L, status, p.err); return status; } @@ -445,29 +443,34 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { ** ======================================================= */ - -static void message (lua_State *L, const TObject *msg, int nofunc) { - TObject *m = L->errorJmp->err; - if (nofunc || ttype(m) != LUA_TFUNCTION) { /* no error function? */ - setobj(m, msg); /* keep error message */ - } - else { /* call error function */ - setobj(L->top, m); - setobj(L->top + 1, msg); - L->top += 2; - luaD_call(L, L->top - 2, 1); - setobj(m, L->top - 1); +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; + } } } -/* -** Reports an error, and jumps up to the available recovery label -*/ -void luaD_errorobj (lua_State *L, const TObject *s, int errcode) { +void luaD_throw (lua_State *L, int errcode) { + seterrorobj(L, errcode, L->errorJmp->err); if (L->errorJmp) { L->errorJmp->status = errcode; - message(L, s, (errcode >= LUA_ERRMEM)); longjmp(L->errorJmp->b, 1); } else { @@ -477,16 +480,6 @@ void luaD_errorobj (lua_State *L, const TObject *s, int errcode) { } -void luaD_error (lua_State *L, const char *s, int errcode) { - TObject errobj; - if (errcode == LUA_ERRMEM && (G(L) == NULL || G(L)->GCthreshold == 0)) - setnilvalue(&errobj); /* error bulding state */ - else - setsvalue(&errobj, luaS_new(L, s)); - luaD_errorobj(L, &errobj, errcode); -} - - int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) { struct lua_longjmp lj; lj.ci = L->ci; diff --git a/ldo.h b/ldo.h index 914eddaa..4ff39092 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.44 2002/05/01 20:40:42 roberto Exp roberto $ +** $Id: ldo.h,v 1.45 2002/05/15 18:57:44 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -35,14 +35,13 @@ 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); +int luaD_pcall (lua_State *L, int nargs, int nresults); 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, int errcode); -void luaD_errorobj (lua_State *L, const TObject *s, int errcode); +void luaD_throw (lua_State *L, int errcode); int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud); diff --git a/llex.c b/llex.c index 14dc2902..7f634757 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.103 2002/06/03 14:09:57 roberto Exp roberto $ +** $Id: llex.c,v 1.104 2002/06/03 20:12:21 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -61,7 +61,7 @@ static void luaX_error (LexState *ls, const char *s, const char *token) { char buff[MAXSRC]; luaO_chunkid(buff, getstr(ls->source), MAXSRC); luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, ls->linenumber, s, token); - luaD_errorobj(L, L->top - 1, LUA_ERRSYNTAX); + luaD_throw(L, LUA_ERRSYNTAX); } diff --git a/lmem.c b/lmem.c index 00c7253b..369b1812 100644 --- a/lmem.c +++ b/lmem.c @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.55 2002/05/15 18:57:44 roberto Exp roberto $ +** $Id: lmem.c,v 1.56 2002/06/11 16:23:47 roberto Exp roberto $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -66,7 +66,7 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem oldsize, lu_mem size) { block = l_realloc(block, oldsize, size); if (block == NULL) { if (L) - luaD_error(L, MEMERRMSG, LUA_ERRMEM); + luaD_throw(L, LUA_ERRMEM); else return NULL; /* error before creating state! */ } } diff --git a/lstate.c b/lstate.c index 45f534ca..2d4bc94c 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.95 2002/06/03 14:09:57 roberto Exp roberto $ +** $Id: lstate.c,v 1.96 2002/06/06 18:17:33 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -7,6 +7,7 @@ #include "lua.h" +#include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" @@ -122,14 +123,13 @@ LUA_API lua_State *lua_newthread (lua_State *OL) { LUA_API lua_State *lua_open (void) { lua_State *L; - TObject dummy; - setnilvalue(&dummy); + 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_runprotected(L, f_luaopen, dummy) != 0) { /* memory allocation error: free partial state */ close_state(L); L = NULL; @@ -169,8 +169,8 @@ static void close_state (lua_State *L) { LUA_API void lua_closethread (lua_State *L, lua_State *thread) { - if (L == thread) lua_error(L, "cannot close only thread of a state"); lua_lock(L); + if (L == thread) luaG_runerror(L, "cannot close only thread of a state"); luaE_closethread(L, thread); lua_unlock(L); } diff --git a/ltests.c b/ltests.c index 2cc66bca..3496a2b1 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.124 2002/06/11 16:23:47 roberto Exp roberto $ +** $Id: ltests.c,v 1.125 2002/06/13 13:44:50 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -338,6 +338,34 @@ static int string_query (lua_State *L) { } +static int xpcall (lua_State *L) { + int status; + luaL_check_type(L, 1, LUA_TFUNCTION); + luaL_check_any(L, 2); + lua_pushliteral(L, LUA_TRACEBACK); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_pushliteral(L, LUA_TRACEBACK); + lua_pushvalue(L, 1); + lua_settable(L, LUA_REGISTRYINDEX); + lua_replace(L, 1); + status = lua_pcall(L, lua_gettop(L) - 2, LUA_MULTRET); + lua_pushliteral(L, LUA_TRACEBACK); + lua_pushvalue(L, 1); + lua_settable(L, LUA_REGISTRYINDEX); + if (status != 0) { + int numres = (status == LUA_ERRRUN) ? 3 : 2; + lua_pushnil(L); + lua_insert(L, -numres); + return numres; + } + else { + lua_pushboolean(L, 1); + lua_insert(L, 2); + return lua_gettop(L) - 1; /* return `true' + all results */ + } +} + + static int tref (lua_State *L) { int level = lua_gettop(L); int lock = luaL_opt_int(L, 2, 1); @@ -402,7 +430,7 @@ static int doonnewstack (lua_State *L) { const char *s = luaL_check_lstr(L, 1, &l); int status = luaL_loadbuffer(L1, s, l, s); if (status == 0) - status = lua_pcall(L1, 0, 0, 0); + status = lua_pcall(L1, 0, 0); lua_pushnumber(L, status); lua_closethread(L, L1); return 1; @@ -639,7 +667,7 @@ static int testC (lua_State *L) { else if EQ("call") { int narg = getnum; int nres = getnum; - lua_call(L, narg, nres); + lua_pcall(L, narg, nres); } else if EQ("loadstring") { size_t sl; @@ -659,7 +687,7 @@ static int testC (lua_State *L) { else if EQ("type") { lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); } - else luaL_verror(L, "unknown instruction %s", buff); + else luaL_error(L, "unknown instruction %s", buff); } return 0; } @@ -677,6 +705,7 @@ static const struct luaL_reg tests_funcs[] = { {"loadlib", loadlib}, {"stacklevel", stacklevel}, {"querystr", string_query}, + {"xpcall", xpcall}, {"querytab", table_query}, {"testC", testC}, {"ref", tref}, diff --git a/lua.h b/lua.h index 5c1de5f6..fd2856e8 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.139 2002/06/13 13:39:55 roberto Exp roberto $ +** $Id: lua.h,v 1.140 2002/06/13 13:44:50 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** http://www.lua.org mailto:info@lua.org @@ -29,6 +29,9 @@ #define LUA_MULTRET (-1) +/* index for a traceback function in the registry */ +#define LUA_TRACEBACK "_TRACEBACK" + /* ** pseudo-indices */ @@ -43,6 +46,7 @@ #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 #define LUA_ERRERR 5 +#define LUA_ERRTHROW 6 typedef struct lua_State lua_State; @@ -180,7 +184,7 @@ LUA_API void lua_setmetatable (lua_State *L, int objindex); ** `load' and `call' functions (load and run Lua code) */ LUA_API void lua_upcall (lua_State *L, int nargs, int nresults); -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errf); +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults); LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, const char *chunkname); @@ -203,7 +207,7 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); ** miscellaneous functions */ -LUA_API int lua_errorobj (lua_State *L); +LUA_API int lua_error (lua_State *L); LUA_API int lua_next (lua_State *L, int index); LUA_API int lua_getn (lua_State *L, int index); @@ -220,8 +224,6 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size); ** =============================================================== */ -#define lua_error(L,s) (lua_pushstring(L, s), lua_errorobj(L)) - #define lua_newpointerbox(L,u) \ (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u)) @@ -275,7 +277,7 @@ LUA_API int lua_pushupvalues (lua_State *L); #define LUA_REFNIL (-1) #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ - (lua_error(L, "unlocked references are obsolete"), 0)) + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))