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
** 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 */
}

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
** 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;
}

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
** 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,

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
** 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);

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
** 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) {
}
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);
}

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
** 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);

89
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
** 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 */
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;
}
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);
}
}
/*
** 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;

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
** 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);

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
** 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);
}

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
** 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! */
}
}

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
** 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);
}

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
** 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},

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
** 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))