diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-04-22 11:40:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-04-22 11:40:50 -0300 |
commit | ee4859b3e3db6c1a3223669d15538b3852ca4791 (patch) | |
tree | a9a9532c03f0a9bc58599e34457cb618aa5f11f2 /ldo.c | |
parent | f388ee4a822b3d8027ed7c28aa21e9406e4a11eb (diff) | |
download | lua-ee4859b3e3db6c1a3223669d15538b3852ca4791.tar.gz lua-ee4859b3e3db6c1a3223669d15538b3852ca4791.tar.bz2 lua-ee4859b3e3db6c1a3223669d15538b3852ca4791.zip |
new way to handle errors (temporary version)
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 107 |
1 files changed, 36 insertions, 71 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.170 2002/04/15 19:34:42 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.171 2002/04/16 17:08:28 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 | */ |
@@ -38,9 +38,11 @@ struct lua_longjmp { | |||
38 | jmp_buf b; | 38 | jmp_buf b; |
39 | int allowhooks; /* `allowhook' state when protection was set */ | 39 | int allowhooks; /* `allowhook' state when protection was set */ |
40 | volatile int status; /* error code */ | 40 | volatile int status; /* error code */ |
41 | TObject err; /* function to be called in case of errors */ | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | 44 | ||
45 | |||
44 | static void correctstack (lua_State *L, TObject *oldstack) { | 46 | static void correctstack (lua_State *L, TObject *oldstack) { |
45 | struct lua_longjmp *lj; | 47 | struct lua_longjmp *lj; |
46 | CallInfo *ci; | 48 | CallInfo *ci; |
@@ -108,11 +110,11 @@ void luaD_growstack (lua_State *L, int n) { | |||
108 | static void luaD_growCI (lua_State *L) { | 110 | static void luaD_growCI (lua_State *L) { |
109 | L->ci--; | 111 | L->ci--; |
110 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ | 112 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ |
111 | luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ | 113 | luaD_error(L, NULL, LUA_ERRERR); /* break run without error message */ |
112 | else { | 114 | else { |
113 | luaD_reallocCI(L, 2*L->size_ci); | 115 | luaD_reallocCI(L, 2*L->size_ci); |
114 | if (L->size_ci > LUA_MAXCALLS) | 116 | if (L->size_ci > LUA_MAXCALLS) |
115 | luaD_error(L, "stack overflow"); | 117 | luaD_runerror(L, "stack overflow"); |
116 | } | 118 | } |
117 | L->ci++; | 119 | L->ci++; |
118 | } | 120 | } |
@@ -278,7 +280,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
278 | firstResult = luaV_execute(L); /* call it */ | 280 | firstResult = luaV_execute(L); /* call it */ |
279 | if (firstResult == NULL) { | 281 | if (firstResult == NULL) { |
280 | luaD_poscall(L, 0, L->top); | 282 | luaD_poscall(L, 0, L->top); |
281 | luaD_error(L, "attempt to `yield' across tag-method/C-call boundary"); | 283 | luaD_runerror(L, "attempt to `yield' across tag-method/C-call boundary"); |
282 | } | 284 | } |
283 | } | 285 | } |
284 | luaD_poscall(L, nResults, firstResult); | 286 | luaD_poscall(L, nResults, firstResult); |
@@ -325,14 +327,17 @@ static void resume (lua_State *L, void *numres) { | |||
325 | LUA_API int lua_resume (lua_State *L, lua_State *co) { | 327 | LUA_API int lua_resume (lua_State *L, lua_State *co) { |
326 | CallInfo *ci; | 328 | CallInfo *ci; |
327 | int numres; | 329 | int numres; |
330 | TObject o; | ||
328 | int status; | 331 | int status; |
329 | lua_lock(L); | 332 | lua_lock(L); |
330 | ci = co->ci; | 333 | ci = co->ci; |
331 | if (ci == co->base_ci) /* no activation record? ?? */ | 334 | if (ci == co->base_ci) /* no activation record? ?? */ |
332 | luaD_error(L, "thread is dead - cannot be resumed"); | 335 | luaD_runerror(L, "thread is dead - cannot be resumed"); |
333 | if (co->errorJmp != NULL) /* ?? */ | 336 | if (co->errorJmp != NULL) /* ?? */ |
334 | luaD_error(L, "thread is active - cannot be resumed"); | 337 | luaD_runerror(L, "thread is active - cannot be resumed"); |
335 | status = luaD_runprotected(co, resume, &numres); | 338 | setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); |
339 | luaV_gettable(L, gt(L), &o, &o); | ||
340 | status = luaD_runprotected(co, resume, &o, &numres); | ||
336 | if (status == 0) | 341 | if (status == 0) |
337 | move_results(L, co->top - numres, co->top); | 342 | move_results(L, co->top - numres, co->top); |
338 | lua_unlock(L); | 343 | lua_unlock(L); |
@@ -345,7 +350,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
345 | lua_lock(L); | 350 | lua_lock(L); |
346 | ci = L->ci; | 351 | ci = L->ci; |
347 | if (ci_func(ci-1)->c.isC) | 352 | if (ci_func(ci-1)->c.isC) |
348 | luaD_error(L, "cannot `yield' a C function"); | 353 | luaD_runerror(L, "cannot `yield' a C function"); |
349 | ci->yield_results = nresults; | 354 | ci->yield_results = nresults; |
350 | lua_unlock(L); | 355 | lua_unlock(L); |
351 | return -1; | 356 | return -1; |
@@ -360,24 +365,23 @@ struct CallS { /* data to `f_call' */ | |||
360 | int nresults; | 365 | int nresults; |
361 | }; | 366 | }; |
362 | 367 | ||
368 | |||
363 | static void f_call (lua_State *L, void *ud) { | 369 | static void f_call (lua_State *L, void *ud) { |
364 | struct CallS *c = cast(struct CallS *, ud); | 370 | struct CallS *c = cast(struct CallS *, ud); |
365 | luaD_call(L, c->func, c->nresults); | 371 | luaD_call(L, c->func, c->nresults); |
366 | } | 372 | } |
367 | 373 | ||
368 | 374 | ||
369 | LUA_API int lua_call (lua_State *L, int nargs, int nresults) { | 375 | int luaD_pcall (lua_State *L, int nargs, int nresults, const TObject *err) { |
370 | struct CallS c; | 376 | struct CallS c; |
371 | int status; | 377 | int status; |
372 | lua_lock(L); | ||
373 | c.func = L->top - (nargs+1); /* function to be called */ | 378 | c.func = L->top - (nargs+1); /* function to be called */ |
374 | c.nresults = nresults; | 379 | c.nresults = nresults; |
375 | status = luaD_runprotected(L, f_call, &c); | 380 | status = luaD_runprotected(L, &f_call, err, &c); |
376 | if (status != 0) { /* an error occurred? */ | 381 | if (status != 0) { /* an error occurred? */ |
377 | L->top -= nargs+1; /* remove parameters and func from the stack */ | 382 | L->top -= nargs+1; /* remove parameters and func from the stack */ |
378 | luaF_close(L, L->top); /* close eventual pending closures */ | 383 | luaF_close(L, L->top); /* close eventual pending closures */ |
379 | } | 384 | } |
380 | lua_unlock(L); | ||
381 | return status; | 385 | return status; |
382 | } | 386 | } |
383 | 387 | ||
@@ -400,8 +404,9 @@ static void f_parser (lua_State *L, void *ud) { | |||
400 | } | 404 | } |
401 | 405 | ||
402 | 406 | ||
403 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 407 | int luaD_protectedparser (lua_State *L, ZIO *z, int bin) { |
404 | struct SParser p; | 408 | struct SParser p; |
409 | TObject o; | ||
405 | lu_mem old_blocks; | 410 | lu_mem old_blocks; |
406 | int status; | 411 | int status; |
407 | lua_lock(L); | 412 | lua_lock(L); |
@@ -410,7 +415,9 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { | |||
410 | if (G(L)->nblocks/8 >= G(L)->GCthreshold/10) | 415 | if (G(L)->nblocks/8 >= G(L)->GCthreshold/10) |
411 | luaC_collectgarbage(L); | 416 | luaC_collectgarbage(L); |
412 | old_blocks = G(L)->nblocks; | 417 | old_blocks = G(L)->nblocks; |
413 | status = luaD_runprotected(L, f_parser, &p); | 418 | setsvalue(&o, luaS_newliteral(L, "_ERRORMESSAGE")); |
419 | luaV_gettable(L, gt(L), &o, &o); | ||
420 | status = luaD_runprotected(L, f_parser, &o, &p); | ||
414 | if (status == 0) { | 421 | if (status == 0) { |
415 | /* add new memory to threshold (as it probably will stay) */ | 422 | /* add new memory to threshold (as it probably will stay) */ |
416 | lua_assert(G(L)->nblocks >= old_blocks); | 423 | lua_assert(G(L)->nblocks >= old_blocks); |
@@ -423,47 +430,6 @@ static int protectedparser (lua_State *L, ZIO *z, int bin) { | |||
423 | } | 430 | } |
424 | 431 | ||
425 | 432 | ||
426 | LUA_API int lua_loadfile (lua_State *L, const char *filename) { | ||
427 | ZIO z; | ||
428 | int status; | ||
429 | int bin; /* flag for file mode */ | ||
430 | int nlevel; /* level on the stack of filename */ | ||
431 | FILE *f = (filename == NULL) ? stdin : fopen(filename, "r"); | ||
432 | if (f == NULL) return LUA_ERRFILE; /* unable to open file */ | ||
433 | bin = (ungetc(getc(f), f) == LUA_SIGNATURE[0]); | ||
434 | if (bin && f != stdin) { | ||
435 | fclose(f); | ||
436 | f = fopen(filename, "rb"); /* reopen in binary mode */ | ||
437 | if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ | ||
438 | } | ||
439 | if (filename == NULL) | ||
440 | lua_pushstring(L, "=stdin"); | ||
441 | else { | ||
442 | lua_pushliteral(L, "@"); | ||
443 | lua_pushstring(L, filename); | ||
444 | lua_concat(L, 2); | ||
445 | } | ||
446 | nlevel = lua_gettop(L); | ||
447 | filename = lua_tostring(L, -1); /* filename = `@'..filename */ | ||
448 | luaZ_Fopen(&z, f, filename); | ||
449 | status = protectedparser(L, &z, bin); | ||
450 | if (ferror(f)) status = LUA_ERRFILE; | ||
451 | lua_remove(L, nlevel); /* remove filename */ | ||
452 | if (f != stdin) | ||
453 | fclose(f); | ||
454 | return status; | ||
455 | } | ||
456 | |||
457 | |||
458 | LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size, | ||
459 | const char *name) { | ||
460 | ZIO z; | ||
461 | if (!name) name = "?"; | ||
462 | luaZ_mopen(&z, buff, size, name); | ||
463 | return protectedparser(L, &z, buff[0]==LUA_SIGNATURE[0]); | ||
464 | } | ||
465 | |||
466 | |||
467 | 433 | ||
468 | /* | 434 | /* |
469 | ** {====================================================== | 435 | ** {====================================================== |
@@ -472,16 +438,14 @@ LUA_API int lua_loadbuffer (lua_State *L, const char *buff, size_t size, | |||
472 | */ | 438 | */ |
473 | 439 | ||
474 | 440 | ||
475 | static void message (lua_State *L, const char *s) { | 441 | static void message (lua_State *L, const char *msg) { |
476 | TObject o, m; | 442 | TObject *m = &L->errorJmp->err; |
477 | setsvalue(&o, luaS_newliteral(L, LUA_ERRORMESSAGE)); | 443 | if (ttype(m) == LUA_TFUNCTION) { |
478 | luaV_gettable(L, gt(L), &o, &m); | 444 | setobj(L->top, m); |
479 | if (ttype(&m) == LUA_TFUNCTION) { | ||
480 | setobj(L->top, &m); | ||
481 | incr_top(L); | 445 | incr_top(L); |
482 | setsvalue(L->top, luaS_new(L, s)); | 446 | setsvalue(L->top, luaS_new(L, msg)); |
483 | incr_top(L); | 447 | incr_top(L); |
484 | luaD_call(L, L->top-2, 0); | 448 | luaD_call(L, L->top - 2, 0); |
485 | } | 449 | } |
486 | } | 450 | } |
487 | 451 | ||
@@ -489,15 +453,10 @@ static void message (lua_State *L, const char *s) { | |||
489 | /* | 453 | /* |
490 | ** Reports an error, and jumps up to the available recovery label | 454 | ** Reports an error, and jumps up to the available recovery label |
491 | */ | 455 | */ |
492 | void luaD_error (lua_State *L, const char *s) { | 456 | void luaD_error (lua_State *L, const char *s, int errcode) { |
493 | if (s) message(L, s); | ||
494 | luaD_breakrun(L, LUA_ERRRUN); | ||
495 | } | ||
496 | |||
497 | |||
498 | void luaD_breakrun (lua_State *L, int errcode) { | ||
499 | if (L->errorJmp) { | 457 | if (L->errorJmp) { |
500 | L->errorJmp->status = errcode; | 458 | L->errorJmp->status = errcode; |
459 | if (s) message(L, s); | ||
501 | longjmp(L->errorJmp->b, 1); | 460 | longjmp(L->errorJmp->b, 1); |
502 | } | 461 | } |
503 | else { | 462 | else { |
@@ -507,12 +466,18 @@ void luaD_breakrun (lua_State *L, int errcode) { | |||
507 | } | 466 | } |
508 | 467 | ||
509 | 468 | ||
510 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | 469 | void luaD_runerror (lua_State *L, const char *s) { |
470 | luaD_error(L, s, LUA_ERRRUN); | ||
471 | } | ||
472 | |||
473 | |||
474 | int luaD_runprotected (lua_State *L, Pfunc f, const TObject *err, void *ud) { | ||
511 | struct lua_longjmp lj; | 475 | struct lua_longjmp lj; |
512 | lj.ci = L->ci; | 476 | lj.ci = L->ci; |
513 | lj.top = L->top; | 477 | lj.top = L->top; |
514 | lj.allowhooks = L->allowhooks; | 478 | lj.allowhooks = L->allowhooks; |
515 | lj.status = 0; | 479 | lj.status = 0; |
480 | lj.err = *err; | ||
516 | lj.previous = L->errorJmp; /* chain new error handler */ | 481 | lj.previous = L->errorJmp; /* chain new error handler */ |
517 | L->errorJmp = &lj; | 482 | L->errorJmp = &lj; |
518 | if (setjmp(lj.b) == 0) | 483 | if (setjmp(lj.b) == 0) |