diff options
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 59 |
1 files changed, 47 insertions, 12 deletions
@@ -98,11 +98,12 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
98 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 98 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); |
99 | break; | 99 | break; |
100 | } | 100 | } |
101 | case CLOSEPROTECT: { | 101 | case LUA_OK: { /* special case only for closing upvalues */ |
102 | setnilvalue(s2v(oldtop)); /* no error message */ | 102 | setnilvalue(s2v(oldtop)); /* no error message */ |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | default: { | 105 | default: { |
106 | lua_assert(errcode >= LUA_ERRRUN); /* real error */ | ||
106 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ | 107 | setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ |
107 | break; | 108 | break; |
108 | } | 109 | } |
@@ -118,7 +119,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
118 | } | 119 | } |
119 | else { /* thread has no error handler */ | 120 | else { /* thread has no error handler */ |
120 | global_State *g = G(L); | 121 | global_State *g = G(L); |
121 | errcode = luaF_close(L, L->stack, errcode); /* close all upvalues */ | 122 | errcode = luaD_closeprotected(L, 0, errcode); /* close all upvalues */ |
122 | L->status = cast_byte(errcode); /* mark it as dead */ | 123 | L->status = cast_byte(errcode); /* mark it as dead */ |
123 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 124 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ |
124 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ | 125 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ |
@@ -409,7 +410,7 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) { | |||
409 | default: /* multiple results (or to-be-closed variables) */ | 410 | default: /* multiple results (or to-be-closed variables) */ |
410 | if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ | 411 | if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ |
411 | ptrdiff_t savedres = savestack(L, res); | 412 | ptrdiff_t savedres = savestack(L, res); |
412 | luaF_close(L, res, LUA_OK); /* may change the stack */ | 413 | luaF_close(L, res, CLOSEKTOP); /* may change the stack */ |
413 | res = restorestack(L, savedres); | 414 | res = restorestack(L, savedres); |
414 | wanted = codeNresults(wanted); /* correct value */ | 415 | wanted = codeNresults(wanted); /* correct value */ |
415 | if (wanted == LUA_MULTRET) | 416 | if (wanted == LUA_MULTRET) |
@@ -636,16 +637,13 @@ static CallInfo *findpcall (lua_State *L) { | |||
636 | ** 'luaD_pcall'. If there is no recover point, returns zero. | 637 | ** 'luaD_pcall'. If there is no recover point, returns zero. |
637 | */ | 638 | */ |
638 | static int recover (lua_State *L, int status) { | 639 | static int recover (lua_State *L, int status) { |
639 | StkId oldtop; | ||
640 | CallInfo *ci = findpcall(L); | 640 | CallInfo *ci = findpcall(L); |
641 | if (ci == NULL) return 0; /* no recovery point */ | 641 | if (ci == NULL) return 0; /* no recovery point */ |
642 | /* "finish" luaD_pcall */ | 642 | /* "finish" luaD_pcall */ |
643 | oldtop = restorestack(L, ci->u2.funcidx); | ||
644 | L->ci = ci; | 643 | L->ci = ci; |
645 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 644 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ |
646 | status = luaF_close(L, oldtop, status); /* may change the stack */ | 645 | status = luaD_closeprotected(L, ci->u2.funcidx, status); |
647 | oldtop = restorestack(L, ci->u2.funcidx); | 646 | luaD_seterrorobj(L, status, restorestack(L, ci->u2.funcidx)); |
648 | luaD_seterrorobj(L, status, oldtop); | ||
649 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ | 647 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ |
650 | L->errfunc = ci->u.c.old_errfunc; | 648 | L->errfunc = ci->u.c.old_errfunc; |
651 | return 1; /* continue running the coroutine */ | 649 | return 1; /* continue running the coroutine */ |
@@ -770,6 +768,45 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
770 | 768 | ||
771 | 769 | ||
772 | /* | 770 | /* |
771 | ** Auxiliary structure to call 'luaF_close' in protected mode. | ||
772 | */ | ||
773 | struct CloseP { | ||
774 | StkId level; | ||
775 | int status; | ||
776 | }; | ||
777 | |||
778 | |||
779 | /* | ||
780 | ** Auxiliary function to call 'luaF_close' in protected mode. | ||
781 | */ | ||
782 | static void closepaux (lua_State *L, void *ud) { | ||
783 | struct CloseP *pcl = cast(struct CloseP *, ud); | ||
784 | luaF_close(L, pcl->level, pcl->status); | ||
785 | } | ||
786 | |||
787 | |||
788 | /* | ||
789 | ** Calls 'luaF_close' in protected mode. Return the original status | ||
790 | ** or, in case of errors, the new status. | ||
791 | */ | ||
792 | int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { | ||
793 | CallInfo *old_ci = L->ci; | ||
794 | lu_byte old_allowhooks = L->allowhook; | ||
795 | for (;;) { /* keep closing upvalues until no more errors */ | ||
796 | struct CloseP pcl; | ||
797 | pcl.level = restorestack(L, level); pcl.status = status; | ||
798 | status = luaD_rawrunprotected(L, &closepaux, &pcl); | ||
799 | if (likely(status == LUA_OK)) /* no more errors? */ | ||
800 | return pcl.status; | ||
801 | else { /* an error occurred; restore saved state and repeat */ | ||
802 | L->ci = old_ci; | ||
803 | L->allowhook = old_allowhooks; | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | |||
809 | /* | ||
773 | ** Call the C function 'func' in protected mode, restoring basic | 810 | ** Call the C function 'func' in protected mode, restoring basic |
774 | ** thread information ('allowhook', etc.) and in particular | 811 | ** thread information ('allowhook', etc.) and in particular |
775 | ** its stack level in case of errors. | 812 | ** its stack level in case of errors. |
@@ -783,12 +820,10 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
783 | L->errfunc = ef; | 820 | L->errfunc = ef; |
784 | status = luaD_rawrunprotected(L, func, u); | 821 | status = luaD_rawrunprotected(L, func, u); |
785 | if (unlikely(status != LUA_OK)) { /* an error occurred? */ | 822 | if (unlikely(status != LUA_OK)) { /* an error occurred? */ |
786 | StkId oldtop = restorestack(L, old_top); | ||
787 | L->ci = old_ci; | 823 | L->ci = old_ci; |
788 | L->allowhook = old_allowhooks; | 824 | L->allowhook = old_allowhooks; |
789 | status = luaF_close(L, oldtop, status); | 825 | status = luaD_closeprotected(L, old_top, status); |
790 | oldtop = restorestack(L, old_top); /* previous call may change stack */ | 826 | luaD_seterrorobj(L, status, restorestack(L, old_top)); |
791 | luaD_seterrorobj(L, status, oldtop); | ||
792 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ | 827 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ |
793 | } | 828 | } |
794 | L->errfunc = old_errfunc; | 829 | L->errfunc = old_errfunc; |