diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-18 12:19:27 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-06-18 12:19:27 -0300 |
commit | 1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b (patch) | |
tree | e845de9ee24b94362146e38410ae0670df18526b /ldo.c | |
parent | 8f080fd683d63b0cd4b38380f6a5bdae5d6e2584 (diff) | |
download | lua-1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b.tar.gz lua-1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b.tar.bz2 lua-1dbe708aa84f3a1e51daf8d7e2f714e2b02f554b.zip |
new protocol for error handling
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 91 |
1 files changed, 42 insertions, 49 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.178 2002/06/03 17:46:34 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.179 2002/06/03 20:12:50 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 | */ |
@@ -37,10 +37,16 @@ struct lua_longjmp { | |||
37 | jmp_buf b; | 37 | jmp_buf b; |
38 | int allowhooks; /* `allowhook' state when protection was set */ | 38 | int allowhooks; /* `allowhook' state when protection was set */ |
39 | volatile int status; /* error code */ | 39 | volatile int status; /* error code */ |
40 | TObject *err; /* error function -> message (start of `ud') */ | 40 | TObject *err; /* error messages (start of `ud') */ |
41 | }; | 41 | }; |
42 | 42 | ||
43 | 43 | ||
44 | static void pusherrormsg (lua_State *L, int status, TObject *err) { | ||
45 | setobj(L->top++, &err[0]); | ||
46 | if (status == LUA_ERRRUN) | ||
47 | setobj(L->top++, &err[1]); | ||
48 | } | ||
49 | |||
44 | 50 | ||
45 | static void correctstack (lua_State *L, TObject *oldstack) { | 51 | static void correctstack (lua_State *L, TObject *oldstack) { |
46 | struct lua_longjmp *lj; | 52 | struct lua_longjmp *lj; |
@@ -109,7 +115,7 @@ void luaD_growstack (lua_State *L, int n) { | |||
109 | static void luaD_growCI (lua_State *L) { | 115 | static void luaD_growCI (lua_State *L) { |
110 | L->ci--; | 116 | L->ci--; |
111 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ | 117 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ |
112 | luaD_error(L, "error in error handling", LUA_ERRERR); | 118 | luaD_throw(L, LUA_ERRERR); |
113 | else { | 119 | else { |
114 | luaD_reallocCI(L, 2*L->size_ci); | 120 | luaD_reallocCI(L, 2*L->size_ci); |
115 | if (L->size_ci > LUA_MAXCALLS) | 121 | if (L->size_ci > LUA_MAXCALLS) |
@@ -302,7 +308,7 @@ static void move_results (lua_State *L, TObject *from, TObject *to) { | |||
302 | 308 | ||
303 | 309 | ||
304 | struct ResS { | 310 | struct ResS { |
305 | TObject err; | 311 | TObject err[2]; |
306 | int numres; | 312 | int numres; |
307 | }; | 313 | }; |
308 | 314 | ||
@@ -337,17 +343,11 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) { | |||
337 | luaG_runerror(L, "thread is dead - cannot be resumed"); | 343 | luaG_runerror(L, "thread is dead - cannot be resumed"); |
338 | if (co->errorJmp != NULL) /* ?? */ | 344 | if (co->errorJmp != NULL) /* ?? */ |
339 | luaG_runerror(L, "thread is active - cannot be resumed"); | 345 | luaG_runerror(L, "thread is active - cannot be resumed"); |
340 | if (L->errorJmp) { | 346 | status = luaD_runprotected(co, resume, ud.err); |
341 | setobj(&ud.err, L->errorJmp->err); | ||
342 | } | ||
343 | else | ||
344 | setnilvalue(&ud.err); | ||
345 | status = luaD_runprotected(co, resume, &ud.err); | ||
346 | if (status == 0) | 347 | if (status == 0) |
347 | move_results(L, co->top - ud.numres, co->top); | 348 | move_results(L, co->top - ud.numres, co->top); |
348 | else { | 349 | else |
349 | setobj(L->top++, &ud.err); | 350 | pusherrormsg(L, status, ud.err); |
350 | } | ||
351 | lua_unlock(L); | 351 | lua_unlock(L); |
352 | return status; | 352 | return status; |
353 | } | 353 | } |
@@ -369,7 +369,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
369 | ** Execute a protected call. | 369 | ** Execute a protected call. |
370 | */ | 370 | */ |
371 | struct CallS { /* data to `f_call' */ | 371 | struct CallS { /* data to `f_call' */ |
372 | TObject err; /* error field... */ | 372 | TObject err[2]; |
373 | StkId func; | 373 | StkId func; |
374 | int nresults; | 374 | int nresults; |
375 | }; | 375 | }; |
@@ -381,17 +381,16 @@ static void f_call (lua_State *L, void *ud) { | |||
381 | } | 381 | } |
382 | 382 | ||
383 | 383 | ||
384 | int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { | 384 | int luaD_pcall (lua_State *L, int nargs, int nresults) { |
385 | struct CallS c; | 385 | struct CallS c; |
386 | int status; | 386 | int status; |
387 | c.func = L->top - (nargs+1); /* function to be called */ | 387 | c.func = L->top - (nargs+1); /* function to be called */ |
388 | c.nresults = nresults; | 388 | c.nresults = nresults; |
389 | c.err = *err; | 389 | status = luaD_runprotected(L, &f_call, c.err); |
390 | status = luaD_runprotected(L, &f_call, &c.err); | ||
391 | if (status != 0) { /* an error occurred? */ | 390 | if (status != 0) { /* an error occurred? */ |
392 | L->top -= nargs+1; /* remove parameters and func from the stack */ | 391 | L->top -= nargs+1; /* remove parameters and func from the stack */ |
393 | luaF_close(L, L->top); /* close eventual pending closures */ | 392 | luaF_close(L, L->top); /* close eventual pending closures */ |
394 | setobj(L->top++, &c.err); | 393 | pusherrormsg(L, status, c.err); |
395 | } | 394 | } |
396 | return status; | 395 | return status; |
397 | } | 396 | } |
@@ -401,7 +400,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { | |||
401 | ** Execute a protected parser. | 400 | ** Execute a protected parser. |
402 | */ | 401 | */ |
403 | struct SParser { /* data to `f_parser' */ | 402 | struct SParser { /* data to `f_parser' */ |
404 | TObject err; /* error field... */ | 403 | TObject err[2]; |
405 | ZIO *z; | 404 | ZIO *z; |
406 | int bin; | 405 | int bin; |
407 | }; | 406 | }; |
@@ -425,15 +424,14 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { | |||
425 | if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold) | 424 | if (G(L)->nblocks + G(L)->nblocks/4 >= G(L)->GCthreshold) |
426 | luaC_collectgarbage(L); | 425 | luaC_collectgarbage(L); |
427 | old_blocks = G(L)->nblocks; | 426 | old_blocks = G(L)->nblocks; |
428 | setnilvalue(&p.err); | 427 | status = luaD_runprotected(L, f_parser, p.err); |
429 | status = luaD_runprotected(L, f_parser, &p.err); | ||
430 | if (status == 0) { | 428 | if (status == 0) { |
431 | /* add new memory to threshold (as it probably will stay) */ | 429 | /* add new memory to threshold (as it probably will stay) */ |
432 | lua_assert(G(L)->nblocks >= old_blocks); | 430 | lua_assert(G(L)->nblocks >= old_blocks); |
433 | G(L)->GCthreshold += (G(L)->nblocks - old_blocks); | 431 | G(L)->GCthreshold += (G(L)->nblocks - old_blocks); |
434 | } | 432 | } |
435 | else | 433 | else |
436 | setobj(L->top++, &p.err); | 434 | pusherrormsg(L, status, p.err); |
437 | return status; | 435 | return status; |
438 | } | 436 | } |
439 | 437 | ||
@@ -445,29 +443,34 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { | |||
445 | ** ======================================================= | 443 | ** ======================================================= |
446 | */ | 444 | */ |
447 | 445 | ||
448 | 446 | static void seterrorobj (lua_State *L, int errcode, TObject *m) { | |
449 | static void message (lua_State *L, const TObject *msg, int nofunc) { | 447 | switch (errcode) { |
450 | TObject *m = L->errorJmp->err; | 448 | case LUA_ERRMEM: { |
451 | if (nofunc || ttype(m) != LUA_TFUNCTION) { /* no error function? */ | 449 | if (G(L) != NULL && G(L)->GCthreshold > 0) /* state is OK? */ |
452 | setobj(m, msg); /* keep error message */ | 450 | setsvalue(&m[0], luaS_new(L, MEMERRMSG)); |
453 | } | 451 | break; |
454 | else { /* call error function */ | 452 | } |
455 | setobj(L->top, m); | 453 | case LUA_ERRERR: { |
456 | setobj(L->top + 1, msg); | 454 | setsvalue(&m[0], luaS_new(L, "error in error handling")); |
457 | L->top += 2; | 455 | break; |
458 | luaD_call(L, L->top - 2, 1); | 456 | } |
459 | setobj(m, L->top - 1); | 457 | case LUA_ERRSYNTAX: { /* message is on stack top */ |
458 | setobj(&m[0], L->top - 1); | ||
459 | break; | ||
460 | } | ||
461 | case LUA_ERRRUN: { /* traceback is on stack top */ | ||
462 | setobj(&m[0], L->top - 2); | ||
463 | setobj(&m[1], L->top - 1); | ||
464 | break; | ||
465 | } | ||
460 | } | 466 | } |
461 | } | 467 | } |
462 | 468 | ||
463 | 469 | ||
464 | /* | 470 | void luaD_throw (lua_State *L, int errcode) { |
465 | ** Reports an error, and jumps up to the available recovery label | 471 | seterrorobj(L, errcode, L->errorJmp->err); |
466 | */ | ||
467 | void luaD_errorobj (lua_State *L, const TObject *s, int errcode) { | ||
468 | if (L->errorJmp) { | 472 | if (L->errorJmp) { |
469 | L->errorJmp->status = errcode; | 473 | L->errorJmp->status = errcode; |
470 | message(L, s, (errcode >= LUA_ERRMEM)); | ||
471 | longjmp(L->errorJmp->b, 1); | 474 | longjmp(L->errorJmp->b, 1); |
472 | } | 475 | } |
473 | else { | 476 | else { |
@@ -477,16 +480,6 @@ void luaD_errorobj (lua_State *L, const TObject *s, int errcode) { | |||
477 | } | 480 | } |
478 | 481 | ||
479 | 482 | ||
480 | void luaD_error (lua_State *L, const char *s, int errcode) { | ||
481 | TObject errobj; | ||
482 | if (errcode == LUA_ERRMEM && (G(L) == NULL || G(L)->GCthreshold == 0)) | ||
483 | setnilvalue(&errobj); /* error bulding state */ | ||
484 | else | ||
485 | setsvalue(&errobj, luaS_new(L, s)); | ||
486 | luaD_errorobj(L, &errobj, errcode); | ||
487 | } | ||
488 | |||
489 | |||
490 | int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) { | 483 | int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) { |
491 | struct lua_longjmp lj; | 484 | struct lua_longjmp lj; |
492 | lj.ci = L->ci; | 485 | lj.ci = L->ci; |