diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-25 13:22:42 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-25 13:22:42 -0300 |
| commit | 13635f7de7c51b26c447ce444a2c045cba83fe7c (patch) | |
| tree | b9461626b368e8ca1161b01e2771447898fdecd8 | |
| parent | d8a442206d2845e1749cc36dd59208428ef1d117 (diff) | |
| download | lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.gz lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.bz2 lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.zip | |
new version of protected execution
| -rw-r--r-- | ldo.c | 168 | ||||
| -rw-r--r-- | ldo.h | 6 | ||||
| -rw-r--r-- | lstate.c | 49 | ||||
| -rw-r--r-- | lstate.h | 14 | ||||
| -rw-r--r-- | ltests.c | 12 |
5 files changed, 149 insertions, 100 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 roberto Exp roberto $ |
| 3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | 201 | ||
| 202 | static void message (lua_State *L, const char *s) { | ||
| 203 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
| 204 | if (*luaO_typename(em) == 'f') { | ||
| 205 | *L->top = *em; | ||
| 206 | incr_top; | ||
| 207 | lua_pushstring(L, s); | ||
| 208 | luaD_call(L, L->top-2, 0); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | |||
| 213 | void luaD_breakrun (lua_State *L, int errcode) { | ||
| 214 | if (L->errorJmp) { | ||
| 215 | L->errorJmp->status = errcode; | ||
| 216 | longjmp(L->errorJmp->b, 1); | ||
| 217 | } | ||
| 218 | else { | ||
| 219 | if (errcode != LUA_ERRMEM) | ||
| 220 | message(L, "unable to recover; exiting\n"); | ||
| 221 | exit(EXIT_FAILURE); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | 202 | /* |
| 226 | ** Reports an error, and jumps up to the available recovery label | 203 | ** Execute a protected call. |
| 227 | */ | 204 | */ |
| 228 | void lua_error (lua_State *L, const char *s) { | 205 | struct CallS { /* data to `f_call' */ |
| 229 | if (s) message(L, s); | 206 | StkId func; |
| 230 | luaD_breakrun(L, LUA_ERRRUN); | 207 | int nresults; |
| 231 | } | 208 | }; |
| 232 | 209 | ||
| 233 | 210 | static void f_call (lua_State *L, void *ud) { | |
| 234 | static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { | 211 | struct CallS *c = (struct CallS *)ud; |
| 235 | lj->status = 0; | 212 | luaD_call(L, c->func, c->nresults); |
| 236 | lj->base = L->Cbase; | ||
| 237 | lj->previous = L->errorJmp; | ||
| 238 | L->errorJmp = lj; | ||
| 239 | } | 213 | } |
| 240 | 214 | ||
| 241 | 215 | ||
| 242 | static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) { | 216 | int lua_call (lua_State *L, int nargs, int nresults) { |
| 243 | L->Cbase = lj->base; | 217 | StkId func = L->top - (nargs+1); /* function to be called */ |
| 244 | L->errorJmp = lj->previous; | 218 | struct CallS c; |
| 245 | return lj->status; | 219 | int status; |
| 220 | c.func = func; c.nresults = nresults; | ||
| 221 | status = luaD_runprotected(L, f_call, &c); | ||
| 222 | if (status != 0) /* an error occurred? */ | ||
| 223 | L->top = func; /* remove parameters from the stack */ | ||
| 224 | return status; | ||
| 246 | } | 225 | } |
| 247 | 226 | ||
| 248 | 227 | ||
| 249 | /* | 228 | /* |
| 250 | ** Execute a protected call. | 229 | ** Execute a protected parser. |
| 251 | */ | 230 | */ |
| 252 | int lua_call (lua_State *L, int nargs, int nresults) { | 231 | struct ParserS { /* data to `f_parser' */ |
| 253 | StkId func = L->top - (nargs+1); /* function to be called */ | 232 | ZIO *z; |
| 254 | struct lua_longjmp myErrorJmp; | 233 | int bin; |
| 255 | chain_longjmp(L, &myErrorJmp); | 234 | }; |
| 256 | if (setjmp(myErrorJmp.b) == 0) { | 235 | |
| 257 | luaD_call(L, func, nresults); | 236 | static void f_parser (lua_State *L, void *ud) { |
| 258 | } | 237 | struct ParserS *p = (struct ParserS *)ud; |
| 259 | else { /* an error occurred: restore the state */ | 238 | Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); |
| 260 | L->top = func; /* remove garbage from the stack */ | 239 | luaV_Lclosure(L, tf, 0); |
| 261 | restore_stack_limit(L); | ||
| 262 | } | ||
| 263 | return restore_longjmp(L, &myErrorJmp); | ||
| 264 | } | 240 | } |
| 265 | 241 | ||
| 266 | 242 | ||
| 267 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 243 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
| 268 | struct lua_longjmp myErrorJmp; | 244 | struct ParserS p; |
| 269 | unsigned long old_blocks; | 245 | unsigned long old_blocks; |
| 246 | int status; | ||
| 247 | p.z = z; p.bin = bin; | ||
| 270 | luaC_checkGC(L); | 248 | luaC_checkGC(L); |
| 271 | old_blocks = L->nblocks; | 249 | old_blocks = L->nblocks; |
| 272 | chain_longjmp(L, &myErrorJmp); | 250 | status = luaD_runprotected(L, f_parser, &p); |
| 273 | if (setjmp(myErrorJmp.b) == 0) { | 251 | if (status == LUA_ERRRUN) /* an error occurred: correct error code */ |
| 274 | Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z); | 252 | status = LUA_ERRSYNTAX; |
| 275 | luaV_Lclosure(L, tf, 0); | ||
| 276 | } | ||
| 277 | else { /* an error occurred: correct error code */ | ||
| 278 | if (myErrorJmp.status == LUA_ERRRUN) | ||
| 279 | myErrorJmp.status = LUA_ERRSYNTAX; | ||
| 280 | } | ||
| 281 | /* add new memory to threshould (as it probably will stay) */ | 253 | /* add new memory to threshould (as it probably will stay) */ |
| 282 | L->GCthreshold += (L->nblocks - old_blocks); | 254 | L->GCthreshold += (L->nblocks - old_blocks); |
| 283 | return restore_longjmp(L, &myErrorJmp); /* error code */ | 255 | return status; |
| 284 | } | 256 | } |
| 285 | 257 | ||
| 286 | 258 | ||
| @@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) { | |||
| 339 | return lua_dobuffer(L, str, strlen(str), str); | 311 | return lua_dobuffer(L, str, strlen(str), str); |
| 340 | } | 312 | } |
| 341 | 313 | ||
| 314 | |||
| 315 | /* | ||
| 316 | ** {====================================================== | ||
| 317 | ** Error-recover functions (based on long jumps) | ||
| 318 | ** ======================================================= | ||
| 319 | */ | ||
| 320 | |||
| 321 | /* chain list of long jump buffers */ | ||
| 322 | struct lua_longjmp { | ||
| 323 | jmp_buf b; | ||
| 324 | struct lua_longjmp *previous; | ||
| 325 | volatile int status; /* error code */ | ||
| 326 | }; | ||
| 327 | |||
| 328 | |||
| 329 | static void message (lua_State *L, const char *s) { | ||
| 330 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
| 331 | if (*luaO_typename(em) == 'f') { | ||
| 332 | *L->top = *em; | ||
| 333 | incr_top; | ||
| 334 | lua_pushstring(L, s); | ||
| 335 | luaD_call(L, L->top-2, 0); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | |||
| 340 | /* | ||
| 341 | ** Reports an error, and jumps up to the available recovery label | ||
| 342 | */ | ||
| 343 | void lua_error (lua_State *L, const char *s) { | ||
| 344 | if (s) message(L, s); | ||
| 345 | luaD_breakrun(L, LUA_ERRRUN); | ||
| 346 | } | ||
| 347 | |||
| 348 | |||
| 349 | void luaD_breakrun (lua_State *L, int errcode) { | ||
| 350 | if (L->errorJmp) { | ||
| 351 | L->errorJmp->status = errcode; | ||
| 352 | longjmp(L->errorJmp->b, 1); | ||
| 353 | } | ||
| 354 | else { | ||
| 355 | if (errcode != LUA_ERRMEM) | ||
| 356 | message(L, "unable to recover; exiting\n"); | ||
| 357 | exit(EXIT_FAILURE); | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | |||
| 362 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | ||
| 363 | StkId oldCbase = L->Cbase; | ||
| 364 | StkId oldtop = L->top; | ||
| 365 | struct lua_longjmp lj; | ||
| 366 | lj.status = 0; | ||
| 367 | lj.previous = L->errorJmp; /* chain new error handler */ | ||
| 368 | L->errorJmp = &lj; | ||
| 369 | if (setjmp(lj.b) == 0) | ||
| 370 | (*f)(L, ud); | ||
| 371 | else { /* an error occurred: restore the state */ | ||
| 372 | L->Cbase = oldCbase; | ||
| 373 | L->top = oldtop; | ||
| 374 | restore_stack_limit(L); | ||
| 375 | } | ||
| 376 | L->errorJmp = lj.previous; /* restore old error handler */ | ||
| 377 | return lj.status; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* }====================================================== */ | ||
| 381 | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 roberto Exp roberto $ |
| 3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra); | |||
| 24 | void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); | 24 | void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); |
| 25 | void luaD_call (lua_State *L, StkId func, int nResults); | 25 | void luaD_call (lua_State *L, StkId func, int nResults); |
| 26 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); | 26 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); |
| 27 | void luaD_breakrun (lua_State *L, int errcode); | ||
| 28 | void luaD_checkstack (lua_State *L, int n); | 27 | void luaD_checkstack (lua_State *L, int n); |
| 29 | 28 | ||
| 29 | void luaD_breakrun (lua_State *L, int errcode); | ||
| 30 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); | ||
| 31 | |||
| 30 | 32 | ||
| 31 | #endif | 33 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | #ifdef DEBUG | 22 | #ifdef DEBUG |
| 23 | extern lua_State *lua_state; | 23 | static lua_State *lua_state = NULL; |
| 24 | void luaB_opentests (lua_State *L); | 24 | void luaB_opentests (lua_State *L); |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| @@ -38,8 +38,29 @@ static int errormessage (lua_State *L) { | |||
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | /* | ||
| 42 | ** open parts that may cause memory-allocation errors | ||
| 43 | */ | ||
| 44 | static void f_luaopen (lua_State *L, void *ud) { | ||
| 45 | int stacksize = *(int *)ud; | ||
| 46 | if (stacksize == 0) | ||
| 47 | stacksize = DEFAULT_STACK_SIZE; | ||
| 48 | else | ||
| 49 | stacksize += LUA_MINSTACK; | ||
| 50 | L->gt = luaH_new(L, 10); | ||
| 51 | luaD_init(L, stacksize); | ||
| 52 | luaS_init(L); | ||
| 53 | luaX_init(L); | ||
| 54 | luaT_init(L); | ||
| 55 | lua_register(L, LUA_ERRORMESSAGE, errormessage); | ||
| 56 | #ifdef DEBUG | ||
| 57 | luaB_opentests(L); | ||
| 58 | if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ | ||
| 59 | #endif | ||
| 60 | } | ||
| 61 | |||
| 62 | |||
| 41 | lua_State *lua_open (int stacksize) { | 63 | lua_State *lua_open (int stacksize) { |
| 42 | struct lua_longjmp myErrorJmp; | ||
| 43 | lua_State *L = luaM_new(NULL, lua_State); | 64 | lua_State *L = luaM_new(NULL, lua_State); |
| 44 | if (L == NULL) return NULL; /* memory allocation error */ | 65 | if (L == NULL) return NULL; /* memory allocation error */ |
| 45 | L->stack = NULL; | 66 | L->stack = NULL; |
| @@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) { | |||
| 62 | L->callhook = NULL; | 83 | L->callhook = NULL; |
| 63 | L->linehook = NULL; | 84 | L->linehook = NULL; |
| 64 | L->allowhooks = 1; | 85 | L->allowhooks = 1; |
| 65 | L->errorJmp = &myErrorJmp; | 86 | L->errorJmp = NULL; |
| 66 | if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */ | 87 | if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) { |
| 67 | L->gt = luaH_new(L, 10); | 88 | /* memory allocation error: free partial state */ |
| 68 | luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE : | ||
| 69 | stacksize+LUA_MINSTACK); | ||
| 70 | luaS_init(L); | ||
| 71 | luaX_init(L); | ||
| 72 | luaT_init(L); | ||
| 73 | lua_register(L, LUA_ERRORMESSAGE, errormessage); | ||
| 74 | #ifdef DEBUG | ||
| 75 | luaB_opentests(L); | ||
| 76 | #endif | ||
| 77 | L->GCthreshold = L->nblocks*4; | ||
| 78 | L->errorJmp = NULL; | ||
| 79 | return L; | ||
| 80 | } | ||
| 81 | else { /* memory allocation error: free partial state */ | ||
| 82 | lua_close(L); | 89 | lua_close(L); |
| 83 | return NULL; | 90 | return NULL; |
| 84 | } | 91 | } |
| 92 | L->GCthreshold = L->nblocks*4; | ||
| 93 | return L; | ||
| 85 | } | 94 | } |
| 86 | 95 | ||
| 87 | 96 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -7,8 +7,6 @@ | |||
| 7 | #ifndef lstate_h | 7 | #ifndef lstate_h |
| 8 | #define lstate_h | 8 | #define lstate_h |
| 9 | 9 | ||
| 10 | #include <setjmp.h> | ||
| 11 | |||
| 12 | #include "lobject.h" | 10 | #include "lobject.h" |
| 13 | #include "lua.h" | 11 | #include "lua.h" |
| 14 | #include "luadebug.h" | 12 | #include "luadebug.h" |
| @@ -33,15 +31,7 @@ struct Ref { | |||
| 33 | }; | 31 | }; |
| 34 | 32 | ||
| 35 | 33 | ||
| 36 | /* | 34 | struct lua_longjmp; /* defined in ldo.c */ |
| 37 | ** chain list of long jumps | ||
| 38 | */ | ||
| 39 | struct lua_longjmp { | ||
| 40 | jmp_buf b; | ||
| 41 | struct lua_longjmp *previous; | ||
| 42 | volatile int status; /* error code */ | ||
| 43 | StkId base; | ||
| 44 | }; | ||
| 45 | 35 | ||
| 46 | 36 | ||
| 47 | typedef struct stringtable { | 37 | typedef struct stringtable { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -422,11 +422,19 @@ static int testC (lua_State *L) { | |||
| 422 | else if EQ("concat") { | 422 | else if EQ("concat") { |
| 423 | lua_concat(L, getnum); | 423 | lua_concat(L, getnum); |
| 424 | } | 424 | } |
| 425 | else if EQ("call") { | 425 | else if EQ("rawcall") { |
| 426 | int narg = getnum; | 426 | int narg = getnum; |
| 427 | int nres = getnum; | 427 | int nres = getnum; |
| 428 | lua_rawcall(L, narg, nres); | 428 | lua_rawcall(L, narg, nres); |
| 429 | } | 429 | } |
| 430 | else if EQ("call") { | ||
| 431 | int narg = getnum; | ||
| 432 | int nres = getnum; | ||
| 433 | lua_call(L, narg, nres); | ||
| 434 | } | ||
| 435 | else if EQ("dostring") { | ||
| 436 | lua_dostring(L, luaL_check_string(L, getnum)); | ||
| 437 | } | ||
| 430 | else if EQ("type") { | 438 | else if EQ("type") { |
| 431 | lua_pushstring(L, lua_type(L, getnum)); | 439 | lua_pushstring(L, lua_type(L, getnum)); |
| 432 | } | 440 | } |
