Browse Source

new (old?) error handling scheme

v5-2
Roberto Ierusalimschy 23 years ago
parent
commit
a2fa48a570
  1. 15
      lapi.c
  2. 6
      lauxlib.c
  3. 22
      lbaselib.c
  4. 27
      ldebug.c
  5. 3
      ldebug.h
  6. 63
      ldo.c
  7. 4
      ldo.h
  8. 8
      lstate.c
  9. 15
      lstate.h
  10. 12
      ltests.c
  11. 74
      lua.c
  12. 5
      lua.h

15
lapi.c

@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 1.205 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: lapi.c,v 1.206 2002/08/05 14:43:38 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@ -610,22 +610,17 @@ LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
}
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults) {
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
int status;
ptrdiff_t func;
lua_lock(L);
status = luaD_pcall(L, nargs, nresults);
func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
status = luaD_pcall(L, nargs, nresults, func);
lua_unlock(L);
return status;
}
LUA_API void lua_pcallreset (lua_State *L) {
lua_lock(L);
luaD_resetprotection(L); /* reset error handler */
lua_unlock(L);
}
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
const char *chunkname) {
ZIO z;

6
lauxlib.c

@ -1,5 +1,5 @@
/*
** $Id: lauxlib.c,v 1.78 2002/07/01 19:23:58 roberto Exp $
** $Id: lauxlib.c,v 1.79 2002/08/05 17:36:24 roberto Exp roberto $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@ -404,9 +404,7 @@ static void callalert (lua_State *L, int status) {
static int aux_do (lua_State *L, int status) {
if (status == 0) { /* parse OK? */
status = lua_pcall(L, 0, LUA_MULTRET); /* call main */
if (status != 0)
lua_pcallreset(L);
status = lua_pcall(L, 0, LUA_MULTRET, 0); /* call main */
}
callalert(L, status);
return status;

22
lbaselib.c

@ -1,5 +1,5 @@
/*
** $Id: lbaselib.c,v 1.91 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: lbaselib.c,v 1.92 2002/08/05 14:46:02 roberto Exp roberto $
** Basic library
** See Copyright Notice in lua.h
*/
@ -276,9 +276,7 @@ static int luaB_unpack (lua_State *L) {
static int luaB_pcall (lua_State *L) {
int status;
luaL_check_any(L, 1);
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET);
if (status) /* error? */
lua_pcallreset(L); /* reset error handler */
status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
lua_pushboolean(L, (status == 0));
lua_insert(L, 1);
return lua_gettop(L); /* return status + all results */
@ -287,22 +285,12 @@ static int luaB_pcall (lua_State *L) {
static int luaB_xpcall (lua_State *L) {
int status;
int ref;
luaL_check_any(L, 2);
lua_settop(L, 2);
ref = lua_ref(L, 1); /* save error function */
status = lua_pcall(L, 0, LUA_MULTRET);
if (status) { /* error? */
if (status == LUA_ERRRUN) { /* run-time error? */
lua_getref(L, ref); /* get error function */
lua_pushvalue(L, -2); /* error message */
lua_call(L, 1, 1); /* call error function */
}
lua_pcallreset(L); /* reset error handler */
}
lua_unref(L, ref); /* free reference */
lua_insert(L, 1); /* put error function under function to be called */
status = lua_pcall(L, 0, LUA_MULTRET, 1);
lua_pushboolean(L, (status == 0));
lua_insert(L, 1);
lua_replace(L, 1);
return lua_gettop(L); /* return status + all results */
}

27
ldebug.c

@ -1,5 +1,5 @@
/*
** $Id: ldebug.c,v 1.125 2002/07/16 14:26:56 roberto Exp roberto $
** $Id: ldebug.c,v 1.126 2002/08/05 14:51:21 roberto Exp roberto $
** Debug Interface
** See Copyright Notice in lua.h
*/
@ -35,7 +35,7 @@ static int isLua (CallInfo *ci) {
static int currentpc (lua_State *L, CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */
if (ci->pc && ci->pc != &luaV_callingmark)
if (ci->pc != &luaV_callingmark) /* is not calling another Lua function? */
ci->u.l.savedpc = *ci->pc; /* `pc' may not be saved; save it */
/* function's pc is saved */
return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
@ -51,19 +51,9 @@ static int currentline (lua_State *L, CallInfo *ci) {
}
/*
** save all `pc's from active Lua functions
*/
void luaG_saveallpcs (lua_State *L) {
CallInfo *ci;
/* first save all not saved `pc's */
for (ci = L->ci; ci != L->base_ci; ci--)
currentpc(L, ci); /* save `pc', if necessary */
}
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) {
int allow;
CallInfo *ci;
lua_lock(L);
allow = allowhook(L);
if (func == NULL) mask = 0;
@ -72,7 +62,8 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) {
L->hookmask = mask;
setallowhook(L, allow);
resethookcount(L);
luaG_saveallpcs(L);
for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */
currentpc(L, ci);
lua_unlock(L);
return 1;
}
@ -547,6 +538,14 @@ static void addinfo (lua_State *L, int internal) {
void luaG_errormsg (lua_State *L, int internal) {
if (ttisstring(L->top - 1))
addinfo(L, internal);
if (L->errfunc != 0) { /* is there an error handling function? */
StkId errfunc = restorestack(L, L->errfunc);
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
setobj(L->top, L->top - 1); /* move argument */
setobj(L->top - 1, errfunc); /* push function */
incr_top(L);
luaD_call(L, L->top - 2, 1); /* call it */
}
luaD_throw(L, LUA_ERRRUN);
}

3
ldebug.h

@ -1,5 +1,5 @@
/*
** $Id: ldebug.h,v 1.25 2002/07/08 20:22:08 roberto Exp roberto $
** $Id: ldebug.h,v 1.26 2002/08/05 14:51:21 roberto Exp roberto $
** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h
*/
@ -23,7 +23,6 @@
#define allowhook(L) ((L->hookmask) & 1)
void luaG_saveallpcs (lua_State *L);
void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);

63
ldo.c

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 1.188 2002/07/16 14:26:56 roberto Exp roberto $
** $Id: ldo.c,v 1.189 2002/08/05 17:36:24 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -64,9 +64,6 @@ static void seterrorobj (lua_State *L, int errcode) {
void luaD_throw (lua_State *L, int errcode) {
if (errcode == LUA_ERRRUN)
luaD_checkstack(L, LUA_MINSTACK); /* ensure stack space to handle error */
luaG_saveallpcs(L); /* C stack will disapear */
if (L->errorJmp) {
L->errorJmp->status = errcode;
longjmp(L->errorJmp->b, 1);
@ -99,30 +96,6 @@ static void restore_stack_limit (lua_State *L) {
}
}
void luaD_resetprotection (lua_State *L) {
Protection *p;
StkId err = L->top - 1; /* error msg. position (if there is one) */
lua_assert(L->number_toreset > 0);
p = &L->toreset[--L->number_toreset];
L->ci = restoreci(L, p->ci);
L->top = restorestack(L, p->top);
L->ci->top = L->top + LUA_MINSTACK;
setallowhook(L, p->allowhooks);
restore_stack_limit(L);
setobj(L->top++, err); /* copy error message to corrected top */
}
/*
** invalidate all pc pointers from stack part that becomes inactive
*/
static void deactivateinfo (lua_State *L, CallInfo *p_ci) {
CallInfo *ci;
for (ci = L->ci; ci > p_ci; ci--)
ci->pc = NULL;
}
/* }====================================================== */
@ -168,7 +141,6 @@ 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_throw(L, LUA_ERRERR);
else {
@ -176,7 +148,6 @@ static void luaD_growCI (lua_State *L) {
if (L->size_ci > LUA_MAXCALLS)
luaG_runerror(L, "stack overflow");
}
L->ci++;
}
@ -412,34 +383,34 @@ struct CallS { /* data to `f_call' */
static void f_call (lua_State *L, void *ud) {
struct CallS *c = cast(struct CallS *, ud);
luaM_growvector(L, L->toreset, L->number_toreset, L->size_toreset,
Protection, MAX_INT, "");
luaD_call(L, c->func, c->nresults);
}
int luaD_pcall (lua_State *L, int nargs, int nresults) {
int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
struct CallS c;
int status;
int protectionlevel = L->number_toreset;
Protection protection;
protection.top = savestack(L, L->top);
protection.ci = saveci(L, L->ci);
protection.allowhooks = allowhook(L);
ptrdiff_t old_top = savestack(L, L->top);
ptrdiff_t old_ci = saveci(L, L->ci);
int old_allowhooks = allowhook(L);
ptrdiff_t old_errfunc = L->errfunc;
L->errfunc = errfunc;
c.func = L->top - (nargs+1); /* function to be called */
c.nresults = nresults;
status = luaD_rawrunprotected(L, &f_call, &c);
if (status != 0) { /* an error occurred? */
/* remove parameters and func from the stack */
protection.top = savestack(L, restorestack(L, protection.top) - (nargs+1));
/* close eventual pending closures */
luaF_close(L, restorestack(L, protection.top));
L->ci->top = L->top + LUA_MINSTACK; /* extra space to handle error */
StkId err; /* error msg. position */
seterrorobj(L, status);
deactivateinfo(L, restoreci(L, protection.ci));
L->number_toreset = protectionlevel + 1;
L->toreset[L->number_toreset - 1] = protection;
err = L->top - 1;
/* remove parameters and func from the stack */
L->top = restorestack(L, old_top) - (nargs+1);
setobj(L->top++, err); /* copy error message to corrected top */
luaF_close(L, L->top); /* close eventual pending closures */
L->ci = restoreci(L, old_ci);
setallowhook(L, old_allowhooks);
restore_stack_limit(L);
}
L->errfunc = old_errfunc;
return status;
}

4
ldo.h

@ -1,5 +1,5 @@
/*
** $Id: ldo.h,v 1.48 2002/07/08 18:21:33 roberto Exp roberto $
** $Id: ldo.h,v 1.49 2002/08/05 17:36:24 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -39,7 +39,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin);
void luaD_callhook (lua_State *L, lua_Hookevent event, 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);
int luaD_pcall (lua_State *L, int nargs, int nresults, int errfunc);
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);

8
lstate.c

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 1.100 2002/08/05 17:36:24 roberto Exp roberto $
** $Id: lstate.c,v 1.101 2002/08/05 18:45:45 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -47,8 +47,6 @@ static void stack_init (lua_State *L, lua_State *OL) {
L->ci->top = L->top + LUA_MINSTACK;
L->size_ci = BASIC_CI_SIZE;
L->end_ci = L->base_ci + L->size_ci;
L->toreset = luaM_newvector(OL, 2, Protection);
L->size_toreset = 2;
}
@ -102,8 +100,7 @@ static void preinit_state (lua_State *L) {
L->openupval = NULL;
L->size_ci = 0;
L->base_ci = L->ci = NULL;
L->toreset = NULL;
L->size_toreset = L->number_toreset = 0;
L->errfunc = 0;
setnilvalue(defaultmeta(L));
setnilvalue(gt(L));
setnilvalue(registry(L));
@ -154,7 +151,6 @@ void luaE_closethread (lua_State *OL, lua_State *L) {
L->previous->next = L->next;
L->next->previous = L->previous;
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
luaM_freearray(OL, L->toreset, L->size_toreset, Protection);
luaM_freearray(OL, L->stack, L->stacksize, TObject);
luaM_freelem(OL, L);
}

15
lstate.h

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 1.89 2002/07/16 14:26:56 roberto Exp roberto $
** $Id: lstate.h,v 1.90 2002/08/05 17:36:24 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -101,15 +101,6 @@ typedef struct CallInfo {
} CallInfo;
/*
** informations about a `protection' (error recovery points)
*/
typedef struct Protection {
ptrdiff_t ci;
ptrdiff_t top;
int allowhooks;
} Protection;
#define ci_func(ci) (clvalue((ci)->base - 1))
@ -154,9 +145,7 @@ struct lua_State {
lua_Hook hook;
UpVal *openupval; /* list of open upvalues in this stack */
struct lua_longjmp *errorJmp; /* current error recover point */
Protection *toreset; /* array of pending pcall resets */
int number_toreset;
int size_toreset;
ptrdiff_t errfunc; /* current error handling function (stack index) */
lua_State *next; /* circular double linked list of states */
lua_State *previous;
TObject globs[NUMGLOBS]; /* registry, table of globals, etc. */

12
ltests.c

@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 1.130 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: ltests.c,v 1.131 2002/08/05 14:10:10 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@ -402,7 +402,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);
status = lua_pcall(L1, 0, 0, 0);
lua_pushnumber(L, status);
lua_closethread(L, L1);
return 1;
@ -456,10 +456,8 @@ static int doremote (lua_State *L) {
int status;
lua_settop(L1, 0);
status = luaL_loadbuffer(L1, code, lcode, code);
if (status == 0) {
status = lua_pcall(L1, 0, LUA_MULTRET);
if (status != 0) lua_pcallreset(L1);
}
if (status == 0)
status = lua_pcall(L1, 0, LUA_MULTRET, 0);
if (status != 0) {
lua_pushnil(L);
lua_pushnumber(L, status);
@ -647,7 +645,7 @@ static int testC (lua_State *L) {
else if EQ("call") {
int narg = getnum;
int nres = getnum;
lua_pcall(L, narg, nres);
lua_pcall(L, narg, nres, 0);
}
else if EQ("loadstring") {
size_t sl;

74
lua.c

@ -1,5 +1,5 @@
/*
** $Id: lua.c,v 1.96 2002/07/10 20:44:34 roberto Exp roberto $
** $Id: lua.c,v 1.97 2002/07/10 20:49:01 roberto Exp roberto $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@ -35,8 +35,8 @@ static int isatty (int x) { return x==0; } /* assume stdin is a tty */
#endif
#ifndef LUA_USERINIT
#define LUA_USERINIT(L) openstdlibs(L)
#ifndef lua_userinit
#define lua_userinit(L) openstdlibs(L)
#endif
@ -80,23 +80,17 @@ static void print_usage (void) {
static void l_message (const char *pname, const char *msg) {
size_t l = strlen(msg);
if (pname) fprintf(stderr, "%s: ", pname);
fprintf(stderr, "%s", msg);
if (l > 0 && msg[l-1] != '\n') /* does not end with newline? */
fprintf(stderr, "\n"); /* add a newline */
}
static void report (int status, int traceback) {
static void report (int status) {
const char *msg;
if (status) {
if (status == LUA_ERRRUN) {
if (!traceback) lua_pop(L, 1); /* remove traceback */
else {
if (lua_isstring(L, -2) && lua_isstring(L, -1))
lua_concat(L, 2); /* concat error message and traceback */
else
lua_remove(L, -2); /* leave only traceback on stack */
}
}
msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(no message)";
l_message(progname, msg);
@ -108,9 +102,12 @@ static void report (int status, int traceback) {
static int lcall (int clear) {
int status;
int top = lua_gettop(L);
lua_getglobal(L, "_TRACEBACK"); /* get traceback function */
lua_insert(L, top); /* put it under chunk */
signal(SIGINT, laction);
status = lua_pcall(L, 0, LUA_MULTRET);
status = lua_pcall(L, 0, LUA_MULTRET, -2);
signal(SIGINT, SIG_DFL);
lua_remove(L, top); /* remove traceback function */
if (status == 0 && clear)
lua_settop(L, top); /* remove eventual results */
return status;
@ -119,13 +116,13 @@ static int lcall (int clear) {
static int l_panic (lua_State *l) {
(void)l;
l_message(progname, "unable to recover; exiting\n");
l_message(progname, "unable to recover; exiting");
return 0;
}
static void print_version (void) {
l_message(NULL, LUA_VERSION " " LUA_COPYRIGHT "\n");
l_message(NULL, LUA_VERSION " " LUA_COPYRIGHT);
}
@ -146,7 +143,7 @@ static void getargs (char *argv[], int n) {
static int docall (int status) {
if (status == 0) status = lcall(1);
report(status, 1);
report(status);
return status;
}
@ -161,13 +158,21 @@ static int dostring (const char *s, const char *name) {
}
#ifndef save_line
#define save_line(b) /* empty */
/*
** this macro can be used by some `history' system to save lines
** read in manual input
*/
#ifndef lua_saveline
#define lua_saveline(L,line) /* empty */
#endif
#ifndef read_line
#define read_line(p) readline(p)
/*
** this macro defines a function to show the prompt and reads the
** next line for manual input
*/
#ifndef lua_readline
#define lua_readline(L,prompt) readline(L,prompt)
/* maximum length of an input line */
#ifndef MAXINPUT
@ -175,7 +180,7 @@ static int dostring (const char *s, const char *name) {
#endif
static int readline (const char *prompt) {
static int readline (lua_State *l, const char *prompt) {
static char buffer[MAXINPUT];
if (prompt) {
fputs(prompt, stdout);
@ -184,10 +189,7 @@ static int readline (const char *prompt) {
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return 0; /* read fails */
else {
size_t l = strlen(buffer);
if (l > 0 && buffer[l-1] == '\n')
buffer[l-1] = '\0'; /* remove eventual `\n' */
lua_pushstring(L, buffer);
lua_pushstring(l, buffer);
return 1;
}
}
@ -219,7 +221,7 @@ static int incomplete (int status) {
static int load_string (void) {
int status;
lua_settop(L, 0);
if (read_line(get_prompt(1)) == 0) /* no input? */
if (lua_readline(L, get_prompt(1)) == 0) /* no input? */
return -1;
if (lua_tostring(L, -1)[0] == '=') { /* line starts with `=' ? */
lua_pushfstring(L, "return %s", lua_tostring(L, -1)+1);/* `=' -> `return' */
@ -228,12 +230,11 @@ static int load_string (void) {
for (;;) { /* repeat until gets a complete line */
status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin");
if (!incomplete(status)) break; /* cannot try to add lines? */
lua_pushliteral(L, "\n"); /* no; add line separator */
if (read_line(get_prompt(0)) == 0) /* no more input? */
if (lua_readline(L, get_prompt(0)) == 0) /* no more input? */
return -1;
lua_concat(L, lua_gettop(L)); /* join lines and line separator */
lua_concat(L, lua_gettop(L)); /* join lines */
}
save_line(lua_tostring(L, 1));
lua_saveline(L, lua_tostring(L, 1));
lua_remove(L, 1); /* remove line */
return status;
}
@ -245,11 +246,12 @@ static void manual_input (void) {
progname = NULL;
while ((status = load_string()) != -1) {
if (status == 0) status = lcall(0);
report(status, 0);
report(status);
if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */
lua_getglobal(L, "print");
lua_insert(L, 1);
lua_pcall(L, lua_gettop(L)-1, 0);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname, "error calling `print'");
}
}
lua_settop(L, 0); /* clear stack */
@ -311,11 +313,11 @@ static int handle_argv (char *argv[], int *interactive) {
break;
}
case 'c': {
l_message(progname, "option `-c' is deprecated\n");
l_message(progname, "option `-c' is deprecated");
break;
}
case 's': {
l_message(progname, "option `-s' is deprecated\n");
l_message(progname, "option `-s' is deprecated");
break;
}
default: {
@ -364,7 +366,7 @@ int main (int argc, char *argv[]) {
progname = argv[0];
L = lua_open(); /* create state */
lua_atpanic(L, l_panic);
lua_pop(L, LUA_USERINIT(L)); /* open libraries, discard any results */
lua_pop(L, lua_userinit(L)); /* open libraries, discard any results */
status = handle_luainit();
if (status != 0) return status;
status = handle_argv(argv, &interactive);

5
lua.h

@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.147 2002/07/17 16:25:13 roberto Exp roberto $
** $Id: lua.h,v 1.148 2002/08/05 14:51:47 roberto Exp roberto $
** Lua - An Extensible Extension Language
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
** http://www.lua.org mailto:info@lua.org
@ -183,10 +183,9 @@ LUA_API int lua_setglobals (lua_State *L, int level);
** `load' and `call' functions (load and run Lua code)
*/
LUA_API void lua_call (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults);
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
const char *chunkname);
LUA_API void lua_pcallreset (lua_State *L);
/*

Loading…
Cancel
Save