new protocol for error handling

This commit is contained in:
Roberto Ierusalimschy 2002-06-18 12:19:27 -03:00
parent 8f080fd683
commit 1dbe708aa8
13 changed files with 181 additions and 161 deletions

12
lapi.c
View File

@ -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 ** Lua API
** See Copyright Notice in lua.h ** 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; int status;
const TObject *err;
lua_lock(L); lua_lock(L);
err = (errf == 0) ? &luaO_nilobject : luaA_index(L, errf); status = luaD_pcall(L, nargs, nresults);
status = luaD_pcall(L, nargs, nresults, err);
lua_unlock(L); lua_unlock(L);
return status; 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); lua_lock(L);
api_checknelems(L, 1); api_checknelems(L, 1);
luaD_errorobj(L, L->top - 1, LUA_ERRRUN); luaG_errormsg(L, 0);
lua_unlock(L); lua_unlock(L);
return 0; /* to avoid warnings */ return 0; /* to avoid warnings */
} }

View File

@ -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 ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** 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) { if (strcmp(ar.namewhat, "method") == 0) {
narg--; /* do not count `self' */ narg--; /* do not count `self' */
if (narg == 0) /* error is in the self argument itself? */ 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 `.')", "calling %s on bad self (perhaps using `:' instead of `.')",
ar.name); ar.name);
} }
if (ar.name == NULL) if (ar.name == NULL)
ar.name = "?"; 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); 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, ...) { LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
lua_Debug ar;
const char *msg;
va_list argp; va_list argp;
va_start(argp, fmt); va_start(argp, fmt);
msg = lua_pushvfstring(L, fmt, argp); lua_pushvfstring(L, fmt, argp);
va_end(argp); va_end(argp);
if (lua_getstack(L, 1, &ar)) { /* check calling function */ return lua_error(L);
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);
} }
/* }====================================================== */ /* }====================================================== */
@ -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) { LUALIB_API void luaL_check_stack (lua_State *L, int space, const char *mes) {
if (!lua_checkstack(L, space)) 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) { static void callalert (lua_State *L, int status) {
if (status != 0) { 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_getglobal(L, "_ALERT");
lua_insert(L, -2); lua_insert(L, -2);
lua_pcall(L, 1, 0, 0); lua_pcall(L, 1, 0);
lua_settop(L, top-1); 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) { static int aux_do (lua_State *L, int status) {
if (status == 0) { /* parse OK? */ if (status == 0) /* parse OK? */
int err = lua_gettop(L); status = lua_pcall(L, 0, LUA_MULTRET); /* call main */
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 */
}
callalert(L, status); callalert(L, status);
return status; return status;
} }

View File

@ -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 ** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h ** 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_type (lua_State *L, int narg, int t);
LUALIB_API void luaL_check_any (lua_State *L, int narg); 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, LUALIB_API int luaL_findstring (const char *name,
const char *const list[]); const char *const list[]);
@ -117,7 +118,6 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B);
#define luaL_checktype luaL_check_type #define luaL_checktype luaL_check_type
#define luaL_checkany luaL_check_any #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_dofile (lua_State *L, const char *filename);
LUALIB_API int lua_dostring (lua_State *L, const char *str); 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, LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,

View File

@ -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 ** Basic library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -37,7 +37,7 @@ static int luaB_print (lua_State *L) {
lua_upcall(L, 1, 1); lua_upcall(L, 1, 1);
s = lua_tostring(L, -1); /* get result */ s = lua_tostring(L, -1); /* get result */
if (s == NULL) 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); if (i>1) fputs("\t", stdout);
fputs(s, stdout); fputs(s, stdout);
lua_pop(L, 1); /* pop result */ lua_pop(L, 1); /* pop result */
@ -76,8 +76,8 @@ static int luaB_tonumber (lua_State *L) {
static int luaB_error (lua_State *L) { static int luaB_error (lua_State *L) {
lua_settop(L, 1); luaL_check_any(L, 1);
return lua_errorobj(L); return lua_error(L);
} }
@ -193,9 +193,10 @@ static int luaB_nexti (lua_State *L) {
static int passresults (lua_State *L, int status) { static int passresults (lua_State *L, int status) {
if (status == 0) return 1; if (status == 0) return 1;
else { else {
int numres = (status == LUA_ERRRUN) ? 3 : 2;
lua_pushnil(L); lua_pushnil(L);
lua_insert(L, -2); lua_insert(L, -numres);
return 2; return numres;
} }
} }
@ -217,7 +218,7 @@ static int luaB_loadfile (lua_State *L) {
static int luaB_assert (lua_State *L) { static int luaB_assert (lua_State *L) {
luaL_check_any(L, 1); luaL_check_any(L, 1);
if (!lua_toboolean(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); lua_settop(L, 1);
return 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) { static int luaB_pcall (lua_State *L) {
int status; int status;
luaL_check_any(L, 1); 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) if (status != 0)
return passresults(L, status); return passresults(L, status);
else { else {
@ -362,7 +348,7 @@ static int luaB_require (lua_State *L) {
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
lua_setglobal(L, "_REQUIREDNAME"); lua_setglobal(L, "_REQUIREDNAME");
lua_getglobal(L, REQTAB); 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); path = getpath(L);
lua_pushvalue(L, 1); /* check package's name in book-keeping table */ lua_pushvalue(L, 1); /* check package's name in book-keeping table */
lua_gettable(L, 2); lua_gettable(L, 2);
@ -385,11 +371,11 @@ static int luaB_require (lua_State *L) {
return 0; return 0;
} }
case LUA_ERRFILE: { /* file not found */ 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)); lua_tostring(L, 1), getpath(L));
} }
default: { 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}, {"rawget", luaB_rawget},
{"rawset", luaB_rawset}, {"rawset", luaB_rawset},
{"pcall", luaB_pcall}, {"pcall", luaB_pcall},
{"xpcall", luaB_xpcall},
{"collectgarbage", luaB_collectgarbage}, {"collectgarbage", luaB_collectgarbage},
{"gcinfo", luaB_gcinfo}, {"gcinfo", luaB_gcinfo},
{"loadfile", luaB_loadfile}, {"loadfile", luaB_loadfile},
@ -432,9 +417,18 @@ static const luaL_reg base_funcs[] = {
static int luaB_resume (lua_State *L) { static int luaB_resume (lua_State *L) {
lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1)); lua_State *co = (lua_State *)lua_getfrombox(L, lua_upvalueindex(1));
int status;
lua_settop(L, 0); lua_settop(L, 0);
if (lua_resume(L, co) != 0) status = lua_resume(L, co);
return lua_errorobj(L); 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); 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, luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
"Lua function expected"); "Lua function expected");
NL = lua_newthread(L); 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 */ /* move function and arguments from L to NL */
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
ref = lua_ref(L, 1); ref = lua_ref(L, 1);

View File

@ -1,11 +1,12 @@
/* /*
** $Id: ldebug.c,v 1.118 2002/06/06 18:17:33 roberto Exp roberto $ ** $Id: ldebug.c,v 1.119 2002/06/13 13:39:55 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "lua.h" #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, ...) { static void addinfo (lua_State *L, int internal) {
const char *msg; CallInfo *ci = (internal) ? L->ci : L->ci - 1;
va_list argp; const char *msg = svalue(L->top - 1);
va_start(argp, fmt); if (strchr(msg, '\n')) return; /* message already `formatted' */
msg = luaO_pushvfstring(L, fmt, argp); if (!isLmark(ci)) { /* no Lua code? */
va_end(argp); luaO_pushfstring(L, "%s\n", msg); /* no extra info */
if (isLmark(L->ci)) { }
char buff[LUA_IDSIZE]; else { /* add file:line information */
int line = currentline(L, L->ci); char buff[LUA_IDSIZE];
luaO_chunkid(buff, getstr(getluaproto(L->ci)->source), LUA_IDSIZE); int line = currentline(L, ci);
msg = luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); 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);
} }

View File

@ -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 ** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h ** 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_aritherror (lua_State *L, StkId p1, const TObject *p2);
void luaG_ordererror (lua_State *L, const TObject *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_runerror (lua_State *L, const char *fmt, ...);
void luaG_errormsg (lua_State *L, int internal);
int luaG_checkcode (const Proto *pt); int luaG_checkcode (const Proto *pt);

91
ldo.c
View File

@ -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 ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -37,10 +37,16 @@ struct lua_longjmp {
jmp_buf b; jmp_buf b;
int allowhooks; /* `allowhook' state when protection was set */ int allowhooks; /* `allowhook' state when protection was set */
volatile int status; /* error code */ 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) { static void correctstack (lua_State *L, TObject *oldstack) {
struct lua_longjmp *lj; struct lua_longjmp *lj;
@ -109,7 +115,7 @@ void luaD_growstack (lua_State *L, int n) {
static void luaD_growCI (lua_State *L) { static void luaD_growCI (lua_State *L) {
L->ci--; L->ci--;
if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ 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 { else {
luaD_reallocCI(L, 2*L->size_ci); luaD_reallocCI(L, 2*L->size_ci);
if (L->size_ci > LUA_MAXCALLS) if (L->size_ci > LUA_MAXCALLS)
@ -302,7 +308,7 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
struct ResS { struct ResS {
TObject err; TObject err[2];
int numres; 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"); luaG_runerror(L, "thread is dead - cannot be resumed");
if (co->errorJmp != NULL) /* ?? */ if (co->errorJmp != NULL) /* ?? */
luaG_runerror(L, "thread is active - cannot be resumed"); luaG_runerror(L, "thread is active - cannot be resumed");
if (L->errorJmp) { status = luaD_runprotected(co, resume, ud.err);
setobj(&ud.err, L->errorJmp->err);
}
else
setnilvalue(&ud.err);
status = luaD_runprotected(co, resume, &ud.err);
if (status == 0) if (status == 0)
move_results(L, co->top - ud.numres, co->top); move_results(L, co->top - ud.numres, co->top);
else { else
setobj(L->top++, &ud.err); pusherrormsg(L, status, ud.err);
}
lua_unlock(L); lua_unlock(L);
return status; return status;
} }
@ -369,7 +369,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
** Execute a protected call. ** Execute a protected call.
*/ */
struct CallS { /* data to `f_call' */ struct CallS { /* data to `f_call' */
TObject err; /* error field... */ TObject err[2];
StkId func; StkId func;
int nresults; 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; struct CallS c;
int status; int status;
c.func = L->top - (nargs+1); /* function to be called */ c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults; 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? */ if (status != 0) { /* an error occurred? */
L->top -= nargs+1; /* remove parameters and func from the stack */ L->top -= nargs+1; /* remove parameters and func from the stack */
luaF_close(L, L->top); /* close eventual pending closures */ luaF_close(L, L->top); /* close eventual pending closures */
setobj(L->top++, &c.err); pusherrormsg(L, status, c.err);
} }
return status; return status;
} }
@ -401,7 +400,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
** Execute a protected parser. ** Execute a protected parser.
*/ */
struct SParser { /* data to `f_parser' */ struct SParser { /* data to `f_parser' */
TObject err; /* error field... */ TObject err[2];
ZIO *z; ZIO *z;
int bin; 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) if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold)
luaC_collectgarbage(L); luaC_collectgarbage(L);
old_blocks = G(L)->nblocks; 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) { if (status == 0) {
/* add new memory to threshold (as it probably will stay) */ /* add new memory to threshold (as it probably will stay) */
lua_assert(G(L)->nblocks >= old_blocks); lua_assert(G(L)->nblocks >= old_blocks);
G(L)->GCthreshold += (G(L)->nblocks - old_blocks); G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
} }
else else
setobj(L->top++, &p.err); pusherrormsg(L, status, p.err);
return status; return status;
} }
@ -445,29 +443,34 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
** ======================================================= ** =======================================================
*/ */
static void seterrorobj (lua_State *L, int errcode, TObject *m) {
static void message (lua_State *L, const TObject *msg, int nofunc) { switch (errcode) {
TObject *m = L->errorJmp->err; case LUA_ERRMEM: {
if (nofunc || ttype(m) != LUA_TFUNCTION) { /* no error function? */ if (G(L) != NULL && G(L)->GCthreshold > 0) /* state is OK? */
setobj(m, msg); /* keep error message */ setsvalue(&m[0], luaS_new(L, MEMERRMSG));
} break;
else { /* call error function */ }
setobj(L->top, m); case LUA_ERRERR: {
setobj(L->top + 1, msg); setsvalue(&m[0], luaS_new(L, "error in error handling"));
L->top += 2; break;
luaD_call(L, L->top - 2, 1); }
setobj(m, L->top - 1); 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) {
** Reports an error, and jumps up to the available recovery label seterrorobj(L, errcode, L->errorJmp->err);
*/
void luaD_errorobj (lua_State *L, const TObject *s, int errcode) {
if (L->errorJmp) { if (L->errorJmp) {
L->errorJmp->status = errcode; L->errorJmp->status = errcode;
message(L, s, (errcode >= LUA_ERRMEM));
longjmp(L->errorJmp->b, 1); longjmp(L->errorJmp->b, 1);
} }
else { 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) { int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
struct lua_longjmp lj; struct lua_longjmp lj;
lj.ci = L->ci; lj.ci = L->ci;

7
ldo.h
View File

@ -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 ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** 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); void luaD_lineHook (lua_State *L, int line);
StkId luaD_precall (lua_State *L, StkId func); StkId luaD_precall (lua_State *L, StkId func);
void luaD_call (lua_State *L, StkId func, int nResults); 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_poscall (lua_State *L, int wanted, StkId firstResult);
void luaD_reallocCI (lua_State *L, int newsize); void luaD_reallocCI (lua_State *L, int newsize);
void luaD_reallocstack (lua_State *L, int newsize); void luaD_reallocstack (lua_State *L, int newsize);
void luaD_growstack (lua_State *L, int n); void luaD_growstack (lua_State *L, int n);
void luaD_error (lua_State *L, const char *s, int errcode); void luaD_throw (lua_State *L, int errcode);
void luaD_errorobj (lua_State *L, const TObject *s, int errcode);
int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud); int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud);

4
llex.c
View File

@ -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 ** Lexical Analyzer
** See Copyright Notice in lua.h ** 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]; char buff[MAXSRC];
luaO_chunkid(buff, getstr(ls->source), MAXSRC); luaO_chunkid(buff, getstr(ls->source), MAXSRC);
luaO_pushfstring(L, "%s:%d: %s near `%s'", buff, ls->linenumber, s, token); 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);
} }

4
lmem.c
View File

@ -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 ** Interface to Memory Manager
** See Copyright Notice in lua.h ** 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); block = l_realloc(block, oldsize, size);
if (block == NULL) { if (block == NULL) {
if (L) if (L)
luaD_error(L, MEMERRMSG, LUA_ERRMEM); luaD_throw(L, LUA_ERRMEM);
else return NULL; /* error before creating state! */ else return NULL; /* error before creating state! */
} }
} }

View File

@ -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 ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -7,6 +7,7 @@
#include "lua.h" #include "lua.h"
#include "ldebug.h"
#include "ldo.h" #include "ldo.h"
#include "lfunc.h" #include "lfunc.h"
#include "lgc.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_API lua_State *lua_open (void) {
lua_State *L; lua_State *L;
TObject dummy; TObject dummy[2];
setnilvalue(&dummy);
L = luaM_new(NULL, lua_State); L = luaM_new(NULL, lua_State);
if (L) { /* allocation OK? */ if (L) { /* allocation OK? */
preinit_state(L); preinit_state(L);
L->l_G = NULL; L->l_G = NULL;
L->next = L->previous = L; 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 */ /* memory allocation error: free partial state */
close_state(L); close_state(L);
L = NULL; L = NULL;
@ -169,8 +169,8 @@ static void close_state (lua_State *L) {
LUA_API void lua_closethread (lua_State *L, lua_State *thread) { 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); lua_lock(L);
if (L == thread) luaG_runerror(L, "cannot close only thread of a state");
luaE_closethread(L, thread); luaE_closethread(L, thread);
lua_unlock(L); lua_unlock(L);
} }

View File

@ -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 ** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h ** 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) { static int tref (lua_State *L) {
int level = lua_gettop(L); int level = lua_gettop(L);
int lock = luaL_opt_int(L, 2, 1); 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); const char *s = luaL_check_lstr(L, 1, &l);
int status = luaL_loadbuffer(L1, s, l, s); int status = luaL_loadbuffer(L1, s, l, s);
if (status == 0) if (status == 0)
status = lua_pcall(L1, 0, 0, 0); status = lua_pcall(L1, 0, 0);
lua_pushnumber(L, status); lua_pushnumber(L, status);
lua_closethread(L, L1); lua_closethread(L, L1);
return 1; return 1;
@ -639,7 +667,7 @@ static int testC (lua_State *L) {
else if EQ("call") { else if EQ("call") {
int narg = getnum; int narg = getnum;
int nres = getnum; int nres = getnum;
lua_call(L, narg, nres); lua_pcall(L, narg, nres);
} }
else if EQ("loadstring") { else if EQ("loadstring") {
size_t sl; size_t sl;
@ -659,7 +687,7 @@ static int testC (lua_State *L) {
else if EQ("type") { else if EQ("type") {
lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); 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; return 0;
} }
@ -677,6 +705,7 @@ static const struct luaL_reg tests_funcs[] = {
{"loadlib", loadlib}, {"loadlib", loadlib},
{"stacklevel", stacklevel}, {"stacklevel", stacklevel},
{"querystr", string_query}, {"querystr", string_query},
{"xpcall", xpcall},
{"querytab", table_query}, {"querytab", table_query},
{"testC", testC}, {"testC", testC},
{"ref", tref}, {"ref", tref},

14
lua.h
View File

@ -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 ** Lua - An Extensible Extension Language
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
** http://www.lua.org mailto:info@lua.org ** http://www.lua.org mailto:info@lua.org
@ -29,6 +29,9 @@
#define LUA_MULTRET (-1) #define LUA_MULTRET (-1)
/* index for a traceback function in the registry */
#define LUA_TRACEBACK "_TRACEBACK"
/* /*
** pseudo-indices ** pseudo-indices
*/ */
@ -43,6 +46,7 @@
#define LUA_ERRSYNTAX 3 #define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4 #define LUA_ERRMEM 4
#define LUA_ERRERR 5 #define LUA_ERRERR 5
#define LUA_ERRTHROW 6
typedef struct lua_State lua_State; 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) ** `load' and `call' functions (load and run Lua code)
*/ */
LUA_API void lua_upcall (lua_State *L, int nargs, int nresults); 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, LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
const char *chunkname); const char *chunkname);
@ -203,7 +207,7 @@ LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold);
** miscellaneous functions ** 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_next (lua_State *L, int index);
LUA_API int lua_getn (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) \ #define lua_newpointerbox(L,u) \
(*(void **)(lua_newuserdata(L, sizeof(void *))) = (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_REFNIL (-1)
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ #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)) #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))