summaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-01 17:48:12 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-05-01 17:48:12 -0300
commit751cd867d3e0338279fa6f3390c8b7ddc0108659 (patch)
tree726f6f3cd49109382b2c0d7ee6a1e0fea740afbd /ldo.c
parentb36b2a061c88be22e36900146cbcad39bab07f5d (diff)
downloadlua-751cd867d3e0338279fa6f3390c8b7ddc0108659.tar.gz
lua-751cd867d3e0338279fa6f3390c8b7ddc0108659.tar.bz2
lua-751cd867d3e0338279fa6f3390c8b7ddc0108659.zip
new way to handle errors
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c90
1 files changed, 59 insertions, 31 deletions
diff --git a/ldo.c b/ldo.c
index c89d3a3c..4dfb7d9e 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,12 +1,11 @@
1/* 1/*
2** $Id: ldo.c,v 1.171 2002/04/16 17:08:28 roberto Exp roberto $ 2** $Id: ldo.c,v 1.172 2002/04/22 14:40: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*/
6 6
7 7
8#include <setjmp.h> 8#include <setjmp.h>
9#include <stdio.h>
10#include <stdlib.h> 9#include <stdlib.h>
11#include <string.h> 10#include <string.h>
12 11
@@ -38,7 +37,7 @@ struct lua_longjmp {
38 jmp_buf b; 37 jmp_buf b;
39 int allowhooks; /* `allowhook' state when protection was set */ 38 int allowhooks; /* `allowhook' state when protection was set */
40 volatile int status; /* error code */ 39 volatile int status; /* error code */
41 TObject err; /* function to be called in case of errors */ 40 TObject *err; /* error function -> message (start of `ud') */
42}; 41};
43 42
44 43
@@ -110,7 +109,7 @@ void luaD_growstack (lua_State *L, int n) {
110static void luaD_growCI (lua_State *L) { 109static void luaD_growCI (lua_State *L) {
111 L->ci--; 110 L->ci--;
112 if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ 111 if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */
113 luaD_error(L, NULL, LUA_ERRERR); /* break run without error message */ 112 luaD_error(L, "error in error handling", LUA_ERRERR);
114 else { 113 else {
115 luaD_reallocCI(L, 2*L->size_ci); 114 luaD_reallocCI(L, 2*L->size_ci);
116 if (L->size_ci > LUA_MAXCALLS) 115 if (L->size_ci > LUA_MAXCALLS)
@@ -303,7 +302,12 @@ static void move_results (lua_State *L, TObject *from, TObject *to) {
303} 302}
304 303
305 304
306static void resume (lua_State *L, void *numres) { 305struct ResS {
306 TObject err;
307 int numres;
308};
309
310static void resume (lua_State *L, void *ud) {
307 StkId firstResult; 311 StkId firstResult;
308 CallInfo *ci = L->ci; 312 CallInfo *ci = L->ci;
309 if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */ 313 if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */
@@ -316,9 +320,9 @@ static void resume (lua_State *L, void *numres) {
316 } 320 }
317 firstResult = luaV_execute(L); 321 firstResult = luaV_execute(L);
318 if (firstResult == NULL) /* yield? */ 322 if (firstResult == NULL) /* yield? */
319 *(int *)numres = L->ci->yield_results; 323 cast(struct ResS *, ud)->numres = L->ci->yield_results;
320 else { /* return */ 324 else { /* return */
321 *(int *)numres = L->top - firstResult; 325 cast(struct ResS *, ud)->numres = L->top - firstResult;
322 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ 326 luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
323 } 327 }
324} 328}
@@ -326,8 +330,7 @@ static void resume (lua_State *L, void *numres) {
326 330
327LUA_API int lua_resume (lua_State *L, lua_State *co) { 331LUA_API int lua_resume (lua_State *L, lua_State *co) {
328 CallInfo *ci; 332 CallInfo *ci;
329 int numres; 333 struct ResS ud;
330 TObject o;
331 int status; 334 int status;
332 lua_lock(L); 335 lua_lock(L);
333 ci = co->ci; 336 ci = co->ci;
@@ -335,11 +338,17 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
335 luaD_runerror(L, "thread is dead - cannot be resumed"); 338 luaD_runerror(L, "thread is dead - cannot be resumed");
336 if (co->errorJmp != NULL) /* ?? */ 339 if (co->errorJmp != NULL) /* ?? */
337 luaD_runerror(L, "thread is active - cannot be resumed"); 340 luaD_runerror(L, "thread is active - cannot be resumed");
338 setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); 341 if (L->errorJmp) {
339 luaV_gettable(L, gt(L), &o, &o); 342 setobj(&ud.err, L->errorJmp->err);
340 status = luaD_runprotected(co, resume, &o, &numres); 343 }
344 else
345 setnilvalue(&ud.err);
346 status = luaD_runprotected(co, resume, &ud.err);
341 if (status == 0) 347 if (status == 0)
342 move_results(L, co->top - numres, co->top); 348 move_results(L, co->top - ud.numres, co->top);
349 else {
350 setobj(L->top++, &ud.err);
351}
343 lua_unlock(L); 352 lua_unlock(L);
344 return status; 353 return status;
345} 354}
@@ -361,6 +370,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
361** Execute a protected call. 370** Execute a protected call.
362*/ 371*/
363struct CallS { /* data to `f_call' */ 372struct CallS { /* data to `f_call' */
373 TObject err; /* error field... */
364 StkId func; 374 StkId func;
365 int nresults; 375 int nresults;
366}; 376};
@@ -377,10 +387,12 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
377 int status; 387 int status;
378 c.func = L->top - (nargs+1); /* function to be called */ 388 c.func = L->top - (nargs+1); /* function to be called */
379 c.nresults = nresults; 389 c.nresults = nresults;
380 status = luaD_runprotected(L, &f_call, err, &c); 390 c.err = *err;
391 status = luaD_runprotected(L, &f_call, &c.err);
381 if (status != 0) { /* an error occurred? */ 392 if (status != 0) { /* an error occurred? */
382 L->top -= nargs+1; /* remove parameters and func from the stack */ 393 L->top -= nargs+1; /* remove parameters and func from the stack */
383 luaF_close(L, L->top); /* close eventual pending closures */ 394 luaF_close(L, L->top); /* close eventual pending closures */
395 setobj(L->top++, &c.err);
384 } 396 }
385 return status; 397 return status;
386} 398}
@@ -390,6 +402,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) {
390** Execute a protected parser. 402** Execute a protected parser.
391*/ 403*/
392struct SParser { /* data to `f_parser' */ 404struct SParser { /* data to `f_parser' */
405 TObject err; /* error field... */
393 ZIO *z; 406 ZIO *z;
394 int bin; 407 int bin;
395}; 408};
@@ -406,7 +419,6 @@ static void f_parser (lua_State *L, void *ud) {
406 419
407int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { 420int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
408 struct SParser p; 421 struct SParser p;
409 TObject o;
410 lu_mem old_blocks; 422 lu_mem old_blocks;
411 int status; 423 int status;
412 lua_lock(L); 424 lua_lock(L);
@@ -415,16 +427,18 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
415 if (G(L)->nblocks/8 >= G(L)->GCthreshold/10) 427 if (G(L)->nblocks/8 >= G(L)->GCthreshold/10)
416 luaC_collectgarbage(L); 428 luaC_collectgarbage(L);
417 old_blocks = G(L)->nblocks; 429 old_blocks = G(L)->nblocks;
418 setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); 430 setnilvalue(&p.err);
419 luaV_gettable(L, gt(L), &o, &o); 431 status = luaD_runprotected(L, f_parser, &p.err);
420 status = luaD_runprotected(L, f_parser, &o, &p);
421 if (status == 0) { 432 if (status == 0) {
422 /* add new memory to threshold (as it probably will stay) */ 433 /* add new memory to threshold (as it probably will stay) */
423 lua_assert(G(L)->nblocks >= old_blocks); 434 lua_assert(G(L)->nblocks >= old_blocks);
424 G(L)->GCthreshold += (G(L)->nblocks - old_blocks); 435 G(L)->GCthreshold += (G(L)->nblocks - old_blocks);
425 } 436 }
426 else if (status == LUA_ERRRUN) /* an error occurred: correct error code */ 437 else {
427 status = LUA_ERRSYNTAX; 438 setobj(L->top++, &p.err);
439 if (status == LUA_ERRRUN) /* an error occurred: correct error code */
440 status = LUA_ERRSYNTAX;
441 }
428 lua_unlock(L); 442 lua_unlock(L);
429 return status; 443 return status;
430} 444}
@@ -438,14 +452,18 @@ int luaD_protectedparser (lua_State *L, ZIO *z, int bin) {
438*/ 452*/
439 453
440 454
441static void message (lua_State *L, const char *msg) { 455static void message (lua_State *L, const TObject *msg, int nofunc) {
442 TObject *m = &L->errorJmp->err; 456 TObject *m = L->errorJmp->err;
443 if (ttype(m) == LUA_TFUNCTION) { 457 if (nofunc || ttype(m) != LUA_TFUNCTION) { /* no error function? */
458 setobj(m, msg); /* keep error message */
459 }
460 else { /* call error function */
444 setobj(L->top, m); 461 setobj(L->top, m);
445 incr_top(L); 462 incr_top(L);
446 setsvalue(L->top, luaS_new(L, msg)); 463 setobj(L->top, msg);
447 incr_top(L); 464 incr_top(L);
448 luaD_call(L, L->top - 2, 0); 465 luaD_call(L, L->top - 2, 1);
466 setobj(m, L->top - 1);
449 } 467 }
450} 468}
451 469
@@ -453,10 +471,10 @@ static void message (lua_State *L, const char *msg) {
453/* 471/*
454** Reports an error, and jumps up to the available recovery label 472** Reports an error, and jumps up to the available recovery label
455*/ 473*/
456void luaD_error (lua_State *L, const char *s, int errcode) { 474void luaD_errorobj (lua_State *L, const TObject *s, int errcode) {
457 if (L->errorJmp) { 475 if (L->errorJmp) {
458 L->errorJmp->status = errcode; 476 L->errorJmp->status = errcode;
459 if (s) message(L, s); 477 message(L, s, (errcode >= LUA_ERRMEM));
460 longjmp(L->errorJmp->b, 1); 478 longjmp(L->errorJmp->b, 1);
461 } 479 }
462 else { 480 else {
@@ -466,24 +484,34 @@ void luaD_error (lua_State *L, const char *s, int errcode) {
466} 484}
467 485
468 486
487void luaD_error (lua_State *L, const char *s, int errcode) {
488 TObject errobj;
489 if (errcode == LUA_ERRMEM && (G(L) == NULL || G(L)->GCthreshold == 0))
490 setnilvalue(&errobj); /* error bulding state */
491 else
492 setsvalue(&errobj, luaS_new(L, s));
493 luaD_errorobj(L, &errobj, errcode);
494}
495
496
469void luaD_runerror (lua_State *L, const char *s) { 497void luaD_runerror (lua_State *L, const char *s) {
470 luaD_error(L, s, LUA_ERRRUN); 498 luaD_error(L, s, LUA_ERRRUN);
471} 499}
472 500
473 501
474int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud) { 502int luaD_runprotected (lua_State *L, Pfunc f, TObject *ud) {
475 struct lua_longjmp lj; 503 struct lua_longjmp lj;
476 lj.ci = L->ci; 504 lj.ci = L->ci;
477 lj.top = L->top; 505 lj.top = L->top;
478 lj.allowhooks = L->allowhooks; 506 lj.allowhooks = L->allowhooks;
479 lj.status = 0; 507 lj.status = 0;
480 lj.err = *err; 508 lj.err = ud;
481 lj.previous = L->errorJmp; /* chain new error handler */ 509 lj.previous = L->errorJmp; /* chain new error handler */
482 L->errorJmp = &lj; 510 L->errorJmp = &lj;
483 if (setjmp(lj.b) == 0) 511 if (setjmp(lj.b) == 0)
484 (*f)(L, ud); 512 (*f)(L, ud);
485 else { /* an error occurred: restore the state */ 513 else { /* an error occurred */
486 L->ci = lj.ci; 514 L->ci = lj.ci; /* restore the state */
487 L->top = lj.top; 515 L->top = lj.top;
488 L->allowhooks = lj.allowhooks; 516 L->allowhooks = lj.allowhooks;
489 restore_stack_limit(L); 517 restore_stack_limit(L);