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 | } |