diff options
author | Li Jin <dragon-fly@qq.com> | 2020-07-18 16:45:50 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-07-18 16:45:50 +0800 |
commit | 8c596dc1efa8a1267c222b168a4de9c8ba254760 (patch) | |
tree | 699c748e101a48ae267b5f7b19adbfea15f3934e /src | |
parent | 8ab0038c09a79fa8401bb10b7a31d03ef5380417 (diff) | |
download | yuescript-8c596dc1efa8a1267c222b168a4de9c8ba254760.tar.gz yuescript-8c596dc1efa8a1267c222b168a4de9c8ba254760.tar.bz2 yuescript-8c596dc1efa8a1267c222b168a4de9c8ba254760.zip |
fix issue for using return statement with export.
Diffstat (limited to 'src')
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 30 | ||||
-rw-r--r-- | src/lua/lapi.c | 43 | ||||
-rw-r--r-- | src/lua/lauxlib.c | 6 | ||||
-rw-r--r-- | src/lua/lcorolib.c | 9 | ||||
-rw-r--r-- | src/lua/ldo.c | 23 | ||||
-rw-r--r-- | src/lua/ldo.h | 6 | ||||
-rw-r--r-- | src/lua/lgc.c | 10 | ||||
-rw-r--r-- | src/lua/liolib.c | 7 | ||||
-rw-r--r-- | src/lua/llimits.h | 10 | ||||
-rw-r--r-- | src/lua/lmem.c | 2 | ||||
-rw-r--r-- | src/lua/lobject.c | 49 | ||||
-rw-r--r-- | src/lua/lstate.c | 6 | ||||
-rw-r--r-- | src/lua/ltm.c | 4 | ||||
-rw-r--r-- | src/lua/lundump.c | 9 | ||||
-rw-r--r-- | src/lua/lvm.c | 18 |
15 files changed, 154 insertions, 78 deletions
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 41d29df..1d9161b 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -49,7 +49,7 @@ inline std::string s(std::string_view sv) { | |||
49 | } | 49 | } |
50 | 50 | ||
51 | const std::string_view version() { | 51 | const std::string_view version() { |
52 | return "0.4.4"sv; | 52 | return "0.4.5"sv; |
53 | } | 53 | } |
54 | 54 | ||
55 | // name of table stored in lua registry | 55 | // name of table stored in lua registry |
@@ -1498,6 +1498,7 @@ private: | |||
1498 | if (usage == ExpUsage::Closure) { | 1498 | if (usage == ExpUsage::Closure) { |
1499 | temp.push_back(s("(function()"sv) + nll(nodes.front())); | 1499 | temp.push_back(s("(function()"sv) + nll(nodes.front())); |
1500 | pushScope(); | 1500 | pushScope(); |
1501 | _enableReturn.push(true); | ||
1501 | } | 1502 | } |
1502 | std::list<std::pair<IfCond_t*, Body_t*>> ifCondPairs; | 1503 | std::list<std::pair<IfCond_t*, Body_t*>> ifCondPairs; |
1503 | ifCondPairs.emplace_back(); | 1504 | ifCondPairs.emplace_back(); |
@@ -1613,6 +1614,7 @@ private: | |||
1613 | temp.push_back(indent() + s("end"sv) + nlr(nodes.front())); | 1614 | temp.push_back(indent() + s("end"sv) + nlr(nodes.front())); |
1614 | } | 1615 | } |
1615 | if (usage == ExpUsage::Closure) { | 1616 | if (usage == ExpUsage::Closure) { |
1617 | _enableReturn.pop(); | ||
1616 | popScope(); | 1618 | popScope(); |
1617 | temp.push_back(indent() + s("end)()"sv)); | 1619 | temp.push_back(indent() + s("end)()"sv)); |
1618 | } | 1620 | } |
@@ -2588,6 +2590,7 @@ private: | |||
2588 | if (usage == ExpUsage::Closure) { | 2590 | if (usage == ExpUsage::Closure) { |
2589 | temp.push_back(s("(function()"sv) + nll(x)); | 2591 | temp.push_back(s("(function()"sv) + nll(x)); |
2590 | pushScope(); | 2592 | pushScope(); |
2593 | _enableReturn.push(true); | ||
2591 | } | 2594 | } |
2592 | auto partOne = x->new_ptr<ChainValue_t>(); | 2595 | auto partOne = x->new_ptr<ChainValue_t>(); |
2593 | for (auto it = chainList.begin();it != opIt;++it) { | 2596 | for (auto it = chainList.begin();it != opIt;++it) { |
@@ -2718,6 +2721,7 @@ private: | |||
2718 | break; | 2721 | break; |
2719 | case ExpUsage::Closure: | 2722 | case ExpUsage::Closure: |
2720 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); | 2723 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); |
2724 | _enableReturn.pop(); | ||
2721 | popScope(); | 2725 | popScope(); |
2722 | temp.push_back(indent() + s("end)()"sv)); | 2726 | temp.push_back(indent() + s("end)()"sv)); |
2723 | break; | 2727 | break; |
@@ -2742,6 +2746,7 @@ private: | |||
2742 | case ExpUsage::Closure: | 2746 | case ExpUsage::Closure: |
2743 | temp.push_back(s("(function()"sv) + nll(x)); | 2747 | temp.push_back(s("(function()"sv) + nll(x)); |
2744 | pushScope(); | 2748 | pushScope(); |
2749 | _enableReturn.push(true); | ||
2745 | break; | 2750 | break; |
2746 | default: | 2751 | default: |
2747 | break; | 2752 | break; |
@@ -2813,6 +2818,7 @@ private: | |||
2813 | temp.push_back(indent() + s("end"sv) + nlr(x)); | 2818 | temp.push_back(indent() + s("end"sv) + nlr(x)); |
2814 | break; | 2819 | break; |
2815 | case ExpUsage::Closure: | 2820 | case ExpUsage::Closure: |
2821 | _enableReturn.pop(); | ||
2816 | popScope(); | 2822 | popScope(); |
2817 | temp.push_back(indent() + s("end)()"sv)); | 2823 | temp.push_back(indent() + s("end)()"sv)); |
2818 | break; | 2824 | break; |
@@ -3359,6 +3365,9 @@ private: | |||
3359 | auto x = comp; | 3365 | auto x = comp; |
3360 | switch (usage) { | 3366 | switch (usage) { |
3361 | case ExpUsage::Closure: | 3367 | case ExpUsage::Closure: |
3368 | _enableReturn.push(true); | ||
3369 | pushScope(); | ||
3370 | break; | ||
3362 | case ExpUsage::Assignment: | 3371 | case ExpUsage::Assignment: |
3363 | pushScope(); | 3372 | pushScope(); |
3364 | break; | 3373 | break; |
@@ -3413,6 +3422,7 @@ private: | |||
3413 | case ExpUsage::Common: | 3422 | case ExpUsage::Common: |
3414 | break; | 3423 | break; |
3415 | case ExpUsage::Closure: { | 3424 | case ExpUsage::Closure: { |
3425 | _enableReturn.pop(); | ||
3416 | out.push_back(clearBuf()); | 3426 | out.push_back(clearBuf()); |
3417 | out.back().append(indent() + s("return "sv) + accumVar + nlr(comp)); | 3427 | out.back().append(indent() + s("return "sv) + accumVar + nlr(comp)); |
3418 | popScope(); | 3428 | popScope(); |
@@ -3697,8 +3707,10 @@ private: | |||
3697 | str_list temp; | 3707 | str_list temp; |
3698 | _buf << "(function()"sv << nll(forNode); | 3708 | _buf << "(function()"sv << nll(forNode); |
3699 | pushScope(); | 3709 | pushScope(); |
3710 | _enableReturn.push(true); | ||
3700 | auto accum = transformForInner(forNode, temp); | 3711 | auto accum = transformForInner(forNode, temp); |
3701 | temp.push_back(indent() + s("return "sv) + accum + nlr(forNode)); | 3712 | temp.push_back(indent() + s("return "sv) + accum + nlr(forNode)); |
3713 | _enableReturn.pop(); | ||
3702 | popScope(); | 3714 | popScope(); |
3703 | temp.push_back(indent() + s("end)()"sv)); | 3715 | temp.push_back(indent() + s("end)()"sv)); |
3704 | out.push_back(join(temp)); | 3716 | out.push_back(join(temp)); |
@@ -3764,8 +3776,10 @@ private: | |||
3764 | str_list temp; | 3776 | str_list temp; |
3765 | _buf << "(function()"sv << nll(forEach); | 3777 | _buf << "(function()"sv << nll(forEach); |
3766 | pushScope(); | 3778 | pushScope(); |
3779 | _enableReturn.push(true); | ||
3767 | auto accum = transformForEachInner(forEach, temp); | 3780 | auto accum = transformForEachInner(forEach, temp); |
3768 | temp.push_back(indent() + s("return "sv) + accum + nlr(forEach)); | 3781 | temp.push_back(indent() + s("return "sv) + accum + nlr(forEach)); |
3782 | _enableReturn.pop(); | ||
3769 | popScope(); | 3783 | popScope(); |
3770 | temp.push_back(indent() + s("end)()"sv)); | 3784 | temp.push_back(indent() + s("end)()"sv)); |
3771 | out.push_back(join(temp)); | 3785 | out.push_back(join(temp)); |
@@ -3918,7 +3932,9 @@ private: | |||
3918 | str_list temp; | 3932 | str_list temp; |
3919 | temp.push_back(s("(function()"sv) + nll(classDecl)); | 3933 | temp.push_back(s("(function()"sv) + nll(classDecl)); |
3920 | pushScope(); | 3934 | pushScope(); |
3935 | _enableReturn.push(true); | ||
3921 | transformClassDecl(classDecl, temp, ExpUsage::Return); | 3936 | transformClassDecl(classDecl, temp, ExpUsage::Return); |
3937 | _enableReturn.pop(); | ||
3922 | popScope(); | 3938 | popScope(); |
3923 | temp.push_back(s("end)()"sv)); | 3939 | temp.push_back(s("end)()"sv)); |
3924 | out.push_back(join(temp)); | 3940 | out.push_back(join(temp)); |
@@ -4280,7 +4296,9 @@ private: | |||
4280 | str_list temp; | 4296 | str_list temp; |
4281 | temp.push_back(s("(function()"sv) + nll(with)); | 4297 | temp.push_back(s("(function()"sv) + nll(with)); |
4282 | pushScope(); | 4298 | pushScope(); |
4299 | _enableReturn.push(true); | ||
4283 | transformWith(with, temp, nullptr, true); | 4300 | transformWith(with, temp, nullptr, true); |
4301 | _enableReturn.pop(); | ||
4284 | popScope(); | 4302 | popScope(); |
4285 | temp.push_back(indent() + s("end)()"sv)); | 4303 | temp.push_back(indent() + s("end)()"sv)); |
4286 | out.push_back(join(temp)); | 4304 | out.push_back(join(temp)); |
@@ -4605,6 +4623,9 @@ private: | |||
4605 | void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 4623 | void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
4606 | switch (usage) { | 4624 | switch (usage) { |
4607 | case ExpUsage::Closure: | 4625 | case ExpUsage::Closure: |
4626 | pushScope(); | ||
4627 | _enableReturn.push(true); | ||
4628 | break; | ||
4608 | case ExpUsage::Assignment: | 4629 | case ExpUsage::Assignment: |
4609 | pushScope(); | 4630 | pushScope(); |
4610 | break; | 4631 | break; |
@@ -4660,6 +4681,7 @@ private: | |||
4660 | case ExpUsage::Closure: | 4681 | case ExpUsage::Closure: |
4661 | out.push_back(clearBuf() + indent() + s("return "sv) + tbl + nlr(comp)); | 4682 | out.push_back(clearBuf() + indent() + s("return "sv) + tbl + nlr(comp)); |
4662 | popScope(); | 4683 | popScope(); |
4684 | _enableReturn.pop(); | ||
4663 | out.back().insert(0, s("(function()"sv) + nll(comp)); | 4685 | out.back().insert(0, s("(function()"sv) + nll(comp)); |
4664 | out.back().append(indent() + s("end)()"sv)); | 4686 | out.back().append(indent() + s("end)()"sv)); |
4665 | break; | 4687 | break; |
@@ -4713,6 +4735,7 @@ private: | |||
4713 | str_list temp; | 4735 | str_list temp; |
4714 | if (usage == ExpUsage::Closure) { | 4736 | if (usage == ExpUsage::Closure) { |
4715 | temp.push_back(s("(function()"sv) + nll(doNode)); | 4737 | temp.push_back(s("(function()"sv) + nll(doNode)); |
4738 | _enableReturn.push(true); | ||
4716 | } else { | 4739 | } else { |
4717 | temp.push_back(indent() + s("do"sv) + nll(doNode)); | 4740 | temp.push_back(indent() + s("do"sv) + nll(doNode)); |
4718 | } | 4741 | } |
@@ -4720,6 +4743,7 @@ private: | |||
4720 | transformBody(doNode->body, temp, usage, assignList); | 4743 | transformBody(doNode->body, temp, usage, assignList); |
4721 | popScope(); | 4744 | popScope(); |
4722 | if (usage == ExpUsage::Closure) { | 4745 | if (usage == ExpUsage::Closure) { |
4746 | _enableReturn.pop(); | ||
4723 | temp.push_back(indent() + s("end)()"sv)); | 4747 | temp.push_back(indent() + s("end)()"sv)); |
4724 | } else { | 4748 | } else { |
4725 | temp.push_back(indent() + s("end"sv) + nlr(doNode)); | 4749 | temp.push_back(indent() + s("end"sv) + nlr(doNode)); |
@@ -4990,6 +5014,7 @@ private: | |||
4990 | str_list temp; | 5014 | str_list temp; |
4991 | temp.push_back(s("(function() "sv) + nll(whileNode)); | 5015 | temp.push_back(s("(function() "sv) + nll(whileNode)); |
4992 | pushScope(); | 5016 | pushScope(); |
5017 | _enableReturn.push(true); | ||
4993 | auto accumVar = getUnusedName("_accum_"sv); | 5018 | auto accumVar = getUnusedName("_accum_"sv); |
4994 | addToScope(accumVar); | 5019 | addToScope(accumVar); |
4995 | auto lenVar = getUnusedName("_len_"sv); | 5020 | auto lenVar = getUnusedName("_len_"sv); |
@@ -5005,6 +5030,7 @@ private: | |||
5005 | popScope(); | 5030 | popScope(); |
5006 | temp.push_back(indent() + s("end"sv) + nlr(whileNode)); | 5031 | temp.push_back(indent() + s("end"sv) + nlr(whileNode)); |
5007 | temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode)); | 5032 | temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode)); |
5033 | _enableReturn.pop(); | ||
5008 | popScope(); | 5034 | popScope(); |
5009 | temp.push_back(indent() + s("end)()"sv)); | 5035 | temp.push_back(indent() + s("end)()"sv)); |
5010 | out.push_back(join(temp)); | 5036 | out.push_back(join(temp)); |
@@ -5039,6 +5065,7 @@ private: | |||
5039 | if (usage == ExpUsage::Closure) { | 5065 | if (usage == ExpUsage::Closure) { |
5040 | temp.push_back(s("(function()"sv) + nll(switchNode)); | 5066 | temp.push_back(s("(function()"sv) + nll(switchNode)); |
5041 | pushScope(); | 5067 | pushScope(); |
5068 | _enableReturn.push(true); | ||
5042 | } | 5069 | } |
5043 | auto objVar = singleVariableFrom(switchNode->target); | 5070 | auto objVar = singleVariableFrom(switchNode->target); |
5044 | if (objVar.empty()) { | 5071 | if (objVar.empty()) { |
@@ -5076,6 +5103,7 @@ private: | |||
5076 | } | 5103 | } |
5077 | temp.push_back(indent() + s("end"sv) + nlr(switchNode)); | 5104 | temp.push_back(indent() + s("end"sv) + nlr(switchNode)); |
5078 | if (usage == ExpUsage::Closure) { | 5105 | if (usage == ExpUsage::Closure) { |
5106 | _enableReturn.pop(); | ||
5079 | popScope(); | 5107 | popScope(); |
5080 | temp.push_back(indent() + s("end)()"sv)); | 5108 | temp.push_back(indent() + s("end)()"sv)); |
5081 | } | 5109 | } |
diff --git a/src/lua/lapi.c b/src/lua/lapi.c index 3e24781..9048245 100644 --- a/src/lua/lapi.c +++ b/src/lua/lapi.c | |||
@@ -97,8 +97,9 @@ static StkId index2stack (lua_State *L, int idx) { | |||
97 | 97 | ||
98 | LUA_API int lua_checkstack (lua_State *L, int n) { | 98 | LUA_API int lua_checkstack (lua_State *L, int n) { |
99 | int res; | 99 | int res; |
100 | CallInfo *ci = L->ci; | 100 | CallInfo *ci; |
101 | lua_lock(L); | 101 | lua_lock(L); |
102 | ci = L->ci; | ||
102 | api_check(L, n >= 0, "negative 'n'"); | 103 | api_check(L, n >= 0, "negative 'n'"); |
103 | if (L->stack_last - L->top > n) /* stack large enough? */ | 104 | if (L->stack_last - L->top > n) /* stack large enough? */ |
104 | res = 1; /* yes; check is OK */ | 105 | res = 1; /* yes; check is OK */ |
@@ -170,10 +171,12 @@ LUA_API int lua_gettop (lua_State *L) { | |||
170 | 171 | ||
171 | 172 | ||
172 | LUA_API void lua_settop (lua_State *L, int idx) { | 173 | LUA_API void lua_settop (lua_State *L, int idx) { |
173 | CallInfo *ci = L->ci; | 174 | CallInfo *ci; |
174 | StkId func = ci->func; | 175 | StkId func; |
175 | ptrdiff_t diff; /* difference for new top */ | 176 | ptrdiff_t diff; /* difference for new top */ |
176 | lua_lock(L); | 177 | lua_lock(L); |
178 | ci = L->ci; | ||
179 | func = ci->func; | ||
177 | if (idx >= 0) { | 180 | if (idx >= 0) { |
178 | api_check(L, idx <= ci->top - (func + 1), "new top too large"); | 181 | api_check(L, idx <= ci->top - (func + 1), "new top too large"); |
179 | diff = ((func + 1) + idx) - L->top; | 182 | diff = ((func + 1) + idx) - L->top; |
@@ -376,20 +379,22 @@ LUA_API int lua_toboolean (lua_State *L, int idx) { | |||
376 | 379 | ||
377 | 380 | ||
378 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | 381 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { |
379 | TValue *o = index2value(L, idx); | 382 | TValue *o; |
383 | lua_lock(L); | ||
384 | o = index2value(L, idx); | ||
380 | if (!ttisstring(o)) { | 385 | if (!ttisstring(o)) { |
381 | if (!cvt2str(o)) { /* not convertible? */ | 386 | if (!cvt2str(o)) { /* not convertible? */ |
382 | if (len != NULL) *len = 0; | 387 | if (len != NULL) *len = 0; |
388 | lua_unlock(L); | ||
383 | return NULL; | 389 | return NULL; |
384 | } | 390 | } |
385 | lua_lock(L); /* 'luaO_tostring' may create a new string */ | ||
386 | luaO_tostring(L, o); | 391 | luaO_tostring(L, o); |
387 | luaC_checkGC(L); | 392 | luaC_checkGC(L); |
388 | o = index2value(L, idx); /* previous call may reallocate the stack */ | 393 | o = index2value(L, idx); /* previous call may reallocate the stack */ |
389 | lua_unlock(L); | ||
390 | } | 394 | } |
391 | if (len != NULL) | 395 | if (len != NULL) |
392 | *len = vslen(o); | 396 | *len = vslen(o); |
397 | lua_unlock(L); | ||
393 | return svalue(o); | 398 | return svalue(o); |
394 | } | 399 | } |
395 | 400 | ||
@@ -563,6 +568,7 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
563 | while (n--) { | 568 | while (n--) { |
564 | setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); | 569 | setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); |
565 | /* does not need barrier because closure is white */ | 570 | /* does not need barrier because closure is white */ |
571 | lua_assert(iswhite(cl)); | ||
566 | } | 572 | } |
567 | setclCvalue(L, s2v(L->top), cl); | 573 | setclCvalue(L, s2v(L->top), cl); |
568 | api_incr_top(L); | 574 | api_incr_top(L); |
@@ -624,8 +630,9 @@ static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | |||
624 | 630 | ||
625 | 631 | ||
626 | LUA_API int lua_getglobal (lua_State *L, const char *name) { | 632 | LUA_API int lua_getglobal (lua_State *L, const char *name) { |
627 | Table *reg = hvalue(&G(L)->l_registry); | 633 | Table *reg; |
628 | lua_lock(L); | 634 | lua_lock(L); |
635 | reg = hvalue(&G(L)->l_registry); | ||
629 | return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); | 636 | return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); |
630 | } | 637 | } |
631 | 638 | ||
@@ -804,8 +811,9 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { | |||
804 | 811 | ||
805 | 812 | ||
806 | LUA_API void lua_setglobal (lua_State *L, const char *name) { | 813 | LUA_API void lua_setglobal (lua_State *L, const char *name) { |
807 | Table *reg = hvalue(&G(L)->l_registry); | 814 | Table *reg; |
808 | lua_lock(L); /* unlock done in 'auxsetstr' */ | 815 | lua_lock(L); /* unlock done in 'auxsetstr' */ |
816 | reg = hvalue(&G(L)->l_registry); | ||
809 | auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); | 817 | auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); |
810 | } | 818 | } |
811 | 819 | ||
@@ -1093,8 +1101,9 @@ LUA_API int lua_status (lua_State *L) { | |||
1093 | LUA_API int lua_gc (lua_State *L, int what, ...) { | 1101 | LUA_API int lua_gc (lua_State *L, int what, ...) { |
1094 | va_list argp; | 1102 | va_list argp; |
1095 | int res = 0; | 1103 | int res = 0; |
1096 | global_State *g = G(L); | 1104 | global_State *g; |
1097 | lua_lock(L); | 1105 | lua_lock(L); |
1106 | g = G(L); | ||
1098 | va_start(argp, what); | 1107 | va_start(argp, what); |
1099 | switch (what) { | 1108 | switch (what) { |
1100 | case LUA_GCSTOP: { | 1109 | case LUA_GCSTOP: { |
@@ -1194,9 +1203,15 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { | |||
1194 | 1203 | ||
1195 | 1204 | ||
1196 | LUA_API int lua_error (lua_State *L) { | 1205 | LUA_API int lua_error (lua_State *L) { |
1206 | TValue *errobj; | ||
1197 | lua_lock(L); | 1207 | lua_lock(L); |
1208 | errobj = s2v(L->top - 1); | ||
1198 | api_checknelems(L, 1); | 1209 | api_checknelems(L, 1); |
1199 | luaG_errormsg(L); | 1210 | /* error object is the memory error message? */ |
1211 | if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) | ||
1212 | luaM_error(L); /* raise a memory error */ | ||
1213 | else | ||
1214 | luaG_errormsg(L); /* raise a regular error */ | ||
1200 | /* code unreachable; will unlock when control actually leaves the kernel */ | 1215 | /* code unreachable; will unlock when control actually leaves the kernel */ |
1201 | return 0; /* to avoid warnings */ | 1216 | return 0; /* to avoid warnings */ |
1202 | } | 1217 | } |
@@ -1238,14 +1253,12 @@ LUA_API void lua_toclose (lua_State *L, int idx) { | |||
1238 | LUA_API void lua_concat (lua_State *L, int n) { | 1253 | LUA_API void lua_concat (lua_State *L, int n) { |
1239 | lua_lock(L); | 1254 | lua_lock(L); |
1240 | api_checknelems(L, n); | 1255 | api_checknelems(L, n); |
1241 | if (n >= 2) { | 1256 | if (n > 0) |
1242 | luaV_concat(L, n); | 1257 | luaV_concat(L, n); |
1243 | } | 1258 | else { /* nothing to concatenate */ |
1244 | else if (n == 0) { /* push empty string */ | 1259 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ |
1245 | setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); | ||
1246 | api_incr_top(L); | 1260 | api_incr_top(L); |
1247 | } | 1261 | } |
1248 | /* else n == 1; nothing to do */ | ||
1249 | luaC_checkGC(L); | 1262 | luaC_checkGC(L); |
1250 | lua_unlock(L); | 1263 | lua_unlock(L); |
1251 | } | 1264 | } |
diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c index e3d9be3..cbe9ed3 100644 --- a/src/lua/lauxlib.c +++ b/src/lua/lauxlib.c | |||
@@ -475,8 +475,10 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) { | |||
475 | lua_Alloc allocf = lua_getallocf(L, &ud); | 475 | lua_Alloc allocf = lua_getallocf(L, &ud); |
476 | UBox *box = (UBox *)lua_touserdata(L, idx); | 476 | UBox *box = (UBox *)lua_touserdata(L, idx); |
477 | void *temp = allocf(ud, box->box, box->bsize, newsize); | 477 | void *temp = allocf(ud, box->box, box->bsize, newsize); |
478 | if (temp == NULL && newsize > 0) /* allocation error? */ | 478 | if (temp == NULL && newsize > 0) { /* allocation error? */ |
479 | luaL_error(L, "not enough memory"); | 479 | lua_pushliteral(L, "not enough memory"); |
480 | lua_error(L); /* raise a memory error */ | ||
481 | } | ||
480 | box->box = temp; | 482 | box->box = temp; |
481 | box->bsize = newsize; | 483 | box->bsize = newsize; |
482 | return temp; | 484 | return temp; |
diff --git a/src/lua/lcorolib.c b/src/lua/lcorolib.c index 7d6e585..c165031 100644 --- a/src/lua/lcorolib.c +++ b/src/lua/lcorolib.c | |||
@@ -73,11 +73,12 @@ static int luaB_coresume (lua_State *L) { | |||
73 | static int luaB_auxwrap (lua_State *L) { | 73 | static int luaB_auxwrap (lua_State *L) { |
74 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | 74 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); |
75 | int r = auxresume(L, co, lua_gettop(L)); | 75 | int r = auxresume(L, co, lua_gettop(L)); |
76 | if (r < 0) { | 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) | 78 | if (stat != LUA_OK && stat != LUA_YIELD) /* error in the coroutine? */ |
79 | lua_resetthread(co); /* close variables in case of errors */ | 79 | lua_resetthread(co); /* close its tbc variables */ |
80 | if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ | 80 | if (stat != LUA_ERRMEM && /* not a memory error and ... */ |
81 | lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ | ||
81 | luaL_where(L, 1); /* add extra info, if available */ | 82 | luaL_where(L, 1); /* add extra info, if available */ |
82 | lua_insert(L, -2); | 83 | lua_insert(L, -2); |
83 | lua_concat(L, 2); | 84 | lua_concat(L, 2); |
diff --git a/src/lua/ldo.c b/src/lua/ldo.c index c563b1d..4c976a1 100644 --- a/src/lua/ldo.c +++ b/src/lua/ldo.c | |||
@@ -245,13 +245,12 @@ static int stackinuse (lua_State *L) { | |||
245 | 245 | ||
246 | void luaD_shrinkstack (lua_State *L) { | 246 | void luaD_shrinkstack (lua_State *L) { |
247 | int inuse = stackinuse(L); | 247 | int inuse = stackinuse(L); |
248 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; | 248 | int goodsize = inuse + BASIC_STACK_SIZE; |
249 | if (goodsize > LUAI_MAXSTACK) | 249 | if (goodsize > LUAI_MAXSTACK) |
250 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ | 250 | goodsize = LUAI_MAXSTACK; /* respect stack limit */ |
251 | /* if thread is currently not handling a stack overflow and its | 251 | /* if thread is currently not handling a stack overflow and its |
252 | good size is smaller than current size, shrink its stack */ | 252 | good size is smaller than current size, shrink its stack */ |
253 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && | 253 | if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize) |
254 | goodsize < L->stacksize) | ||
255 | luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ | 254 | luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ |
256 | else /* don't change stack */ | 255 | else /* don't change stack */ |
257 | condmovestack(L,{},{}); /* (change only for debugging) */ | 256 | condmovestack(L,{},{}); /* (change only for debugging) */ |
@@ -466,13 +465,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
466 | f = fvalue(s2v(func)); | 465 | f = fvalue(s2v(func)); |
467 | Cfunc: { | 466 | Cfunc: { |
468 | int n; /* number of returns */ | 467 | int n; /* number of returns */ |
469 | CallInfo *ci = next_ci(L); | 468 | CallInfo *ci; |
470 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 469 | checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
470 | L->ci = ci = next_ci(L); | ||
471 | ci->nresults = nresults; | 471 | ci->nresults = nresults; |
472 | ci->callstatus = CIST_C; | 472 | ci->callstatus = CIST_C; |
473 | ci->top = L->top + LUA_MINSTACK; | 473 | ci->top = L->top + LUA_MINSTACK; |
474 | ci->func = func; | 474 | ci->func = func; |
475 | L->ci = ci; | ||
476 | lua_assert(ci->top <= L->stack_last); | 475 | lua_assert(ci->top <= L->stack_last); |
477 | if (L->hookmask & LUA_MASKCALL) { | 476 | if (L->hookmask & LUA_MASKCALL) { |
478 | int narg = cast_int(L->top - func) - 1; | 477 | int narg = cast_int(L->top - func) - 1; |
@@ -486,12 +485,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
486 | break; | 485 | break; |
487 | } | 486 | } |
488 | case LUA_VLCL: { /* Lua function */ | 487 | case LUA_VLCL: { /* Lua function */ |
489 | CallInfo *ci = next_ci(L); | 488 | CallInfo *ci; |
490 | Proto *p = clLvalue(s2v(func))->p; | 489 | Proto *p = clLvalue(s2v(func))->p; |
491 | int narg = cast_int(L->top - func) - 1; /* number of real arguments */ | 490 | int narg = cast_int(L->top - func) - 1; /* number of real arguments */ |
492 | int nfixparams = p->numparams; | 491 | int nfixparams = p->numparams; |
493 | int fsize = p->maxstacksize; /* frame size */ | 492 | int fsize = p->maxstacksize; /* frame size */ |
494 | checkstackp(L, fsize, func); | 493 | checkstackGCp(L, fsize, func); |
494 | L->ci = ci = next_ci(L); | ||
495 | ci->nresults = nresults; | 495 | ci->nresults = nresults; |
496 | ci->u.l.savedpc = p->code; /* starting point */ | 496 | ci->u.l.savedpc = p->code; /* starting point */ |
497 | ci->callstatus = 0; | 497 | ci->callstatus = 0; |
@@ -505,7 +505,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { | |||
505 | break; | 505 | break; |
506 | } | 506 | } |
507 | default: { /* not a function */ | 507 | default: { /* not a function */ |
508 | checkstackp(L, 1, func); /* space for metamethod */ | 508 | checkstackGCp(L, 1, func); /* space for metamethod */ |
509 | luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ | 509 | luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ |
510 | goto retry; /* try again with metamethod */ | 510 | goto retry; /* try again with metamethod */ |
511 | } | 511 | } |
@@ -674,7 +674,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
674 | if (from == NULL) | 674 | if (from == NULL) |
675 | L->nCcalls = CSTACKTHREAD; | 675 | L->nCcalls = CSTACKTHREAD; |
676 | else /* correct 'nCcalls' for this thread */ | 676 | else /* correct 'nCcalls' for this thread */ |
677 | L->nCcalls = getCcalls(from) + from->nci - L->nci - CSTACKCF; | 677 | L->nCcalls = getCcalls(from) - L->nci - CSTACKCF; |
678 | if (L->nCcalls <= CSTACKERR) | 678 | if (L->nCcalls <= CSTACKERR) |
679 | return resume_error(L, "C stack overflow", nargs); | 679 | return resume_error(L, "C stack overflow", nargs); |
680 | luai_userstateresume(L, nargs); | 680 | luai_userstateresume(L, nargs); |
@@ -706,9 +706,10 @@ LUA_API int lua_isyieldable (lua_State *L) { | |||
706 | 706 | ||
707 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | 707 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, |
708 | lua_KFunction k) { | 708 | lua_KFunction k) { |
709 | CallInfo *ci = L->ci; | 709 | CallInfo *ci; |
710 | luai_userstateyield(L, nresults); | 710 | luai_userstateyield(L, nresults); |
711 | lua_lock(L); | 711 | lua_lock(L); |
712 | ci = L->ci; | ||
712 | api_checknelems(L, nresults); | 713 | api_checknelems(L, nresults); |
713 | if (unlikely(!yieldable(L))) { | 714 | if (unlikely(!yieldable(L))) { |
714 | if (L != G(L)->mainthread) | 715 | if (L != G(L)->mainthread) |
diff --git a/src/lua/ldo.h b/src/lua/ldo.h index 7760f85..6c6cb28 100644 --- a/src/lua/ldo.h +++ b/src/lua/ldo.h | |||
@@ -17,6 +17,8 @@ | |||
17 | ** Macro to check stack size and grow stack if needed. Parameters | 17 | ** Macro to check stack size and grow stack if needed. Parameters |
18 | ** 'pre'/'pos' allow the macro to preserve a pointer into the | 18 | ** 'pre'/'pos' allow the macro to preserve a pointer into the |
19 | ** stack across reallocations, doing the work only when needed. | 19 | ** stack across reallocations, doing the work only when needed. |
20 | ** It also allows the running of one GC step when the stack is | ||
21 | ** reallocated. | ||
20 | ** 'condmovestack' is used in heavy tests to force a stack reallocation | 22 | ** 'condmovestack' is used in heavy tests to force a stack reallocation |
21 | ** at every check. | 23 | ** at every check. |
22 | */ | 24 | */ |
@@ -35,7 +37,7 @@ | |||
35 | 37 | ||
36 | 38 | ||
37 | /* macro to check stack size, preserving 'p' */ | 39 | /* macro to check stack size, preserving 'p' */ |
38 | #define checkstackp(L,n,p) \ | 40 | #define checkstackGCp(L,n,p) \ |
39 | luaD_checkstackaux(L, n, \ | 41 | luaD_checkstackaux(L, n, \ |
40 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ | 42 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ |
41 | luaC_checkGC(L), /* stack grow uses memory */ \ | 43 | luaC_checkGC(L), /* stack grow uses memory */ \ |
@@ -44,7 +46,7 @@ | |||
44 | 46 | ||
45 | /* macro to check stack size and GC */ | 47 | /* macro to check stack size and GC */ |
46 | #define checkstackGC(L,fsize) \ | 48 | #define checkstackGC(L,fsize) \ |
47 | luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) | 49 | luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0) |
48 | 50 | ||
49 | 51 | ||
50 | /* type of protected functions, to be ran by 'runprotected' */ | 52 | /* type of protected functions, to be ran by 'runprotected' */ |
diff --git a/src/lua/lgc.c b/src/lua/lgc.c index f26c921..f7fd7a5 100644 --- a/src/lua/lgc.c +++ b/src/lua/lgc.c | |||
@@ -1131,16 +1131,14 @@ static void finishgencycle (lua_State *L, global_State *g) { | |||
1131 | 1131 | ||
1132 | 1132 | ||
1133 | /* | 1133 | /* |
1134 | ** Does a young collection. First, mark 'OLD1' objects. (Only survival | 1134 | ** Does a young collection. First, mark 'OLD1' objects. Then does the |
1135 | ** and "recent old" lists can contain 'OLD1' objects. New lists cannot | 1135 | ** atomic step. Then, sweep all lists and advance pointers. Finally, |
1136 | ** contain 'OLD1' objects, at most 'OLD0' objects that were already | 1136 | ** finish the collection. |
1137 | ** visited when marked old.) Then does the atomic step. Then, | ||
1138 | ** sweep all lists and advance pointers. Finally, finish the collection. | ||
1139 | */ | 1137 | */ |
1140 | static void youngcollection (lua_State *L, global_State *g) { | 1138 | static void youngcollection (lua_State *L, global_State *g) { |
1141 | GCObject **psurvival; /* to point to first non-dead survival object */ | 1139 | GCObject **psurvival; /* to point to first non-dead survival object */ |
1142 | lua_assert(g->gcstate == GCSpropagate); | 1140 | lua_assert(g->gcstate == GCSpropagate); |
1143 | markold(g, g->survival, g->reallyold); | 1141 | markold(g, g->allgc, g->reallyold); |
1144 | markold(g, g->finobj, g->finobjrold); | 1142 | markold(g, g->finobj, g->finobjrold); |
1145 | atomic(L); | 1143 | atomic(L); |
1146 | 1144 | ||
diff --git a/src/lua/liolib.c b/src/lua/liolib.c index 7ac3444..60ab1bf 100644 --- a/src/lua/liolib.c +++ b/src/lua/liolib.c | |||
@@ -52,6 +52,12 @@ static int l_checkmode (const char *mode) { | |||
52 | ** ======================================================= | 52 | ** ======================================================= |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #if !defined(l_checkmodep) | ||
56 | /* By default, Lua accepts only "r" or "w" as mode */ | ||
57 | #define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') | ||
58 | #endif | ||
59 | |||
60 | |||
55 | #if !defined(l_popen) /* { */ | 61 | #if !defined(l_popen) /* { */ |
56 | 62 | ||
57 | #if defined(LUA_USE_POSIX) /* { */ | 63 | #if defined(LUA_USE_POSIX) /* { */ |
@@ -279,6 +285,7 @@ static int io_popen (lua_State *L) { | |||
279 | const char *filename = luaL_checkstring(L, 1); | 285 | const char *filename = luaL_checkstring(L, 1); |
280 | const char *mode = luaL_optstring(L, 2, "r"); | 286 | const char *mode = luaL_optstring(L, 2, "r"); |
281 | LStream *p = newprefile(L); | 287 | LStream *p = newprefile(L); |
288 | luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode"); | ||
282 | p->f = l_popen(L, filename, mode); | 289 | p->f = l_popen(L, filename, mode); |
283 | p->closef = &io_pclose; | 290 | p->closef = &io_pclose; |
284 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; | 291 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; |
diff --git a/src/lua/llimits.h b/src/lua/llimits.h index b86d345..48c97f9 100644 --- a/src/lua/llimits.h +++ b/src/lua/llimits.h | |||
@@ -84,7 +84,15 @@ typedef LUAI_UACNUMBER l_uacNumber; | |||
84 | typedef LUAI_UACINT l_uacInt; | 84 | typedef LUAI_UACINT l_uacInt; |
85 | 85 | ||
86 | 86 | ||
87 | /* internal assertions for in-house debugging */ | 87 | /* |
88 | ** Internal assertions for in-house debugging | ||
89 | */ | ||
90 | #if defined LUAI_ASSERT | ||
91 | #undef NDEBUG | ||
92 | #include <assert.h> | ||
93 | #define lua_assert(c) assert(c) | ||
94 | #endif | ||
95 | |||
88 | #if defined(lua_assert) | 96 | #if defined(lua_assert) |
89 | #define check_exp(c,e) (lua_assert(c), (e)) | 97 | #define check_exp(c,e) (lua_assert(c), (e)) |
90 | /* to avoid problems with conditions too long */ | 98 | /* to avoid problems with conditions too long */ |
diff --git a/src/lua/lmem.c b/src/lua/lmem.c index 65bfa52..43739bf 100644 --- a/src/lua/lmem.c +++ b/src/lua/lmem.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "lstate.h" | 22 | #include "lstate.h" |
23 | 23 | ||
24 | 24 | ||
25 | #if defined(HARDMEMTESTS) | 25 | #if defined(EMERGENCYGCTESTS) |
26 | /* | 26 | /* |
27 | ** First allocation will fail whenever not building initial state | 27 | ** First allocation will fail whenever not building initial state |
28 | ** and not shrinking a block. (This fail will trigger 'tryagain' and | 28 | ** and not shrinking a block. (This fail will trigger 'tryagain' and |
diff --git a/src/lua/lobject.c b/src/lua/lobject.c index b4efae4..f8ea917 100644 --- a/src/lua/lobject.c +++ b/src/lua/lobject.c | |||
@@ -215,37 +215,42 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { | |||
215 | /* }====================================================== */ | 215 | /* }====================================================== */ |
216 | 216 | ||
217 | 217 | ||
218 | /* maximum length of a numeral */ | 218 | /* maximum length of a numeral to be converted to a number */ |
219 | #if !defined (L_MAXLENNUM) | 219 | #if !defined (L_MAXLENNUM) |
220 | #define L_MAXLENNUM 200 | 220 | #define L_MAXLENNUM 200 |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | /* | ||
224 | ** Convert string 's' to a Lua number (put in 'result'). Return NULL on | ||
225 | ** fail or the address of the ending '\0' on success. ('mode' == 'x') | ||
226 | ** means a hexadecimal numeral. | ||
227 | */ | ||
223 | static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { | 228 | static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { |
224 | char *endptr; | 229 | char *endptr; |
225 | *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ | 230 | *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ |
226 | : lua_str2number(s, &endptr); | 231 | : lua_str2number(s, &endptr); |
227 | if (endptr == s) return NULL; /* nothing recognized? */ | 232 | if (endptr == s) return NULL; /* nothing recognized? */ |
228 | while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ | 233 | while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ |
229 | return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ | 234 | return (*endptr == '\0') ? endptr : NULL; /* OK iff no trailing chars */ |
230 | } | 235 | } |
231 | 236 | ||
232 | 237 | ||
233 | /* | 238 | /* |
234 | ** Convert string 's' to a Lua number (put in 'result'). Return NULL | 239 | ** Convert string 's' to a Lua number (put in 'result') handling the |
235 | ** on fail or the address of the ending '\0' on success. | 240 | ** current locale. |
236 | ** 'pmode' points to (and 'mode' contains) special things in the string: | ||
237 | ** - 'x'/'X' means a hexadecimal numeral | ||
238 | ** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) | ||
239 | ** - '.' just optimizes the search for the common case (nothing special) | ||
240 | ** This function accepts both the current locale or a dot as the radix | 241 | ** This function accepts both the current locale or a dot as the radix |
241 | ** mark. If the conversion fails, it may mean number has a dot but | 242 | ** mark. If the conversion fails, it may mean number has a dot but |
242 | ** locale accepts something else. In that case, the code copies 's' | 243 | ** locale accepts something else. In that case, the code copies 's' |
243 | ** to a buffer (because 's' is read-only), changes the dot to the | 244 | ** to a buffer (because 's' is read-only), changes the dot to the |
244 | ** current locale radix mark, and tries to convert again. | 245 | ** current locale radix mark, and tries to convert again. |
246 | ** The variable 'mode' checks for special characters in the string: | ||
247 | ** - 'n' means 'inf' or 'nan' (which should be rejected) | ||
248 | ** - 'x' means a hexadecimal numeral | ||
249 | ** - '.' just optimizes the search for the common case (no special chars) | ||
245 | */ | 250 | */ |
246 | static const char *l_str2d (const char *s, lua_Number *result) { | 251 | static const char *l_str2d (const char *s, lua_Number *result) { |
247 | const char *endptr; | 252 | const char *endptr; |
248 | const char *pmode = strpbrk(s, ".xXnN"); | 253 | const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */ |
249 | int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; | 254 | int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; |
250 | if (mode == 'n') /* reject 'inf' and 'nan' */ | 255 | if (mode == 'n') /* reject 'inf' and 'nan' */ |
251 | return NULL; | 256 | return NULL; |
@@ -333,8 +338,15 @@ int luaO_utf8esc (char *buff, unsigned long x) { | |||
333 | } | 338 | } |
334 | 339 | ||
335 | 340 | ||
336 | /* maximum length of the conversion of a number to a string */ | 341 | /* |
337 | #define MAXNUMBER2STR 50 | 342 | ** Maximum length of the conversion of a number to a string. Must be |
343 | ** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. | ||
344 | ** (For a long long int, this is 19 digits plus a sign and a final '\0', | ||
345 | ** adding to 21. For a long double, it can go to a sign, 33 digits, | ||
346 | ** the dot, an exponent letter, an exponent sign, 5 exponent digits, | ||
347 | ** and a final '\0', adding to 43.) | ||
348 | */ | ||
349 | #define MAXNUMBER2STR 44 | ||
338 | 350 | ||
339 | 351 | ||
340 | /* | 352 | /* |
@@ -375,7 +387,7 @@ void luaO_tostring (lua_State *L, TValue *obj) { | |||
375 | */ | 387 | */ |
376 | 388 | ||
377 | /* size for buffer space used by 'luaO_pushvfstring' */ | 389 | /* size for buffer space used by 'luaO_pushvfstring' */ |
378 | #define BUFVFS 400 | 390 | #define BUFVFS 200 |
379 | 391 | ||
380 | /* buffer used by 'luaO_pushvfstring' */ | 392 | /* buffer used by 'luaO_pushvfstring' */ |
381 | typedef struct BuffFS { | 393 | typedef struct BuffFS { |
@@ -387,18 +399,16 @@ typedef struct BuffFS { | |||
387 | 399 | ||
388 | 400 | ||
389 | /* | 401 | /* |
390 | ** Push given string to the stack, as part of the buffer. If the stack | 402 | ** Push given string to the stack, as part of the buffer, and |
391 | ** is almost full, join all partial strings in the stack into one. | 403 | ** join the partial strings in the stack into one. |
392 | */ | 404 | */ |
393 | static void pushstr (BuffFS *buff, const char *str, size_t l) { | 405 | static void pushstr (BuffFS *buff, const char *str, size_t l) { |
394 | lua_State *L = buff->L; | 406 | lua_State *L = buff->L; |
395 | setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); | 407 | setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); |
396 | L->top++; /* may use one extra slot */ | 408 | L->top++; /* may use one extra slot */ |
397 | buff->pushed++; | 409 | buff->pushed++; |
398 | if (buff->pushed > 1 && L->top + 1 >= L->stack_last) { | 410 | luaV_concat(L, buff->pushed); /* join partial results into one */ |
399 | luaV_concat(L, buff->pushed); /* join all partial results into one */ | 411 | buff->pushed = 1; |
400 | buff->pushed = 1; | ||
401 | } | ||
402 | } | 412 | } |
403 | 413 | ||
404 | 414 | ||
@@ -521,8 +531,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | |||
521 | } | 531 | } |
522 | addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ | 532 | addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ |
523 | clearbuff(&buff); /* empty buffer into the stack */ | 533 | clearbuff(&buff); /* empty buffer into the stack */ |
524 | if (buff.pushed > 1) | 534 | lua_assert(buff.pushed == 1); |
525 | luaV_concat(L, buff.pushed); /* join all partial results */ | ||
526 | return svalue(s2v(L->top - 1)); | 535 | return svalue(s2v(L->top - 1)); |
527 | } | 536 | } |
528 | 537 | ||
diff --git a/src/lua/lstate.c b/src/lua/lstate.c index 4434211..28853dc 100644 --- a/src/lua/lstate.c +++ b/src/lua/lstate.c | |||
@@ -318,9 +318,10 @@ static void close_state (lua_State *L) { | |||
318 | 318 | ||
319 | 319 | ||
320 | LUA_API lua_State *lua_newthread (lua_State *L) { | 320 | LUA_API lua_State *lua_newthread (lua_State *L) { |
321 | global_State *g = G(L); | 321 | global_State *g; |
322 | lua_State *L1; | 322 | lua_State *L1; |
323 | lua_lock(L); | 323 | lua_lock(L); |
324 | g = G(L); | ||
324 | luaC_checkGC(L); | 325 | luaC_checkGC(L); |
325 | /* create new thread */ | 326 | /* create new thread */ |
326 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; | 327 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; |
@@ -395,6 +396,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
395 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ | 396 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ |
396 | L->next = NULL; | 397 | L->next = NULL; |
397 | g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; | 398 | g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; |
399 | incnny(L); /* main thread is always non yieldable */ | ||
398 | g->frealloc = f; | 400 | g->frealloc = f; |
399 | g->ud = ud; | 401 | g->ud = ud; |
400 | g->warnf = NULL; | 402 | g->warnf = NULL; |
@@ -436,8 +438,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
436 | 438 | ||
437 | 439 | ||
438 | LUA_API void lua_close (lua_State *L) { | 440 | LUA_API void lua_close (lua_State *L) { |
439 | L = G(L)->mainthread; /* only the main thread can be closed */ | ||
440 | lua_lock(L); | 441 | lua_lock(L); |
442 | L = G(L)->mainthread; /* only the main thread can be closed */ | ||
441 | close_state(L); | 443 | close_state(L); |
442 | } | 444 | } |
443 | 445 | ||
diff --git a/src/lua/ltm.c b/src/lua/ltm.c index ae60983..4770f96 100644 --- a/src/lua/ltm.c +++ b/src/lua/ltm.c | |||
@@ -240,7 +240,7 @@ void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, | |||
240 | int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ | 240 | int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ |
241 | int nextra = actual - nfixparams; /* number of extra arguments */ | 241 | int nextra = actual - nfixparams; /* number of extra arguments */ |
242 | ci->u.l.nextraargs = nextra; | 242 | ci->u.l.nextraargs = nextra; |
243 | checkstackGC(L, p->maxstacksize + 1); | 243 | luaD_checkstack(L, p->maxstacksize + 1); |
244 | /* copy function to the top of the stack */ | 244 | /* copy function to the top of the stack */ |
245 | setobjs2s(L, L->top++, ci->func); | 245 | setobjs2s(L, L->top++, ci->func); |
246 | /* move fixed parameters to the top of the stack */ | 246 | /* move fixed parameters to the top of the stack */ |
@@ -259,7 +259,7 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { | |||
259 | int nextra = ci->u.l.nextraargs; | 259 | int nextra = ci->u.l.nextraargs; |
260 | if (wanted < 0) { | 260 | if (wanted < 0) { |
261 | wanted = nextra; /* get all extra arguments available */ | 261 | wanted = nextra; /* get all extra arguments available */ |
262 | checkstackp(L, nextra, where); /* ensure stack space */ | 262 | checkstackGCp(L, nextra, where); /* ensure stack space */ |
263 | L->top = where + nextra; /* next instruction will need top */ | 263 | L->top = where + nextra; /* next instruction will need top */ |
264 | } | 264 | } |
265 | for (i = 0; i < wanted && i < nextra; i++) | 265 | for (i = 0; i < wanted && i < nextra; i++) |
diff --git a/src/lua/lundump.c b/src/lua/lundump.c index 4243678..cb124d6 100644 --- a/src/lua/lundump.c +++ b/src/lua/lundump.c | |||
@@ -200,13 +200,20 @@ static void loadProtos (LoadState *S, Proto *f) { | |||
200 | } | 200 | } |
201 | 201 | ||
202 | 202 | ||
203 | /* | ||
204 | ** Load the upvalues for a function. The names must be filled first, | ||
205 | ** because the filling of the other fields can raise read errors and | ||
206 | ** the creation of the error message can call an emergency collection; | ||
207 | ** in that case all prototypes must be consistent for the GC. | ||
208 | */ | ||
203 | static void loadUpvalues (LoadState *S, Proto *f) { | 209 | static void loadUpvalues (LoadState *S, Proto *f) { |
204 | int i, n; | 210 | int i, n; |
205 | n = loadInt(S); | 211 | n = loadInt(S); |
206 | f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); | 212 | f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); |
207 | f->sizeupvalues = n; | 213 | f->sizeupvalues = n; |
208 | for (i = 0; i < n; i++) { | 214 | for (i = 0; i < n; i++) /* make array valid for GC */ |
209 | f->upvalues[i].name = NULL; | 215 | f->upvalues[i].name = NULL; |
216 | for (i = 0; i < n; i++) { /* following calls can raise errors */ | ||
210 | f->upvalues[i].instack = loadByte(S); | 217 | f->upvalues[i].instack = loadByte(S); |
211 | f->upvalues[i].idx = loadByte(S); | 218 | f->upvalues[i].idx = loadByte(S); |
212 | f->upvalues[i].kind = loadByte(S); | 219 | f->upvalues[i].kind = loadByte(S); |
diff --git a/src/lua/lvm.c b/src/lua/lvm.c index e7781db..66d451b 100644 --- a/src/lua/lvm.c +++ b/src/lua/lvm.c | |||
@@ -634,7 +634,8 @@ static void copy2buff (StkId top, int n, char *buff) { | |||
634 | ** from 'L->top - total' up to 'L->top - 1'. | 634 | ** from 'L->top - total' up to 'L->top - 1'. |
635 | */ | 635 | */ |
636 | void luaV_concat (lua_State *L, int total) { | 636 | void luaV_concat (lua_State *L, int total) { |
637 | lua_assert(total >= 2); | 637 | if (total == 1) |
638 | return; /* "all" values already concatenated */ | ||
638 | do { | 639 | do { |
639 | StkId top = L->top; | 640 | StkId top = L->top; |
640 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 641 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
@@ -840,10 +841,8 @@ void luaV_finishOp (lua_State *L) { | |||
840 | int a = GETARG_A(inst); /* first element to concatenate */ | 841 | int a = GETARG_A(inst); /* first element to concatenate */ |
841 | int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ | 842 | int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ |
842 | setobjs2s(L, top - 2, top); /* put TM result in proper position */ | 843 | setobjs2s(L, top - 2, top); /* put TM result in proper position */ |
843 | if (total > 1) { /* are there elements to concat? */ | 844 | L->top = top - 1; /* top is one after last element (at top-2) */ |
844 | L->top = top - 1; /* top is one after last element (at top-2) */ | 845 | luaV_concat(L, total); /* concat them (may yield again) */ |
845 | luaV_concat(L, total); /* concat them (may yield again) */ | ||
846 | } | ||
847 | break; | 846 | break; |
848 | } | 847 | } |
849 | default: { | 848 | default: { |
@@ -1102,9 +1101,9 @@ void luaV_finishOp (lua_State *L) { | |||
1102 | /* idem, but without changing the stack */ | 1101 | /* idem, but without changing the stack */ |
1103 | #define halfProtectNT(exp) (savepc(L), (exp)) | 1102 | #define halfProtectNT(exp) (savepc(L), (exp)) |
1104 | 1103 | ||
1105 | 1104 | /* 'c' is the limit of live values in the stack */ | |
1106 | #define checkGC(L,c) \ | 1105 | #define checkGC(L,c) \ |
1107 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ | 1106 | { luaC_condGC(L, (savepc(L), L->top = (c)), \ |
1108 | updatetrap(ci)); \ | 1107 | updatetrap(ci)); \ |
1109 | luai_threadyield(L); } | 1108 | luai_threadyield(L); } |
1110 | 1109 | ||
@@ -1635,7 +1634,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1635 | while (!ttisfunction(s2v(ra))) { /* not a function? */ | 1634 | while (!ttisfunction(s2v(ra))) { /* not a function? */ |
1636 | luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ | 1635 | luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ |
1637 | b++; /* there is now one extra argument */ | 1636 | b++; /* there is now one extra argument */ |
1638 | checkstackp(L, 1, ra); | 1637 | checkstackGCp(L, 1, ra); |
1639 | } | 1638 | } |
1640 | if (!ttisLclosure(s2v(ra))) { /* C function? */ | 1639 | if (!ttisLclosure(s2v(ra))) { /* C function? */ |
1641 | luaD_call(L, ra, LUA_MULTRET); /* call it */ | 1640 | luaD_call(L, ra, LUA_MULTRET); /* call it */ |
@@ -1792,8 +1791,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1792 | vmbreak; | 1791 | vmbreak; |
1793 | } | 1792 | } |
1794 | vmcase(OP_VARARGPREP) { | 1793 | vmcase(OP_VARARGPREP) { |
1795 | luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p); | 1794 | ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); |
1796 | updatetrap(ci); | ||
1797 | if (trap) { | 1795 | if (trap) { |
1798 | luaD_hookcall(L, ci); | 1796 | luaD_hookcall(L, ci); |
1799 | L->oldpc = pc + 1; /* next opcode will be seen as a "new" line */ | 1797 | L->oldpc = pc + 1; /* next opcode will be seen as a "new" line */ |