diff options
| author | Li Jin <dragon-fly@qq.com> | 2021-01-22 17:54:39 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2021-01-22 17:54:39 +0800 |
| commit | 236bcc6e10f59b9336603571f1683cbe4aa411a9 (patch) | |
| tree | 7116190d16a12bfcb0819e802c6e1d4ac8b0ec70 | |
| parent | f61b96675547c8bf40c7f646e3766f4139efd927 (diff) | |
| download | yuescript-236bcc6e10f59b9336603571f1683cbe4aa411a9.tar.gz yuescript-236bcc6e10f59b9336603571f1683cbe4aa411a9.tar.bz2 yuescript-236bcc6e10f59b9336603571f1683cbe4aa411a9.zip | |
update included Lua.
| -rw-r--r-- | src/lua/lapi.c | 21 | ||||
| -rw-r--r-- | src/lua/lauxlib.c | 8 | ||||
| -rw-r--r-- | src/lua/lcorolib.c | 7 | ||||
| -rw-r--r-- | src/lua/ldebug.c | 23 | ||||
| -rw-r--r-- | src/lua/ldebug.h | 1 | ||||
| -rw-r--r-- | src/lua/ldo.c | 125 | ||||
| -rw-r--r-- | src/lua/ldo.h | 1 | ||||
| -rw-r--r-- | src/lua/lfunc.c | 117 | ||||
| -rw-r--r-- | src/lua/lfunc.h | 6 | ||||
| -rw-r--r-- | src/lua/lobject.h | 3 | ||||
| -rw-r--r-- | src/lua/lstate.c | 32 | ||||
| -rw-r--r-- | src/lua/lstate.h | 1 | ||||
| -rw-r--r-- | src/lua/lstrlib.c | 70 | ||||
| -rw-r--r-- | src/lua/ltable.c | 2 | ||||
| -rw-r--r-- | src/lua/lua.h | 3 | ||||
| -rw-r--r-- | src/lua/lvm.c | 10 |
16 files changed, 261 insertions, 169 deletions
diff --git a/src/lua/lapi.c b/src/lua/lapi.c index 03e756d..3583e9c 100644 --- a/src/lua/lapi.c +++ b/src/lua/lapi.c | |||
| @@ -187,9 +187,26 @@ LUA_API void lua_settop (lua_State *L, int idx) { | |||
| 187 | api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); | 187 | api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); |
| 188 | diff = idx + 1; /* will "subtract" index (as it is negative) */ | 188 | diff = idx + 1; /* will "subtract" index (as it is negative) */ |
| 189 | } | 189 | } |
| 190 | #if defined(LUA_COMPAT_5_4_0) | ||
| 190 | if (diff < 0 && hastocloseCfunc(ci->nresults)) | 191 | if (diff < 0 && hastocloseCfunc(ci->nresults)) |
| 191 | luaF_close(L, L->top + diff, LUA_OK); | 192 | luaF_close(L, L->top + diff, CLOSEKTOP, 0); |
| 192 | L->top += diff; /* correct top only after closing any upvalue */ | 193 | #endif |
| 194 | L->top += diff; | ||
| 195 | api_check(L, L->openupval == NULL || uplevel(L->openupval) < L->top, | ||
| 196 | "cannot pop an unclosed slot"); | ||
| 197 | lua_unlock(L); | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | LUA_API void lua_closeslot (lua_State *L, int idx) { | ||
| 202 | StkId level; | ||
| 203 | lua_lock(L); | ||
| 204 | level = index2stack(L, idx); | ||
| 205 | api_check(L, hastocloseCfunc(L->ci->nresults) && L->openupval != NULL && | ||
| 206 | uplevel(L->openupval) == level, | ||
| 207 | "no variable to close at given level"); | ||
| 208 | luaF_close(L, level, CLOSEKTOP, 0); | ||
| 209 | setnilvalue(s2v(level)); | ||
| 193 | lua_unlock(L); | 210 | lua_unlock(L); |
| 194 | } | 211 | } |
| 195 | 212 | ||
diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c index 074ff08..e8fc486 100644 --- a/src/lua/lauxlib.c +++ b/src/lua/lauxlib.c | |||
| @@ -545,10 +545,8 @@ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { | |||
| 545 | if (buffonstack(B)) /* buffer already has a box? */ | 545 | if (buffonstack(B)) /* buffer already has a box? */ |
| 546 | newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ | 546 | newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ |
| 547 | else { /* no box yet */ | 547 | else { /* no box yet */ |
| 548 | lua_pushnil(L); /* reserve slot for final result */ | ||
| 549 | newbox(L); /* create a new box */ | 548 | newbox(L); /* create a new box */ |
| 550 | /* move box (and slot) to its intended position */ | 549 | lua_insert(L, boxidx); /* move box to its intended position */ |
| 551 | lua_rotate(L, boxidx - 1, 2); | ||
| 552 | lua_toclose(L, boxidx); | 550 | lua_toclose(L, boxidx); |
| 553 | newbuff = (char *)resizebox(L, boxidx, newsize); | 551 | newbuff = (char *)resizebox(L, boxidx, newsize); |
| 554 | memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ | 552 | memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ |
| @@ -585,8 +583,8 @@ LUALIB_API void luaL_pushresult (luaL_Buffer *B) { | |||
| 585 | lua_State *L = B->L; | 583 | lua_State *L = B->L; |
| 586 | lua_pushlstring(L, B->b, B->n); | 584 | lua_pushlstring(L, B->b, B->n); |
| 587 | if (buffonstack(B)) { | 585 | if (buffonstack(B)) { |
| 588 | lua_copy(L, -1, -3); /* move string to reserved slot */ | 586 | lua_closeslot(L, -2); /* close the box */ |
| 589 | lua_pop(L, 2); /* pop string and box (closing the box) */ | 587 | lua_remove(L, -2); /* remove box from the stack */ |
| 590 | } | 588 | } |
| 591 | } | 589 | } |
| 592 | 590 | ||
diff --git a/src/lua/lcorolib.c b/src/lua/lcorolib.c index c165031..ed7c58b 100644 --- a/src/lua/lcorolib.c +++ b/src/lua/lcorolib.c | |||
| @@ -75,8 +75,11 @@ static int luaB_auxwrap (lua_State *L) { | |||
| 75 | int r = auxresume(L, co, lua_gettop(L)); | 75 | int r = auxresume(L, co, lua_gettop(L)); |
| 76 | if (r < 0) { /* error? */ | 76 | if (r < 0) { /* error? */ |
| 77 | int stat = lua_status(co); | 77 | int stat = lua_status(co); |
| 78 | if (stat != LUA_OK && stat != LUA_YIELD) /* error in the coroutine? */ | 78 | if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ |
| 79 | lua_resetthread(co); /* close its tbc variables */ | 79 | stat = lua_resetthread(co); /* close its tbc variables */ |
| 80 | lua_assert(stat != LUA_OK); | ||
| 81 | lua_xmove(co, L, 1); /* copy error message */ | ||
| 82 | } | ||
| 80 | if (stat != LUA_ERRMEM && /* not a memory error and ... */ | 83 | if (stat != LUA_ERRMEM && /* not a memory error and ... */ |
| 81 | lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ | 84 | lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ |
| 82 | luaL_where(L, 1); /* add extra info, if available */ | 85 | luaL_where(L, 1); /* add extra info, if available */ |
diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c index 8cb00e5..819550d 100644 --- a/src/lua/ldebug.c +++ b/src/lua/ldebug.c | |||
| @@ -629,12 +629,10 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | |||
| 629 | case OP_LEN: tm = TM_LEN; break; | 629 | case OP_LEN: tm = TM_LEN; break; |
| 630 | case OP_CONCAT: tm = TM_CONCAT; break; | 630 | case OP_CONCAT: tm = TM_CONCAT; break; |
| 631 | case OP_EQ: tm = TM_EQ; break; | 631 | case OP_EQ: tm = TM_EQ; break; |
| 632 | case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: | 632 | /* no cases for OP_EQI and OP_EQK, as they don't call metamethods */ |
| 633 | *name = "order"; /* '<=' can call '__lt', etc. */ | 633 | case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break; |
| 634 | return "metamethod"; | 634 | case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break; |
| 635 | case OP_CLOSE: case OP_RETURN: | 635 | case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break; |
| 636 | *name = "close"; | ||
| 637 | return "metamethod"; | ||
| 638 | default: | 636 | default: |
| 639 | return NULL; /* cannot find a reasonable name */ | 637 | return NULL; /* cannot find a reasonable name */ |
| 640 | } | 638 | } |
| @@ -697,6 +695,19 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
| 697 | } | 695 | } |
| 698 | 696 | ||
| 699 | 697 | ||
| 698 | l_noret luaG_callerror (lua_State *L, const TValue *o) { | ||
| 699 | CallInfo *ci = L->ci; | ||
| 700 | const char *name = NULL; /* to avoid warnings */ | ||
| 701 | const char *what = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL; | ||
| 702 | if (what != NULL) { | ||
| 703 | const char *t = luaT_objtypename(L, o); | ||
| 704 | luaG_runerror(L, "%s '%s' is not callable (a %s value)", what, name, t); | ||
| 705 | } | ||
| 706 | else | ||
| 707 | luaG_typeerror(L, o, "call"); | ||
| 708 | } | ||
| 709 | |||
| 710 | |||
| 700 | l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { | 711 | l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { |
| 701 | luaG_runerror(L, "bad 'for' %s (number expected, got %s)", | 712 | luaG_runerror(L, "bad 'for' %s (number expected, got %s)", |
| 702 | what, luaT_objtypename(L, o)); | 713 | what, luaT_objtypename(L, o)); |
diff --git a/src/lua/ldebug.h b/src/lua/ldebug.h index a0a5848..55b3ae0 100644 --- a/src/lua/ldebug.h +++ b/src/lua/ldebug.h | |||
| @@ -31,6 +31,7 @@ LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, | |||
| 31 | StkId *pos); | 31 | StkId *pos); |
| 32 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, | 32 | LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, |
| 33 | const char *opname); | 33 | const char *opname); |
| 34 | LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o); | ||
| 34 | LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, | 35 | LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, |
| 35 | const char *what); | 36 | const char *what); |
| 36 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, | 37 | LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, |
diff --git a/src/lua/ldo.c b/src/lua/ldo.c index 4b55c31..aa159cf 100644 --- a/src/lua/ldo.c +++ b/src/lua/ldo.c | |||
| @@ -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(errorstatus(errcode)); /* 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,17 +119,13 @@ 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 = luaE_resetthread(L, errcode); /* close all upvalues */ |
| 122 | L->status = cast_byte(errcode); /* mark it as dead */ | ||
| 123 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 123 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ |
| 124 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ | 124 | setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ |
| 125 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ | 125 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ |
| 126 | } | 126 | } |
| 127 | else { /* no handler at all; abort */ | 127 | else { /* no handler at all; abort */ |
| 128 | if (g->panic) { /* panic function? */ | 128 | if (g->panic) { /* panic function? */ |
| 129 | luaD_seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ | ||
| 130 | if (L->ci->top < L->top) | ||
| 131 | L->ci->top = L->top; /* pushing msg. can break this invariant */ | ||
| 132 | lua_unlock(L); | 129 | lua_unlock(L); |
| 133 | g->panic(L); /* call panic function (last chance to jump out) */ | 130 | g->panic(L); /* call panic function (last chance to jump out) */ |
| 134 | } | 131 | } |
| @@ -375,7 +372,7 @@ void luaD_tryfuncTM (lua_State *L, StkId func) { | |||
| 375 | const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); | 372 | const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); |
| 376 | StkId p; | 373 | StkId p; |
| 377 | if (unlikely(ttisnil(tm))) | 374 | if (unlikely(ttisnil(tm))) |
| 378 | luaG_typeerror(L, s2v(func), "call"); /* nothing to call */ | 375 | luaG_callerror(L, s2v(func)); /* nothing to call */ |
| 379 | for (p = L->top; p > func; p--) /* open space for metamethod */ | 376 | for (p = L->top; p > func; p--) /* open space for metamethod */ |
| 380 | setobjs2s(L, p, p-1); | 377 | setobjs2s(L, p, p-1); |
| 381 | L->top++; /* stack space pre-allocated by the caller */ | 378 | L->top++; /* stack space pre-allocated by the caller */ |
| @@ -409,7 +406,7 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) { | |||
| 409 | default: /* multiple results (or to-be-closed variables) */ | 406 | default: /* multiple results (or to-be-closed variables) */ |
| 410 | if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ | 407 | if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ |
| 411 | ptrdiff_t savedres = savestack(L, res); | 408 | ptrdiff_t savedres = savestack(L, res); |
| 412 | luaF_close(L, res, LUA_OK); /* may change the stack */ | 409 | luaF_close(L, res, CLOSEKTOP, 0); /* may change the stack */ |
| 413 | res = restorestack(L, savedres); | 410 | res = restorestack(L, savedres); |
| 414 | wanted = codeNresults(wanted); /* correct value */ | 411 | wanted = codeNresults(wanted); /* correct value */ |
| 415 | if (wanted == LUA_MULTRET) | 412 | if (wanted == LUA_MULTRET) |
| @@ -596,15 +593,11 @@ static void finishCcall (lua_State *L, int status) { | |||
| 596 | /* | 593 | /* |
| 597 | ** Executes "full continuation" (everything in the stack) of a | 594 | ** Executes "full continuation" (everything in the stack) of a |
| 598 | ** previously interrupted coroutine until the stack is empty (or another | 595 | ** previously interrupted coroutine until the stack is empty (or another |
| 599 | ** interruption long-jumps out of the loop). If the coroutine is | 596 | ** interruption long-jumps out of the loop). |
| 600 | ** recovering from an error, 'ud' points to the error status, which must | ||
| 601 | ** be passed to the first continuation function (otherwise the default | ||
| 602 | ** status is LUA_YIELD). | ||
| 603 | */ | 597 | */ |
| 604 | static void unroll (lua_State *L, void *ud) { | 598 | static void unroll (lua_State *L, void *ud) { |
| 605 | CallInfo *ci; | 599 | CallInfo *ci; |
| 606 | if (ud != NULL) /* error status? */ | 600 | UNUSED(ud); |
| 607 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ | ||
| 608 | while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ | 601 | while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ |
| 609 | if (!isLua(ci)) /* C function? */ | 602 | if (!isLua(ci)) /* C function? */ |
| 610 | finishCcall(L, LUA_YIELD); /* complete its execution */ | 603 | finishCcall(L, LUA_YIELD); /* complete its execution */ |
| @@ -631,24 +624,36 @@ static CallInfo *findpcall (lua_State *L) { | |||
| 631 | 624 | ||
| 632 | 625 | ||
| 633 | /* | 626 | /* |
| 634 | ** Recovers from an error in a coroutine. Finds a recover point (if | 627 | ** Auxiliary structure to call 'recover' in protected mode. |
| 635 | ** there is one) and completes the execution of the interrupted | ||
| 636 | ** 'luaD_pcall'. If there is no recover point, returns zero. | ||
| 637 | */ | 628 | */ |
| 638 | static int recover (lua_State *L, int status) { | 629 | struct RecoverS { |
| 639 | StkId oldtop; | 630 | int status; |
| 640 | CallInfo *ci = findpcall(L); | 631 | CallInfo *ci; |
| 641 | if (ci == NULL) return 0; /* no recovery point */ | 632 | }; |
| 633 | |||
| 634 | |||
| 635 | /* | ||
| 636 | ** Recovers from an error in a coroutine: completes the execution of the | ||
| 637 | ** interrupted 'luaD_pcall', completes the interrupted C function which | ||
| 638 | ** called 'lua_pcallk', and continues running the coroutine. If there is | ||
| 639 | ** an error in 'luaF_close', this function will be called again and the | ||
| 640 | ** coroutine will continue from where it left. | ||
| 641 | */ | ||
| 642 | static void recover (lua_State *L, void *ud) { | ||
| 643 | struct RecoverS *r = cast(struct RecoverS *, ud); | ||
| 644 | int status = r->status; | ||
| 645 | CallInfo *ci = r->ci; /* recover point */ | ||
| 646 | StkId func = restorestack(L, ci->u2.funcidx); | ||
| 642 | /* "finish" luaD_pcall */ | 647 | /* "finish" luaD_pcall */ |
| 643 | oldtop = restorestack(L, ci->u2.funcidx); | ||
| 644 | L->ci = ci; | 648 | L->ci = ci; |
| 645 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 649 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ |
| 646 | status = luaF_close(L, oldtop, status); /* may change the stack */ | 650 | luaF_close(L, func, status, 0); /* may change the stack */ |
| 647 | oldtop = restorestack(L, ci->u2.funcidx); | 651 | func = restorestack(L, ci->u2.funcidx); |
| 648 | luaD_seterrorobj(L, status, oldtop); | 652 | luaD_seterrorobj(L, status, func); |
| 649 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ | 653 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ |
| 650 | L->errfunc = ci->u.c.old_errfunc; | 654 | L->errfunc = ci->u.c.old_errfunc; |
| 651 | return 1; /* continue running the coroutine */ | 655 | finishCcall(L, status); /* finish 'lua_pcallk' callee */ |
| 656 | unroll(L, NULL); /* continue running the coroutine */ | ||
| 652 | } | 657 | } |
| 653 | 658 | ||
| 654 | 659 | ||
| @@ -698,6 +703,24 @@ static void resume (lua_State *L, void *ud) { | |||
| 698 | } | 703 | } |
| 699 | } | 704 | } |
| 700 | 705 | ||
| 706 | |||
| 707 | /* | ||
| 708 | ** Calls 'recover' in protected mode, repeating while there are | ||
| 709 | ** recoverable errors, that is, errors inside a protected call. (Any | ||
| 710 | ** error interrupts 'recover', and this loop protects it again so it | ||
| 711 | ** can continue.) Stops with a normal end (status == LUA_OK), an yield | ||
| 712 | ** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't | ||
| 713 | ** find a recover point). | ||
| 714 | */ | ||
| 715 | static int p_recover (lua_State *L, int status) { | ||
| 716 | struct RecoverS r; | ||
| 717 | r.status = status; | ||
| 718 | while (errorstatus(status) && (r.ci = findpcall(L)) != NULL) | ||
| 719 | r.status = luaD_rawrunprotected(L, recover, &r); | ||
| 720 | return r.status; | ||
| 721 | } | ||
| 722 | |||
| 723 | |||
| 701 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | 724 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, |
| 702 | int *nresults) { | 725 | int *nresults) { |
| 703 | int status; | 726 | int status; |
| @@ -715,10 +738,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
| 715 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | 738 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); |
| 716 | status = luaD_rawrunprotected(L, resume, &nargs); | 739 | status = luaD_rawrunprotected(L, resume, &nargs); |
| 717 | /* continue running after recoverable errors */ | 740 | /* continue running after recoverable errors */ |
| 718 | while (errorstatus(status) && recover(L, status)) { | 741 | status = p_recover(L, status); |
| 719 | /* unroll continuation */ | ||
| 720 | status = luaD_rawrunprotected(L, unroll, &status); | ||
| 721 | } | ||
| 722 | if (likely(!errorstatus(status))) | 742 | if (likely(!errorstatus(status))) |
| 723 | lua_assert(status == L->status); /* normal end or yield */ | 743 | lua_assert(status == L->status); /* normal end or yield */ |
| 724 | else { /* unrecoverable error */ | 744 | else { /* unrecoverable error */ |
| @@ -770,6 +790,45 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
| 770 | 790 | ||
| 771 | 791 | ||
| 772 | /* | 792 | /* |
| 793 | ** Auxiliary structure to call 'luaF_close' in protected mode. | ||
| 794 | */ | ||
| 795 | struct CloseP { | ||
| 796 | StkId level; | ||
| 797 | int status; | ||
| 798 | }; | ||
| 799 | |||
| 800 | |||
| 801 | /* | ||
| 802 | ** Auxiliary function to call 'luaF_close' in protected mode. | ||
| 803 | */ | ||
| 804 | static void closepaux (lua_State *L, void *ud) { | ||
| 805 | struct CloseP *pcl = cast(struct CloseP *, ud); | ||
| 806 | luaF_close(L, pcl->level, pcl->status, 0); | ||
| 807 | } | ||
| 808 | |||
| 809 | |||
| 810 | /* | ||
| 811 | ** Calls 'luaF_close' in protected mode. Return the original status | ||
| 812 | ** or, in case of errors, the new status. | ||
| 813 | */ | ||
| 814 | int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { | ||
| 815 | CallInfo *old_ci = L->ci; | ||
| 816 | lu_byte old_allowhooks = L->allowhook; | ||
| 817 | for (;;) { /* keep closing upvalues until no more errors */ | ||
| 818 | struct CloseP pcl; | ||
| 819 | pcl.level = restorestack(L, level); pcl.status = status; | ||
| 820 | status = luaD_rawrunprotected(L, &closepaux, &pcl); | ||
| 821 | if (likely(status == LUA_OK)) /* no more errors? */ | ||
| 822 | return pcl.status; | ||
| 823 | else { /* an error occurred; restore saved state and repeat */ | ||
| 824 | L->ci = old_ci; | ||
| 825 | L->allowhook = old_allowhooks; | ||
| 826 | } | ||
| 827 | } | ||
| 828 | } | ||
| 829 | |||
| 830 | |||
| 831 | /* | ||
| 773 | ** Call the C function 'func' in protected mode, restoring basic | 832 | ** Call the C function 'func' in protected mode, restoring basic |
| 774 | ** thread information ('allowhook', etc.) and in particular | 833 | ** thread information ('allowhook', etc.) and in particular |
| 775 | ** its stack level in case of errors. | 834 | ** its stack level in case of errors. |
| @@ -783,12 +842,10 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
| 783 | L->errfunc = ef; | 842 | L->errfunc = ef; |
| 784 | status = luaD_rawrunprotected(L, func, u); | 843 | status = luaD_rawrunprotected(L, func, u); |
| 785 | if (unlikely(status != LUA_OK)) { /* an error occurred? */ | 844 | if (unlikely(status != LUA_OK)) { /* an error occurred? */ |
| 786 | StkId oldtop = restorestack(L, old_top); | ||
| 787 | L->ci = old_ci; | 845 | L->ci = old_ci; |
| 788 | L->allowhook = old_allowhooks; | 846 | L->allowhook = old_allowhooks; |
| 789 | status = luaF_close(L, oldtop, status); | 847 | status = luaD_closeprotected(L, old_top, status); |
| 790 | oldtop = restorestack(L, old_top); /* previous call may change stack */ | 848 | 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 */ | 849 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ |
| 793 | } | 850 | } |
| 794 | L->errfunc = old_errfunc; | 851 | L->errfunc = old_errfunc; |
diff --git a/src/lua/ldo.h b/src/lua/ldo.h index 4d30d07..c7721d6 100644 --- a/src/lua/ldo.h +++ b/src/lua/ldo.h | |||
| @@ -63,6 +63,7 @@ LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); | |||
| 63 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); | 63 | LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); |
| 64 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); | 64 | LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); |
| 65 | LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func); | 65 | LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func); |
| 66 | LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status); | ||
| 66 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | 67 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, |
| 67 | ptrdiff_t oldtop, ptrdiff_t ef); | 68 | ptrdiff_t oldtop, ptrdiff_t ef); |
| 68 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); | 69 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); |
diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c index c4360f0..13e44d4 100644 --- a/src/lua/lfunc.c +++ b/src/lua/lfunc.c | |||
| @@ -100,80 +100,57 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | 102 | ||
| 103 | static void callclose (lua_State *L, void *ud) { | ||
| 104 | UNUSED(ud); | ||
| 105 | luaD_callnoyield(L, L->top - 3, 0); | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | /* | 103 | /* |
| 110 | ** Prepare closing method plus its arguments for object 'obj' with | 104 | ** Call closing method for object 'obj' with error message 'err'. The |
| 111 | ** error message 'err'. (This function assumes EXTRA_STACK.) | 105 | ** boolean 'yy' controls whether the call is yieldable. |
| 106 | ** (This function assumes EXTRA_STACK.) | ||
| 112 | */ | 107 | */ |
| 113 | static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { | 108 | static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { |
| 114 | StkId top = L->top; | 109 | StkId top = L->top; |
| 115 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); | 110 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); |
| 116 | if (ttisnil(tm)) /* no metamethod? */ | ||
| 117 | return 0; /* nothing to call */ | ||
| 118 | setobj2s(L, top, tm); /* will call metamethod... */ | 111 | setobj2s(L, top, tm); /* will call metamethod... */ |
| 119 | setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ | 112 | setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ |
| 120 | setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ | 113 | setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ |
| 121 | L->top = top + 3; /* add function and arguments */ | 114 | L->top = top + 3; /* add function and arguments */ |
| 122 | return 1; | 115 | if (yy) |
| 116 | luaD_call(L, top, 0); | ||
| 117 | else | ||
| 118 | luaD_callnoyield(L, top, 0); | ||
| 123 | } | 119 | } |
| 124 | 120 | ||
| 125 | 121 | ||
| 126 | /* | 122 | /* |
| 127 | ** Raise an error with message 'msg', inserting the name of the | 123 | ** Check whether 'obj' has a close metamethod and raise an error |
| 128 | ** local variable at position 'level' in the stack. | 124 | ** if not. |
| 129 | */ | 125 | */ |
| 130 | static void varerror (lua_State *L, StkId level, const char *msg) { | 126 | static void checkclosemth (lua_State *L, StkId level, const TValue *obj) { |
| 131 | int idx = cast_int(level - L->ci->func); | 127 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); |
| 132 | const char *vname = luaG_findlocal(L, L->ci, idx, NULL); | 128 | if (ttisnil(tm)) { /* no metamethod? */ |
| 133 | if (vname == NULL) vname = "?"; | 129 | int idx = cast_int(level - L->ci->func); /* variable index */ |
| 134 | luaG_runerror(L, msg, vname); | 130 | const char *vname = luaG_findlocal(L, L->ci, idx, NULL); |
| 131 | if (vname == NULL) vname = "?"; | ||
| 132 | luaG_runerror(L, "variable '%s' got a non-closable value", vname); | ||
| 133 | } | ||
| 135 | } | 134 | } |
| 136 | 135 | ||
| 137 | 136 | ||
| 138 | /* | 137 | /* |
| 139 | ** Prepare and call a closing method. If status is OK, code is still | 138 | ** Prepare and call a closing method. |
| 140 | ** inside the original protected call, and so any error will be handled | 139 | ** If status is CLOSEKTOP, the call to the closing method will be pushed |
| 141 | ** there. Otherwise, a previous error already activated the original | 140 | ** at the top of the stack. Otherwise, values can be pushed right after |
| 142 | ** protected call, and so the call to the closing method must be | 141 | ** the 'level' of the upvalue being closed, as everything after that |
| 143 | ** protected here. (A status == CLOSEPROTECT behaves like a previous | 142 | ** won't be used again. |
| 144 | ** error, to also run the closing method in protected mode). | ||
| 145 | ** If status is OK, the call to the closing method will be pushed | ||
| 146 | ** at the top of the stack. Otherwise, values are pushed after | ||
| 147 | ** the 'level' of the upvalue being closed, as everything after | ||
| 148 | ** that won't be used again. | ||
| 149 | */ | 143 | */ |
| 150 | static int callclosemth (lua_State *L, StkId level, int status) { | 144 | static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { |
| 151 | TValue *uv = s2v(level); /* value being closed */ | 145 | TValue *uv = s2v(level); /* value being closed */ |
| 152 | if (likely(status == LUA_OK)) { | 146 | TValue *errobj; |
| 153 | if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ | 147 | if (status == CLOSEKTOP) |
| 154 | callclose(L, NULL); /* call closing method */ | 148 | errobj = &G(L)->nilvalue; /* error object is nil */ |
| 155 | else if (!l_isfalse(uv)) /* non-closable non-false value? */ | 149 | else { /* 'luaD_seterrorobj' will set top to level + 2 */ |
| 156 | varerror(L, level, "attempt to close non-closable variable '%s'"); | 150 | errobj = s2v(level + 1); /* error object goes after 'uv' */ |
| 151 | luaD_seterrorobj(L, status, level + 1); /* set error object */ | ||
| 157 | } | 152 | } |
| 158 | else { /* must close the object in protected mode */ | 153 | callclosemethod(L, uv, errobj, yy); |
| 159 | ptrdiff_t oldtop; | ||
| 160 | level++; /* space for error message */ | ||
| 161 | oldtop = savestack(L, level + 1); /* top will be after that */ | ||
| 162 | luaD_seterrorobj(L, status, level); /* set error message */ | ||
| 163 | if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ | ||
| 164 | int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); | ||
| 165 | if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ | ||
| 166 | status = newstatus; /* this will be the new error */ | ||
| 167 | else { | ||
| 168 | if (newstatus != LUA_OK) /* suppressed error? */ | ||
| 169 | luaE_warnerror(L, "__close metamethod"); | ||
| 170 | /* leave original error (or nil) on top */ | ||
| 171 | L->top = restorestack(L, oldtop); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | /* else no metamethod; ignore this case and keep original error */ | ||
| 175 | } | ||
| 176 | return status; | ||
| 177 | } | 154 | } |
| 178 | 155 | ||
| 179 | 156 | ||
| @@ -196,16 +173,12 @@ void luaF_newtbcupval (lua_State *L, StkId level) { | |||
| 196 | lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); | 173 | lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); |
| 197 | if (!l_isfalse(obj)) { /* false doesn't need to be closed */ | 174 | if (!l_isfalse(obj)) { /* false doesn't need to be closed */ |
| 198 | int status; | 175 | int status; |
| 199 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); | 176 | checkclosemth(L, level, obj); |
| 200 | if (ttisnil(tm)) /* no metamethod? */ | ||
| 201 | varerror(L, level, "variable '%s' got a non-closable value"); | ||
| 202 | status = luaD_rawrunprotected(L, trynewtbcupval, level); | 177 | status = luaD_rawrunprotected(L, trynewtbcupval, level); |
| 203 | if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ | 178 | if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ |
| 204 | lua_assert(status == LUA_ERRMEM); | 179 | lua_assert(status == LUA_ERRMEM); |
| 205 | luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */ | 180 | luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */ |
| 206 | /* next call must succeed, as object is closable */ | 181 | callclosemethod(L, s2v(level), s2v(level + 1), 0); |
| 207 | prepclosingmethod(L, s2v(level), s2v(level + 1)); | ||
| 208 | callclose(L, NULL); /* call closing method */ | ||
| 209 | luaD_throw(L, LUA_ERRMEM); /* throw memory error */ | 182 | luaD_throw(L, LUA_ERRMEM); /* throw memory error */ |
| 210 | } | 183 | } |
| 211 | } | 184 | } |
| @@ -220,26 +193,30 @@ void luaF_unlinkupval (UpVal *uv) { | |||
| 220 | } | 193 | } |
| 221 | 194 | ||
| 222 | 195 | ||
| 223 | int luaF_close (lua_State *L, StkId level, int status) { | 196 | /* |
| 197 | ** Close all upvalues up to the given stack level. A 'status' equal | ||
| 198 | ** to NOCLOSINGMETH closes upvalues without running any __close | ||
| 199 | ** metamethods. | ||
| 200 | */ | ||
| 201 | void luaF_close (lua_State *L, StkId level, int status, int yy) { | ||
| 224 | UpVal *uv; | 202 | UpVal *uv; |
| 225 | while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { | 203 | StkId upl; /* stack index pointed by 'uv' */ |
| 204 | while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { | ||
| 226 | TValue *slot = &uv->u.value; /* new position for value */ | 205 | TValue *slot = &uv->u.value; /* new position for value */ |
| 227 | lua_assert(uplevel(uv) < L->top); | 206 | lua_assert(uplevel(uv) < L->top); |
| 228 | if (uv->tbc && status != NOCLOSINGMETH) { | 207 | luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ |
| 229 | /* must run closing method, which may change the stack */ | ||
| 230 | ptrdiff_t levelrel = savestack(L, level); | ||
| 231 | status = callclosemth(L, uplevel(uv), status); | ||
| 232 | level = restorestack(L, levelrel); | ||
| 233 | } | ||
| 234 | luaF_unlinkupval(uv); | ||
| 235 | setobj(L, slot, uv->v); /* move value to upvalue slot */ | 208 | setobj(L, slot, uv->v); /* move value to upvalue slot */ |
| 236 | uv->v = slot; /* now current value lives here */ | 209 | uv->v = slot; /* now current value lives here */ |
| 237 | if (!iswhite(uv)) { /* neither white nor dead? */ | 210 | if (!iswhite(uv)) { /* neither white nor dead? */ |
| 238 | nw2black(uv); /* closed upvalues cannot be gray */ | 211 | nw2black(uv); /* closed upvalues cannot be gray */ |
| 239 | luaC_barrier(L, uv, slot); | 212 | luaC_barrier(L, uv, slot); |
| 240 | } | 213 | } |
| 214 | if (uv->tbc && status != NOCLOSINGMETH) { | ||
| 215 | ptrdiff_t levelrel = savestack(L, level); | ||
| 216 | prepcallclosemth(L, upl, status, yy); /* may change the stack */ | ||
| 217 | level = restorestack(L, levelrel); | ||
| 218 | } | ||
| 241 | } | 219 | } |
| 242 | return status; | ||
| 243 | } | 220 | } |
| 244 | 221 | ||
| 245 | 222 | ||
diff --git a/src/lua/lfunc.h b/src/lua/lfunc.h index 8d6f965..2e6df53 100644 --- a/src/lua/lfunc.h +++ b/src/lua/lfunc.h | |||
| @@ -49,8 +49,8 @@ | |||
| 49 | /* close upvalues without running their closing methods */ | 49 | /* close upvalues without running their closing methods */ |
| 50 | #define NOCLOSINGMETH (-1) | 50 | #define NOCLOSINGMETH (-1) |
| 51 | 51 | ||
| 52 | /* close upvalues running all closing methods in protected mode */ | 52 | /* special status to close upvalues preserving the top of the stack */ |
| 53 | #define CLOSEPROTECT (-2) | 53 | #define CLOSEKTOP (-2) |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); | 56 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); |
| @@ -59,7 +59,7 @@ LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals); | |||
| 59 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); | 59 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); |
| 60 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); | 60 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); |
| 61 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); | 61 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); |
| 62 | LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status); | 62 | LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); |
| 63 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); | 63 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); |
| 64 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); | 64 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); |
| 65 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, | 65 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, |
diff --git a/src/lua/lobject.h b/src/lua/lobject.h index 1cc8e75..470b17d 100644 --- a/src/lua/lobject.h +++ b/src/lua/lobject.h | |||
| @@ -570,10 +570,11 @@ typedef struct Proto { | |||
| 570 | #define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */ | 570 | #define LUA_VCCL makevariant(LUA_TFUNCTION, 2) /* C closure */ |
| 571 | 571 | ||
| 572 | #define ttisfunction(o) checktype(o, LUA_TFUNCTION) | 572 | #define ttisfunction(o) checktype(o, LUA_TFUNCTION) |
| 573 | #define ttisclosure(o) ((rawtt(o) & 0x1F) == LUA_VLCL) | ||
| 574 | #define ttisLclosure(o) checktag((o), ctb(LUA_VLCL)) | 573 | #define ttisLclosure(o) checktag((o), ctb(LUA_VLCL)) |
| 575 | #define ttislcf(o) checktag((o), LUA_VLCF) | 574 | #define ttislcf(o) checktag((o), LUA_VLCF) |
| 576 | #define ttisCclosure(o) checktag((o), ctb(LUA_VCCL)) | 575 | #define ttisCclosure(o) checktag((o), ctb(LUA_VCCL)) |
| 576 | #define ttisclosure(o) (ttisLclosure(o) || ttisCclosure(o)) | ||
| 577 | |||
| 577 | 578 | ||
| 578 | #define isLfunction(o) ttisLclosure(o) | 579 | #define isLfunction(o) ttisLclosure(o) |
| 579 | 580 | ||
diff --git a/src/lua/lstate.c b/src/lua/lstate.c index 1596b51..92ccbf9 100644 --- a/src/lua/lstate.c +++ b/src/lua/lstate.c | |||
| @@ -268,7 +268,7 @@ static void preinit_thread (lua_State *L, global_State *g) { | |||
| 268 | 268 | ||
| 269 | static void close_state (lua_State *L) { | 269 | static void close_state (lua_State *L) { |
| 270 | global_State *g = G(L); | 270 | global_State *g = G(L); |
| 271 | luaF_close(L, L->stack, CLOSEPROTECT); /* close all upvalues */ | 271 | luaD_closeprotected(L, 0, LUA_OK); /* close all upvalues */ |
| 272 | luaC_freeallobjects(L); /* collect all objects */ | 272 | luaC_freeallobjects(L); /* collect all objects */ |
| 273 | if (ttisnil(&g->nilvalue)) /* closing a fully built state? */ | 273 | if (ttisnil(&g->nilvalue)) /* closing a fully built state? */ |
| 274 | luai_userstateclose(L); | 274 | luai_userstateclose(L); |
| @@ -313,7 +313,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
| 313 | 313 | ||
| 314 | void luaE_freethread (lua_State *L, lua_State *L1) { | 314 | void luaE_freethread (lua_State *L, lua_State *L1) { |
| 315 | LX *l = fromstate(L1); | 315 | LX *l = fromstate(L1); |
| 316 | luaF_close(L1, L1->stack, NOCLOSINGMETH); /* close all upvalues */ | 316 | luaF_close(L1, L1->stack, NOCLOSINGMETH, 0); /* close all upvalues */ |
| 317 | lua_assert(L1->openupval == NULL); | 317 | lua_assert(L1->openupval == NULL); |
| 318 | luai_userstatefree(L, L1); | 318 | luai_userstatefree(L, L1); |
| 319 | freestack(L1); | 319 | freestack(L1); |
| @@ -321,23 +321,29 @@ void luaE_freethread (lua_State *L, lua_State *L1) { | |||
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | 323 | ||
| 324 | int lua_resetthread (lua_State *L) { | 324 | int luaE_resetthread (lua_State *L, int status) { |
| 325 | CallInfo *ci; | 325 | CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ |
| 326 | int status; | ||
| 327 | lua_lock(L); | ||
| 328 | L->ci = ci = &L->base_ci; /* unwind CallInfo list */ | ||
| 329 | setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ | 326 | setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ |
| 330 | ci->func = L->stack; | 327 | ci->func = L->stack; |
| 331 | ci->callstatus = CIST_C; | 328 | ci->callstatus = CIST_C; |
| 332 | status = luaF_close(L, L->stack, CLOSEPROTECT); | 329 | if (status == LUA_YIELD) |
| 333 | if (status != CLOSEPROTECT) /* real errors? */ | ||
| 334 | luaD_seterrorobj(L, status, L->stack + 1); | ||
| 335 | else { | ||
| 336 | status = LUA_OK; | 330 | status = LUA_OK; |
| 331 | status = luaD_closeprotected(L, 0, status); | ||
| 332 | if (status != LUA_OK) /* errors? */ | ||
| 333 | luaD_seterrorobj(L, status, L->stack + 1); | ||
| 334 | else | ||
| 337 | L->top = L->stack + 1; | 335 | L->top = L->stack + 1; |
| 338 | } | ||
| 339 | ci->top = L->top + LUA_MINSTACK; | 336 | ci->top = L->top + LUA_MINSTACK; |
| 340 | L->status = status; | 337 | L->status = cast_byte(status); |
| 338 | luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); | ||
| 339 | return status; | ||
| 340 | } | ||
| 341 | |||
| 342 | |||
| 343 | LUA_API int lua_resetthread (lua_State *L) { | ||
| 344 | int status; | ||
| 345 | lua_lock(L); | ||
| 346 | status = luaE_resetthread(L, L->status); | ||
| 341 | lua_unlock(L); | 347 | lua_unlock(L); |
| 342 | return status; | 348 | return status; |
| 343 | } | 349 | } |
diff --git a/src/lua/lstate.h b/src/lua/lstate.h index cbcf07e..38a6c9b 100644 --- a/src/lua/lstate.h +++ b/src/lua/lstate.h | |||
| @@ -359,6 +359,7 @@ LUAI_FUNC void luaE_checkcstack (lua_State *L); | |||
| 359 | LUAI_FUNC void luaE_incCstack (lua_State *L); | 359 | LUAI_FUNC void luaE_incCstack (lua_State *L); |
| 360 | LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); | 360 | LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); |
| 361 | LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); | 361 | LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); |
| 362 | LUAI_FUNC int luaE_resetthread (lua_State *L, int status); | ||
| 362 | 363 | ||
| 363 | 364 | ||
| 364 | #endif | 365 | #endif |
diff --git a/src/lua/lstrlib.c b/src/lua/lstrlib.c index 940a14c..c7242ea 100644 --- a/src/lua/lstrlib.c +++ b/src/lua/lstrlib.c | |||
| @@ -1359,16 +1359,6 @@ struct cD { | |||
| 1359 | 1359 | ||
| 1360 | 1360 | ||
| 1361 | /* | 1361 | /* |
| 1362 | ** Union for serializing floats | ||
| 1363 | */ | ||
| 1364 | typedef union Ftypes { | ||
| 1365 | float f; | ||
| 1366 | double d; | ||
| 1367 | lua_Number n; | ||
| 1368 | } Ftypes; | ||
| 1369 | |||
| 1370 | |||
| 1371 | /* | ||
| 1372 | ** information to pack/unpack stuff | 1362 | ** information to pack/unpack stuff |
| 1373 | */ | 1363 | */ |
| 1374 | typedef struct Header { | 1364 | typedef struct Header { |
| @@ -1384,7 +1374,9 @@ typedef struct Header { | |||
| 1384 | typedef enum KOption { | 1374 | typedef enum KOption { |
| 1385 | Kint, /* signed integers */ | 1375 | Kint, /* signed integers */ |
| 1386 | Kuint, /* unsigned integers */ | 1376 | Kuint, /* unsigned integers */ |
| 1387 | Kfloat, /* floating-point numbers */ | 1377 | Kfloat, /* single-precision floating-point numbers */ |
| 1378 | Knumber, /* Lua "native" floating-point numbers */ | ||
| 1379 | Kdouble, /* double-precision floating-point numbers */ | ||
| 1388 | Kchar, /* fixed-length strings */ | 1380 | Kchar, /* fixed-length strings */ |
| 1389 | Kstring, /* strings with prefixed length */ | 1381 | Kstring, /* strings with prefixed length */ |
| 1390 | Kzstr, /* zero-terminated strings */ | 1382 | Kzstr, /* zero-terminated strings */ |
| @@ -1453,8 +1445,8 @@ static KOption getoption (Header *h, const char **fmt, int *size) { | |||
| 1453 | case 'J': *size = sizeof(lua_Integer); return Kuint; | 1445 | case 'J': *size = sizeof(lua_Integer); return Kuint; |
| 1454 | case 'T': *size = sizeof(size_t); return Kuint; | 1446 | case 'T': *size = sizeof(size_t); return Kuint; |
| 1455 | case 'f': *size = sizeof(float); return Kfloat; | 1447 | case 'f': *size = sizeof(float); return Kfloat; |
| 1456 | case 'd': *size = sizeof(double); return Kfloat; | 1448 | case 'n': *size = sizeof(lua_Number); return Knumber; |
| 1457 | case 'n': *size = sizeof(lua_Number); return Kfloat; | 1449 | case 'd': *size = sizeof(double); return Kdouble; |
| 1458 | case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; | 1450 | case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; |
| 1459 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; | 1451 | case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; |
| 1460 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; | 1452 | case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; |
| @@ -1580,15 +1572,27 @@ static int str_pack (lua_State *L) { | |||
| 1580 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); | 1572 | packint(&b, (lua_Unsigned)n, h.islittle, size, 0); |
| 1581 | break; | 1573 | break; |
| 1582 | } | 1574 | } |
| 1583 | case Kfloat: { /* floating-point options */ | 1575 | case Kfloat: { /* C float */ |
| 1584 | Ftypes u; | 1576 | float f = (float)luaL_checknumber(L, arg); /* get argument */ |
| 1585 | char *buff = luaL_prepbuffsize(&b, size); | 1577 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); |
| 1586 | lua_Number n = luaL_checknumber(L, arg); /* get argument */ | 1578 | /* move 'f' to final result, correcting endianness if needed */ |
| 1587 | if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ | 1579 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); |
| 1588 | else if (size == sizeof(u.d)) u.d = (double)n; | 1580 | luaL_addsize(&b, size); |
| 1589 | else u.n = n; | 1581 | break; |
| 1590 | /* move 'u' to final result, correcting endianness if needed */ | 1582 | } |
| 1591 | copywithendian(buff, (char *)&u, size, h.islittle); | 1583 | case Knumber: { /* Lua float */ |
| 1584 | lua_Number f = luaL_checknumber(L, arg); /* get argument */ | ||
| 1585 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); | ||
| 1586 | /* move 'f' to final result, correcting endianness if needed */ | ||
| 1587 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); | ||
| 1588 | luaL_addsize(&b, size); | ||
| 1589 | break; | ||
| 1590 | } | ||
| 1591 | case Kdouble: { /* C double */ | ||
| 1592 | double f = (double)luaL_checknumber(L, arg); /* get argument */ | ||
| 1593 | char *buff = luaL_prepbuffsize(&b, sizeof(f)); | ||
| 1594 | /* move 'f' to final result, correcting endianness if needed */ | ||
| 1595 | copywithendian(buff, (char *)&f, sizeof(f), h.islittle); | ||
| 1592 | luaL_addsize(&b, size); | 1596 | luaL_addsize(&b, size); |
| 1593 | break; | 1597 | break; |
| 1594 | } | 1598 | } |
| @@ -1714,13 +1718,21 @@ static int str_unpack (lua_State *L) { | |||
| 1714 | break; | 1718 | break; |
| 1715 | } | 1719 | } |
| 1716 | case Kfloat: { | 1720 | case Kfloat: { |
| 1717 | Ftypes u; | 1721 | float f; |
| 1718 | lua_Number num; | 1722 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); |
| 1719 | copywithendian((char *)&u, data + pos, size, h.islittle); | 1723 | lua_pushnumber(L, (lua_Number)f); |
| 1720 | if (size == sizeof(u.f)) num = (lua_Number)u.f; | 1724 | break; |
| 1721 | else if (size == sizeof(u.d)) num = (lua_Number)u.d; | 1725 | } |
| 1722 | else num = u.n; | 1726 | case Knumber: { |
| 1723 | lua_pushnumber(L, num); | 1727 | lua_Number f; |
| 1728 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); | ||
| 1729 | lua_pushnumber(L, f); | ||
| 1730 | break; | ||
| 1731 | } | ||
| 1732 | case Kdouble: { | ||
| 1733 | double f; | ||
| 1734 | copywithendian((char *)&f, data + pos, sizeof(f), h.islittle); | ||
| 1735 | lua_pushnumber(L, (lua_Number)f); | ||
| 1724 | break; | 1736 | break; |
| 1725 | } | 1737 | } |
| 1726 | case Kchar: { | 1738 | case Kchar: { |
diff --git a/src/lua/ltable.c b/src/lua/ltable.c index e9410f9..e98bab7 100644 --- a/src/lua/ltable.c +++ b/src/lua/ltable.c | |||
| @@ -647,6 +647,8 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { | |||
| 647 | else if (unlikely(luai_numisnan(f))) | 647 | else if (unlikely(luai_numisnan(f))) |
| 648 | luaG_runerror(L, "table index is NaN"); | 648 | luaG_runerror(L, "table index is NaN"); |
| 649 | } | 649 | } |
| 650 | if (ttisnil(value)) | ||
| 651 | return; /* do not insert nil values */ | ||
| 650 | mp = mainpositionTV(t, key); | 652 | mp = mainpositionTV(t, key); |
| 651 | if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ | 653 | if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
| 652 | Node *othern; | 654 | Node *othern; |
diff --git a/src/lua/lua.h b/src/lua/lua.h index c9d64d7..aec70da 100644 --- a/src/lua/lua.h +++ b/src/lua/lua.h | |||
| @@ -347,7 +347,8 @@ LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); | |||
| 347 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); | 347 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); |
| 348 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | 348 | LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); |
| 349 | 349 | ||
| 350 | LUA_API void (lua_toclose) (lua_State *L, int idx); | 350 | LUA_API void (lua_toclose) (lua_State *L, int idx); |
| 351 | LUA_API void (lua_closeslot) (lua_State *L, int idx); | ||
| 351 | 352 | ||
| 352 | 353 | ||
| 353 | /* | 354 | /* |
diff --git a/src/lua/lvm.c b/src/lua/lvm.c index ccebdbe..d6c05bb 100644 --- a/src/lua/lvm.c +++ b/src/lua/lvm.c | |||
| @@ -842,6 +842,10 @@ void luaV_finishOp (lua_State *L) { | |||
| 842 | luaV_concat(L, total); /* concat them (may yield again) */ | 842 | luaV_concat(L, total); /* concat them (may yield again) */ |
| 843 | break; | 843 | break; |
| 844 | } | 844 | } |
| 845 | case OP_CLOSE: case OP_RETURN: { /* yielded closing variables */ | ||
| 846 | ci->u.l.savedpc--; /* repeat instruction to close other vars. */ | ||
| 847 | break; | ||
| 848 | } | ||
| 845 | default: { | 849 | default: { |
| 846 | /* only these other opcodes can yield */ | 850 | /* only these other opcodes can yield */ |
| 847 | lua_assert(op == OP_TFORCALL || op == OP_CALL || | 851 | lua_assert(op == OP_TFORCALL || op == OP_CALL || |
| @@ -1524,7 +1528,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1524 | vmbreak; | 1528 | vmbreak; |
| 1525 | } | 1529 | } |
| 1526 | vmcase(OP_CLOSE) { | 1530 | vmcase(OP_CLOSE) { |
| 1527 | Protect(luaF_close(L, ra, LUA_OK)); | 1531 | Protect(luaF_close(L, ra, LUA_OK, 1)); |
| 1528 | vmbreak; | 1532 | vmbreak; |
| 1529 | } | 1533 | } |
| 1530 | vmcase(OP_TBC) { | 1534 | vmcase(OP_TBC) { |
| @@ -1632,7 +1636,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1632 | /* close upvalues from current call; the compiler ensures | 1636 | /* close upvalues from current call; the compiler ensures |
| 1633 | that there are no to-be-closed variables here, so this | 1637 | that there are no to-be-closed variables here, so this |
| 1634 | call cannot change the stack */ | 1638 | call cannot change the stack */ |
| 1635 | luaF_close(L, base, NOCLOSINGMETH); | 1639 | luaF_close(L, base, NOCLOSINGMETH, 0); |
| 1636 | lua_assert(base == ci->func + 1); | 1640 | lua_assert(base == ci->func + 1); |
| 1637 | } | 1641 | } |
| 1638 | while (!ttisfunction(s2v(ra))) { /* not a function? */ | 1642 | while (!ttisfunction(s2v(ra))) { /* not a function? */ |
| @@ -1662,7 +1666,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1662 | if (TESTARG_k(i)) { /* may there be open upvalues? */ | 1666 | if (TESTARG_k(i)) { /* may there be open upvalues? */ |
| 1663 | if (L->top < ci->top) | 1667 | if (L->top < ci->top) |
| 1664 | L->top = ci->top; | 1668 | L->top = ci->top; |
| 1665 | luaF_close(L, base, LUA_OK); | 1669 | luaF_close(L, base, CLOSEKTOP, 1); |
| 1666 | updatetrap(ci); | 1670 | updatetrap(ci); |
| 1667 | updatestack(ci); | 1671 | updatestack(ci); |
| 1668 | } | 1672 | } |
