summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-06-18 12:19:27 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-06-18 12:19:27 -0300
commit1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b (patch)
treee845de9ee24b94362146e38410ae0670df18526b
parent8f080fd683d63b0cd4b38380f6a5bdae5d6e2584 (diff)
downloadlua-github-1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b.tar.gz
new protocol for error handling
-rw-r--r--lapi.c12
-rw-r--r--lauxlib.c49
-rw-r--r--lauxlib.h6
-rw-r--r--lbaselib.c54
-rw-r--r--ldebug.c45
-rw-r--r--ldebug.h3
-rw-r--r--ldo.c91
-rw-r--r--ldo.h7
-rw-r--r--llex.c4
-rw-r--r--lmem.c4
-rw-r--r--lstate.c10
-rw-r--r--ltests.c37
-rw-r--r--lua.h14
13 files changed, 178 insertions, 158 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<n; i++) {
ref = lua_ref(L, 1);
diff --git a/ldebug.c b/ldebug.c
index f2de75a1..cd8d481d 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -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
** See Copyright Notice in lua.h
*/
#include <stdlib.h>
+#include <string.h>
#include "lua.h"
@@ -510,18 +511,42 @@ void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2) {
}
+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);
+ }
+}
+
+
+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, ...) {
- const char *msg;
va_list argp;
va_start(argp, fmt);
- msg = luaO_pushvfstring(L, fmt, argp);
+ 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);
- }
- luaD_error(L, msg, LUA_ERRRUN);
+ 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))