mirror of
https://github.com/lua/lua
synced 2025-04-12 16:02:52 +03:00
new version of protected execution
This commit is contained in:
parent
d8a442206d
commit
13635f7de7
178
ldo.c
178
ldo.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $
|
** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 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
|
||||||
*/
|
*/
|
||||||
@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void message (lua_State *L, const char *s) {
|
|
||||||
const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE);
|
|
||||||
if (*luaO_typename(em) == 'f') {
|
|
||||||
*L->top = *em;
|
|
||||||
incr_top;
|
|
||||||
lua_pushstring(L, s);
|
|
||||||
luaD_call(L, L->top-2, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void luaD_breakrun (lua_State *L, int errcode) {
|
|
||||||
if (L->errorJmp) {
|
|
||||||
L->errorJmp->status = errcode;
|
|
||||||
longjmp(L->errorJmp->b, 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (errcode != LUA_ERRMEM)
|
|
||||||
message(L, "unable to recover; exiting\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Reports an error, and jumps up to the available recovery label
|
|
||||||
*/
|
|
||||||
void lua_error (lua_State *L, const char *s) {
|
|
||||||
if (s) message(L, s);
|
|
||||||
luaD_breakrun(L, LUA_ERRRUN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) {
|
|
||||||
lj->status = 0;
|
|
||||||
lj->base = L->Cbase;
|
|
||||||
lj->previous = L->errorJmp;
|
|
||||||
L->errorJmp = lj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) {
|
|
||||||
L->Cbase = lj->base;
|
|
||||||
L->errorJmp = lj->previous;
|
|
||||||
return lj->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Execute a protected call.
|
** Execute a protected call.
|
||||||
*/
|
*/
|
||||||
|
struct CallS { /* data to `f_call' */
|
||||||
|
StkId func;
|
||||||
|
int nresults;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void f_call (lua_State *L, void *ud) {
|
||||||
|
struct CallS *c = (struct CallS *)ud;
|
||||||
|
luaD_call(L, c->func, c->nresults);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int lua_call (lua_State *L, int nargs, int nresults) {
|
int lua_call (lua_State *L, int nargs, int nresults) {
|
||||||
StkId func = L->top - (nargs+1); /* function to be called */
|
StkId func = L->top - (nargs+1); /* function to be called */
|
||||||
struct lua_longjmp myErrorJmp;
|
struct CallS c;
|
||||||
chain_longjmp(L, &myErrorJmp);
|
int status;
|
||||||
if (setjmp(myErrorJmp.b) == 0) {
|
c.func = func; c.nresults = nresults;
|
||||||
luaD_call(L, func, nresults);
|
status = luaD_runprotected(L, f_call, &c);
|
||||||
}
|
if (status != 0) /* an error occurred? */
|
||||||
else { /* an error occurred: restore the state */
|
L->top = func; /* remove parameters from the stack */
|
||||||
L->top = func; /* remove garbage from the stack */
|
return status;
|
||||||
restore_stack_limit(L);
|
}
|
||||||
}
|
|
||||||
return restore_longjmp(L, &myErrorJmp);
|
|
||||||
|
/*
|
||||||
|
** Execute a protected parser.
|
||||||
|
*/
|
||||||
|
struct ParserS { /* data to `f_parser' */
|
||||||
|
ZIO *z;
|
||||||
|
int bin;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void f_parser (lua_State *L, void *ud) {
|
||||||
|
struct ParserS *p = (struct ParserS *)ud;
|
||||||
|
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
|
||||||
|
luaV_Lclosure(L, tf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int protectedparser (lua_State *L, ZIO *z, int bin) {
|
static int protectedparser (lua_State *L, ZIO *z, int bin) {
|
||||||
struct lua_longjmp myErrorJmp;
|
struct ParserS p;
|
||||||
unsigned long old_blocks;
|
unsigned long old_blocks;
|
||||||
|
int status;
|
||||||
|
p.z = z; p.bin = bin;
|
||||||
luaC_checkGC(L);
|
luaC_checkGC(L);
|
||||||
old_blocks = L->nblocks;
|
old_blocks = L->nblocks;
|
||||||
chain_longjmp(L, &myErrorJmp);
|
status = luaD_runprotected(L, f_parser, &p);
|
||||||
if (setjmp(myErrorJmp.b) == 0) {
|
if (status == LUA_ERRRUN) /* an error occurred: correct error code */
|
||||||
Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z);
|
status = LUA_ERRSYNTAX;
|
||||||
luaV_Lclosure(L, tf, 0);
|
|
||||||
}
|
|
||||||
else { /* an error occurred: correct error code */
|
|
||||||
if (myErrorJmp.status == LUA_ERRRUN)
|
|
||||||
myErrorJmp.status = LUA_ERRSYNTAX;
|
|
||||||
}
|
|
||||||
/* add new memory to threshould (as it probably will stay) */
|
/* add new memory to threshould (as it probably will stay) */
|
||||||
L->GCthreshold += (L->nblocks - old_blocks);
|
L->GCthreshold += (L->nblocks - old_blocks);
|
||||||
return restore_longjmp(L, &myErrorJmp); /* error code */
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) {
|
|||||||
return lua_dobuffer(L, str, strlen(str), str);
|
return lua_dobuffer(L, str, strlen(str), str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** {======================================================
|
||||||
|
** Error-recover functions (based on long jumps)
|
||||||
|
** =======================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* chain list of long jump buffers */
|
||||||
|
struct lua_longjmp {
|
||||||
|
jmp_buf b;
|
||||||
|
struct lua_longjmp *previous;
|
||||||
|
volatile int status; /* error code */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void message (lua_State *L, const char *s) {
|
||||||
|
const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE);
|
||||||
|
if (*luaO_typename(em) == 'f') {
|
||||||
|
*L->top = *em;
|
||||||
|
incr_top;
|
||||||
|
lua_pushstring(L, s);
|
||||||
|
luaD_call(L, L->top-2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Reports an error, and jumps up to the available recovery label
|
||||||
|
*/
|
||||||
|
void lua_error (lua_State *L, const char *s) {
|
||||||
|
if (s) message(L, s);
|
||||||
|
luaD_breakrun(L, LUA_ERRRUN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void luaD_breakrun (lua_State *L, int errcode) {
|
||||||
|
if (L->errorJmp) {
|
||||||
|
L->errorJmp->status = errcode;
|
||||||
|
longjmp(L->errorJmp->b, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (errcode != LUA_ERRMEM)
|
||||||
|
message(L, "unable to recover; exiting\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
|
||||||
|
StkId oldCbase = L->Cbase;
|
||||||
|
StkId oldtop = L->top;
|
||||||
|
struct lua_longjmp lj;
|
||||||
|
lj.status = 0;
|
||||||
|
lj.previous = L->errorJmp; /* chain new error handler */
|
||||||
|
L->errorJmp = &lj;
|
||||||
|
if (setjmp(lj.b) == 0)
|
||||||
|
(*f)(L, ud);
|
||||||
|
else { /* an error occurred: restore the state */
|
||||||
|
L->Cbase = oldCbase;
|
||||||
|
L->top = oldtop;
|
||||||
|
restore_stack_limit(L);
|
||||||
|
}
|
||||||
|
L->errorJmp = lj.previous; /* restore old error handler */
|
||||||
|
return lj.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }====================================================== */
|
||||||
|
|
||||||
|
6
ldo.h
6
ldo.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $
|
** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 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
|
||||||
*/
|
*/
|
||||||
@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra);
|
|||||||
void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
|
void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook);
|
||||||
void luaD_call (lua_State *L, StkId func, int nResults);
|
void luaD_call (lua_State *L, StkId func, int nResults);
|
||||||
void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
|
void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults);
|
||||||
void luaD_breakrun (lua_State *L, int errcode);
|
|
||||||
void luaD_checkstack (lua_State *L, int n);
|
void luaD_checkstack (lua_State *L, int n);
|
||||||
|
|
||||||
|
void luaD_breakrun (lua_State *L, int errcode);
|
||||||
|
int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
49
lstate.c
49
lstate.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $
|
** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
extern lua_State *lua_state;
|
static lua_State *lua_state = NULL;
|
||||||
void luaB_opentests (lua_State *L);
|
void luaB_opentests (lua_State *L);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -38,8 +38,29 @@ static int errormessage (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** open parts that may cause memory-allocation errors
|
||||||
|
*/
|
||||||
|
static void f_luaopen (lua_State *L, void *ud) {
|
||||||
|
int stacksize = *(int *)ud;
|
||||||
|
if (stacksize == 0)
|
||||||
|
stacksize = DEFAULT_STACK_SIZE;
|
||||||
|
else
|
||||||
|
stacksize += LUA_MINSTACK;
|
||||||
|
L->gt = luaH_new(L, 10);
|
||||||
|
luaD_init(L, stacksize);
|
||||||
|
luaS_init(L);
|
||||||
|
luaX_init(L);
|
||||||
|
luaT_init(L);
|
||||||
|
lua_register(L, LUA_ERRORMESSAGE, errormessage);
|
||||||
|
#ifdef DEBUG
|
||||||
|
luaB_opentests(L);
|
||||||
|
if (lua_state == NULL) lua_state = L; /* keep first state to be opened */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
lua_State *lua_open (int stacksize) {
|
lua_State *lua_open (int stacksize) {
|
||||||
struct lua_longjmp myErrorJmp;
|
|
||||||
lua_State *L = luaM_new(NULL, lua_State);
|
lua_State *L = luaM_new(NULL, lua_State);
|
||||||
if (L == NULL) return NULL; /* memory allocation error */
|
if (L == NULL) return NULL; /* memory allocation error */
|
||||||
L->stack = NULL;
|
L->stack = NULL;
|
||||||
@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) {
|
|||||||
L->callhook = NULL;
|
L->callhook = NULL;
|
||||||
L->linehook = NULL;
|
L->linehook = NULL;
|
||||||
L->allowhooks = 1;
|
L->allowhooks = 1;
|
||||||
L->errorJmp = &myErrorJmp;
|
L->errorJmp = NULL;
|
||||||
if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */
|
if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) {
|
||||||
L->gt = luaH_new(L, 10);
|
/* memory allocation error: free partial state */
|
||||||
luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE :
|
|
||||||
stacksize+LUA_MINSTACK);
|
|
||||||
luaS_init(L);
|
|
||||||
luaX_init(L);
|
|
||||||
luaT_init(L);
|
|
||||||
lua_register(L, LUA_ERRORMESSAGE, errormessage);
|
|
||||||
#ifdef DEBUG
|
|
||||||
luaB_opentests(L);
|
|
||||||
#endif
|
|
||||||
L->GCthreshold = L->nblocks*4;
|
|
||||||
L->errorJmp = NULL;
|
|
||||||
return L;
|
|
||||||
}
|
|
||||||
else { /* memory allocation error: free partial state */
|
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
L->GCthreshold = L->nblocks*4;
|
||||||
|
return L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
14
lstate.h
14
lstate.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $
|
** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -7,8 +7,6 @@
|
|||||||
#ifndef lstate_h
|
#ifndef lstate_h
|
||||||
#define lstate_h
|
#define lstate_h
|
||||||
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "luadebug.h"
|
#include "luadebug.h"
|
||||||
@ -33,15 +31,7 @@ struct Ref {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
struct lua_longjmp; /* defined in ldo.c */
|
||||||
** chain list of long jumps
|
|
||||||
*/
|
|
||||||
struct lua_longjmp {
|
|
||||||
jmp_buf b;
|
|
||||||
struct lua_longjmp *previous;
|
|
||||||
volatile int status; /* error code */
|
|
||||||
StkId base;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct stringtable {
|
typedef struct stringtable {
|
||||||
|
12
ltests.c
12
ltests.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $
|
** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 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
|
||||||
*/
|
*/
|
||||||
@ -422,11 +422,19 @@ static int testC (lua_State *L) {
|
|||||||
else if EQ("concat") {
|
else if EQ("concat") {
|
||||||
lua_concat(L, getnum);
|
lua_concat(L, getnum);
|
||||||
}
|
}
|
||||||
else if EQ("call") {
|
else if EQ("rawcall") {
|
||||||
int narg = getnum;
|
int narg = getnum;
|
||||||
int nres = getnum;
|
int nres = getnum;
|
||||||
lua_rawcall(L, narg, nres);
|
lua_rawcall(L, narg, nres);
|
||||||
}
|
}
|
||||||
|
else if EQ("call") {
|
||||||
|
int narg = getnum;
|
||||||
|
int nres = getnum;
|
||||||
|
lua_call(L, narg, nres);
|
||||||
|
}
|
||||||
|
else if EQ("dostring") {
|
||||||
|
lua_dostring(L, luaL_check_string(L, getnum));
|
||||||
|
}
|
||||||
else if EQ("type") {
|
else if EQ("type") {
|
||||||
lua_pushstring(L, lua_type(L, getnum));
|
lua_pushstring(L, lua_type(L, getnum));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user