diff options
Diffstat (limited to '')
-rw-r--r-- | lapi.c | 10 | ||||
-rw-r--r-- | lauxlib.c | 10 | ||||
-rw-r--r-- | lcode.c | 23 | ||||
-rw-r--r-- | lcode.h | 2 | ||||
-rw-r--r-- | lcorolib.c | 16 | ||||
-rw-r--r-- | lctype.c | 2 | ||||
-rw-r--r-- | ldebug.c | 19 | ||||
-rw-r--r-- | ldo.c | 26 | ||||
-rw-r--r-- | ldo.h | 1 | ||||
-rw-r--r-- | ldump.c | 27 | ||||
-rw-r--r-- | lgc.c | 52 | ||||
-rw-r--r-- | llex.c | 18 | ||||
-rw-r--r-- | llex.h | 6 | ||||
-rw-r--r-- | llimits.h | 4 | ||||
-rw-r--r-- | loadlib.c | 75 | ||||
-rw-r--r-- | lobject.c | 12 | ||||
-rw-r--r-- | lobject.h | 12 | ||||
-rw-r--r-- | lopcodes.h | 46 | ||||
-rw-r--r-- | loslib.c | 5 | ||||
-rw-r--r-- | lparser.c | 321 | ||||
-rw-r--r-- | lparser.h | 41 | ||||
-rw-r--r-- | lstate.c | 2 | ||||
-rw-r--r-- | lstate.h | 4 | ||||
-rw-r--r-- | lstring.c | 46 | ||||
-rw-r--r-- | lstring.h | 3 | ||||
-rw-r--r-- | lstrlib.c | 28 | ||||
-rw-r--r-- | ltable.c | 132 | ||||
-rw-r--r-- | ltable.h | 2 | ||||
-rw-r--r-- | ltests.c | 36 | ||||
-rw-r--r-- | ltests.h | 2 | ||||
-rw-r--r-- | lua.c | 71 | ||||
-rw-r--r-- | lua.h | 6 | ||||
-rw-r--r-- | luaconf.h | 26 | ||||
-rw-r--r-- | lundump.c | 35 | ||||
-rw-r--r-- | lutf8lib.c | 11 | ||||
-rw-r--r-- | lvm.c | 110 | ||||
-rwxr-xr-x | manual/2html | 6 | ||||
-rw-r--r-- | manual/manual.of | 350 | ||||
-rwxr-xr-x | testes/all.lua | 8 | ||||
-rw-r--r-- | testes/api.lua | 6 | ||||
-rw-r--r-- | testes/attrib.lua | 24 | ||||
-rw-r--r-- | testes/bwcoercion.lua | 2 | ||||
-rw-r--r-- | testes/calls.lua | 15 | ||||
-rw-r--r-- | testes/closure.lua | 2 | ||||
-rw-r--r-- | testes/code.lua | 24 | ||||
-rw-r--r-- | testes/constructs.lua | 2 | ||||
-rw-r--r-- | testes/coroutine.lua | 65 | ||||
-rw-r--r-- | testes/db.lua | 21 | ||||
-rw-r--r-- | testes/errors.lua | 16 | ||||
-rw-r--r-- | testes/files.lua | 10 | ||||
-rw-r--r-- | testes/gc.lua | 25 | ||||
-rw-r--r-- | testes/goto.lua | 170 | ||||
-rw-r--r-- | testes/libs/lib22.c | 51 | ||||
-rw-r--r-- | testes/literals.lua | 2 | ||||
-rw-r--r-- | testes/locals.lua | 42 | ||||
-rw-r--r-- | testes/main.lua | 13 | ||||
-rw-r--r-- | testes/math.lua | 21 | ||||
-rw-r--r-- | testes/nextvar.lua | 23 | ||||
-rw-r--r-- | testes/pm.lua | 6 | ||||
-rw-r--r-- | testes/strings.lua | 1 | ||||
-rw-r--r-- | testes/tracegc.lua | 2 | ||||
-rw-r--r-- | testes/utf8.lua | 13 |
62 files changed, 1490 insertions, 672 deletions
@@ -440,7 +440,7 @@ LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { | |||
440 | case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen); | 440 | case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen); |
441 | case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen); | 441 | case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen); |
442 | case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len); | 442 | case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len); |
443 | case LUA_VTABLE: return luaH_getn(hvalue(o)); | 443 | case LUA_VTABLE: return luaH_getn(L, hvalue(o)); |
444 | default: return 0; | 444 | default: return 0; |
445 | } | 445 | } |
446 | } | 446 | } |
@@ -593,12 +593,8 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { | |||
593 | const char *ret; | 593 | const char *ret; |
594 | va_list argp; | 594 | va_list argp; |
595 | lua_lock(L); | 595 | lua_lock(L); |
596 | va_start(argp, fmt); | 596 | pushvfstring(L, argp, fmt, ret); |
597 | ret = luaO_pushvfstring(L, fmt, argp); | ||
598 | va_end(argp); | ||
599 | luaC_checkGC(L); | 597 | luaC_checkGC(L); |
600 | if (ret == NULL) /* error? */ | ||
601 | luaD_throw(L, LUA_ERRMEM); | ||
602 | lua_unlock(L); | 598 | lua_unlock(L); |
603 | return ret; | 599 | return ret; |
604 | } | 600 | } |
@@ -683,7 +679,7 @@ static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | |||
683 | 679 | ||
684 | /* | 680 | /* |
685 | ** The following function assumes that the registry cannot be a weak | 681 | ** The following function assumes that the registry cannot be a weak |
686 | ** table, so that en mergency collection while using the global table | 682 | ** table; so, an emergency collection while using the global table |
687 | ** cannot collect it. | 683 | ** cannot collect it. |
688 | */ | 684 | */ |
689 | static void getGlobalTable (lua_State *L, TValue *gt) { | 685 | static void getGlobalTable (lua_State *L, TValue *gt) { |
@@ -94,14 +94,14 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { | |||
94 | 94 | ||
95 | 95 | ||
96 | static void pushfuncname (lua_State *L, lua_Debug *ar) { | 96 | static void pushfuncname (lua_State *L, lua_Debug *ar) { |
97 | if (pushglobalfuncname(L, ar)) { /* try first a global name */ | 97 | if (*ar->namewhat != '\0') /* is there a name from code? */ |
98 | lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); | ||
99 | lua_remove(L, -2); /* remove name */ | ||
100 | } | ||
101 | else if (*ar->namewhat != '\0') /* is there a name from code? */ | ||
102 | lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ | 98 | lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ |
103 | else if (*ar->what == 'm') /* main? */ | 99 | else if (*ar->what == 'm') /* main? */ |
104 | lua_pushliteral(L, "main chunk"); | 100 | lua_pushliteral(L, "main chunk"); |
101 | else if (pushglobalfuncname(L, ar)) { /* try a global name */ | ||
102 | lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); | ||
103 | lua_remove(L, -2); /* remove name */ | ||
104 | } | ||
105 | else if (*ar->what != 'C') /* for Lua functions, use <file:line> */ | 105 | else if (*ar->what != 'C') /* for Lua functions, use <file:line> */ |
106 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); | 106 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); |
107 | else /* nothing left... */ | 107 | else /* nothing left... */ |
@@ -40,7 +40,10 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k); | |||
40 | 40 | ||
41 | 41 | ||
42 | /* semantic error */ | 42 | /* semantic error */ |
43 | l_noret luaK_semerror (LexState *ls, const char *msg) { | 43 | l_noret luaK_semerror (LexState *ls, const char *fmt, ...) { |
44 | const char *msg; | ||
45 | va_list argp; | ||
46 | pushvfstring(ls->L, argp, fmt, msg); | ||
44 | ls->t.token = 0; /* remove "near <token>" from final message */ | 47 | ls->t.token = 0; /* remove "near <token>" from final message */ |
45 | luaX_syntaxerror(ls, msg); | 48 | luaX_syntaxerror(ls, msg); |
46 | } | 49 | } |
@@ -750,10 +753,11 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { | |||
750 | /* | 753 | /* |
751 | ** Convert a VKSTR to a VK | 754 | ** Convert a VKSTR to a VK |
752 | */ | 755 | */ |
753 | static void str2K (FuncState *fs, expdesc *e) { | 756 | static int str2K (FuncState *fs, expdesc *e) { |
754 | lua_assert(e->k == VKSTR); | 757 | lua_assert(e->k == VKSTR); |
755 | e->u.info = stringK(fs, e->u.strval); | 758 | e->u.info = stringK(fs, e->u.strval); |
756 | e->k = VK; | 759 | e->k = VK; |
760 | return e->u.info; | ||
757 | } | 761 | } |
758 | 762 | ||
759 | 763 | ||
@@ -1304,35 +1308,38 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
1304 | ** values in registers. | 1308 | ** values in registers. |
1305 | */ | 1309 | */ |
1306 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 1310 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { |
1311 | int keystr = -1; | ||
1307 | if (k->k == VKSTR) | 1312 | if (k->k == VKSTR) |
1308 | str2K(fs, k); | 1313 | keystr = str2K(fs, k); |
1309 | lua_assert(!hasjumps(t) && | 1314 | lua_assert(!hasjumps(t) && |
1310 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); | 1315 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); |
1311 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ | 1316 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ |
1312 | luaK_exp2anyreg(fs, t); /* put it in a register */ | 1317 | luaK_exp2anyreg(fs, t); /* put it in a register */ |
1313 | if (t->k == VUPVAL) { | 1318 | if (t->k == VUPVAL) { |
1314 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ | 1319 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ |
1315 | lua_assert(isKstr(fs, k)); | ||
1316 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ | 1320 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ |
1317 | t->u.ind.idx = cast(short, k->u.info); /* literal short string */ | 1321 | lua_assert(isKstr(fs, k)); |
1322 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ | ||
1318 | t->k = VINDEXUP; | 1323 | t->k = VINDEXUP; |
1319 | } | 1324 | } |
1320 | else { | 1325 | else { |
1321 | /* register index of the table */ | 1326 | /* register index of the table */ |
1322 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); | 1327 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); |
1323 | if (isKstr(fs, k)) { | 1328 | if (isKstr(fs, k)) { |
1324 | t->u.ind.idx = cast(short, k->u.info); /* literal short string */ | 1329 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ |
1325 | t->k = VINDEXSTR; | 1330 | t->k = VINDEXSTR; |
1326 | } | 1331 | } |
1327 | else if (isCint(k)) { /* int. constant in proper range? */ | 1332 | else if (isCint(k)) { /* int. constant in proper range? */ |
1328 | t->u.ind.idx = cast(short, k->u.ival); | 1333 | t->u.ind.idx = cast_short(k->u.ival); |
1329 | t->k = VINDEXI; | 1334 | t->k = VINDEXI; |
1330 | } | 1335 | } |
1331 | else { | 1336 | else { |
1332 | t->u.ind.idx = cast(short, luaK_exp2anyreg(fs, k)); /* register */ | 1337 | t->u.ind.idx = cast_short(luaK_exp2anyreg(fs, k)); /* register */ |
1333 | t->k = VINDEXED; | 1338 | t->k = VINDEXED; |
1334 | } | 1339 | } |
1335 | } | 1340 | } |
1341 | t->u.ind.keystr = keystr; /* string index in 'k' */ | ||
1342 | t->u.ind.ro = 0; /* by default, not read-only */ | ||
1336 | } | 1343 | } |
1337 | 1344 | ||
1338 | 1345 | ||
@@ -97,7 +97,7 @@ LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, | |||
97 | int ra, int asize, int hsize); | 97 | int ra, int asize, int hsize); |
98 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 98 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
99 | LUAI_FUNC void luaK_finish (FuncState *fs); | 99 | LUAI_FUNC void luaK_finish (FuncState *fs); |
100 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); | 100 | LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *fmt, ...); |
101 | 101 | ||
102 | 102 | ||
103 | #endif | 103 | #endif |
@@ -154,8 +154,13 @@ static int luaB_costatus (lua_State *L) { | |||
154 | } | 154 | } |
155 | 155 | ||
156 | 156 | ||
157 | static lua_State *getoptco (lua_State *L) { | ||
158 | return (lua_isnone(L, 1) ? L : getco(L)); | ||
159 | } | ||
160 | |||
161 | |||
157 | static int luaB_yieldable (lua_State *L) { | 162 | static int luaB_yieldable (lua_State *L) { |
158 | lua_State *co = lua_isnone(L, 1) ? L : getco(L); | 163 | lua_State *co = getoptco(L); |
159 | lua_pushboolean(L, lua_isyieldable(co)); | 164 | lua_pushboolean(L, lua_isyieldable(co)); |
160 | return 1; | 165 | return 1; |
161 | } | 166 | } |
@@ -169,7 +174,7 @@ static int luaB_corunning (lua_State *L) { | |||
169 | 174 | ||
170 | 175 | ||
171 | static int luaB_close (lua_State *L) { | 176 | static int luaB_close (lua_State *L) { |
172 | lua_State *co = getco(L); | 177 | lua_State *co = getoptco(L); |
173 | int status = auxstatus(L, co); | 178 | int status = auxstatus(L, co); |
174 | switch (status) { | 179 | switch (status) { |
175 | case COS_DEAD: case COS_YIELD: { | 180 | case COS_DEAD: case COS_YIELD: { |
@@ -184,6 +189,13 @@ static int luaB_close (lua_State *L) { | |||
184 | return 2; | 189 | return 2; |
185 | } | 190 | } |
186 | } | 191 | } |
192 | case COS_RUN: /* running coroutine? */ | ||
193 | lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); /* get main */ | ||
194 | if (lua_tothread(L, -1) == co) | ||
195 | return luaL_error(L, "cannot close main thread"); | ||
196 | lua_closethread(co, L); /* close itself */ | ||
197 | lua_assert(0); /* previous call does not return */ | ||
198 | return 0; | ||
187 | default: /* normal or running coroutine */ | 199 | default: /* normal or running coroutine */ |
188 | return luaL_error(L, "cannot close a %s coroutine", statname[status]); | 200 | return luaL_error(L, "cannot close a %s coroutine", statname[status]); |
189 | } | 201 | } |
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | 19 | ||
20 | #if defined (LUA_UCID) /* accept UniCode IDentifiers? */ | 20 | #if defined (LUA_UCID) /* accept UniCode IDentifiers? */ |
21 | /* consider all non-ascii codepoints to be alphabetic */ | 21 | /* consider all non-ASCII codepoints to be alphabetic */ |
22 | #define NONA 0x01 | 22 | #define NONA 0x01 |
23 | #else | 23 | #else |
24 | #define NONA 0x00 /* default */ | 24 | #define NONA 0x00 /* default */ |
@@ -817,16 +817,15 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { | |||
817 | /* add src:line information to 'msg' */ | 817 | /* add src:line information to 'msg' */ |
818 | const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, | 818 | const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, |
819 | int line) { | 819 | int line) { |
820 | char buff[LUA_IDSIZE]; | 820 | if (src == NULL) /* no debug information? */ |
821 | if (src) { | 821 | return luaO_pushfstring(L, "?:?: %s", msg); |
822 | else { | ||
823 | char buff[LUA_IDSIZE]; | ||
822 | size_t idlen; | 824 | size_t idlen; |
823 | const char *id = getlstr(src, idlen); | 825 | const char *id = getlstr(src, idlen); |
824 | luaO_chunkid(buff, id, idlen); | 826 | luaO_chunkid(buff, id, idlen); |
827 | return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | ||
825 | } | 828 | } |
826 | else { /* no source available; use "?" instead */ | ||
827 | buff[0] = '?'; buff[1] = '\0'; | ||
828 | } | ||
829 | return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); | ||
830 | } | 829 | } |
831 | 830 | ||
832 | 831 | ||
@@ -852,12 +851,8 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { | |||
852 | const char *msg; | 851 | const char *msg; |
853 | va_list argp; | 852 | va_list argp; |
854 | luaC_checkGC(L); /* error message uses memory */ | 853 | luaC_checkGC(L); /* error message uses memory */ |
855 | va_start(argp, fmt); | 854 | pushvfstring(L, argp, fmt, msg); |
856 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ | 855 | if (isLua(ci)) { /* Lua function? */ |
857 | va_end(argp); | ||
858 | if (msg == NULL) /* no memory to format message? */ | ||
859 | luaD_throw(L, LUA_ERRMEM); | ||
860 | else if (isLua(ci)) { /* Lua function? */ | ||
861 | /* add source:line information */ | 856 | /* add source:line information */ |
862 | luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); | 857 | luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); |
863 | setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ | 858 | setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ |
@@ -139,6 +139,16 @@ l_noret luaD_throw (lua_State *L, TStatus errcode) { | |||
139 | } | 139 | } |
140 | 140 | ||
141 | 141 | ||
142 | l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode) { | ||
143 | if (L->errorJmp) { | ||
144 | /* unroll error entries up to the first level */ | ||
145 | while (L->errorJmp->previous != NULL) | ||
146 | L->errorJmp = L->errorJmp->previous; | ||
147 | } | ||
148 | luaD_throw(L, errcode); | ||
149 | } | ||
150 | |||
151 | |||
142 | TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 152 | TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
143 | l_uint32 oldnCcalls = L->nCcalls; | 153 | l_uint32 oldnCcalls = L->nCcalls; |
144 | struct lua_longjmp lj; | 154 | struct lua_longjmp lj; |
@@ -164,6 +174,20 @@ TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
164 | #define STACKERRSPACE 200 | 174 | #define STACKERRSPACE 200 |
165 | 175 | ||
166 | 176 | ||
177 | /* | ||
178 | ** LUAI_MAXSTACK limits the size of the Lua stack. | ||
179 | ** It must fit into INT_MAX/2. | ||
180 | */ | ||
181 | |||
182 | #if !defined(LUAI_MAXSTACK) | ||
183 | #if 1000000 < (INT_MAX / 2) | ||
184 | #define LUAI_MAXSTACK 1000000 | ||
185 | #else | ||
186 | #define LUAI_MAXSTACK (INT_MAX / 2u) | ||
187 | #endif | ||
188 | #endif | ||
189 | |||
190 | |||
167 | /* maximum stack size that respects size_t */ | 191 | /* maximum stack size that respects size_t */ |
168 | #define MAXSTACK_BYSIZET ((MAX_SIZET / sizeof(StackValue)) - STACKERRSPACE) | 192 | #define MAXSTACK_BYSIZET ((MAX_SIZET / sizeof(StackValue)) - STACKERRSPACE) |
169 | 193 | ||
@@ -513,7 +537,7 @@ l_sinline void genmoveresults (lua_State *L, StkId res, int nres, | |||
513 | ** to 'res'. Handle most typical cases (zero results for commands, | 537 | ** to 'res'. Handle most typical cases (zero results for commands, |
514 | ** one result for expressions, multiple results for tail calls/single | 538 | ** one result for expressions, multiple results for tail calls/single |
515 | ** parameters) separated. The flag CIST_TBC in 'fwanted', if set, | 539 | ** parameters) separated. The flag CIST_TBC in 'fwanted', if set, |
516 | ** forces the swicth to go to the default case. | 540 | ** forces the switch to go to the default case. |
517 | */ | 541 | */ |
518 | l_sinline void moveresults (lua_State *L, StkId res, int nres, | 542 | l_sinline void moveresults (lua_State *L, StkId res, int nres, |
519 | l_uint32 fwanted) { | 543 | l_uint32 fwanted) { |
@@ -91,6 +91,7 @@ LUAI_FUNC void luaD_shrinkstack (lua_State *L); | |||
91 | LUAI_FUNC void luaD_inctop (lua_State *L); | 91 | LUAI_FUNC void luaD_inctop (lua_State *L); |
92 | 92 | ||
93 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); | 93 | LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); |
94 | LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); | ||
94 | LUAI_FUNC TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); | 95 | LUAI_FUNC TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); |
95 | 96 | ||
96 | #endif | 97 | #endif |
@@ -31,7 +31,7 @@ typedef struct { | |||
31 | int strip; | 31 | int strip; |
32 | int status; | 32 | int status; |
33 | Table *h; /* table to track saved strings */ | 33 | Table *h; /* table to track saved strings */ |
34 | lua_Integer nstr; /* counter for counting saved strings */ | 34 | lua_Unsigned nstr; /* counter for counting saved strings */ |
35 | } DumpState; | 35 | } DumpState; |
36 | 36 | ||
37 | 37 | ||
@@ -87,12 +87,12 @@ static void dumpByte (DumpState *D, int y) { | |||
87 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. | 87 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. |
88 | ** (The "+6" rounds up the division.) | 88 | ** (The "+6" rounds up the division.) |
89 | */ | 89 | */ |
90 | #define DIBS ((l_numbits(size_t) + 6) / 7) | 90 | #define DIBS ((l_numbits(lua_Unsigned) + 6) / 7) |
91 | 91 | ||
92 | /* | 92 | /* |
93 | ** Dumps an unsigned integer using the MSB Varint encoding | 93 | ** Dumps an unsigned integer using the MSB Varint encoding |
94 | */ | 94 | */ |
95 | static void dumpVarint (DumpState *D, size_t x) { | 95 | static void dumpVarint (DumpState *D, lua_Unsigned x) { |
96 | lu_byte buff[DIBS]; | 96 | lu_byte buff[DIBS]; |
97 | unsigned n = 1; | 97 | unsigned n = 1; |
98 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ | 98 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ |
@@ -103,12 +103,13 @@ static void dumpVarint (DumpState *D, size_t x) { | |||
103 | 103 | ||
104 | 104 | ||
105 | static void dumpSize (DumpState *D, size_t sz) { | 105 | static void dumpSize (DumpState *D, size_t sz) { |
106 | dumpVarint(D, sz); | 106 | dumpVarint(D, cast(lua_Unsigned, sz)); |
107 | } | 107 | } |
108 | 108 | ||
109 | |||
109 | static void dumpInt (DumpState *D, int x) { | 110 | static void dumpInt (DumpState *D, int x) { |
110 | lua_assert(x >= 0); | 111 | lua_assert(x >= 0); |
111 | dumpVarint(D, cast(size_t, x)); | 112 | dumpVarint(D, cast_uint(x)); |
112 | } | 113 | } |
113 | 114 | ||
114 | 115 | ||
@@ -117,8 +118,16 @@ static void dumpNumber (DumpState *D, lua_Number x) { | |||
117 | } | 118 | } |
118 | 119 | ||
119 | 120 | ||
121 | /* | ||
122 | ** Signed integers are coded to keep small values small. (Coding -1 as | ||
123 | ** 0xfff...fff would use too many bytes to save a quite common value.) | ||
124 | ** A non-negative x is coded as 2x; a negative x is coded as -2x - 1. | ||
125 | ** (0 => 0; -1 => 1; 1 => 2; -2 => 3; 2 => 4; ...) | ||
126 | */ | ||
120 | static void dumpInteger (DumpState *D, lua_Integer x) { | 127 | static void dumpInteger (DumpState *D, lua_Integer x) { |
121 | dumpVar(D, x); | 128 | lua_Unsigned cx = (x >= 0) ? 2u * l_castS2U(x) |
129 | : (2u * ~l_castS2U(x)) + 1; | ||
130 | dumpVarint(D, cx); | ||
122 | } | 131 | } |
123 | 132 | ||
124 | 133 | ||
@@ -136,8 +145,8 @@ static void dumpString (DumpState *D, TString *ts) { | |||
136 | TValue idx; | 145 | TValue idx; |
137 | int tag = luaH_getstr(D->h, ts, &idx); | 146 | int tag = luaH_getstr(D->h, ts, &idx); |
138 | if (!tagisempty(tag)) { /* string already saved? */ | 147 | if (!tagisempty(tag)) { /* string already saved? */ |
139 | dumpSize(D, 1); /* reuse a saved string */ | 148 | dumpVarint(D, 1); /* reuse a saved string */ |
140 | dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ | 149 | dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ |
141 | } | 150 | } |
142 | else { /* must write and save the string */ | 151 | else { /* must write and save the string */ |
143 | TValue key, value; /* to save the string in the hash */ | 152 | TValue key, value; /* to save the string in the hash */ |
@@ -147,7 +156,7 @@ static void dumpString (DumpState *D, TString *ts) { | |||
147 | dumpVector(D, s, size + 1); /* include ending '\0' */ | 156 | dumpVector(D, s, size + 1); /* include ending '\0' */ |
148 | D->nstr++; /* one more saved string */ | 157 | D->nstr++; /* one more saved string */ |
149 | setsvalue(D->L, &key, ts); /* the string is the key */ | 158 | setsvalue(D->L, &key, ts); /* the string is the key */ |
150 | setivalue(&value, D->nstr); /* its index is the value */ | 159 | setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */ |
151 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ | 160 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ |
152 | /* integer value does not need barrier */ | 161 | /* integer value does not need barrier */ |
153 | } | 162 | } |
@@ -126,7 +126,6 @@ static l_mem objsize (GCObject *o) { | |||
126 | CClosure *cl = gco2ccl(o); | 126 | CClosure *cl = gco2ccl(o); |
127 | res = sizeCclosure(cl->nupvalues); | 127 | res = sizeCclosure(cl->nupvalues); |
128 | break; | 128 | break; |
129 | break; | ||
130 | } | 129 | } |
131 | case LUA_VUSERDATA: { | 130 | case LUA_VUSERDATA: { |
132 | Udata *u = gco2u(o); | 131 | Udata *u = gco2u(o); |
@@ -465,6 +464,8 @@ static void restartcollection (global_State *g) { | |||
465 | ** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go | 464 | ** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go |
466 | ** back to a gray list, but then it must become OLD. (That is what | 465 | ** back to a gray list, but then it must become OLD. (That is what |
467 | ** 'correctgraylist' does when it finds a TOUCHED2 object.) | 466 | ** 'correctgraylist' does when it finds a TOUCHED2 object.) |
467 | ** This function is a no-op in incremental mode, as objects cannot be | ||
468 | ** marked as touched in that mode. | ||
468 | */ | 469 | */ |
469 | static void genlink (global_State *g, GCObject *o) { | 470 | static void genlink (global_State *g, GCObject *o) { |
470 | lua_assert(isblack(o)); | 471 | lua_assert(isblack(o)); |
@@ -480,7 +481,8 @@ static void genlink (global_State *g, GCObject *o) { | |||
480 | ** Traverse a table with weak values and link it to proper list. During | 481 | ** Traverse a table with weak values and link it to proper list. During |
481 | ** propagate phase, keep it in 'grayagain' list, to be revisited in the | 482 | ** propagate phase, keep it in 'grayagain' list, to be revisited in the |
482 | ** atomic phase. In the atomic phase, if table has any white value, | 483 | ** atomic phase. In the atomic phase, if table has any white value, |
483 | ** put it in 'weak' list, to be cleared. | 484 | ** put it in 'weak' list, to be cleared; otherwise, call 'genlink' |
485 | ** to check table age in generational mode. | ||
484 | */ | 486 | */ |
485 | static void traverseweakvalue (global_State *g, Table *h) { | 487 | static void traverseweakvalue (global_State *g, Table *h) { |
486 | Node *n, *limit = gnodelast(h); | 488 | Node *n, *limit = gnodelast(h); |
@@ -501,6 +503,8 @@ static void traverseweakvalue (global_State *g, Table *h) { | |||
501 | linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ | 503 | linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ |
502 | else if (hasclears) | 504 | else if (hasclears) |
503 | linkgclist(h, g->weak); /* has to be cleared later */ | 505 | linkgclist(h, g->weak); /* has to be cleared later */ |
506 | else | ||
507 | genlink(g, obj2gco(h)); | ||
504 | } | 508 | } |
505 | 509 | ||
506 | 510 | ||
@@ -585,25 +589,41 @@ static void traversestrongtable (global_State *g, Table *h) { | |||
585 | } | 589 | } |
586 | 590 | ||
587 | 591 | ||
588 | static l_mem traversetable (global_State *g, Table *h) { | 592 | /* |
589 | const char *weakkey, *weakvalue; | 593 | ** (result & 1) iff weak values; (result & 2) iff weak keys. |
594 | */ | ||
595 | static int getmode (global_State *g, Table *h) { | ||
590 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); | 596 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); |
591 | TString *smode; | 597 | if (mode == NULL || !ttisshrstring(mode)) |
598 | return 0; /* ignore non-(short)string modes */ | ||
599 | else { | ||
600 | const char *smode = getshrstr(tsvalue(mode)); | ||
601 | const char *weakkey = strchr(smode, 'k'); | ||
602 | const char *weakvalue = strchr(smode, 'v'); | ||
603 | return ((weakkey != NULL) << 1) | (weakvalue != NULL); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | |||
608 | static l_mem traversetable (global_State *g, Table *h) { | ||
592 | markobjectN(g, h->metatable); | 609 | markobjectN(g, h->metatable); |
593 | if (mode && ttisshrstring(mode) && /* is there a weak mode? */ | 610 | switch (getmode(g, h)) { |
594 | (cast_void(smode = tsvalue(mode)), | 611 | case 0: /* not weak */ |
595 | cast_void(weakkey = strchr(getshrstr(smode), 'k')), | 612 | traversestrongtable(g, h); |
596 | cast_void(weakvalue = strchr(getshrstr(smode), 'v')), | 613 | break; |
597 | (weakkey || weakvalue))) { /* is really weak? */ | 614 | case 1: /* weak values */ |
598 | if (!weakkey) /* strong keys? */ | ||
599 | traverseweakvalue(g, h); | 615 | traverseweakvalue(g, h); |
600 | else if (!weakvalue) /* strong values? */ | 616 | break; |
617 | case 2: /* weak keys */ | ||
601 | traverseephemeron(g, h, 0); | 618 | traverseephemeron(g, h, 0); |
602 | else /* all weak */ | 619 | break; |
603 | linkgclist(h, g->allweak); /* nothing to traverse now */ | 620 | case 3: /* all weak; nothing to traverse */ |
621 | if (g->gcstate == GCSpropagate) | ||
622 | linkgclist(h, g->grayagain); /* must visit again its metatable */ | ||
623 | else | ||
624 | linkgclist(h, g->allweak); /* must clear collected entries */ | ||
625 | break; | ||
604 | } | 626 | } |
605 | else /* not weak */ | ||
606 | traversestrongtable(g, h); | ||
607 | return 1 + 2*sizenode(h) + h->asize; | 627 | return 1 + 2*sizenode(h) + h->asize; |
608 | } | 628 | } |
609 | 629 | ||
@@ -44,7 +44,7 @@ | |||
44 | /* ORDER RESERVED */ | 44 | /* ORDER RESERVED */ |
45 | static const char *const luaX_tokens [] = { | 45 | static const char *const luaX_tokens [] = { |
46 | "and", "break", "do", "else", "elseif", | 46 | "and", "break", "do", "else", "elseif", |
47 | "end", "false", "for", "function", "goto", "if", | 47 | "end", "false", "for", "function", "global", "goto", "if", |
48 | "in", "local", "nil", "not", "or", "repeat", | 48 | "in", "local", "nil", "not", "or", "repeat", |
49 | "return", "then", "true", "until", "while", | 49 | "return", "then", "true", "until", "while", |
50 | "//", "..", "...", "==", ">=", "<=", "~=", | 50 | "//", "..", "...", "==", ">=", "<=", "~=", |
@@ -184,7 +184,15 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, | |||
184 | ls->linenumber = 1; | 184 | ls->linenumber = 1; |
185 | ls->lastline = 1; | 185 | ls->lastline = 1; |
186 | ls->source = source; | 186 | ls->source = source; |
187 | ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ | 187 | /* all three strings here ("_ENV", "break", "global") were fixed, |
188 | so they cannot be collected */ | ||
189 | ls->envn = luaS_newliteral(L, LUA_ENV); /* get env string */ | ||
190 | ls->brkn = luaS_newliteral(L, "break"); /* get "break" string */ | ||
191 | #if defined(LUA_COMPAT_GLOBAL) | ||
192 | /* compatibility mode: "global" is not a reserved word */ | ||
193 | ls->glbn = luaS_newliteral(L, "global"); /* get "global" string */ | ||
194 | ls->glbn->extra = 0; /* mark it as not reserved */ | ||
195 | #endif | ||
188 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ | 196 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ |
189 | } | 197 | } |
190 | 198 | ||
@@ -354,12 +362,12 @@ static int readhexaesc (LexState *ls) { | |||
354 | ** for error reporting in case of errors; 'i' counts the number of | 362 | ** for error reporting in case of errors; 'i' counts the number of |
355 | ** saved characters, so that they can be removed if case of success. | 363 | ** saved characters, so that they can be removed if case of success. |
356 | */ | 364 | */ |
357 | static unsigned long readutf8esc (LexState *ls) { | 365 | static l_uint32 readutf8esc (LexState *ls) { |
358 | unsigned long r; | 366 | l_uint32 r; |
359 | int i = 4; /* number of chars to be removed: start with #"\u{X" */ | 367 | int i = 4; /* number of chars to be removed: start with #"\u{X" */ |
360 | save_and_next(ls); /* skip 'u' */ | 368 | save_and_next(ls); /* skip 'u' */ |
361 | esccheck(ls, ls->current == '{', "missing '{'"); | 369 | esccheck(ls, ls->current == '{', "missing '{'"); |
362 | r = cast_ulong(gethexa(ls)); /* must have at least one digit */ | 370 | r = cast_uint(gethexa(ls)); /* must have at least one digit */ |
363 | while (cast_void(save_and_next(ls)), lisxdigit(ls->current)) { | 371 | while (cast_void(save_and_next(ls)), lisxdigit(ls->current)) { |
364 | i++; | 372 | i++; |
365 | esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large"); | 373 | esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large"); |
@@ -33,8 +33,8 @@ enum RESERVED { | |||
33 | /* terminal symbols denoted by reserved words */ | 33 | /* terminal symbols denoted by reserved words */ |
34 | TK_AND = FIRST_RESERVED, TK_BREAK, | 34 | TK_AND = FIRST_RESERVED, TK_BREAK, |
35 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, | 35 | TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, |
36 | TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, | 36 | TK_GLOBAL, TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, |
37 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, | 37 | TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, |
38 | /* other terminal symbols */ | 38 | /* other terminal symbols */ |
39 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, | 39 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, |
40 | TK_SHL, TK_SHR, | 40 | TK_SHL, TK_SHR, |
@@ -75,6 +75,8 @@ typedef struct LexState { | |||
75 | struct Dyndata *dyd; /* dynamic structures used by the parser */ | 75 | struct Dyndata *dyd; /* dynamic structures used by the parser */ |
76 | TString *source; /* current source name */ | 76 | TString *source; /* current source name */ |
77 | TString *envn; /* environment variable name */ | 77 | TString *envn; /* environment variable name */ |
78 | TString *brkn; /* "break" name (used as a label) */ | ||
79 | TString *glbn; /* "global" name (when not a reserved word) */ | ||
78 | } LexState; | 80 | } LexState; |
79 | 81 | ||
80 | 82 | ||
@@ -137,13 +137,15 @@ typedef LUAI_UACINT l_uacInt; | |||
137 | #define cast_voidp(i) cast(void *, (i)) | 137 | #define cast_voidp(i) cast(void *, (i)) |
138 | #define cast_num(i) cast(lua_Number, (i)) | 138 | #define cast_num(i) cast(lua_Number, (i)) |
139 | #define cast_int(i) cast(int, (i)) | 139 | #define cast_int(i) cast(int, (i)) |
140 | #define cast_short(i) cast(short, (i)) | ||
140 | #define cast_uint(i) cast(unsigned int, (i)) | 141 | #define cast_uint(i) cast(unsigned int, (i)) |
141 | #define cast_ulong(i) cast(unsigned long, (i)) | ||
142 | #define cast_byte(i) cast(lu_byte, (i)) | 142 | #define cast_byte(i) cast(lu_byte, (i)) |
143 | #define cast_uchar(i) cast(unsigned char, (i)) | 143 | #define cast_uchar(i) cast(unsigned char, (i)) |
144 | #define cast_char(i) cast(char, (i)) | 144 | #define cast_char(i) cast(char, (i)) |
145 | #define cast_charp(i) cast(char *, (i)) | 145 | #define cast_charp(i) cast(char *, (i)) |
146 | #define cast_sizet(i) cast(size_t, (i)) | 146 | #define cast_sizet(i) cast(size_t, (i)) |
147 | #define cast_Integer(i) cast(lua_Integer, (i)) | ||
148 | #define cast_Inst(i) cast(Instruction, (i)) | ||
147 | 149 | ||
148 | 150 | ||
149 | /* cast a signed lua_Integer to lua_Unsigned */ | 151 | /* cast a signed lua_Integer to lua_Unsigned */ |
@@ -307,6 +307,16 @@ static void setpath (lua_State *L, const char *fieldname, | |||
307 | 307 | ||
308 | 308 | ||
309 | /* | 309 | /* |
310 | ** External strings created by DLLs may need the DLL code to be | ||
311 | ** deallocated. This implies that a DLL can only be unloaded after all | ||
312 | ** its strings were deallocated. To ensure that, we create a 'library | ||
313 | ** string' to represent each DLL, and when this string is deallocated | ||
314 | ** it closes its corresponding DLL. | ||
315 | ** (The string itself is irrelevant; its userdata is the DLL pointer.) | ||
316 | */ | ||
317 | |||
318 | |||
319 | /* | ||
310 | ** return registry.CLIBS[path] | 320 | ** return registry.CLIBS[path] |
311 | */ | 321 | */ |
312 | static void *checkclib (lua_State *L, const char *path) { | 322 | static void *checkclib (lua_State *L, const char *path) { |
@@ -320,34 +330,41 @@ static void *checkclib (lua_State *L, const char *path) { | |||
320 | 330 | ||
321 | 331 | ||
322 | /* | 332 | /* |
323 | ** registry.CLIBS[path] = plib -- for queries | 333 | ** Deallocate function for library strings. |
324 | ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries | 334 | ** Unload the DLL associated with the string being deallocated. |
325 | */ | 335 | */ |
326 | static void addtoclib (lua_State *L, const char *path, void *plib) { | 336 | static void *freelib (void *ud, void *ptr, size_t osize, size_t nsize) { |
327 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | 337 | /* string itself is irrelevant and static */ |
328 | lua_pushlightuserdata(L, plib); | 338 | (void)ptr; (void)osize; (void)nsize; |
329 | lua_pushvalue(L, -1); | 339 | lsys_unloadlib(ud); /* unload library represented by the string */ |
330 | lua_setfield(L, -3, path); /* CLIBS[path] = plib */ | 340 | return NULL; |
331 | lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ | ||
332 | lua_pop(L, 1); /* pop CLIBS table */ | ||
333 | } | 341 | } |
334 | 342 | ||
335 | 343 | ||
336 | /* | 344 | /* |
337 | ** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib | 345 | ** Create a library string that, when deallocated, will unload 'plib' |
338 | ** handles in list CLIBS | ||
339 | */ | 346 | */ |
340 | static int gctm (lua_State *L) { | 347 | static void createlibstr (lua_State *L, void *plib) { |
341 | lua_Integer n = luaL_len(L, 1); | 348 | /* common content for all library strings */ |
342 | for (; n >= 1; n--) { /* for each handle, in reverse order */ | 349 | static const char dummy[] = "01234567890"; |
343 | lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ | 350 | lua_pushexternalstring(L, dummy, sizeof(dummy) - 1, freelib, plib); |
344 | lsys_unloadlib(lua_touserdata(L, -1)); | ||
345 | lua_pop(L, 1); /* pop handle */ | ||
346 | } | ||
347 | return 0; | ||
348 | } | 351 | } |
349 | 352 | ||
350 | 353 | ||
354 | /* | ||
355 | ** registry.CLIBS[path] = plib -- for queries. | ||
356 | ** Also create a reference to strlib, so that the library string will | ||
357 | ** only be collected when registry.CLIBS is collected. | ||
358 | */ | ||
359 | static void addtoclib (lua_State *L, const char *path, void *plib) { | ||
360 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
361 | lua_pushlightuserdata(L, plib); | ||
362 | lua_setfield(L, -2, path); /* CLIBS[path] = plib */ | ||
363 | createlibstr(L, plib); | ||
364 | luaL_ref(L, -2); /* keep library string in CLIBS */ | ||
365 | lua_pop(L, 1); /* pop CLIBS table */ | ||
366 | } | ||
367 | |||
351 | 368 | ||
352 | /* error codes for 'lookforfunc' */ | 369 | /* error codes for 'lookforfunc' */ |
353 | #define ERRLIB 1 | 370 | #define ERRLIB 1 |
@@ -361,8 +378,8 @@ static int gctm (lua_State *L) { | |||
361 | ** Then, if 'sym' is '*', return true (as library has been loaded). | 378 | ** Then, if 'sym' is '*', return true (as library has been loaded). |
362 | ** Otherwise, look for symbol 'sym' in the library and push a | 379 | ** Otherwise, look for symbol 'sym' in the library and push a |
363 | ** C function with that symbol. | 380 | ** C function with that symbol. |
364 | ** Return 0 and 'true' or a function in the stack; in case of | 381 | ** Return 0 with 'true' or a function in the stack; in case of |
365 | ** errors, return an error code and an error message in the stack. | 382 | ** errors, return an error code with an error message in the stack. |
366 | */ | 383 | */ |
367 | static int lookforfunc (lua_State *L, const char *path, const char *sym) { | 384 | static int lookforfunc (lua_State *L, const char *path, const char *sym) { |
368 | void *reg = checkclib(L, path); /* check loaded C libraries */ | 385 | void *reg = checkclib(L, path); /* check loaded C libraries */ |
@@ -704,21 +721,9 @@ static void createsearcherstable (lua_State *L) { | |||
704 | } | 721 | } |
705 | 722 | ||
706 | 723 | ||
707 | /* | ||
708 | ** create table CLIBS to keep track of loaded C libraries, | ||
709 | ** setting a finalizer to close all libraries when closing state. | ||
710 | */ | ||
711 | static void createclibstable (lua_State *L) { | ||
712 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ | ||
713 | lua_createtable(L, 0, 1); /* create metatable for CLIBS */ | ||
714 | lua_pushcfunction(L, gctm); | ||
715 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | ||
716 | lua_setmetatable(L, -2); | ||
717 | } | ||
718 | |||
719 | |||
720 | LUAMOD_API int luaopen_package (lua_State *L) { | 724 | LUAMOD_API int luaopen_package (lua_State *L) { |
721 | createclibstable(L); | 725 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ |
726 | lua_pop(L, 1); /* will not use it now */ | ||
722 | luaL_newlib(L, pk_funcs); /* create 'package' table */ | 727 | luaL_newlib(L, pk_funcs); /* create 'package' table */ |
723 | createsearcherstable(L); | 728 | createsearcherstable(L); |
724 | /* set paths */ | 729 | /* set paths */ |
@@ -31,7 +31,8 @@ | |||
31 | 31 | ||
32 | 32 | ||
33 | /* | 33 | /* |
34 | ** Computes ceil(log2(x)) | 34 | ** Computes ceil(log2(x)), which is the smallest integer n such that |
35 | ** x <= (1 << n). | ||
35 | */ | 36 | */ |
36 | lu_byte luaO_ceillog2 (unsigned int x) { | 37 | lu_byte luaO_ceillog2 (unsigned int x) { |
37 | static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ | 38 | static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ |
@@ -382,10 +383,10 @@ size_t luaO_str2num (const char *s, TValue *o) { | |||
382 | } | 383 | } |
383 | 384 | ||
384 | 385 | ||
385 | int luaO_utf8esc (char *buff, unsigned long x) { | 386 | int luaO_utf8esc (char *buff, l_uint32 x) { |
386 | int n = 1; /* number of bytes put in buffer (backwards) */ | 387 | int n = 1; /* number of bytes put in buffer (backwards) */ |
387 | lua_assert(x <= 0x7FFFFFFFu); | 388 | lua_assert(x <= 0x7FFFFFFFu); |
388 | if (x < 0x80) /* ascii? */ | 389 | if (x < 0x80) /* ASCII? */ |
389 | buff[UTF8BUFFSZ - 1] = cast_char(x); | 390 | buff[UTF8BUFFSZ - 1] = cast_char(x); |
390 | else { /* need continuation bytes */ | 391 | else { /* need continuation bytes */ |
391 | unsigned int mfb = 0x3f; /* maximum that fits in first byte */ | 392 | unsigned int mfb = 0x3f; /* maximum that fits in first byte */ |
@@ -618,7 +619,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | |||
618 | } | 619 | } |
619 | case 'I': { /* a 'lua_Integer' */ | 620 | case 'I': { /* a 'lua_Integer' */ |
620 | TValue num; | 621 | TValue num; |
621 | setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt))); | 622 | setivalue(&num, cast_Integer(va_arg(argp, l_uacInt))); |
622 | addnum2buff(&buff, &num); | 623 | addnum2buff(&buff, &num); |
623 | break; | 624 | break; |
624 | } | 625 | } |
@@ -637,7 +638,8 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | |||
637 | } | 638 | } |
638 | case 'U': { /* an 'unsigned long' as a UTF-8 sequence */ | 639 | case 'U': { /* an 'unsigned long' as a UTF-8 sequence */ |
639 | char bf[UTF8BUFFSZ]; | 640 | char bf[UTF8BUFFSZ]; |
640 | int len = luaO_utf8esc(bf, va_arg(argp, unsigned long)); | 641 | unsigned long arg = va_arg(argp, unsigned long); |
642 | int len = luaO_utf8esc(bf, cast(l_uint32, arg)); | ||
641 | addstr2buff(&buff, bf + UTF8BUFFSZ - len, cast_uint(len)); | 643 | addstr2buff(&buff, bf + UTF8BUFFSZ - len, cast_uint(len)); |
642 | break; | 644 | break; |
643 | } | 645 | } |
@@ -418,6 +418,7 @@ typedef struct TString { | |||
418 | 418 | ||
419 | 419 | ||
420 | #define strisshr(ts) ((ts)->shrlen >= 0) | 420 | #define strisshr(ts) ((ts)->shrlen >= 0) |
421 | #define isextstr(ts) (ttislngstring(ts) && tsvalue(ts)->shrlen != LSTRREG) | ||
421 | 422 | ||
422 | 423 | ||
423 | /* | 424 | /* |
@@ -822,7 +823,16 @@ typedef struct Table { | |||
822 | /* size of buffer for 'luaO_utf8esc' function */ | 823 | /* size of buffer for 'luaO_utf8esc' function */ |
823 | #define UTF8BUFFSZ 8 | 824 | #define UTF8BUFFSZ 8 |
824 | 825 | ||
825 | LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); | 826 | |
827 | /* macro to call 'luaO_pushvfstring' correctly */ | ||
828 | #define pushvfstring(L, argp, fmt, msg) \ | ||
829 | { va_start(argp, fmt); \ | ||
830 | msg = luaO_pushvfstring(L, fmt, argp); \ | ||
831 | va_end(argp); \ | ||
832 | if (msg == NULL) luaD_throw(L, LUA_ERRMEM); /* only after 'va_end' */ } | ||
833 | |||
834 | |||
835 | LUAI_FUNC int luaO_utf8esc (char *buff, l_uint32 x); | ||
826 | LUAI_FUNC lu_byte luaO_ceillog2 (unsigned int x); | 836 | LUAI_FUNC lu_byte luaO_ceillog2 (unsigned int x); |
827 | LUAI_FUNC lu_byte luaO_codeparam (unsigned int p); | 837 | LUAI_FUNC lu_byte luaO_codeparam (unsigned int p); |
828 | LUAI_FUNC l_mem luaO_applyparam (lu_byte p, l_mem x); | 838 | LUAI_FUNC l_mem luaO_applyparam (lu_byte p, l_mem x); |
@@ -126,14 +126,14 @@ enum OpMode {iABC, ivABC, iABx, iAsBx, iAx, isJ}; | |||
126 | 126 | ||
127 | #define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) | 127 | #define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) |
128 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ | 128 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ |
129 | ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) | 129 | ((cast_Inst(o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) |
130 | 130 | ||
131 | #define checkopm(i,m) (getOpMode(GET_OPCODE(i)) == m) | 131 | #define checkopm(i,m) (getOpMode(GET_OPCODE(i)) == m) |
132 | 132 | ||
133 | 133 | ||
134 | #define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0))) | 134 | #define getarg(i,pos,size) (cast_int(((i)>>(pos)) & MASK1(size,0))) |
135 | #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ | 135 | #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ |
136 | ((cast(Instruction, v)<<pos)&MASK1(size,pos)))) | 136 | ((cast_Inst(v)<<pos)&MASK1(size,pos)))) |
137 | 137 | ||
138 | #define GETARG_A(i) getarg(i, POS_A, SIZE_A) | 138 | #define GETARG_A(i) getarg(i, POS_A, SIZE_A) |
139 | #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) | 139 | #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) |
@@ -174,28 +174,28 @@ enum OpMode {iABC, ivABC, iABx, iAsBx, iAx, isJ}; | |||
174 | setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ) | 174 | setarg(i, cast_uint((j)+OFFSET_sJ), POS_sJ, SIZE_sJ) |
175 | 175 | ||
176 | 176 | ||
177 | #define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \ | 177 | #define CREATE_ABCk(o,a,b,c,k) ((cast_Inst(o)<<POS_OP) \ |
178 | | (cast(Instruction, a)<<POS_A) \ | 178 | | (cast_Inst(a)<<POS_A) \ |
179 | | (cast(Instruction, b)<<POS_B) \ | 179 | | (cast_Inst(b)<<POS_B) \ |
180 | | (cast(Instruction, c)<<POS_C) \ | 180 | | (cast_Inst(c)<<POS_C) \ |
181 | | (cast(Instruction, k)<<POS_k)) | 181 | | (cast_Inst(k)<<POS_k)) |
182 | 182 | ||
183 | #define CREATE_vABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \ | 183 | #define CREATE_vABCk(o,a,b,c,k) ((cast_Inst(o)<<POS_OP) \ |
184 | | (cast(Instruction, a)<<POS_A) \ | 184 | | (cast_Inst(a)<<POS_A) \ |
185 | | (cast(Instruction, b)<<POS_vB) \ | 185 | | (cast_Inst(b)<<POS_vB) \ |
186 | | (cast(Instruction, c)<<POS_vC) \ | 186 | | (cast_Inst(c)<<POS_vC) \ |
187 | | (cast(Instruction, k)<<POS_k)) | 187 | | (cast_Inst(k)<<POS_k)) |
188 | 188 | ||
189 | #define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ | 189 | #define CREATE_ABx(o,a,bc) ((cast_Inst(o)<<POS_OP) \ |
190 | | (cast(Instruction, a)<<POS_A) \ | 190 | | (cast_Inst(a)<<POS_A) \ |
191 | | (cast(Instruction, bc)<<POS_Bx)) | 191 | | (cast_Inst(bc)<<POS_Bx)) |
192 | 192 | ||
193 | #define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ | 193 | #define CREATE_Ax(o,a) ((cast_Inst(o)<<POS_OP) \ |
194 | | (cast(Instruction, a)<<POS_Ax)) | 194 | | (cast_Inst(a)<<POS_Ax)) |
195 | 195 | ||
196 | #define CREATE_sJ(o,j,k) ((cast(Instruction, o) << POS_OP) \ | 196 | #define CREATE_sJ(o,j,k) ((cast_Inst(o) << POS_OP) \ |
197 | | (cast(Instruction, j) << POS_sJ) \ | 197 | | (cast_Inst(j) << POS_sJ) \ |
198 | | (cast(Instruction, k) << POS_k)) | 198 | | (cast_Inst(k) << POS_k)) |
199 | 199 | ||
200 | 200 | ||
201 | #if !defined(MAXINDEXRK) /* (for debugging only) */ | 201 | #if !defined(MAXINDEXRK) /* (for debugging only) */ |
@@ -254,7 +254,7 @@ OP_SETTABLE,/* A B C R[A][R[B]] := RK(C) */ | |||
254 | OP_SETI,/* A B C R[A][B] := RK(C) */ | 254 | OP_SETI,/* A B C R[A][B] := RK(C) */ |
255 | OP_SETFIELD,/* A B C R[A][K[B]:shortstring] := RK(C) */ | 255 | OP_SETFIELD,/* A B C R[A][K[B]:shortstring] := RK(C) */ |
256 | 256 | ||
257 | OP_NEWTABLE,/* A B C k R[A] := {} */ | 257 | OP_NEWTABLE,/* A vB vC k R[A] := {} */ |
258 | 258 | ||
259 | OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][K[C]:shortstring] */ | 259 | OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][K[C]:shortstring] */ |
260 | 260 | ||
@@ -378,9 +378,9 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
378 | real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the | 378 | real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the |
379 | bits of C). | 379 | bits of C). |
380 | 380 | ||
381 | (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a | 381 | (*) In OP_NEWTABLE, vB is log2 of the hash size (which is always a |
382 | power of 2) plus 1, or zero for size zero. If not k, the array size | 382 | power of 2) plus 1, or zero for size zero. If not k, the array size |
383 | is C. Otherwise, the array size is EXTRAARG _ C. | 383 | is vC. Otherwise, the array size is EXTRAARG _ vC. |
384 | 384 | ||
385 | (*) For comparisons, k specifies what condition the test should accept | 385 | (*) For comparisons, k specifies what condition the test should accept |
386 | (true or false). | 386 | (true or false). |
@@ -273,7 +273,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { | |||
273 | 273 | ||
274 | 274 | ||
275 | static const char *checkoption (lua_State *L, const char *conv, | 275 | static const char *checkoption (lua_State *L, const char *conv, |
276 | ptrdiff_t convlen, char *buff) { | 276 | size_t convlen, char *buff) { |
277 | const char *option = LUA_STRFTIMEOPTIONS; | 277 | const char *option = LUA_STRFTIMEOPTIONS; |
278 | unsigned oplen = 1; /* length of options being checked */ | 278 | unsigned oplen = 1; /* length of options being checked */ |
279 | for (; *option != '\0' && oplen <= convlen; option += oplen) { | 279 | for (; *option != '\0' && oplen <= convlen; option += oplen) { |
@@ -333,7 +333,8 @@ static int os_date (lua_State *L) { | |||
333 | size_t reslen; | 333 | size_t reslen; |
334 | char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); | 334 | char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); |
335 | s++; /* skip '%' */ | 335 | s++; /* skip '%' */ |
336 | s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ | 336 | /* copy specifier to 'cc' */ |
337 | s = checkoption(L, s, ct_diff2sz(se - s), cc + 1); | ||
337 | reslen = strftime(buff, SIZETIMEFMT, cc, stm); | 338 | reslen = strftime(buff, SIZETIMEFMT, cc, stm); |
338 | luaL_addsize(&b, reslen); | 339 | luaL_addsize(&b, reslen); |
339 | } | 340 | } |
@@ -30,8 +30,8 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | 32 | ||
33 | /* maximum number of local variables per function (must be smaller | 33 | /* maximum number of variable declarations per function (must be |
34 | than 250, due to the bytecode format) */ | 34 | smaller than 250, due to the bytecode format) */ |
35 | #define MAXVARS 200 | 35 | #define MAXVARS 200 |
36 | 36 | ||
37 | 37 | ||
@@ -50,7 +50,7 @@ typedef struct BlockCnt { | |||
50 | struct BlockCnt *previous; /* chain */ | 50 | struct BlockCnt *previous; /* chain */ |
51 | int firstlabel; /* index of first label in this block */ | 51 | int firstlabel; /* index of first label in this block */ |
52 | int firstgoto; /* index of first pending goto in this block */ | 52 | int firstgoto; /* index of first pending goto in this block */ |
53 | lu_byte nactvar; /* # active locals outside the block */ | 53 | short nactvar; /* number of active declarations at block entry */ |
54 | lu_byte upval; /* true if some variable in the block is an upvalue */ | 54 | lu_byte upval; /* true if some variable in the block is an upvalue */ |
55 | lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */ | 55 | lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */ |
56 | lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ | 56 | lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ |
@@ -188,18 +188,16 @@ static short registerlocalvar (LexState *ls, FuncState *fs, | |||
188 | 188 | ||
189 | 189 | ||
190 | /* | 190 | /* |
191 | ** Create a new local variable with the given 'name' and given 'kind'. | 191 | ** Create a new variable with the given 'name' and given 'kind'. |
192 | ** Return its index in the function. | 192 | ** Return its index in the function. |
193 | */ | 193 | */ |
194 | static int new_localvarkind (LexState *ls, TString *name, lu_byte kind) { | 194 | static int new_varkind (LexState *ls, TString *name, lu_byte kind) { |
195 | lua_State *L = ls->L; | 195 | lua_State *L = ls->L; |
196 | FuncState *fs = ls->fs; | 196 | FuncState *fs = ls->fs; |
197 | Dyndata *dyd = ls->dyd; | 197 | Dyndata *dyd = ls->dyd; |
198 | Vardesc *var; | 198 | Vardesc *var; |
199 | luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, | ||
200 | MAXVARS, "local variables"); | ||
201 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 199 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
202 | dyd->actvar.size, Vardesc, SHRT_MAX, "local variables"); | 200 | dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarations"); |
203 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 201 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
204 | var->vd.kind = kind; /* default */ | 202 | var->vd.kind = kind; /* default */ |
205 | var->vd.name = name; | 203 | var->vd.name = name; |
@@ -211,7 +209,7 @@ static int new_localvarkind (LexState *ls, TString *name, lu_byte kind) { | |||
211 | ** Create a new local variable with the given 'name' and regular kind. | 209 | ** Create a new local variable with the given 'name' and regular kind. |
212 | */ | 210 | */ |
213 | static int new_localvar (LexState *ls, TString *name) { | 211 | static int new_localvar (LexState *ls, TString *name) { |
214 | return new_localvarkind(ls, name, VDKREG); | 212 | return new_varkind(ls, name, VDKREG); |
215 | } | 213 | } |
216 | 214 | ||
217 | #define new_localvarliteral(ls,v) \ | 215 | #define new_localvarliteral(ls,v) \ |
@@ -238,7 +236,7 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { | |||
238 | static lu_byte reglevel (FuncState *fs, int nvar) { | 236 | static lu_byte reglevel (FuncState *fs, int nvar) { |
239 | while (nvar-- > 0) { | 237 | while (nvar-- > 0) { |
240 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ | 238 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ |
241 | if (vd->vd.kind != RDKCTC) /* is in a register? */ | 239 | if (varinreg(vd)) /* is in a register? */ |
242 | return cast_byte(vd->vd.ridx + 1); | 240 | return cast_byte(vd->vd.ridx + 1); |
243 | } | 241 | } |
244 | return 0; /* no variables in registers */ | 242 | return 0; /* no variables in registers */ |
@@ -259,7 +257,7 @@ lu_byte luaY_nvarstack (FuncState *fs) { | |||
259 | */ | 257 | */ |
260 | static LocVar *localdebuginfo (FuncState *fs, int vidx) { | 258 | static LocVar *localdebuginfo (FuncState *fs, int vidx) { |
261 | Vardesc *vd = getlocalvardesc(fs, vidx); | 259 | Vardesc *vd = getlocalvardesc(fs, vidx); |
262 | if (vd->vd.kind == RDKCTC) | 260 | if (!varinreg(vd)) |
263 | return NULL; /* no debug info. for constants */ | 261 | return NULL; /* no debug info. for constants */ |
264 | else { | 262 | else { |
265 | int idx = vd->vd.pidx; | 263 | int idx = vd->vd.pidx; |
@@ -275,7 +273,7 @@ static LocVar *localdebuginfo (FuncState *fs, int vidx) { | |||
275 | static void init_var (FuncState *fs, expdesc *e, int vidx) { | 273 | static void init_var (FuncState *fs, expdesc *e, int vidx) { |
276 | e->f = e->t = NO_JUMP; | 274 | e->f = e->t = NO_JUMP; |
277 | e->k = VLOCAL; | 275 | e->k = VLOCAL; |
278 | e->u.var.vidx = cast(unsigned short, vidx); | 276 | e->u.var.vidx = cast_short(vidx); |
279 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; | 277 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; |
280 | } | 278 | } |
281 | 279 | ||
@@ -303,14 +301,18 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
303 | varname = up->name; | 301 | varname = up->name; |
304 | break; | 302 | break; |
305 | } | 303 | } |
304 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ | ||
305 | if (e->u.ind.ro) /* read-only? */ | ||
306 | varname = tsvalue(&fs->f->k[e->u.ind.keystr]); | ||
307 | break; | ||
308 | } | ||
306 | default: | 309 | default: |
307 | return; /* other cases cannot be read-only */ | 310 | lua_assert(e->k == VINDEXI); /* this one doesn't need any check */ |
308 | } | 311 | return; /* integer index cannot be read-only */ |
309 | if (varname) { | ||
310 | const char *msg = luaO_pushfstring(ls->L, | ||
311 | "attempt to assign to const variable '%s'", getstr(varname)); | ||
312 | luaK_semerror(ls, msg); /* error */ | ||
313 | } | 312 | } |
313 | if (varname) | ||
314 | luaK_semerror(ls, "attempt to assign to const variable '%s'", | ||
315 | getstr(varname)); | ||
314 | } | 316 | } |
315 | 317 | ||
316 | 318 | ||
@@ -326,6 +328,7 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
326 | Vardesc *var = getlocalvardesc(fs, vidx); | 328 | Vardesc *var = getlocalvardesc(fs, vidx); |
327 | var->vd.ridx = cast_byte(reglevel++); | 329 | var->vd.ridx = cast_byte(reglevel++); |
328 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); | 330 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); |
331 | luaY_checklimit(fs, reglevel, MAXVARS, "local variables"); | ||
329 | } | 332 | } |
330 | } | 333 | } |
331 | 334 | ||
@@ -392,18 +395,38 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
392 | 395 | ||
393 | 396 | ||
394 | /* | 397 | /* |
395 | ** Look for an active local variable with the name 'n' in the | 398 | ** Look for an active variable with the name 'n' in the |
396 | ** function 'fs'. If found, initialize 'var' with it and return | 399 | ** function 'fs'. If found, initialize 'var' with it and return |
397 | ** its expression kind; otherwise return -1. | 400 | ** its expression kind; otherwise return -1. While searching, |
401 | ** var->u.info==-1 means that the preambular global declaration is | ||
402 | ** active (the default while there is no other global declaration); | ||
403 | ** var->u.info==-2 means there is no active collective declaration | ||
404 | ** (some previous global declaration but no collective declaration); | ||
405 | ** and var->u.info>=0 points to the inner-most (the first one found) | ||
406 | ** collective declaration, if there is one. | ||
398 | */ | 407 | */ |
399 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { | 408 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { |
400 | int i; | 409 | int i; |
401 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 410 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
402 | Vardesc *vd = getlocalvardesc(fs, i); | 411 | Vardesc *vd = getlocalvardesc(fs, i); |
403 | if (eqstr(n, vd->vd.name)) { /* found? */ | 412 | if (varglobal(vd)) { /* global declaration? */ |
413 | if (vd->vd.name == NULL) { /* collective declaration? */ | ||
414 | if (var->u.info < 0) /* no previous collective declaration? */ | ||
415 | var->u.info = fs->firstlocal + i; /* this is the first one */ | ||
416 | } | ||
417 | else { /* global name */ | ||
418 | if (eqstr(n, vd->vd.name)) { /* found? */ | ||
419 | init_exp(var, VGLOBAL, fs->firstlocal + i); | ||
420 | return VGLOBAL; | ||
421 | } | ||
422 | else if (var->u.info == -1) /* active preambular declaration? */ | ||
423 | var->u.info = -2; /* invalidate preambular declaration */ | ||
424 | } | ||
425 | } | ||
426 | else if (eqstr(n, vd->vd.name)) { /* found? */ | ||
404 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ | 427 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ |
405 | init_exp(var, VCONST, fs->firstlocal + i); | 428 | init_exp(var, VCONST, fs->firstlocal + i); |
406 | else /* real variable */ | 429 | else /* local variable */ |
407 | init_var(fs, var, i); | 430 | init_var(fs, var, i); |
408 | return cast_int(var->k); | 431 | return cast_int(var->k); |
409 | } | 432 | } |
@@ -442,48 +465,67 @@ static void marktobeclosed (FuncState *fs) { | |||
442 | ** 'var' as 'void' as a flag. | 465 | ** 'var' as 'void' as a flag. |
443 | */ | 466 | */ |
444 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 467 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
445 | if (fs == NULL) /* no more levels? */ | 468 | int v = searchvar(fs, n, var); /* look up variables at current level */ |
446 | init_exp(var, VVOID, 0); /* default is global */ | 469 | if (v >= 0) { /* found? */ |
447 | else { | 470 | if (v == VLOCAL && !base) |
448 | int v = searchvar(fs, n, var); /* look up locals at current level */ | 471 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ |
449 | if (v >= 0) { /* found? */ | 472 | } |
450 | if (v == VLOCAL && !base) | 473 | else { /* not found at current level; try upvalues */ |
451 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ | 474 | int idx = searchupvalue(fs, n); /* try existing upvalues */ |
452 | } | 475 | if (idx < 0) { /* not found? */ |
453 | else { /* not found as local at current level; try upvalues */ | 476 | if (fs->prev != NULL) /* more levels? */ |
454 | int idx = searchupvalue(fs, n); /* try existing upvalues */ | ||
455 | if (idx < 0) { /* not found? */ | ||
456 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ | 477 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ |
457 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ | 478 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ |
458 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ | 479 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ |
459 | else /* it is a global or a constant */ | 480 | else /* it is a global or a constant */ |
460 | return; /* don't need to do anything at this level */ | 481 | return; /* don't need to do anything at this level */ |
461 | } | ||
462 | init_exp(var, VUPVAL, idx); /* new or old upvalue */ | ||
463 | } | 482 | } |
483 | init_exp(var, VUPVAL, idx); /* new or old upvalue */ | ||
464 | } | 484 | } |
465 | } | 485 | } |
466 | 486 | ||
467 | 487 | ||
488 | static void buildglobal (LexState *ls, TString *varname, expdesc *var) { | ||
489 | FuncState *fs = ls->fs; | ||
490 | expdesc key; | ||
491 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
492 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | ||
493 | if (var->k == VGLOBAL) | ||
494 | luaK_semerror(ls, "_ENV is global when accessing variable '%s'", | ||
495 | getstr(varname)); | ||
496 | luaK_exp2anyregup(fs, var); /* _ENV could be a constant */ | ||
497 | codestring(&key, varname); /* key is variable name */ | ||
498 | luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */ | ||
499 | } | ||
500 | |||
501 | |||
468 | /* | 502 | /* |
469 | ** Find a variable with the given name 'n', handling global variables | 503 | ** Find a variable with the given name 'n', handling global variables |
470 | ** too. | 504 | ** too. |
471 | */ | 505 | */ |
472 | static void singlevar (LexState *ls, expdesc *var) { | 506 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { |
473 | TString *varname = str_checkname(ls); | ||
474 | FuncState *fs = ls->fs; | 507 | FuncState *fs = ls->fs; |
508 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
475 | singlevaraux(fs, varname, var, 1); | 509 | singlevaraux(fs, varname, var, 1); |
476 | if (var->k == VVOID) { /* global name? */ | 510 | if (var->k == VGLOBAL) { /* global name? */ |
477 | expdesc key; | 511 | int info = var->u.info; |
478 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | 512 | /* global by default in the scope of a global declaration? */ |
479 | lua_assert(var->k != VVOID); /* this one must exist */ | 513 | if (info == -2) |
480 | luaK_exp2anyregup(fs, var); /* but could be a constant */ | 514 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); |
481 | codestring(&key, varname); /* key is variable name */ | 515 | buildglobal(ls, varname, var); |
482 | luaK_indexed(fs, var, &key); /* env[varname] */ | 516 | if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) |
517 | var->u.ind.ro = 1; /* mark variable as read-only */ | ||
518 | else /* anyway must be a global */ | ||
519 | lua_assert(info == -1 || ls->dyd->actvar.arr[info].vd.kind == GDKREG); | ||
483 | } | 520 | } |
484 | } | 521 | } |
485 | 522 | ||
486 | 523 | ||
524 | static void singlevar (LexState *ls, expdesc *var) { | ||
525 | buildvar(ls, str_checkname(ls), var); | ||
526 | } | ||
527 | |||
528 | |||
487 | /* | 529 | /* |
488 | ** Adjust the number of results from an expression list 'e' with 'nexps' | 530 | ** Adjust the number of results from an expression list 'e' with 'nexps' |
489 | ** expressions to 'nvars' values. | 531 | ** expressions to 'nvars' values. |
@@ -518,14 +560,14 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
518 | 560 | ||
519 | /* | 561 | /* |
520 | ** Generates an error that a goto jumps into the scope of some | 562 | ** Generates an error that a goto jumps into the scope of some |
521 | ** local variable. | 563 | ** variable declaration. |
522 | */ | 564 | */ |
523 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { | 565 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { |
524 | TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name; | 566 | TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name; |
525 | const char *varname = getstr(tsname); | 567 | const char *varname = (tsname != NULL) ? getstr(tsname) : "*"; |
526 | const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'"; | 568 | luaK_semerror(ls, |
527 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); | 569 | "<goto %s> at line %d jumps into the scope of '%s'", |
528 | luaK_semerror(ls, msg); /* raise the error */ | 570 | getstr(gt->name), gt->line, varname); /* raise the error */ |
529 | } | 571 | } |
530 | 572 | ||
531 | 573 | ||
@@ -563,7 +605,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label, int bup) { | |||
563 | 605 | ||
564 | /* | 606 | /* |
565 | ** Search for an active label with the given name, starting at | 607 | ** Search for an active label with the given name, starting at |
566 | ** index 'ilb' (so that it can searh for all labels in current block | 608 | ** index 'ilb' (so that it can search for all labels in current block |
567 | ** or all labels in current function). | 609 | ** or all labels in current function). |
568 | */ | 610 | */ |
569 | static Labeldesc *findlabel (LexState *ls, TString *name, int ilb) { | 611 | static Labeldesc *findlabel (LexState *ls, TString *name, int ilb) { |
@@ -630,7 +672,7 @@ static void createlabel (LexState *ls, TString *name, int line, int last) { | |||
630 | 672 | ||
631 | 673 | ||
632 | /* | 674 | /* |
633 | ** Traverse the pending goto's of the finishing block checking whether | 675 | ** Traverse the pending gotos of the finishing block checking whether |
634 | ** each match some label of that block. Those that do not match are | 676 | ** each match some label of that block. Those that do not match are |
635 | ** "exported" to the outer block, to be solved there. In particular, | 677 | ** "exported" to the outer block, to be solved there. In particular, |
636 | ** its 'nactvar' is updated with the level of the inner block, | 678 | ** its 'nactvar' is updated with the level of the inner block, |
@@ -666,8 +708,9 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
666 | bl->firstlabel = fs->ls->dyd->label.n; | 708 | bl->firstlabel = fs->ls->dyd->label.n; |
667 | bl->firstgoto = fs->ls->dyd->gt.n; | 709 | bl->firstgoto = fs->ls->dyd->gt.n; |
668 | bl->upval = 0; | 710 | bl->upval = 0; |
711 | /* inherit 'insidetbc' from enclosing block */ | ||
669 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); | 712 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); |
670 | bl->previous = fs->bl; | 713 | bl->previous = fs->bl; /* link block in function's block list */ |
671 | fs->bl = bl; | 714 | fs->bl = bl; |
672 | lua_assert(fs->freereg == luaY_nvarstack(fs)); | 715 | lua_assert(fs->freereg == luaY_nvarstack(fs)); |
673 | } | 716 | } |
@@ -677,11 +720,10 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
677 | ** generates an error for an undefined 'goto'. | 720 | ** generates an error for an undefined 'goto'. |
678 | */ | 721 | */ |
679 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { | 722 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { |
680 | const char *msg = "no visible label '%s' for <goto> at line %d"; | ||
681 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); | ||
682 | /* breaks are checked when created, cannot be undefined */ | 723 | /* breaks are checked when created, cannot be undefined */ |
683 | lua_assert(!eqstr(gt->name, luaS_newliteral(ls->L, "break"))); | 724 | lua_assert(!eqstr(gt->name, ls->brkn)); |
684 | luaK_semerror(ls, msg); | 725 | luaK_semerror(ls, "no visible label '%s' for <goto> at line %d", |
726 | getstr(gt->name), gt->line); | ||
685 | } | 727 | } |
686 | 728 | ||
687 | 729 | ||
@@ -695,7 +737,7 @@ static void leaveblock (FuncState *fs) { | |||
695 | removevars(fs, bl->nactvar); /* remove block locals */ | 737 | removevars(fs, bl->nactvar); /* remove block locals */ |
696 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ | 738 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ |
697 | if (bl->isloop == 2) /* has to fix pending breaks? */ | 739 | if (bl->isloop == 2) /* has to fix pending breaks? */ |
698 | createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); | 740 | createlabel(ls, ls->brkn, 0, 0); |
699 | solvegotos(fs, bl); | 741 | solvegotos(fs, bl); |
700 | if (bl->previous == NULL) { /* was it the last block? */ | 742 | if (bl->previous == NULL) { /* was it the last block? */ |
701 | if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ | 743 | if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ |
@@ -868,10 +910,8 @@ static void recfield (LexState *ls, ConsControl *cc) { | |||
868 | FuncState *fs = ls->fs; | 910 | FuncState *fs = ls->fs; |
869 | lu_byte reg = ls->fs->freereg; | 911 | lu_byte reg = ls->fs->freereg; |
870 | expdesc tab, key, val; | 912 | expdesc tab, key, val; |
871 | if (ls->t.token == TK_NAME) { | 913 | if (ls->t.token == TK_NAME) |
872 | luaY_checklimit(fs, cc->nh, INT_MAX / 2, "items in a constructor"); | ||
873 | codename(ls, &key); | 914 | codename(ls, &key); |
874 | } | ||
875 | else /* ls->t.token == '[' */ | 915 | else /* ls->t.token == '[' */ |
876 | yindex(ls, &key); | 916 | yindex(ls, &key); |
877 | cc->nh++; | 917 | cc->nh++; |
@@ -1402,6 +1442,15 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1402 | } | 1442 | } |
1403 | } | 1443 | } |
1404 | 1444 | ||
1445 | |||
1446 | /* Create code to store the "top" register in 'var' */ | ||
1447 | static void storevartop (FuncState *fs, expdesc *var) { | ||
1448 | expdesc e; | ||
1449 | init_exp(&e, VNONRELOC, fs->freereg - 1); | ||
1450 | luaK_storevar(fs, var, &e); /* will also free the top register */ | ||
1451 | } | ||
1452 | |||
1453 | |||
1405 | /* | 1454 | /* |
1406 | ** Parse and compile a multiple assignment. The first "variable" | 1455 | ** Parse and compile a multiple assignment. The first "variable" |
1407 | ** (a 'suffixedexp') was already read by the caller. | 1456 | ** (a 'suffixedexp') was already read by the caller. |
@@ -1435,8 +1484,7 @@ static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
1435 | return; /* avoid default */ | 1484 | return; /* avoid default */ |
1436 | } | 1485 | } |
1437 | } | 1486 | } |
1438 | init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ | 1487 | storevartop(ls->fs, &lh->v); /* default assignment */ |
1439 | luaK_storevar(ls->fs, &lh->v, &e); | ||
1440 | } | 1488 | } |
1441 | 1489 | ||
1442 | 1490 | ||
@@ -1469,7 +1517,7 @@ static void breakstat (LexState *ls, int line) { | |||
1469 | ok: | 1517 | ok: |
1470 | bl->isloop = 2; /* signal that block has pending breaks */ | 1518 | bl->isloop = 2; /* signal that block has pending breaks */ |
1471 | luaX_next(ls); /* skip break */ | 1519 | luaX_next(ls); /* skip break */ |
1472 | newgotoentry(ls, luaS_newliteral(ls->L, "break"), line); | 1520 | newgotoentry(ls, ls->brkn, line); |
1473 | } | 1521 | } |
1474 | 1522 | ||
1475 | 1523 | ||
@@ -1479,11 +1527,9 @@ static void breakstat (LexState *ls, int line) { | |||
1479 | */ | 1527 | */ |
1480 | static void checkrepeated (LexState *ls, TString *name) { | 1528 | static void checkrepeated (LexState *ls, TString *name) { |
1481 | Labeldesc *lb = findlabel(ls, name, ls->fs->firstlabel); | 1529 | Labeldesc *lb = findlabel(ls, name, ls->fs->firstlabel); |
1482 | if (l_unlikely(lb != NULL)) { /* already defined? */ | 1530 | if (l_unlikely(lb != NULL)) /* already defined? */ |
1483 | const char *msg = "label '%s' already defined on line %d"; | 1531 | luaK_semerror(ls, "label '%s' already defined on line %d", |
1484 | msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); | 1532 | getstr(name), lb->line); /* error */ |
1485 | luaK_semerror(ls, msg); /* error */ | ||
1486 | } | ||
1487 | } | 1533 | } |
1488 | 1534 | ||
1489 | 1535 | ||
@@ -1605,7 +1651,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1605 | int base = fs->freereg; | 1651 | int base = fs->freereg; |
1606 | new_localvarliteral(ls, "(for state)"); | 1652 | new_localvarliteral(ls, "(for state)"); |
1607 | new_localvarliteral(ls, "(for state)"); | 1653 | new_localvarliteral(ls, "(for state)"); |
1608 | new_localvarkind(ls, varname, RDKCONST); /* control variable */ | 1654 | new_varkind(ls, varname, RDKCONST); /* control variable */ |
1609 | checknext(ls, '='); | 1655 | checknext(ls, '='); |
1610 | exp1(ls); /* initial value */ | 1656 | exp1(ls); /* initial value */ |
1611 | checknext(ls, ','); | 1657 | checknext(ls, ','); |
@@ -1632,7 +1678,7 @@ static void forlist (LexState *ls, TString *indexname) { | |||
1632 | new_localvarliteral(ls, "(for state)"); /* iterator function */ | 1678 | new_localvarliteral(ls, "(for state)"); /* iterator function */ |
1633 | new_localvarliteral(ls, "(for state)"); /* state */ | 1679 | new_localvarliteral(ls, "(for state)"); /* state */ |
1634 | new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ | 1680 | new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ |
1635 | new_localvarkind(ls, indexname, RDKCONST); /* control variable */ | 1681 | new_varkind(ls, indexname, RDKCONST); /* control variable */ |
1636 | /* other declared variables */ | 1682 | /* other declared variables */ |
1637 | while (testnext(ls, ',')) { | 1683 | while (testnext(ls, ',')) { |
1638 | new_localvar(ls, str_checkname(ls)); | 1684 | new_localvar(ls, str_checkname(ls)); |
@@ -1707,8 +1753,8 @@ static void localfunc (LexState *ls) { | |||
1707 | } | 1753 | } |
1708 | 1754 | ||
1709 | 1755 | ||
1710 | static lu_byte getlocalattribute (LexState *ls) { | 1756 | static lu_byte getvarattribute (LexState *ls, lu_byte df) { |
1711 | /* ATTRIB -> ['<' Name '>'] */ | 1757 | /* attrib -> ['<' NAME '>'] */ |
1712 | if (testnext(ls, '<')) { | 1758 | if (testnext(ls, '<')) { |
1713 | TString *ts = str_checkname(ls); | 1759 | TString *ts = str_checkname(ls); |
1714 | const char *attr = getstr(ts); | 1760 | const char *attr = getstr(ts); |
@@ -1718,10 +1764,9 @@ static lu_byte getlocalattribute (LexState *ls) { | |||
1718 | else if (strcmp(attr, "close") == 0) | 1764 | else if (strcmp(attr, "close") == 0) |
1719 | return RDKTOCLOSE; /* to-be-closed variable */ | 1765 | return RDKTOCLOSE; /* to-be-closed variable */ |
1720 | else | 1766 | else |
1721 | luaK_semerror(ls, | 1767 | luaK_semerror(ls, "unknown attribute '%s'", attr); |
1722 | luaO_pushfstring(ls->L, "unknown attribute '%s'", attr)); | ||
1723 | } | 1768 | } |
1724 | return VDKREG; /* regular variable */ | 1769 | return df; /* return default value */ |
1725 | } | 1770 | } |
1726 | 1771 | ||
1727 | 1772 | ||
@@ -1734,7 +1779,7 @@ static void checktoclose (FuncState *fs, int level) { | |||
1734 | 1779 | ||
1735 | 1780 | ||
1736 | static void localstat (LexState *ls) { | 1781 | static void localstat (LexState *ls) { |
1737 | /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ | 1782 | /* stat -> LOCAL NAME attrib { ',' NAME attrib } ['=' explist] */ |
1738 | FuncState *fs = ls->fs; | 1783 | FuncState *fs = ls->fs; |
1739 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1784 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
1740 | Vardesc *var; /* last variable */ | 1785 | Vardesc *var; /* last variable */ |
@@ -1742,10 +1787,12 @@ static void localstat (LexState *ls) { | |||
1742 | int nvars = 0; | 1787 | int nvars = 0; |
1743 | int nexps; | 1788 | int nexps; |
1744 | expdesc e; | 1789 | expdesc e; |
1745 | do { | 1790 | /* get prefixed attribute (if any); default is regular local variable */ |
1746 | TString *vname = str_checkname(ls); | 1791 | lu_byte defkind = getvarattribute(ls, VDKREG); |
1747 | lu_byte kind = getlocalattribute(ls); | 1792 | do { /* for each variable */ |
1748 | vidx = new_localvarkind(ls, vname, kind); | 1793 | TString *vname = str_checkname(ls); /* get its name */ |
1794 | lu_byte kind = getvarattribute(ls, defkind); /* postfixed attribute */ | ||
1795 | vidx = new_varkind(ls, vname, kind); /* predeclare it */ | ||
1749 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ | 1796 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ |
1750 | if (toclose != -1) /* one already present? */ | 1797 | if (toclose != -1) /* one already present? */ |
1751 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); | 1798 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); |
@@ -1753,13 +1800,13 @@ static void localstat (LexState *ls) { | |||
1753 | } | 1800 | } |
1754 | nvars++; | 1801 | nvars++; |
1755 | } while (testnext(ls, ',')); | 1802 | } while (testnext(ls, ',')); |
1756 | if (testnext(ls, '=')) | 1803 | if (testnext(ls, '=')) /* initialization? */ |
1757 | nexps = explist(ls, &e); | 1804 | nexps = explist(ls, &e); |
1758 | else { | 1805 | else { |
1759 | e.k = VVOID; | 1806 | e.k = VVOID; |
1760 | nexps = 0; | 1807 | nexps = 0; |
1761 | } | 1808 | } |
1762 | var = getlocalvardesc(fs, vidx); /* get last variable */ | 1809 | var = getlocalvardesc(fs, vidx); /* retrieve last variable */ |
1763 | if (nvars == nexps && /* no adjustments? */ | 1810 | if (nvars == nexps && /* no adjustments? */ |
1764 | var->vd.kind == RDKCONST && /* last variable is const? */ | 1811 | var->vd.kind == RDKCONST && /* last variable is const? */ |
1765 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ | 1812 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ |
@@ -1775,6 +1822,86 @@ static void localstat (LexState *ls) { | |||
1775 | } | 1822 | } |
1776 | 1823 | ||
1777 | 1824 | ||
1825 | static lu_byte getglobalattribute (LexState *ls, lu_byte df) { | ||
1826 | lu_byte kind = getvarattribute(ls, df); | ||
1827 | switch (kind) { | ||
1828 | case RDKTOCLOSE: | ||
1829 | luaK_semerror(ls, "global variables cannot be to-be-closed"); | ||
1830 | break; /* to avoid warnings */ | ||
1831 | case RDKCONST: | ||
1832 | return GDKCONST; /* adjust kind for global variable */ | ||
1833 | default: | ||
1834 | return kind; | ||
1835 | } | ||
1836 | } | ||
1837 | |||
1838 | |||
1839 | static void globalnames (LexState *ls, lu_byte defkind) { | ||
1840 | FuncState *fs = ls->fs; | ||
1841 | int nvars = 0; | ||
1842 | int lastidx; /* index of last registered variable */ | ||
1843 | do { /* for each name */ | ||
1844 | TString *vname = str_checkname(ls); | ||
1845 | lu_byte kind = getglobalattribute(ls, defkind); | ||
1846 | lastidx = new_varkind(ls, vname, kind); | ||
1847 | nvars++; | ||
1848 | } while (testnext(ls, ',')); | ||
1849 | if (testnext(ls, '=')) { /* initialization? */ | ||
1850 | expdesc e; | ||
1851 | int i; | ||
1852 | int nexps = explist(ls, &e); /* read list of expressions */ | ||
1853 | adjust_assign(ls, nvars, nexps, &e); | ||
1854 | for (i = 0; i < nvars; i++) { /* for each variable */ | ||
1855 | expdesc var; | ||
1856 | TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name; | ||
1857 | buildglobal(ls, varname, &var); /* create global variable in 'var' */ | ||
1858 | storevartop(fs, &var); | ||
1859 | } | ||
1860 | } | ||
1861 | fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */ | ||
1862 | } | ||
1863 | |||
1864 | |||
1865 | static void globalstat (LexState *ls) { | ||
1866 | /* globalstat -> (GLOBAL) attrib '*' | ||
1867 | globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */ | ||
1868 | FuncState *fs = ls->fs; | ||
1869 | /* get prefixed attribute (if any); default is regular global variable */ | ||
1870 | lu_byte defkind = getglobalattribute(ls, GDKREG); | ||
1871 | if (!testnext(ls, '*')) | ||
1872 | globalnames(ls, defkind); | ||
1873 | else { | ||
1874 | /* use NULL as name to represent '*' entries */ | ||
1875 | new_varkind(ls, NULL, defkind); | ||
1876 | fs->nactvar++; /* activate declaration */ | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | |||
1881 | static void globalfunc (LexState *ls, int line) { | ||
1882 | /* globalfunc -> (GLOBAL FUNCTION) NAME body */ | ||
1883 | expdesc var, b; | ||
1884 | FuncState *fs = ls->fs; | ||
1885 | TString *fname = str_checkname(ls); | ||
1886 | new_varkind(ls, fname, GDKREG); /* declare global variable */ | ||
1887 | fs->nactvar++; /* enter its scope */ | ||
1888 | buildglobal(ls, fname, &var); | ||
1889 | body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ | ||
1890 | luaK_storevar(fs, &var, &b); | ||
1891 | luaK_fixline(fs, line); /* definition "happens" in the first line */ | ||
1892 | } | ||
1893 | |||
1894 | |||
1895 | static void globalstatfunc (LexState *ls, int line) { | ||
1896 | /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ | ||
1897 | luaX_next(ls); /* skip 'global' */ | ||
1898 | if (testnext(ls, TK_FUNCTION)) | ||
1899 | globalfunc(ls, line); | ||
1900 | else | ||
1901 | globalstat(ls); | ||
1902 | } | ||
1903 | |||
1904 | |||
1778 | static int funcname (LexState *ls, expdesc *v) { | 1905 | static int funcname (LexState *ls, expdesc *v) { |
1779 | /* funcname -> NAME {fieldsel} [':' NAME] */ | 1906 | /* funcname -> NAME {fieldsel} [':' NAME] */ |
1780 | int ismethod = 0; | 1907 | int ismethod = 0; |
@@ -1795,8 +1922,8 @@ static void funcstat (LexState *ls, int line) { | |||
1795 | expdesc v, b; | 1922 | expdesc v, b; |
1796 | luaX_next(ls); /* skip FUNCTION */ | 1923 | luaX_next(ls); /* skip FUNCTION */ |
1797 | ismethod = funcname(ls, &v); | 1924 | ismethod = funcname(ls, &v); |
1798 | body(ls, &b, ismethod, line); | ||
1799 | check_readonly(ls, &v); | 1925 | check_readonly(ls, &v); |
1926 | body(ls, &b, ismethod, line); | ||
1800 | luaK_storevar(ls->fs, &v, &b); | 1927 | luaK_storevar(ls->fs, &v, &b); |
1801 | luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ | 1928 | luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ |
1802 | } | 1929 | } |
@@ -1894,6 +2021,10 @@ static void statement (LexState *ls) { | |||
1894 | localstat(ls); | 2021 | localstat(ls); |
1895 | break; | 2022 | break; |
1896 | } | 2023 | } |
2024 | case TK_GLOBAL: { /* stat -> globalstatfunc */ | ||
2025 | globalstatfunc(ls, line); | ||
2026 | break; | ||
2027 | } | ||
1897 | case TK_DBCOLON: { /* stat -> label */ | 2028 | case TK_DBCOLON: { /* stat -> label */ |
1898 | luaX_next(ls); /* skip double colon */ | 2029 | luaX_next(ls); /* skip double colon */ |
1899 | labelstat(ls, str_checkname(ls), line); | 2030 | labelstat(ls, str_checkname(ls), line); |
@@ -1913,6 +2044,22 @@ static void statement (LexState *ls) { | |||
1913 | gotostat(ls, line); | 2044 | gotostat(ls, line); |
1914 | break; | 2045 | break; |
1915 | } | 2046 | } |
2047 | #if defined(LUA_COMPAT_GLOBAL) | ||
2048 | case TK_NAME: { | ||
2049 | /* compatibility code to parse global keyword when "global" | ||
2050 | is not reserved */ | ||
2051 | if (ls->t.seminfo.ts == ls->glbn) { /* current = "global"? */ | ||
2052 | int lk = luaX_lookahead(ls); | ||
2053 | if (lk == '<' || lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) { | ||
2054 | /* 'global <attrib>' or 'global name' or 'global *' or | ||
2055 | 'global function' */ | ||
2056 | globalstatfunc(ls, line); | ||
2057 | break; | ||
2058 | } | ||
2059 | } /* else... */ | ||
2060 | } | ||
2061 | #endif | ||
2062 | /* FALLTHROUGH */ | ||
1916 | default: { /* stat -> func | assignment */ | 2063 | default: { /* stat -> func | assignment */ |
1917 | exprstat(ls); | 2064 | exprstat(ls); |
1918 | break; | 2065 | break; |
@@ -37,21 +37,27 @@ typedef enum { | |||
37 | info = result register */ | 37 | info = result register */ |
38 | VLOCAL, /* local variable; var.ridx = register index; | 38 | VLOCAL, /* local variable; var.ridx = register index; |
39 | var.vidx = relative index in 'actvar.arr' */ | 39 | var.vidx = relative index in 'actvar.arr' */ |
40 | VGLOBAL, /* global variable; | ||
41 | info = relative index in 'actvar.arr' (or -1 for | ||
42 | implicit declaration) */ | ||
40 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ | 43 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ |
41 | VCONST, /* compile-time <const> variable; | 44 | VCONST, /* compile-time <const> variable; |
42 | info = absolute index in 'actvar.arr' */ | 45 | info = absolute index in 'actvar.arr' */ |
43 | VINDEXED, /* indexed variable; | 46 | VINDEXED, /* indexed variable; |
44 | ind.t = table register; | 47 | ind.t = table register; |
45 | ind.idx = key's R index */ | 48 | ind.idx = key's R index; |
49 | ind.ro = true if it represents a read-only global; | ||
50 | ind.keystr = if key is a string, index in 'k' of that string; | ||
51 | -1 if key is not a string */ | ||
46 | VINDEXUP, /* indexed upvalue; | 52 | VINDEXUP, /* indexed upvalue; |
47 | ind.t = table upvalue; | 53 | ind.idx = key's K index; |
48 | ind.idx = key's K index */ | 54 | ind.* as in VINDEXED */ |
49 | VINDEXI, /* indexed variable with constant integer; | 55 | VINDEXI, /* indexed variable with constant integer; |
50 | ind.t = table register; | 56 | ind.t = table register; |
51 | ind.idx = key's value */ | 57 | ind.idx = key's value */ |
52 | VINDEXSTR, /* indexed variable with literal string; | 58 | VINDEXSTR, /* indexed variable with literal string; |
53 | ind.t = table register; | 59 | ind.idx = key's K index; |
54 | ind.idx = key's K index */ | 60 | ind.* as in VINDEXED */ |
55 | VJMP, /* expression is a test/comparison; | 61 | VJMP, /* expression is a test/comparison; |
56 | info = pc of corresponding jump instruction */ | 62 | info = pc of corresponding jump instruction */ |
57 | VRELOC, /* expression can put result in any register; | 63 | VRELOC, /* expression can put result in any register; |
@@ -75,10 +81,12 @@ typedef struct expdesc { | |||
75 | struct { /* for indexed variables */ | 81 | struct { /* for indexed variables */ |
76 | short idx; /* index (R or "long" K) */ | 82 | short idx; /* index (R or "long" K) */ |
77 | lu_byte t; /* table (register or upvalue) */ | 83 | lu_byte t; /* table (register or upvalue) */ |
84 | lu_byte ro; /* true if variable is read-only */ | ||
85 | int keystr; /* index in 'k' of string key, or -1 if not a string */ | ||
78 | } ind; | 86 | } ind; |
79 | struct { /* for local variables */ | 87 | struct { /* for local variables */ |
80 | lu_byte ridx; /* register holding the variable */ | 88 | lu_byte ridx; /* register holding the variable */ |
81 | unsigned short vidx; /* compiler index (in 'actvar.arr') */ | 89 | short vidx; /* index in 'actvar.arr' */ |
82 | } var; | 90 | } var; |
83 | } u; | 91 | } u; |
84 | int t; /* patch list of 'exit when true' */ | 92 | int t; /* patch list of 'exit when true' */ |
@@ -87,12 +95,21 @@ typedef struct expdesc { | |||
87 | 95 | ||
88 | 96 | ||
89 | /* kinds of variables */ | 97 | /* kinds of variables */ |
90 | #define VDKREG 0 /* regular */ | 98 | #define VDKREG 0 /* regular local */ |
91 | #define RDKCONST 1 /* constant */ | 99 | #define RDKCONST 1 /* local constant */ |
92 | #define RDKTOCLOSE 2 /* to-be-closed */ | 100 | #define RDKTOCLOSE 2 /* to-be-closed */ |
93 | #define RDKCTC 3 /* compile-time constant */ | 101 | #define RDKCTC 3 /* local compile-time constant */ |
102 | #define GDKREG 4 /* regular global */ | ||
103 | #define GDKCONST 5 /* global constant */ | ||
104 | |||
105 | /* variables that live in registers */ | ||
106 | #define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE) | ||
107 | |||
108 | /* test for global variables */ | ||
109 | #define varglobal(v) ((v)->vd.kind >= GDKREG) | ||
110 | |||
94 | 111 | ||
95 | /* description of an active local variable */ | 112 | /* description of an active variable */ |
96 | typedef union Vardesc { | 113 | typedef union Vardesc { |
97 | struct { | 114 | struct { |
98 | TValuefields; /* constant value (if it is a compile-time constant) */ | 115 | TValuefields; /* constant value (if it is a compile-time constant) */ |
@@ -111,7 +128,7 @@ typedef struct Labeldesc { | |||
111 | TString *name; /* label identifier */ | 128 | TString *name; /* label identifier */ |
112 | int pc; /* position in code */ | 129 | int pc; /* position in code */ |
113 | int line; /* line where it appeared */ | 130 | int line; /* line where it appeared */ |
114 | lu_byte nactvar; /* number of active variables in that position */ | 131 | short nactvar; /* number of active variables in that position */ |
115 | lu_byte close; /* true for goto that escapes upvalues */ | 132 | lu_byte close; /* true for goto that escapes upvalues */ |
116 | } Labeldesc; | 133 | } Labeldesc; |
117 | 134 | ||
@@ -156,7 +173,7 @@ typedef struct FuncState { | |||
156 | int firstlocal; /* index of first local var (in Dyndata array) */ | 173 | int firstlocal; /* index of first local var (in Dyndata array) */ |
157 | int firstlabel; /* index of first label (in 'dyd->label->arr') */ | 174 | int firstlabel; /* index of first label (in 'dyd->label->arr') */ |
158 | short ndebugvars; /* number of elements in 'f->locvars' */ | 175 | short ndebugvars; /* number of elements in 'f->locvars' */ |
159 | lu_byte nactvar; /* number of active local variables */ | 176 | short nactvar; /* number of active variable declarations */ |
160 | lu_byte nups; /* number of upvalues */ | 177 | lu_byte nups; /* number of upvalues */ |
161 | lu_byte freereg; /* first free register */ | 178 | lu_byte freereg; /* first free register */ |
162 | lu_byte iwthabs; /* instructions issued since last absolute line info */ | 179 | lu_byte iwthabs; /* instructions issued since last absolute line info */ |
@@ -326,6 +326,8 @@ LUA_API int lua_closethread (lua_State *L, lua_State *from) { | |||
326 | lua_lock(L); | 326 | lua_lock(L); |
327 | L->nCcalls = (from) ? getCcalls(from) : 0; | 327 | L->nCcalls = (from) ? getCcalls(from) : 0; |
328 | status = luaE_resetthread(L, L->status); | 328 | status = luaE_resetthread(L, L->status); |
329 | if (L == from) /* closing itself? */ | ||
330 | luaD_throwbaselevel(L, status); | ||
329 | lua_unlock(L); | 331 | lua_unlock(L); |
330 | return APIstatus(status); | 332 | return APIstatus(status); |
331 | } | 333 | } |
@@ -85,7 +85,7 @@ typedef struct CallInfo CallInfo; | |||
85 | ** they must be visited again at the end of the cycle), but they are | 85 | ** they must be visited again at the end of the cycle), but they are |
86 | ** marked black because assignments to them must activate barriers (to | 86 | ** marked black because assignments to them must activate barriers (to |
87 | ** move them back to TOUCHED1). | 87 | ** move them back to TOUCHED1). |
88 | ** - Open upvales are kept gray to avoid barriers, but they stay out | 88 | ** - Open upvalues are kept gray to avoid barriers, but they stay out |
89 | ** of gray lists. (They don't even have a 'gclist' field.) | 89 | ** of gray lists. (They don't even have a 'gclist' field.) |
90 | */ | 90 | */ |
91 | 91 | ||
@@ -232,7 +232,7 @@ struct CallInfo { | |||
232 | /* call is running a C function (still in first 16 bits) */ | 232 | /* call is running a C function (still in first 16 bits) */ |
233 | #define CIST_C (1u << (CIST_RECST + 3)) | 233 | #define CIST_C (1u << (CIST_RECST + 3)) |
234 | /* call is on a fresh "luaV_execute" frame */ | 234 | /* call is on a fresh "luaV_execute" frame */ |
235 | #define CIST_FRESH cast(l_uint32, CIST_C << 1) | 235 | #define CIST_FRESH (cast(l_uint32, CIST_C) << 1) |
236 | /* function is closing tbc variables */ | 236 | /* function is closing tbc variables */ |
237 | #define CIST_CLSRET (CIST_FRESH << 1) | 237 | #define CIST_CLSRET (CIST_FRESH << 1) |
238 | /* function has tbc variables to close */ | 238 | /* function has tbc variables to close */ |
@@ -39,14 +39,14 @@ | |||
39 | 39 | ||
40 | 40 | ||
41 | /* | 41 | /* |
42 | ** equality for long strings | 42 | ** generic equality for strings |
43 | */ | 43 | */ |
44 | int luaS_eqlngstr (TString *a, TString *b) { | 44 | int luaS_eqstr (TString *a, TString *b) { |
45 | size_t len = a->u.lnglen; | 45 | size_t len1, len2; |
46 | lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR); | 46 | const char *s1 = getlstr(a, len1); |
47 | return (a == b) || /* same instance or... */ | 47 | const char *s2 = getlstr(b, len2); |
48 | ((len == b->u.lnglen) && /* equal length and ... */ | 48 | return ((len1 == len2) && /* equal length and ... */ |
49 | (memcmp(getlngstr(a), getlngstr(b), len) == 0)); /* equal contents */ | 49 | (memcmp(s1, s2, len1) == 0)); /* equal contents */ |
50 | } | 50 | } |
51 | 51 | ||
52 | 52 | ||
@@ -315,28 +315,9 @@ static void f_newext (lua_State *L, void *ud) { | |||
315 | } | 315 | } |
316 | 316 | ||
317 | 317 | ||
318 | static void f_pintern (lua_State *L, void *ud) { | ||
319 | struct NewExt *ne = cast(struct NewExt *, ud); | ||
320 | ne->ts = internshrstr(L, ne->s, ne->len); | ||
321 | } | ||
322 | |||
323 | |||
324 | TString *luaS_newextlstr (lua_State *L, | 318 | TString *luaS_newextlstr (lua_State *L, |
325 | const char *s, size_t len, lua_Alloc falloc, void *ud) { | 319 | const char *s, size_t len, lua_Alloc falloc, void *ud) { |
326 | struct NewExt ne; | 320 | struct NewExt ne; |
327 | if (len <= LUAI_MAXSHORTLEN) { /* short string? */ | ||
328 | ne.s = s; ne.len = len; | ||
329 | if (!falloc) | ||
330 | f_pintern(L, &ne); /* just internalize string */ | ||
331 | else { | ||
332 | TStatus status = luaD_rawrunprotected(L, f_pintern, &ne); | ||
333 | (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ | ||
334 | if (status != LUA_OK) /* memory error? */ | ||
335 | luaM_error(L); /* re-raise memory error */ | ||
336 | } | ||
337 | return ne.ts; | ||
338 | } | ||
339 | /* "normal" case: long strings */ | ||
340 | if (!falloc) { | 321 | if (!falloc) { |
341 | ne.kind = LSTRFIX; | 322 | ne.kind = LSTRFIX; |
342 | f_newext(L, &ne); /* just create header */ | 323 | f_newext(L, &ne); /* just create header */ |
@@ -357,3 +338,16 @@ TString *luaS_newextlstr (lua_State *L, | |||
357 | } | 338 | } |
358 | 339 | ||
359 | 340 | ||
341 | /* | ||
342 | ** Normalize an external string: If it is short, internalize it. | ||
343 | */ | ||
344 | TString *luaS_normstr (lua_State *L, TString *ts) { | ||
345 | size_t len = ts->u.lnglen; | ||
346 | if (len > LUAI_MAXSHORTLEN) | ||
347 | return ts; /* long string; keep the original */ | ||
348 | else { | ||
349 | const char *str = getlngstr(ts); | ||
350 | return internshrstr(L, str, len); | ||
351 | } | ||
352 | } | ||
353 | |||
@@ -56,7 +56,7 @@ | |||
56 | 56 | ||
57 | LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed); | 57 | LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed); |
58 | LUAI_FUNC unsigned luaS_hashlongstr (TString *ts); | 58 | LUAI_FUNC unsigned luaS_hashlongstr (TString *ts); |
59 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); | 59 | LUAI_FUNC int luaS_eqstr (TString *a, TString *b); |
60 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); | 60 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); |
61 | LUAI_FUNC void luaS_clearcache (global_State *g); | 61 | LUAI_FUNC void luaS_clearcache (global_State *g); |
62 | LUAI_FUNC void luaS_init (lua_State *L); | 62 | LUAI_FUNC void luaS_init (lua_State *L); |
@@ -69,5 +69,6 @@ LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); | |||
69 | LUAI_FUNC TString *luaS_newextlstr (lua_State *L, | 69 | LUAI_FUNC TString *luaS_newextlstr (lua_State *L, |
70 | const char *s, size_t len, lua_Alloc falloc, void *ud); | 70 | const char *s, size_t len, lua_Alloc falloc, void *ud); |
71 | LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind); | 71 | LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind); |
72 | LUAI_FUNC TString *luaS_normstr (lua_State *L, TString *ts); | ||
72 | 73 | ||
73 | #endif | 74 | #endif |
@@ -132,27 +132,31 @@ static int str_upper (lua_State *L) { | |||
132 | } | 132 | } |
133 | 133 | ||
134 | 134 | ||
135 | /* | ||
136 | ** MAX_SIZE is limited both by size_t and lua_Integer. | ||
137 | ** When x <= MAX_SIZE, x can be safely cast to size_t or lua_Integer. | ||
138 | */ | ||
135 | static int str_rep (lua_State *L) { | 139 | static int str_rep (lua_State *L) { |
136 | size_t l, lsep; | 140 | size_t len, lsep; |
137 | const char *s = luaL_checklstring(L, 1, &l); | 141 | const char *s = luaL_checklstring(L, 1, &len); |
138 | lua_Integer n = luaL_checkinteger(L, 2); | 142 | lua_Integer n = luaL_checkinteger(L, 2); |
139 | const char *sep = luaL_optlstring(L, 3, "", &lsep); | 143 | const char *sep = luaL_optlstring(L, 3, "", &lsep); |
140 | if (n <= 0) | 144 | if (n <= 0) |
141 | lua_pushliteral(L, ""); | 145 | lua_pushliteral(L, ""); |
142 | else if (l_unlikely(l + lsep < l || l + lsep > MAX_SIZE / cast_sizet(n))) | 146 | else if (l_unlikely(len > MAX_SIZE - lsep || |
147 | cast_st2S(len + lsep) > cast_st2S(MAX_SIZE) / n)) | ||
143 | return luaL_error(L, "resulting string too large"); | 148 | return luaL_error(L, "resulting string too large"); |
144 | else { | 149 | else { |
145 | size_t totallen = ((size_t)n * (l + lsep)) - lsep; | 150 | size_t totallen = (cast_sizet(n) * (len + lsep)) - lsep; |
146 | luaL_Buffer b; | 151 | luaL_Buffer b; |
147 | char *p = luaL_buffinitsize(L, &b, totallen); | 152 | char *p = luaL_buffinitsize(L, &b, totallen); |
148 | while (n-- > 1) { /* first n-1 copies (followed by separator) */ | 153 | while (n-- > 1) { /* first n-1 copies (followed by separator) */ |
149 | memcpy(p, s, l * sizeof(char)); p += l; | 154 | memcpy(p, s, len * sizeof(char)); p += len; |
150 | if (lsep > 0) { /* empty 'memcpy' is not that cheap */ | 155 | if (lsep > 0) { /* empty 'memcpy' is not that cheap */ |
151 | memcpy(p, sep, lsep * sizeof(char)); | 156 | memcpy(p, sep, lsep * sizeof(char)); p += lsep; |
152 | p += lsep; | ||
153 | } | 157 | } |
154 | } | 158 | } |
155 | memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ | 159 | memcpy(p, s, len * sizeof(char)); /* last copy without separator */ |
156 | luaL_pushresultsize(&b, totallen); | 160 | luaL_pushresultsize(&b, totallen); |
157 | } | 161 | } |
158 | return 1; | 162 | return 1; |
@@ -1544,8 +1548,10 @@ static KOption getdetails (Header *h, size_t totalsize, const char **fmt, | |||
1544 | else { | 1548 | else { |
1545 | if (align > h->maxalign) /* enforce maximum alignment */ | 1549 | if (align > h->maxalign) /* enforce maximum alignment */ |
1546 | align = h->maxalign; | 1550 | align = h->maxalign; |
1547 | if (l_unlikely(!ispow2(align))) /* not a power of 2? */ | 1551 | if (l_unlikely(!ispow2(align))) { /* not a power of 2? */ |
1552 | *ntoalign = 0; /* to avoid warnings */ | ||
1548 | luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); | 1553 | luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); |
1554 | } | ||
1549 | else { | 1555 | else { |
1550 | /* 'szmoda' = totalsize % align */ | 1556 | /* 'szmoda' = totalsize % align */ |
1551 | unsigned szmoda = cast_uint(totalsize & (align - 1)); | 1557 | unsigned szmoda = cast_uint(totalsize & (align - 1)); |
@@ -1809,8 +1815,8 @@ static int str_unpack (lua_State *L) { | |||
1809 | lua_Unsigned len = (lua_Unsigned)unpackint(L, data + pos, | 1815 | lua_Unsigned len = (lua_Unsigned)unpackint(L, data + pos, |
1810 | h.islittle, cast_int(size), 0); | 1816 | h.islittle, cast_int(size), 0); |
1811 | luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); | 1817 | luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); |
1812 | lua_pushlstring(L, data + pos + size, len); | 1818 | lua_pushlstring(L, data + pos + size, cast_sizet(len)); |
1813 | pos += len; /* skip string */ | 1819 | pos += cast_sizet(len); /* skip string */ |
1814 | break; | 1820 | break; |
1815 | } | 1821 | } |
1816 | case Kzstr: { | 1822 | case Kzstr: { |
@@ -234,41 +234,51 @@ l_sinline Node *mainpositionfromnode (const Table *t, Node *nd) { | |||
234 | ** Check whether key 'k1' is equal to the key in node 'n2'. This | 234 | ** Check whether key 'k1' is equal to the key in node 'n2'. This |
235 | ** equality is raw, so there are no metamethods. Floats with integer | 235 | ** equality is raw, so there are no metamethods. Floats with integer |
236 | ** values have been normalized, so integers cannot be equal to | 236 | ** values have been normalized, so integers cannot be equal to |
237 | ** floats. It is assumed that 'eqshrstr' is simply pointer equality, so | 237 | ** floats. It is assumed that 'eqshrstr' is simply pointer equality, |
238 | ** that short strings are handled in the default case. | 238 | ** so that short strings are handled in the default case. The flag |
239 | ** A true 'deadok' means to accept dead keys as equal to their original | 239 | ** 'deadok' means to accept dead keys as equal to their original values. |
240 | ** values. All dead keys are compared in the default case, by pointer | 240 | ** (Only collectable objects can produce dead keys.) Note that dead |
241 | ** identity. (Only collectable objects can produce dead keys.) Note that | 241 | ** long strings are also compared by identity. Once a key is dead, |
242 | ** dead long strings are also compared by identity. | 242 | ** its corresponding value may be collected, and then another value |
243 | ** Once a key is dead, its corresponding value may be collected, and | 243 | ** can be created with the same address. If this other value is given |
244 | ** then another value can be created with the same address. If this | 244 | ** to 'next', 'equalkey' will signal a false positive. In a regular |
245 | ** other value is given to 'next', 'equalkey' will signal a false | 245 | ** traversal, this situation should never happen, as all keys given to |
246 | ** positive. In a regular traversal, this situation should never happen, | 246 | ** 'next' came from the table itself, and therefore could not have been |
247 | ** as all keys given to 'next' came from the table itself, and therefore | 247 | ** collected. Outside a regular traversal, we have garbage in, garbage |
248 | ** could not have been collected. Outside a regular traversal, we | 248 | ** out. What is relevant is that this false positive does not break |
249 | ** have garbage in, garbage out. What is relevant is that this false | 249 | ** anything. (In particular, 'next' will return some other valid item |
250 | ** positive does not break anything. (In particular, 'next' will return | 250 | ** on the table or nil.) |
251 | ** some other valid item on the table or nil.) | ||
252 | */ | 251 | */ |
253 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { | 252 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { |
254 | if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ | 253 | if (rawtt(k1) != keytt(n2)) { /* not the same variants? */ |
255 | !(deadok && keyisdead(n2) && iscollectable(k1))) | 254 | if (keyisshrstr(n2) && ttislngstring(k1)) { |
256 | return 0; /* cannot be same key */ | 255 | /* an external string can be equal to a short-string key */ |
257 | switch (keytt(n2)) { | 256 | return luaS_eqstr(tsvalue(k1), keystrval(n2)); |
258 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: | 257 | } |
259 | return 1; | 258 | else if (deadok && keyisdead(n2) && iscollectable(k1)) { |
260 | case LUA_VNUMINT: | 259 | /* a collectable value can be equal to a dead key */ |
261 | return (ivalue(k1) == keyival(n2)); | ||
262 | case LUA_VNUMFLT: | ||
263 | return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); | ||
264 | case LUA_VLIGHTUSERDATA: | ||
265 | return pvalue(k1) == pvalueraw(keyval(n2)); | ||
266 | case LUA_VLCF: | ||
267 | return fvalue(k1) == fvalueraw(keyval(n2)); | ||
268 | case ctb(LUA_VLNGSTR): | ||
269 | return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); | ||
270 | default: | ||
271 | return gcvalue(k1) == gcvalueraw(keyval(n2)); | 260 | return gcvalue(k1) == gcvalueraw(keyval(n2)); |
261 | } | ||
262 | else | ||
263 | return 0; /* otherwise, different variants cannot be equal */ | ||
264 | } | ||
265 | else { /* equal variants */ | ||
266 | switch (keytt(n2)) { | ||
267 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: | ||
268 | return 1; | ||
269 | case LUA_VNUMINT: | ||
270 | return (ivalue(k1) == keyival(n2)); | ||
271 | case LUA_VNUMFLT: | ||
272 | return luai_numeq(fltvalue(k1), fltvalueraw(keyval(n2))); | ||
273 | case LUA_VLIGHTUSERDATA: | ||
274 | return pvalue(k1) == pvalueraw(keyval(n2)); | ||
275 | case LUA_VLCF: | ||
276 | return fvalue(k1) == fvalueraw(keyval(n2)); | ||
277 | case ctb(LUA_VLNGSTR): | ||
278 | return luaS_eqstr(tsvalue(k1), keystrval(n2)); | ||
279 | default: | ||
280 | return gcvalue(k1) == gcvalueraw(keyval(n2)); | ||
281 | } | ||
272 | } | 282 | } |
273 | } | 283 | } |
274 | 284 | ||
@@ -1158,6 +1168,14 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, | |||
1158 | else if (l_unlikely(luai_numisnan(f))) | 1168 | else if (l_unlikely(luai_numisnan(f))) |
1159 | luaG_runerror(L, "table index is NaN"); | 1169 | luaG_runerror(L, "table index is NaN"); |
1160 | } | 1170 | } |
1171 | else if (isextstr(key)) { /* external string? */ | ||
1172 | /* If string is short, must internalize it to be used as table key */ | ||
1173 | TString *ts = luaS_normstr(L, tsvalue(key)); | ||
1174 | setsvalue2s(L, L->top.p++, ts); /* anchor 'ts' (EXTRA_STACK) */ | ||
1175 | luaH_newkey(L, t, s2v(L->top.p - 1), value); | ||
1176 | L->top.p--; | ||
1177 | return; | ||
1178 | } | ||
1161 | luaH_newkey(L, t, key, value); | 1179 | luaH_newkey(L, t, key, value); |
1162 | } | 1180 | } |
1163 | else if (hres > 0) { /* regular Node? */ | 1181 | else if (hres > 0) { /* regular Node? */ |
@@ -1202,24 +1220,36 @@ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | |||
1202 | 1220 | ||
1203 | /* | 1221 | /* |
1204 | ** Try to find a boundary in the hash part of table 't'. From the | 1222 | ** Try to find a boundary in the hash part of table 't'. From the |
1205 | ** caller, we know that 'j' is zero or present and that 'j + 1' is | 1223 | ** caller, we know that 'asize + 1' is present. We want to find a larger |
1206 | ** present. We want to find a larger key that is absent from the | 1224 | ** key that is absent from the table, so that we can do a binary search |
1207 | ** table, so that we can do a binary search between the two keys to | 1225 | ** between the two keys to find a boundary. We keep doubling 'j' until |
1208 | ** find a boundary. We keep doubling 'j' until we get an absent index. | 1226 | ** we get an absent index. If the doubling would overflow, we try |
1209 | ** If the doubling would overflow, we try LUA_MAXINTEGER. If it is | 1227 | ** LUA_MAXINTEGER. If it is absent, we are ready for the binary search. |
1210 | ** absent, we are ready for the binary search. ('j', being max integer, | 1228 | ** ('j', being max integer, is larger or equal to 'i', but it cannot be |
1211 | ** is larger or equal to 'i', but it cannot be equal because it is | 1229 | ** equal because it is absent while 'i' is present.) Otherwise, 'j' is a |
1212 | ** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a | 1230 | ** boundary. ('j + 1' cannot be a present integer key because it is not |
1213 | ** boundary. ('j + 1' cannot be a present integer key because it is | 1231 | ** a valid integer in Lua.) |
1214 | ** not a valid integer in Lua.) | 1232 | ** About 'rnd': If we used a fixed algorithm, a bad actor could fill |
1233 | ** a table with only the keys that would be probed, in such a way that | ||
1234 | ** a small table could result in a huge length. To avoid that, we use | ||
1235 | ** the state's seed as a source of randomness. For the first probe, | ||
1236 | ** we "randomly double" 'i' by adding to it a random number roughly its | ||
1237 | ** width. | ||
1215 | */ | 1238 | */ |
1216 | static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | 1239 | static lua_Unsigned hash_search (lua_State *L, Table *t, unsigned asize) { |
1217 | lua_Unsigned i; | 1240 | lua_Unsigned i = asize + 1; /* caller ensures t[i] is present */ |
1218 | if (j == 0) j++; /* the caller ensures 'j + 1' is present */ | 1241 | unsigned rnd = G(L)->seed; |
1219 | do { | 1242 | int n = (asize > 0) ? luaO_ceillog2(asize) : 0; /* width of 'asize' */ |
1243 | unsigned mask = (1u << n) - 1; /* 11...111 with the width of 'asize' */ | ||
1244 | unsigned incr = (rnd & mask) + 1; /* first increment (at least 1) */ | ||
1245 | lua_Unsigned j = (incr <= l_castS2U(LUA_MAXINTEGER) - i) ? i + incr : i + 1; | ||
1246 | rnd >>= n; /* used 'n' bits from 'rnd' */ | ||
1247 | while (!hashkeyisempty(t, j)) { /* repeat until an absent t[j] */ | ||
1220 | i = j; /* 'i' is a present index */ | 1248 | i = j; /* 'i' is a present index */ |
1221 | if (j <= l_castS2U(LUA_MAXINTEGER) / 2) | 1249 | if (j <= l_castS2U(LUA_MAXINTEGER)/2 - 1) { |
1222 | j *= 2; | 1250 | j = j*2 + (rnd & 1); /* try again with 2j or 2j+1 */ |
1251 | rnd >>= 1; | ||
1252 | } | ||
1223 | else { | 1253 | else { |
1224 | j = LUA_MAXINTEGER; | 1254 | j = LUA_MAXINTEGER; |
1225 | if (hashkeyisempty(t, j)) /* t[j] not present? */ | 1255 | if (hashkeyisempty(t, j)) /* t[j] not present? */ |
@@ -1227,7 +1257,7 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { | |||
1227 | else /* weird case */ | 1257 | else /* weird case */ |
1228 | return j; /* well, max integer is a boundary... */ | 1258 | return j; /* well, max integer is a boundary... */ |
1229 | } | 1259 | } |
1230 | } while (!hashkeyisempty(t, j)); /* repeat until an absent t[j] */ | 1260 | } |
1231 | /* i < j && t[i] present && t[j] absent */ | 1261 | /* i < j && t[i] present && t[j] absent */ |
1232 | while (j - i > 1u) { /* do a binary search between them */ | 1262 | while (j - i > 1u) { /* do a binary search between them */ |
1233 | lua_Unsigned m = (i + j) / 2; | 1263 | lua_Unsigned m = (i + j) / 2; |
@@ -1268,7 +1298,7 @@ static lua_Unsigned newhint (Table *t, unsigned hint) { | |||
1268 | ** If there is no array part, or its last element is non empty, the | 1298 | ** If there is no array part, or its last element is non empty, the |
1269 | ** border may be in the hash part. | 1299 | ** border may be in the hash part. |
1270 | */ | 1300 | */ |
1271 | lua_Unsigned luaH_getn (Table *t) { | 1301 | lua_Unsigned luaH_getn (lua_State *L, Table *t) { |
1272 | unsigned asize = t->asize; | 1302 | unsigned asize = t->asize; |
1273 | if (asize > 0) { /* is there an array part? */ | 1303 | if (asize > 0) { /* is there an array part? */ |
1274 | const unsigned maxvicinity = 4; | 1304 | const unsigned maxvicinity = 4; |
@@ -1309,7 +1339,7 @@ lua_Unsigned luaH_getn (Table *t) { | |||
1309 | if (isdummy(t) || hashkeyisempty(t, asize + 1)) | 1339 | if (isdummy(t) || hashkeyisempty(t, asize + 1)) |
1310 | return asize; /* 'asize + 1' is empty */ | 1340 | return asize; /* 'asize + 1' is empty */ |
1311 | else /* 'asize + 1' is also non empty */ | 1341 | else /* 'asize + 1' is also non empty */ |
1312 | return hash_search(t, asize); | 1342 | return hash_search(L, t, asize); |
1313 | } | 1343 | } |
1314 | 1344 | ||
1315 | 1345 | ||
@@ -173,7 +173,7 @@ LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned nasize); | |||
173 | LUAI_FUNC lu_mem luaH_size (Table *t); | 173 | LUAI_FUNC lu_mem luaH_size (Table *t); |
174 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); | 174 | LUAI_FUNC void luaH_free (lua_State *L, Table *t); |
175 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); | 175 | LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); |
176 | LUAI_FUNC lua_Unsigned luaH_getn (Table *t); | 176 | LUAI_FUNC lua_Unsigned luaH_getn (lua_State *L, Table *t); |
177 | 177 | ||
178 | 178 | ||
179 | #if defined(LUA_DEBUG) | 179 | #if defined(LUA_DEBUG) |
@@ -910,9 +910,9 @@ static int get_limits (lua_State *L) { | |||
910 | 910 | ||
911 | static int mem_query (lua_State *L) { | 911 | static int mem_query (lua_State *L) { |
912 | if (lua_isnone(L, 1)) { | 912 | if (lua_isnone(L, 1)) { |
913 | lua_pushinteger(L, cast(lua_Integer, l_memcontrol.total)); | 913 | lua_pushinteger(L, cast_Integer(l_memcontrol.total)); |
914 | lua_pushinteger(L, cast(lua_Integer, l_memcontrol.numblocks)); | 914 | lua_pushinteger(L, cast_Integer(l_memcontrol.numblocks)); |
915 | lua_pushinteger(L, cast(lua_Integer, l_memcontrol.maxmem)); | 915 | lua_pushinteger(L, cast_Integer(l_memcontrol.maxmem)); |
916 | return 3; | 916 | return 3; |
917 | } | 917 | } |
918 | else if (lua_isnumber(L, 1)) { | 918 | else if (lua_isnumber(L, 1)) { |
@@ -926,7 +926,7 @@ static int mem_query (lua_State *L) { | |||
926 | int i; | 926 | int i; |
927 | for (i = LUA_NUMTYPES - 1; i >= 0; i--) { | 927 | for (i = LUA_NUMTYPES - 1; i >= 0; i--) { |
928 | if (strcmp(t, ttypename(i)) == 0) { | 928 | if (strcmp(t, ttypename(i)) == 0) { |
929 | lua_pushinteger(L, cast(lua_Integer, l_memcontrol.objcount[i])); | 929 | lua_pushinteger(L, cast_Integer(l_memcontrol.objcount[i])); |
930 | return 1; | 930 | return 1; |
931 | } | 931 | } |
932 | } | 932 | } |
@@ -1066,15 +1066,19 @@ static int tracegc (lua_State *L) { | |||
1066 | 1066 | ||
1067 | static int hash_query (lua_State *L) { | 1067 | static int hash_query (lua_State *L) { |
1068 | if (lua_isnone(L, 2)) { | 1068 | if (lua_isnone(L, 2)) { |
1069 | TString *ts; | ||
1069 | luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); | 1070 | luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); |
1070 | lua_pushinteger(L, cast_int(tsvalue(obj_at(L, 1))->hash)); | 1071 | ts = tsvalue(obj_at(L, 1)); |
1072 | if (ts->tt == LUA_VLNGSTR) | ||
1073 | luaS_hashlongstr(ts); /* make sure long string has a hash */ | ||
1074 | lua_pushinteger(L, cast_int(ts->hash)); | ||
1071 | } | 1075 | } |
1072 | else { | 1076 | else { |
1073 | TValue *o = obj_at(L, 1); | 1077 | TValue *o = obj_at(L, 1); |
1074 | Table *t; | 1078 | Table *t; |
1075 | luaL_checktype(L, 2, LUA_TTABLE); | 1079 | luaL_checktype(L, 2, LUA_TTABLE); |
1076 | t = hvalue(obj_at(L, 2)); | 1080 | t = hvalue(obj_at(L, 2)); |
1077 | lua_pushinteger(L, cast(lua_Integer, luaH_mainposition(t, o) - t->node)); | 1081 | lua_pushinteger(L, cast_Integer(luaH_mainposition(t, o) - t->node)); |
1078 | } | 1082 | } |
1079 | return 1; | 1083 | return 1; |
1080 | } | 1084 | } |
@@ -1082,9 +1086,9 @@ static int hash_query (lua_State *L) { | |||
1082 | 1086 | ||
1083 | static int stacklevel (lua_State *L) { | 1087 | static int stacklevel (lua_State *L) { |
1084 | int a = 0; | 1088 | int a = 0; |
1085 | lua_pushinteger(L, cast(lua_Integer, L->top.p - L->stack.p)); | 1089 | lua_pushinteger(L, cast_Integer(L->top.p - L->stack.p)); |
1086 | lua_pushinteger(L, stacksize(L)); | 1090 | lua_pushinteger(L, stacksize(L)); |
1087 | lua_pushinteger(L, cast(lua_Integer, L->nCcalls)); | 1091 | lua_pushinteger(L, cast_Integer(L->nCcalls)); |
1088 | lua_pushinteger(L, L->nci); | 1092 | lua_pushinteger(L, L->nci); |
1089 | lua_pushinteger(L, (lua_Integer)(size_t)&a); | 1093 | lua_pushinteger(L, (lua_Integer)(size_t)&a); |
1090 | return 5; | 1094 | return 5; |
@@ -1099,9 +1103,9 @@ static int table_query (lua_State *L) { | |||
1099 | t = hvalue(obj_at(L, 1)); | 1103 | t = hvalue(obj_at(L, 1)); |
1100 | asize = t->asize; | 1104 | asize = t->asize; |
1101 | if (i == -1) { | 1105 | if (i == -1) { |
1102 | lua_pushinteger(L, cast(lua_Integer, asize)); | 1106 | lua_pushinteger(L, cast_Integer(asize)); |
1103 | lua_pushinteger(L, cast(lua_Integer, allocsizenode(t))); | 1107 | lua_pushinteger(L, cast_Integer(allocsizenode(t))); |
1104 | lua_pushinteger(L, cast(lua_Integer, asize > 0 ? *lenhint(t) : 0)); | 1108 | lua_pushinteger(L, cast_Integer(asize > 0 ? *lenhint(t) : 0)); |
1105 | return 3; | 1109 | return 3; |
1106 | } | 1110 | } |
1107 | else if (cast_uint(i) < asize) { | 1111 | else if (cast_uint(i) < asize) { |
@@ -1157,7 +1161,7 @@ static int test_codeparam (lua_State *L) { | |||
1157 | static int test_applyparam (lua_State *L) { | 1161 | static int test_applyparam (lua_State *L) { |
1158 | lua_Integer p = luaL_checkinteger(L, 1); | 1162 | lua_Integer p = luaL_checkinteger(L, 1); |
1159 | lua_Integer x = luaL_checkinteger(L, 2); | 1163 | lua_Integer x = luaL_checkinteger(L, 2); |
1160 | lua_pushinteger(L, cast(lua_Integer, luaO_applyparam(cast_byte(p), x))); | 1164 | lua_pushinteger(L, cast_Integer(luaO_applyparam(cast_byte(p), x))); |
1161 | return 1; | 1165 | return 1; |
1162 | } | 1166 | } |
1163 | 1167 | ||
@@ -1257,7 +1261,7 @@ static int pushuserdata (lua_State *L) { | |||
1257 | 1261 | ||
1258 | 1262 | ||
1259 | static int udataval (lua_State *L) { | 1263 | static int udataval (lua_State *L) { |
1260 | lua_pushinteger(L, cast(lua_Integer, cast(size_t, lua_touserdata(L, 1)))); | 1264 | lua_pushinteger(L, cast_st2S(cast_sizet(lua_touserdata(L, 1)))); |
1261 | return 1; | 1265 | return 1; |
1262 | } | 1266 | } |
1263 | 1267 | ||
@@ -1294,7 +1298,7 @@ static int num2int (lua_State *L) { | |||
1294 | 1298 | ||
1295 | 1299 | ||
1296 | static int makeseed (lua_State *L) { | 1300 | static int makeseed (lua_State *L) { |
1297 | lua_pushinteger(L, cast(lua_Integer, luaL_makeseed(L))); | 1301 | lua_pushinteger(L, cast_Integer(luaL_makeseed(L))); |
1298 | return 1; | 1302 | return 1; |
1299 | } | 1303 | } |
1300 | 1304 | ||
@@ -1638,7 +1642,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { | |||
1638 | } | 1642 | } |
1639 | else if EQ("func2num") { | 1643 | else if EQ("func2num") { |
1640 | lua_CFunction func = lua_tocfunction(L1, getindex); | 1644 | lua_CFunction func = lua_tocfunction(L1, getindex); |
1641 | lua_pushinteger(L1, cast(lua_Integer, cast(size_t, func))); | 1645 | lua_pushinteger(L1, cast_st2S(cast_sizet(func))); |
1642 | } | 1646 | } |
1643 | else if EQ("getfield") { | 1647 | else if EQ("getfield") { |
1644 | int t = getindex; | 1648 | int t = getindex; |
@@ -2011,7 +2015,7 @@ static int Cfunc (lua_State *L) { | |||
2011 | static int Cfunck (lua_State *L, int status, lua_KContext ctx) { | 2015 | static int Cfunck (lua_State *L, int status, lua_KContext ctx) { |
2012 | lua_pushstring(L, statcodes[status]); | 2016 | lua_pushstring(L, statcodes[status]); |
2013 | lua_setglobal(L, "status"); | 2017 | lua_setglobal(L, "status"); |
2014 | lua_pushinteger(L, cast(lua_Integer, ctx)); | 2018 | lua_pushinteger(L, cast_Integer(ctx)); |
2015 | lua_setglobal(L, "ctx"); | 2019 | lua_setglobal(L, "ctx"); |
2016 | return runC(L, L, lua_tostring(L, cast_int(ctx))); | 2020 | return runC(L, L, lua_tostring(L, cast_int(ctx))); |
2017 | } | 2021 | } |
@@ -14,6 +14,7 @@ | |||
14 | /* test Lua with compatibility code */ | 14 | /* test Lua with compatibility code */ |
15 | #define LUA_COMPAT_MATHLIB | 15 | #define LUA_COMPAT_MATHLIB |
16 | #define LUA_COMPAT_LT_LE | 16 | #define LUA_COMPAT_LT_LE |
17 | #undef LUA_COMPAT_GLOBAL | ||
17 | 18 | ||
18 | 19 | ||
19 | #define LUA_DEBUG | 20 | #define LUA_DEBUG |
@@ -154,7 +155,6 @@ LUA_API void *debug_realloc (void *ud, void *block, | |||
154 | ** Reduce maximum stack size to make stack-overflow tests run faster. | 155 | ** Reduce maximum stack size to make stack-overflow tests run faster. |
155 | ** (But value is still large enough to overflow smaller integers.) | 156 | ** (But value is still large enough to overflow smaller integers.) |
156 | */ | 157 | */ |
157 | #undef LUAI_MAXSTACK | ||
158 | #define LUAI_MAXSTACK 68000 | 158 | #define LUAI_MAXSTACK 68000 |
159 | 159 | ||
160 | 160 | ||
@@ -303,7 +303,8 @@ static int collectargs (char **argv, int *first) { | |||
303 | case '-': /* '--' */ | 303 | case '-': /* '--' */ |
304 | if (argv[i][2] != '\0') /* extra characters after '--'? */ | 304 | if (argv[i][2] != '\0') /* extra characters after '--'? */ |
305 | return has_error; /* invalid option */ | 305 | return has_error; /* invalid option */ |
306 | *first = i + 1; | 306 | /* if there is a script name, it comes after '--' */ |
307 | *first = (argv[i + 1] != NULL) ? i + 1 : 0; | ||
307 | return args; | 308 | return args; |
308 | case '\0': /* '-' */ | 309 | case '\0': /* '-' */ |
309 | return args; /* script "name" is '-' */ | 310 | return args; /* script "name" is '-' */ |
@@ -432,32 +433,41 @@ static int handle_luainit (lua_State *L) { | |||
432 | 433 | ||
433 | 434 | ||
434 | /* | 435 | /* |
435 | ** lua_readline defines how to show a prompt and then read a line from | 436 | ** * lua_initreadline initializes the readline system. |
436 | ** the standard input. | 437 | ** * lua_readline defines how to show a prompt and then read a line from |
437 | ** lua_saveline defines how to "save" a read line in a "history". | 438 | ** the standard input. |
438 | ** lua_freeline defines how to free a line read by lua_readline. | 439 | ** * lua_saveline defines how to "save" a read line in a "history". |
440 | ** * lua_freeline defines how to free a line read by lua_readline. | ||
439 | */ | 441 | */ |
440 | 442 | ||
441 | #if defined(LUA_USE_READLINE) | 443 | #if !defined(lua_readline) /* { */ |
444 | /* Otherwise, all previously listed functions should be defined. */ | ||
445 | |||
446 | #if defined(LUA_USE_READLINE) /* { */ | ||
447 | /* Lua will be linked with '-lreadline' */ | ||
442 | 448 | ||
443 | #include <readline/readline.h> | 449 | #include <readline/readline.h> |
444 | #include <readline/history.h> | 450 | #include <readline/history.h> |
451 | |||
445 | #define lua_initreadline(L) ((void)L, rl_readline_name="lua") | 452 | #define lua_initreadline(L) ((void)L, rl_readline_name="lua") |
446 | #define lua_readline(b,p) ((void)b, readline(p)) | 453 | #define lua_readline(buff,prompt) ((void)buff, readline(prompt)) |
447 | #define lua_saveline(line) add_history(line) | 454 | #define lua_saveline(line) add_history(line) |
448 | #define lua_freeline(b) free(b) | 455 | #define lua_freeline(line) free(line) |
449 | 456 | ||
450 | #endif | 457 | #else /* }{ */ |
458 | /* use dynamically loaded readline (or nothing) */ | ||
451 | 459 | ||
460 | /* pointer to 'readline' function (if any) */ | ||
461 | typedef char *(*l_readlineT) (const char *prompt); | ||
462 | static l_readlineT l_readline = NULL; | ||
452 | 463 | ||
453 | #if !defined(lua_readline) /* { */ | 464 | /* pointer to 'add_history' function (if any) */ |
465 | typedef void (*l_addhistT) (const char *string); | ||
466 | static l_addhistT l_addhist = NULL; | ||
454 | 467 | ||
455 | /* pointer to dynamically loaded 'readline' function (if any) */ | ||
456 | typedef char *(*l_readline_t) (const char *prompt); | ||
457 | static l_readline_t l_readline = NULL; | ||
458 | 468 | ||
459 | static char *lua_readline (char *buff, const char *prompt) { | 469 | static char *lua_readline (char *buff, const char *prompt) { |
460 | if (l_readline != NULL) /* is there a dynamic 'readline'? */ | 470 | if (l_readline != NULL) /* is there a 'readline'? */ |
461 | return (*l_readline)(prompt); /* use it */ | 471 | return (*l_readline)(prompt); /* use it */ |
462 | else { /* emulate 'readline' over 'buff' */ | 472 | else { /* emulate 'readline' over 'buff' */ |
463 | fputs(prompt, stdout); | 473 | fputs(prompt, stdout); |
@@ -467,33 +477,25 @@ static char *lua_readline (char *buff, const char *prompt) { | |||
467 | } | 477 | } |
468 | 478 | ||
469 | 479 | ||
470 | /* pointer to dynamically loaded 'add_history' function (if any) */ | ||
471 | typedef void (*l_addhist_t) (const char *string); | ||
472 | static l_addhist_t l_addhist = NULL; | ||
473 | |||
474 | static void lua_saveline (const char *line) { | 480 | static void lua_saveline (const char *line) { |
475 | if (l_addhist != NULL) /* is there a dynamic 'add_history'? */ | 481 | if (l_addhist != NULL) /* is there an 'add_history'? */ |
476 | (*l_addhist)(line); /* use it */ | 482 | (*l_addhist)(line); /* use it */ |
477 | /* else nothing to be done */ | 483 | /* else nothing to be done */ |
478 | } | 484 | } |
479 | 485 | ||
480 | 486 | ||
481 | static void lua_freeline (char *line) { | 487 | static void lua_freeline (char *line) { |
482 | if (l_readline != NULL) /* is there a dynamic 'readline'? */ | 488 | if (l_readline != NULL) /* is there a 'readline'? */ |
483 | free(line); /* free line created by it */ | 489 | free(line); /* free line created by it */ |
484 | /* else 'lua_readline' used an automatic buffer; nothing to free */ | 490 | /* else 'lua_readline' used an automatic buffer; nothing to free */ |
485 | } | 491 | } |
486 | 492 | ||
487 | 493 | ||
488 | #if !defined(LUA_USE_DLOPEN) || !defined(LUA_READLINELIB) | 494 | #if defined(LUA_USE_DLOPEN) && defined(LUA_READLINELIB) /* { */ |
489 | 495 | /* try to load 'readline' dynamically */ | |
490 | #define lua_initreadline(L) ((void)L) | ||
491 | |||
492 | #else /* { */ | ||
493 | 496 | ||
494 | #include <dlfcn.h> | 497 | #include <dlfcn.h> |
495 | 498 | ||
496 | |||
497 | static void lua_initreadline (lua_State *L) { | 499 | static void lua_initreadline (lua_State *L) { |
498 | void *lib = dlopen(LUA_READLINELIB, RTLD_NOW | RTLD_LOCAL); | 500 | void *lib = dlopen(LUA_READLINELIB, RTLD_NOW | RTLD_LOCAL); |
499 | if (lib == NULL) | 501 | if (lib == NULL) |
@@ -501,16 +503,23 @@ static void lua_initreadline (lua_State *L) { | |||
501 | else { | 503 | else { |
502 | const char **name = cast(const char**, dlsym(lib, "rl_readline_name")); | 504 | const char **name = cast(const char**, dlsym(lib, "rl_readline_name")); |
503 | if (name != NULL) | 505 | if (name != NULL) |
504 | *name = "Lua"; | 506 | *name = "lua"; |
505 | l_readline = cast(l_readline_t, cast_func(dlsym(lib, "readline"))); | 507 | l_readline = cast(l_readlineT, cast_func(dlsym(lib, "readline"))); |
508 | l_addhist = cast(l_addhistT, cast_func(dlsym(lib, "add_history"))); | ||
506 | if (l_readline == NULL) | 509 | if (l_readline == NULL) |
507 | lua_warning(L, "unable to load 'readline'", 0); | 510 | lua_warning(L, "unable to load 'readline'", 0); |
508 | else | ||
509 | l_addhist = cast(l_addhist_t, cast_func(dlsym(lib, "add_history"))); | ||
510 | } | 511 | } |
511 | } | 512 | } |
512 | 513 | ||
513 | #endif /* } */ | 514 | #else /* }{ */ |
515 | /* no dlopen or LUA_READLINELIB undefined */ | ||
516 | |||
517 | /* Leave pointers with NULL */ | ||
518 | #define lua_initreadline(L) ((void)L) | ||
519 | |||
520 | #endif /* } */ | ||
521 | |||
522 | #endif /* } */ | ||
514 | 523 | ||
515 | #endif /* } */ | 524 | #endif /* } */ |
516 | 525 | ||
@@ -37,10 +37,10 @@ | |||
37 | 37 | ||
38 | /* | 38 | /* |
39 | ** Pseudo-indices | 39 | ** Pseudo-indices |
40 | ** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty | 40 | ** (The stack size is limited to INT_MAX/2; we keep some free empty |
41 | ** space after that to help overflow detection) | 41 | ** space after that to help overflow detection.) |
42 | */ | 42 | */ |
43 | #define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) | 43 | #define LUA_REGISTRYINDEX (-(INT_MAX/2 + 1000)) |
44 | #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) | 44 | #define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) |
45 | 45 | ||
46 | 46 | ||
@@ -59,7 +59,7 @@ | |||
59 | 59 | ||
60 | 60 | ||
61 | /* | 61 | /* |
62 | ** When Posix DLL ('LUA_USE_DLOPEN') is enabled, the Lua stand-alone | 62 | ** When POSIX DLL ('LUA_USE_DLOPEN') is enabled, the Lua stand-alone |
63 | ** application will try to dynamically link a 'readline' facility | 63 | ** application will try to dynamically link a 'readline' facility |
64 | ** for its REPL. In that case, LUA_READLINELIB is the name of the | 64 | ** for its REPL. In that case, LUA_READLINELIB is the name of the |
65 | ** library it will look for those facilities. If lua.c cannot open | 65 | ** library it will look for those facilities. If lua.c cannot open |
@@ -76,7 +76,7 @@ | |||
76 | 76 | ||
77 | #if defined(LUA_USE_MACOSX) | 77 | #if defined(LUA_USE_MACOSX) |
78 | #define LUA_USE_POSIX | 78 | #define LUA_USE_POSIX |
79 | #define LUA_USE_DLOPEN /* MacOS does not need -ldl */ | 79 | #define LUA_USE_DLOPEN /* macOS does not need -ldl */ |
80 | #define LUA_READLINELIB "libedit.dylib" | 80 | #define LUA_READLINELIB "libedit.dylib" |
81 | #endif | 81 | #endif |
82 | 82 | ||
@@ -88,7 +88,7 @@ | |||
88 | 88 | ||
89 | 89 | ||
90 | #if defined(LUA_USE_C89) && defined(LUA_USE_POSIX) | 90 | #if defined(LUA_USE_C89) && defined(LUA_USE_POSIX) |
91 | #error "Posix is not compatible with C89" | 91 | #error "POSIX is not compatible with C89" |
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | 94 | ||
@@ -356,6 +356,12 @@ | |||
356 | */ | 356 | */ |
357 | 357 | ||
358 | /* | 358 | /* |
359 | @@ LUA_COMPAT_GLOBAL avoids 'global' being a reserved word | ||
360 | */ | ||
361 | #define LUA_COMPAT_GLOBAL | ||
362 | |||
363 | |||
364 | /* | ||
359 | @@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. | 365 | @@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. |
360 | ** You can define it to get all options, or change specific options | 366 | ** You can define it to get all options, or change specific options |
361 | ** to fit your specific needs. | 367 | ** to fit your specific needs. |
@@ -758,20 +764,6 @@ | |||
758 | */ | 764 | */ |
759 | 765 | ||
760 | /* | 766 | /* |
761 | @@ LUAI_MAXSTACK limits the size of the Lua stack. | ||
762 | ** CHANGE it if you need a different limit. This limit is arbitrary; | ||
763 | ** its only purpose is to stop Lua from consuming unlimited stack | ||
764 | ** space and to reserve some numbers for pseudo-indices. | ||
765 | ** (It must fit into max(int)/2.) | ||
766 | */ | ||
767 | #if 1000000 < (INT_MAX / 2) | ||
768 | #define LUAI_MAXSTACK 1000000 | ||
769 | #else | ||
770 | #define LUAI_MAXSTACK (INT_MAX / 2u) | ||
771 | #endif | ||
772 | |||
773 | |||
774 | /* | ||
775 | @@ LUA_EXTRASPACE defines the size of a raw memory area associated with | 767 | @@ LUA_EXTRASPACE defines the size of a raw memory area associated with |
776 | ** a Lua state with very fast access. | 768 | ** a Lua state with very fast access. |
777 | ** CHANGE it if you need a different size. | 769 | ** CHANGE it if you need a different size. |
@@ -37,7 +37,7 @@ typedef struct { | |||
37 | const char *name; | 37 | const char *name; |
38 | Table *h; /* list for string reuse */ | 38 | Table *h; /* list for string reuse */ |
39 | size_t offset; /* current position relative to beginning of dump */ | 39 | size_t offset; /* current position relative to beginning of dump */ |
40 | lua_Integer nstr; /* number of strings in the list */ | 40 | lua_Unsigned nstr; /* number of strings in the list */ |
41 | lu_byte fixed; /* dump is fixed in memory */ | 41 | lu_byte fixed; /* dump is fixed in memory */ |
42 | } LoadState; | 42 | } LoadState; |
43 | 43 | ||
@@ -94,8 +94,8 @@ static lu_byte loadByte (LoadState *S) { | |||
94 | } | 94 | } |
95 | 95 | ||
96 | 96 | ||
97 | static size_t loadVarint (LoadState *S, size_t limit) { | 97 | static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { |
98 | size_t x = 0; | 98 | lua_Unsigned x = 0; |
99 | int b; | 99 | int b; |
100 | limit >>= 7; | 100 | limit >>= 7; |
101 | do { | 101 | do { |
@@ -109,7 +109,7 @@ static size_t loadVarint (LoadState *S, size_t limit) { | |||
109 | 109 | ||
110 | 110 | ||
111 | static size_t loadSize (LoadState *S) { | 111 | static size_t loadSize (LoadState *S) { |
112 | return loadVarint(S, MAX_SIZE); | 112 | return cast_sizet(loadVarint(S, MAX_SIZE)); |
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
@@ -127,9 +127,12 @@ static lua_Number loadNumber (LoadState *S) { | |||
127 | 127 | ||
128 | 128 | ||
129 | static lua_Integer loadInteger (LoadState *S) { | 129 | static lua_Integer loadInteger (LoadState *S) { |
130 | lua_Integer x; | 130 | lua_Unsigned cx = loadVarint(S, LUA_MAXUNSIGNED); |
131 | loadVar(S, x); | 131 | /* decode unsigned to signed */ |
132 | return x; | 132 | if ((cx & 1) != 0) |
133 | return l_castU2S(~(cx >> 1)); | ||
134 | else | ||
135 | return l_castU2S(cx >> 1); | ||
133 | } | 136 | } |
134 | 137 | ||
135 | 138 | ||
@@ -149,10 +152,11 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
149 | return; | 152 | return; |
150 | } | 153 | } |
151 | else if (size == 1) { /* previously saved string? */ | 154 | else if (size == 1) { /* previously saved string? */ |
152 | lua_Integer idx = cast(lua_Integer, loadSize(S)); /* get its index */ | 155 | lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ |
153 | TValue stv; | 156 | TValue stv; |
154 | luaH_getint(S->h, idx, &stv); /* get its value */ | 157 | if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING) |
155 | *sl = ts = tsvalue(&stv); | 158 | error(S, "invalid string index"); |
159 | *sl = ts = tsvalue(&stv); /* get its value */ | ||
156 | luaC_objbarrier(L, p, ts); | 160 | luaC_objbarrier(L, p, ts); |
157 | return; /* do not save it again */ | 161 | return; /* do not save it again */ |
158 | } | 162 | } |
@@ -175,7 +179,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
175 | /* add string to list of saved strings */ | 179 | /* add string to list of saved strings */ |
176 | S->nstr++; | 180 | S->nstr++; |
177 | setsvalue(L, &sv, ts); | 181 | setsvalue(L, &sv, ts); |
178 | luaH_setint(L, S->h, S->nstr, &sv); | 182 | luaH_setint(L, S->h, l_castU2S(S->nstr), &sv); |
179 | luaC_objbarrierback(L, obj2gco(S->h), ts); | 183 | luaC_objbarrierback(L, obj2gco(S->h), ts); |
180 | } | 184 | } |
181 | 185 | ||
@@ -234,7 +238,7 @@ static void loadConstants (LoadState *S, Proto *f) { | |||
234 | f->source = NULL; | 238 | f->source = NULL; |
235 | break; | 239 | break; |
236 | } | 240 | } |
237 | default: lua_assert(0); | 241 | default: error(S, "invalid constant"); |
238 | } | 242 | } |
239 | } | 243 | } |
240 | } | 244 | } |
@@ -391,11 +395,10 @@ LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { | |||
391 | LoadState S; | 395 | LoadState S; |
392 | LClosure *cl; | 396 | LClosure *cl; |
393 | if (*name == '@' || *name == '=') | 397 | if (*name == '@' || *name == '=') |
394 | S.name = name + 1; | 398 | name = name + 1; |
395 | else if (*name == LUA_SIGNATURE[0]) | 399 | else if (*name == LUA_SIGNATURE[0]) |
396 | S.name = "binary string"; | 400 | name = "binary string"; |
397 | else | 401 | S.name = name; |
398 | S.name = name; | ||
399 | S.L = L; | 402 | S.L = L; |
400 | S.Z = Z; | 403 | S.Z = Z; |
401 | S.fixed = cast_byte(fixed); | 404 | S.fixed = cast_byte(fixed); |
@@ -47,7 +47,7 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) { | |||
47 | ** Decode one UTF-8 sequence, returning NULL if byte sequence is | 47 | ** Decode one UTF-8 sequence, returning NULL if byte sequence is |
48 | ** invalid. The array 'limits' stores the minimum value for each | 48 | ** invalid. The array 'limits' stores the minimum value for each |
49 | ** sequence length, to check for overlong representations. Its first | 49 | ** sequence length, to check for overlong representations. Its first |
50 | ** entry forces an error for non-ascii bytes with no continuation | 50 | ** entry forces an error for non-ASCII bytes with no continuation |
51 | ** bytes (count == 0). | 51 | ** bytes (count == 0). |
52 | */ | 52 | */ |
53 | static const char *utf8_decode (const char *s, l_uint32 *val, int strict) { | 53 | static const char *utf8_decode (const char *s, l_uint32 *val, int strict) { |
@@ -55,7 +55,7 @@ static const char *utf8_decode (const char *s, l_uint32 *val, int strict) { | |||
55 | {~(l_uint32)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; | 55 | {~(l_uint32)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; |
56 | unsigned int c = (unsigned char)s[0]; | 56 | unsigned int c = (unsigned char)s[0]; |
57 | l_uint32 res = 0; /* final result */ | 57 | l_uint32 res = 0; /* final result */ |
58 | if (c < 0x80) /* ascii? */ | 58 | if (c < 0x80) /* ASCII? */ |
59 | res = c; | 59 | res = c; |
60 | else { | 60 | else { |
61 | int count = 0; /* to count number of continuation bytes */ | 61 | int count = 0; /* to count number of continuation bytes */ |
@@ -215,9 +215,10 @@ static int byteoffset (lua_State *L) { | |||
215 | } | 215 | } |
216 | lua_pushinteger(L, posi + 1); /* initial position */ | 216 | lua_pushinteger(L, posi + 1); /* initial position */ |
217 | if ((s[posi] & 0x80) != 0) { /* multi-byte character? */ | 217 | if ((s[posi] & 0x80) != 0) { /* multi-byte character? */ |
218 | do { | 218 | if (iscont(s[posi])) |
219 | posi++; | 219 | return luaL_error(L, "initial position is a continuation byte"); |
220 | } while (iscontp(s + posi + 1)); /* skip to final byte */ | 220 | while (iscontp(s + posi + 1)) |
221 | posi++; /* skip to last continuation byte */ | ||
221 | } | 222 | } |
222 | /* else one-byte character: final position is the initial one */ | 223 | /* else one-byte character: final position is the initial one */ |
223 | lua_pushinteger(L, posi + 1); /* 'posi' now is the final position */ | 224 | lua_pushinteger(L, posi + 1); /* 'posi' now is the final position */ |
@@ -327,7 +327,7 @@ lu_byte luaV_finishget (lua_State *L, const TValue *t, TValue *key, | |||
327 | ** Finish a table assignment 't[key] = val'. | 327 | ** Finish a table assignment 't[key] = val'. |
328 | ** About anchoring the table before the call to 'luaH_finishset': | 328 | ** About anchoring the table before the call to 'luaH_finishset': |
329 | ** This call may trigger an emergency collection. When loop>0, | 329 | ** This call may trigger an emergency collection. When loop>0, |
330 | ** the table being acessed is a field in some metatable. If this | 330 | ** the table being accessed is a field in some metatable. If this |
331 | ** metatable is weak and the table is not anchored, this collection | 331 | ** metatable is weak and the table is not anchored, this collection |
332 | ** could collect that table while it is being updated. | 332 | ** could collect that table while it is being updated. |
333 | */ | 333 | */ |
@@ -573,52 +573,74 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | |||
573 | */ | 573 | */ |
574 | int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | 574 | int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { |
575 | const TValue *tm; | 575 | const TValue *tm; |
576 | if (ttypetag(t1) != ttypetag(t2)) { /* not the same variant? */ | 576 | if (ttype(t1) != ttype(t2)) /* not the same type? */ |
577 | if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER) | 577 | return 0; |
578 | return 0; /* only numbers can be equal with different variants */ | 578 | else if (ttypetag(t1) != ttypetag(t2)) { |
579 | else { /* two numbers with different variants */ | 579 | switch (ttypetag(t1)) { |
580 | /* One of them is an integer. If the other does not have an | 580 | case LUA_VNUMINT: { /* integer == float? */ |
581 | integer value, they cannot be equal; otherwise, compare their | 581 | /* integer and float can only be equal if float has an integer |
582 | integer values. */ | 582 | value equal to the integer */ |
583 | lua_Integer i1, i2; | 583 | lua_Integer i2; |
584 | return (luaV_tointegerns(t1, &i1, F2Ieq) && | 584 | return (luaV_flttointeger(fltvalue(t2), &i2, F2Ieq) && |
585 | luaV_tointegerns(t2, &i2, F2Ieq) && | 585 | ivalue(t1) == i2); |
586 | i1 == i2); | 586 | } |
587 | case LUA_VNUMFLT: { /* float == integer? */ | ||
588 | lua_Integer i1; /* see comment in previous case */ | ||
589 | return (luaV_flttointeger(fltvalue(t1), &i1, F2Ieq) && | ||
590 | i1 == ivalue(t2)); | ||
591 | } | ||
592 | case LUA_VSHRSTR: case LUA_VLNGSTR: { | ||
593 | /* compare two strings with different variants: they can be | ||
594 | equal when one string is a short string and the other is | ||
595 | an external string */ | ||
596 | return luaS_eqstr(tsvalue(t1), tsvalue(t2)); | ||
597 | } | ||
598 | default: | ||
599 | /* only numbers (integer/float) and strings (long/short) can have | ||
600 | equal values with different variants */ | ||
601 | return 0; | ||
587 | } | 602 | } |
588 | } | 603 | } |
589 | /* values have same type and same variant */ | 604 | else { /* equal variants */ |
590 | switch (ttypetag(t1)) { | 605 | switch (ttypetag(t1)) { |
591 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1; | 606 | case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: |
592 | case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2)); | 607 | return 1; |
593 | case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); | 608 | case LUA_VNUMINT: |
594 | case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); | 609 | return (ivalue(t1) == ivalue(t2)); |
595 | case LUA_VLCF: return fvalue(t1) == fvalue(t2); | 610 | case LUA_VNUMFLT: |
596 | case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); | 611 | return (fltvalue(t1) == fltvalue(t2)); |
597 | case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); | 612 | case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); |
598 | case LUA_VUSERDATA: { | 613 | case LUA_VSHRSTR: |
599 | if (uvalue(t1) == uvalue(t2)) return 1; | 614 | return eqshrstr(tsvalue(t1), tsvalue(t2)); |
600 | else if (L == NULL) return 0; | 615 | case LUA_VLNGSTR: |
601 | tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); | 616 | return luaS_eqstr(tsvalue(t1), tsvalue(t2)); |
602 | if (tm == NULL) | 617 | case LUA_VUSERDATA: { |
603 | tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); | 618 | if (uvalue(t1) == uvalue(t2)) return 1; |
604 | break; /* will try TM */ | 619 | else if (L == NULL) return 0; |
620 | tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); | ||
621 | if (tm == NULL) | ||
622 | tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); | ||
623 | break; /* will try TM */ | ||
624 | } | ||
625 | case LUA_VTABLE: { | ||
626 | if (hvalue(t1) == hvalue(t2)) return 1; | ||
627 | else if (L == NULL) return 0; | ||
628 | tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); | ||
629 | if (tm == NULL) | ||
630 | tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); | ||
631 | break; /* will try TM */ | ||
632 | } | ||
633 | case LUA_VLCF: | ||
634 | return (fvalue(t1) == fvalue(t2)); | ||
635 | default: /* functions and threads */ | ||
636 | return (gcvalue(t1) == gcvalue(t2)); | ||
605 | } | 637 | } |
606 | case LUA_VTABLE: { | 638 | if (tm == NULL) /* no TM? */ |
607 | if (hvalue(t1) == hvalue(t2)) return 1; | 639 | return 0; /* objects are different */ |
608 | else if (L == NULL) return 0; | 640 | else { |
609 | tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); | 641 | int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ |
610 | if (tm == NULL) | 642 | return !tagisfalse(tag); |
611 | tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); | ||
612 | break; /* will try TM */ | ||
613 | } | 643 | } |
614 | default: | ||
615 | return gcvalue(t1) == gcvalue(t2); | ||
616 | } | ||
617 | if (tm == NULL) /* no TM? */ | ||
618 | return 0; /* objects are different */ | ||
619 | else { | ||
620 | int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ | ||
621 | return !tagisfalse(tag); | ||
622 | } | 644 | } |
623 | } | 645 | } |
624 | 646 | ||
@@ -700,7 +722,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | |||
700 | Table *h = hvalue(rb); | 722 | Table *h = hvalue(rb); |
701 | tm = fasttm(L, h->metatable, TM_LEN); | 723 | tm = fasttm(L, h->metatable, TM_LEN); |
702 | if (tm) break; /* metamethod? break switch to call it */ | 724 | if (tm) break; /* metamethod? break switch to call it */ |
703 | setivalue(s2v(ra), l_castU2S(luaH_getn(h))); /* else primitive len */ | 725 | setivalue(s2v(ra), l_castU2S(luaH_getn(L, h))); /* else primitive len */ |
704 | return; | 726 | return; |
705 | } | 727 | } |
706 | case LUA_VSHRSTR: { | 728 | case LUA_VSHRSTR: { |
diff --git a/manual/2html b/manual/2html index ac5ea043..b7afd2a6 100755 --- a/manual/2html +++ b/manual/2html | |||
@@ -8,11 +8,11 @@ | |||
8 | 8 | ||
9 | --------------------------------------------------------------- | 9 | --------------------------------------------------------------- |
10 | header = [[ | 10 | header = [[ |
11 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> | 11 | <!DOCTYPE html> |
12 | <html> | 12 | <html> |
13 | 13 | ||
14 | <head> | 14 | <head> |
15 | <title>Lua 5.4 Reference Manual</title> | 15 | <title>Lua 5.5 Reference Manual</title> |
16 | <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> | 16 | <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> |
17 | <link rel="stylesheet" href="lua.css"> | 17 | <link rel="stylesheet" href="lua.css"> |
18 | <link rel="stylesheet" href="manual.css"> | 18 | <link rel="stylesheet" href="manual.css"> |
@@ -23,7 +23,7 @@ header = [[ | |||
23 | <hr> | 23 | <hr> |
24 | <h1> | 24 | <h1> |
25 | <a href="http://www.lua.org/home.html"><img src="logo.gif" alt="[Lua logo]" border="0"></a> | 25 | <a href="http://www.lua.org/home.html"><img src="logo.gif" alt="[Lua logo]" border="0"></a> |
26 | Lua 5.4 Reference Manual | 26 | Lua 5.5 Reference Manual |
27 | </h1> | 27 | </h1> |
28 | 28 | ||
29 | by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes | 29 | by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes |
diff --git a/manual/manual.of b/manual/manual.of index 7cd0d4db..b2765774 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -213,11 +213,89 @@ of a given value @seeF{type}. | |||
213 | 213 | ||
214 | } | 214 | } |
215 | 215 | ||
216 | @sect2{globalenv| @title{Environments and the Global Environment} | 216 | @sect2{globalenv| @title{Scopes, Variables, and Environments} |
217 | @index{visibility} | ||
218 | |||
219 | A variable name refers to a global or a local variable according | ||
220 | to the declaration that is in context at that point of the code. | ||
221 | (For the purposes of this discussion, | ||
222 | a function's formal parameter is equivalent to a local variable.) | ||
223 | |||
224 | All chunks start with an implicit declaration @T{global *}, | ||
225 | which declares all free names as global variables; | ||
226 | this preambular declaration becomes void inside the scope of any other | ||
227 | @Rw{global} declaration, | ||
228 | as the following example illustrates: | ||
229 | @verbatim{ | ||
230 | X = 1 -- Ok, global by default | ||
231 | do | ||
232 | global Y -- voids the implicit initial declaration | ||
233 | Y = 1 -- Ok, Y declared as global | ||
234 | X = 1 -- ERROR, X not declared | ||
235 | end | ||
236 | X = 2 -- Ok, global by default again | ||
237 | } | ||
238 | So, outside any global declaration, | ||
239 | Lua works as @x{global-by-default}. | ||
240 | Inside any global declaration, | ||
241 | Lua works without a default: | ||
242 | All variables must be declared. | ||
243 | |||
244 | Lua is a lexically scoped language. | ||
245 | The scope of a variable declaration begins at the first statement after | ||
246 | the declaration and lasts until the last non-void statement | ||
247 | of the innermost block that includes the declaration. | ||
248 | (@emph{Void statements} are labels and empty statements.) | ||
249 | |||
250 | A declaration shadows any declaration for the same name that | ||
251 | is in context at the point of the declaration. Inside this | ||
252 | shadow, any outer declaration for that name is void. | ||
253 | See the next example: | ||
254 | @verbatim{ | ||
255 | global print, x | ||
256 | x = 10 -- global variable | ||
257 | do -- new block | ||
258 | local x = x -- new 'x', with value 10 | ||
259 | print(x) --> 10 | ||
260 | x = x+1 | ||
261 | do -- another block | ||
262 | local x = x+1 -- another 'x' | ||
263 | print(x) --> 12 | ||
264 | end | ||
265 | print(x) --> 11 | ||
266 | end | ||
267 | print(x) --> 10 (the global one) | ||
268 | } | ||
269 | |||
270 | Notice that, in a declaration like @T{local x = x}, | ||
271 | the new @id{x} being declared is not in scope yet, | ||
272 | and so the @id{x} in the right-hand side refers to the outside variable. | ||
273 | |||
274 | Because of the @x{lexical scoping} rules, | ||
275 | local variables can be freely accessed by functions | ||
276 | defined inside their scope. | ||
277 | A local variable used by an inner function is called an @def{upvalue} | ||
278 | (or @emphx{external local variable}, or simply @emphx{external variable}) | ||
279 | inside the inner function. | ||
280 | |||
281 | Notice that each execution of a @Rw{local} statement | ||
282 | defines new local variables. | ||
283 | Consider the following example: | ||
284 | @verbatim{ | ||
285 | a = {} | ||
286 | local x = 20 | ||
287 | for i = 1, 10 do | ||
288 | local y = 0 | ||
289 | a[i] = function () y = y + 1; return x + y end | ||
290 | end | ||
291 | } | ||
292 | The loop creates ten closures | ||
293 | (that is, ten instances of the anonymous function). | ||
294 | Each of these closures uses a different @id{y} variable, | ||
295 | while all of them share the same @id{x}. | ||
217 | 296 | ||
218 | As we will discuss further in @refsec{variables} and @refsec{assignment}, | 297 | As we will discuss further in @refsec{variables} and @refsec{assignment}, |
219 | any reference to a free name | 298 | any reference to a global variable @id{var} |
220 | (that is, a name not bound to any declaration) @id{var} | ||
221 | is syntactically translated to @T{_ENV.var}. | 299 | is syntactically translated to @T{_ENV.var}. |
222 | Moreover, every chunk is compiled in the scope of | 300 | Moreover, every chunk is compiled in the scope of |
223 | an external local variable named @id{_ENV} @see{chunks}, | 301 | an external local variable named @id{_ENV} @see{chunks}, |
@@ -225,12 +303,14 @@ so @id{_ENV} itself is never a free name in a chunk. | |||
225 | 303 | ||
226 | Despite the existence of this external @id{_ENV} variable and | 304 | Despite the existence of this external @id{_ENV} variable and |
227 | the translation of free names, | 305 | the translation of free names, |
228 | @id{_ENV} is a completely regular name. | 306 | @id{_ENV} is a regular name. |
229 | In particular, | 307 | In particular, |
230 | you can define new variables and parameters with that name. | 308 | you can define new variables and parameters with that name. |
231 | Each reference to a free name uses the @id{_ENV} that is | 309 | (However, you should not define @id{_ENV} as a global variable, |
232 | visible at that point in the program, | 310 | otherwise @T{_ENV.var} would translate to |
233 | following the usual visibility rules of Lua @see{visibility}. | 311 | @T{_ENV._ENV.var} and so on, in an infinite loop.) |
312 | Each reference to a global variable name uses the @id{_ENV} that is | ||
313 | visible at that point in the program. | ||
234 | 314 | ||
235 | Any table used as the value of @id{_ENV} is called an @def{environment}. | 315 | Any table used as the value of @id{_ENV} is called an @def{environment}. |
236 | 316 | ||
@@ -244,8 +324,8 @@ When Lua loads a chunk, | |||
244 | the default value for its @id{_ENV} variable | 324 | the default value for its @id{_ENV} variable |
245 | is the global environment @seeF{load}. | 325 | is the global environment @seeF{load}. |
246 | Therefore, by default, | 326 | Therefore, by default, |
247 | free names in Lua code refer to entries in the global environment | 327 | global variables in Lua code refer to entries in the global environment |
248 | and, therefore, they are also called @def{global variables}. | 328 | and, therefore, they act as conventional global variables. |
249 | Moreover, all standard libraries are loaded in the global environment | 329 | Moreover, all standard libraries are loaded in the global environment |
250 | and some functions there operate on that environment. | 330 | and some functions there operate on that environment. |
251 | You can use @Lid{load} (or @Lid{loadfile}) | 331 | You can use @Lid{load} (or @Lid{loadfile}) |
@@ -1031,9 +1111,9 @@ and cannot be used as names: | |||
1031 | @index{reserved words} | 1111 | @index{reserved words} |
1032 | @verbatim{ | 1112 | @verbatim{ |
1033 | and break do else elseif end | 1113 | and break do else elseif end |
1034 | false for function goto if in | 1114 | false for function global goto if |
1035 | local nil not or repeat return | 1115 | in local nil not or repeat |
1036 | then true until while | 1116 | return then true until while |
1037 | } | 1117 | } |
1038 | 1118 | ||
1039 | Lua is a case-sensitive language: | 1119 | Lua is a case-sensitive language: |
@@ -1198,17 +1278,15 @@ global variables, local variables, and table fields. | |||
1198 | 1278 | ||
1199 | A single name can denote a global variable or a local variable | 1279 | A single name can denote a global variable or a local variable |
1200 | (or a function's formal parameter, | 1280 | (or a function's formal parameter, |
1201 | which is a particular kind of local variable): | 1281 | which is a particular kind of local variable) @see{globalenv}: |
1202 | @Produc{ | 1282 | @Produc{ |
1203 | @producname{var}@producbody{@bnfNter{Name}} | 1283 | @producname{var}@producbody{@bnfNter{Name}} |
1204 | } | 1284 | } |
1205 | @bnfNter{Name} denotes identifiers @see{lexical}. | 1285 | @bnfNter{Name} denotes identifiers @see{lexical}. |
1206 | 1286 | ||
1207 | Any variable name is assumed to be global unless explicitly declared | 1287 | Because variables are @emph{lexically scoped}, |
1208 | as a local @see{localvar}. | ||
1209 | @x{Local variables} are @emph{lexically scoped}: | ||
1210 | local variables can be freely accessed by functions | 1288 | local variables can be freely accessed by functions |
1211 | defined inside their scope @see{visibility}. | 1289 | defined inside their scope @see{globalenv}. |
1212 | 1290 | ||
1213 | Before the first assignment to a variable, its value is @nil. | 1291 | Before the first assignment to a variable, its value is @nil. |
1214 | 1292 | ||
@@ -1227,8 +1305,6 @@ The syntax @id{var.Name} is just syntactic sugar for | |||
1227 | 1305 | ||
1228 | An access to a global variable @id{x} | 1306 | An access to a global variable @id{x} |
1229 | is equivalent to @id{_ENV.x}. | 1307 | is equivalent to @id{_ENV.x}. |
1230 | Due to the way that chunks are compiled, | ||
1231 | the variable @id{_ENV} itself is never global @see{globalenv}. | ||
1232 | 1308 | ||
1233 | } | 1309 | } |
1234 | 1310 | ||
@@ -1326,6 +1402,8 @@ Chunks can also be precompiled into binary form; | |||
1326 | see the program @idx{luac} and the function @Lid{string.dump} for details. | 1402 | see the program @idx{luac} and the function @Lid{string.dump} for details. |
1327 | Programs in source and compiled forms are interchangeable; | 1403 | Programs in source and compiled forms are interchangeable; |
1328 | Lua automatically detects the file type and acts accordingly @seeF{load}. | 1404 | Lua automatically detects the file type and acts accordingly @seeF{load}. |
1405 | Be aware that, unlike source code, | ||
1406 | maliciously crafted binary chunks can crash the interpreter. | ||
1329 | 1407 | ||
1330 | } | 1408 | } |
1331 | 1409 | ||
@@ -1428,7 +1506,7 @@ labels in Lua are considered statements too: | |||
1428 | A label is visible in the entire block where it is defined, | 1506 | A label is visible in the entire block where it is defined, |
1429 | except inside nested functions. | 1507 | except inside nested functions. |
1430 | A goto can jump to any visible label as long as it does not | 1508 | A goto can jump to any visible label as long as it does not |
1431 | enter into the scope of a local variable. | 1509 | enter into the scope of a variable declaration. |
1432 | A label should not be declared | 1510 | A label should not be declared |
1433 | where a previous label with the same name is visible, | 1511 | where a previous label with the same name is visible, |
1434 | even if this other label has been declared in an enclosing block. | 1512 | even if this other label has been declared in an enclosing block. |
@@ -1571,35 +1649,85 @@ Function calls are explained in @See{functioncall}. | |||
1571 | 1649 | ||
1572 | } | 1650 | } |
1573 | 1651 | ||
1574 | @sect3{localvar| @title{Local Declarations} | 1652 | @sect3{localvar| @title{Variable Declarations} |
1575 | @x{Local variables} can be declared anywhere inside a block. | 1653 | Local and global variables can be declared anywhere inside a block. |
1576 | The declaration can include an initialization: | 1654 | The declaration can include an initialization: |
1577 | @Produc{ | 1655 | @Produc{ |
1578 | @producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}} | 1656 | @producname{stat}@producbody{@Rw{local} |
1579 | @producname{attnamelist}@producbody{ | 1657 | attnamelist @bnfopt{@bnfter{=} explist}} |
1580 | @bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}} | 1658 | @producname{stat}@producbody{@Rw{global} |
1659 | attnamelist @bnfopt{@bnfter{=} explist}} | ||
1581 | } | 1660 | } |
1582 | If present, an initial assignment has the same semantics | 1661 | If present, an initial assignment has the same semantics |
1583 | of a multiple assignment @see{assignment}. | 1662 | of a multiple assignment @see{assignment}. |
1584 | Otherwise, all variables are initialized with @nil. | 1663 | Otherwise, all local variables are initialized with @nil. |
1585 | 1664 | ||
1586 | Each variable name may be postfixed by an attribute | 1665 | The list of names may be prefixed by an attribute |
1587 | (a name between angle brackets): | 1666 | (a name between angle brackets) |
1667 | and each variable name may be postfixed by an attribute: | ||
1588 | @Produc{ | 1668 | @Produc{ |
1589 | @producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}} | 1669 | @producname{attnamelist}@producbody{ |
1670 | @bnfopt{attrib} @bnfNter{Name} @bnfopt{attrib} | ||
1671 | @bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}} | ||
1672 | @producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}} | ||
1590 | } | 1673 | } |
1674 | A prefixed attribute applies to all names in the list; | ||
1675 | a postfixed attribute applies to its particular name. | ||
1591 | There are two possible attributes: | 1676 | There are two possible attributes: |
1592 | @id{const}, which declares a @emph{constant} or @emph{read-only} variable, | 1677 | @id{const}, which declares a @emph{constant} or @emph{read-only} variable, |
1593 | @index{constant variable} | 1678 | @index{constant variable} |
1594 | that is, a variable that cannot be assigned to | 1679 | that is, a variable that cannot be used as the left-hand side of an |
1595 | after its initialization; | 1680 | assignment, |
1596 | and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. | 1681 | and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. |
1682 | Only local variables can have the @id{close} attribute. | ||
1597 | A list of variables can contain at most one to-be-closed variable. | 1683 | A list of variables can contain at most one to-be-closed variable. |
1598 | 1684 | ||
1685 | Lua offers also a collective declaration for global variables: | ||
1686 | @Produc{ | ||
1687 | @producname{stat}@producbody{@Rw{global} @bnfopt{attrib} @bnfter{*}} | ||
1688 | } | ||
1689 | This special form implicitly declares | ||
1690 | as globals all names not explicitly declared previously. | ||
1691 | In particular, | ||
1692 | @T{global<const> *} implicitly declares | ||
1693 | as read-only globals all names not explicitly declared previously; | ||
1694 | see the following example: | ||
1695 | @verbatim{ | ||
1696 | global X | ||
1697 | global<const> * | ||
1698 | print(math.pi) -- Ok, 'print' and 'math' are read-only | ||
1699 | X = 1 -- Ok, declared as read-write | ||
1700 | Y = 1 -- Error, Y is read-only | ||
1701 | } | ||
1702 | |||
1703 | As noted in @See{globalenv}, | ||
1704 | all chunks start with an implicit declaration @T{global *}, | ||
1705 | but this preambular declaration becomes void inside | ||
1706 | the scope of any other @Rw{global} declaration. | ||
1707 | Therefore, a program that does not use global declarations | ||
1708 | or start with @T{global *} | ||
1709 | has free read-write access to any global; | ||
1710 | a program that starts with @T{global<const> *} | ||
1711 | has free read-only access to any global; | ||
1712 | and a program that starts with any other global declaration | ||
1713 | (e.g., @T{global none}) can only refer to declared variables. | ||
1714 | |||
1715 | Note that, for global variables, | ||
1716 | the effect of any declaration is only syntactical | ||
1717 | (except for the optional assignment): | ||
1718 | @verbatim{ | ||
1719 | global X <const>, _G | ||
1720 | X = 1 -- ERROR | ||
1721 | _ENV.X = 1 -- Ok | ||
1722 | _G.print(X) -- Ok | ||
1723 | foo() -- 'foo' can freely change any global | ||
1724 | } | ||
1725 | |||
1599 | A chunk is also a block @see{chunks}, | 1726 | A chunk is also a block @see{chunks}, |
1600 | and so local variables can be declared in a chunk outside any explicit block. | 1727 | and so variables can be declared in a chunk outside any explicit block. |
1601 | 1728 | ||
1602 | The visibility rules for local variables are explained in @See{visibility}. | 1729 | The visibility rules for variable declarations |
1730 | are explained in @See{globalenv}. | ||
1603 | 1731 | ||
1604 | } | 1732 | } |
1605 | 1733 | ||
@@ -2142,6 +2270,7 @@ The following syntactic sugar simplifies function definitions: | |||
2142 | @Produc{ | 2270 | @Produc{ |
2143 | @producname{stat}@producbody{@Rw{function} funcname funcbody} | 2271 | @producname{stat}@producbody{@Rw{function} funcname funcbody} |
2144 | @producname{stat}@producbody{@Rw{local} @Rw{function} @bnfNter{Name} funcbody} | 2272 | @producname{stat}@producbody{@Rw{local} @Rw{function} @bnfNter{Name} funcbody} |
2273 | @producname{stat}@producbody{@Rw{global} @Rw{function} @bnfNter{Name} funcbody} | ||
2145 | @producname{funcname}@producbody{@bnfNter{Name} @bnfrep{@bnfter{.} @bnfNter{Name}} @bnfopt{@bnfter{:} @bnfNter{Name}}} | 2274 | @producname{funcname}@producbody{@bnfNter{Name} @bnfrep{@bnfter{.} @bnfNter{Name}} @bnfopt{@bnfter{:} @bnfNter{Name}}} |
2146 | } | 2275 | } |
2147 | The statement | 2276 | The statement |
@@ -2160,6 +2289,7 @@ translates to | |||
2160 | @verbatim{ | 2289 | @verbatim{ |
2161 | t.a.b.c.f = function () @rep{body} end | 2290 | t.a.b.c.f = function () @rep{body} end |
2162 | } | 2291 | } |
2292 | |||
2163 | The statement | 2293 | The statement |
2164 | @verbatim{ | 2294 | @verbatim{ |
2165 | local function f () @rep{body} end | 2295 | local function f () @rep{body} end |
@@ -2173,7 +2303,15 @@ not to | |||
2173 | local f = function () @rep{body} end | 2303 | local f = function () @rep{body} end |
2174 | } | 2304 | } |
2175 | (This only makes a difference when the body of the function | 2305 | (This only makes a difference when the body of the function |
2176 | contains references to @id{f}.) | 2306 | contains recursive references to @id{f}.) |
2307 | Similarly, the statement | ||
2308 | @verbatim{ | ||
2309 | global function f () @rep{body} end | ||
2310 | } | ||
2311 | translates to | ||
2312 | @verbatim{ | ||
2313 | global f; f = function () @rep{body} end | ||
2314 | } | ||
2177 | 2315 | ||
2178 | A function definition is an executable expression, | 2316 | A function definition is an executable expression, |
2179 | whose value has type @emph{function}. | 2317 | whose value has type @emph{function}. |
@@ -2236,7 +2374,7 @@ then the function returns with no results. | |||
2236 | @index{multiple return} | 2374 | @index{multiple return} |
2237 | There is a system-dependent limit on the number of values | 2375 | There is a system-dependent limit on the number of values |
2238 | that a function may return. | 2376 | that a function may return. |
2239 | This limit is guaranteed to be greater than 1000. | 2377 | This limit is guaranteed to be at least 1000. |
2240 | 2378 | ||
2241 | The @emphx{colon} syntax | 2379 | The @emphx{colon} syntax |
2242 | is used to emulate @def{methods}, | 2380 | is used to emulate @def{methods}, |
@@ -2281,8 +2419,8 @@ for instance @T{foo(e1, e2, e3)} @see{functioncall}.} | |||
2281 | @item{A multiple assignment, | 2419 | @item{A multiple assignment, |
2282 | for instance @T{a , b, c = e1, e2, e3} @see{assignment}.} | 2420 | for instance @T{a , b, c = e1, e2, e3} @see{assignment}.} |
2283 | 2421 | ||
2284 | @item{A local declaration, | 2422 | @item{A local or global declaration, |
2285 | for instance @T{local a , b, c = e1, e2, e3} @see{localvar}.} | 2423 | which is a special case of multiple assignment.} |
2286 | 2424 | ||
2287 | @item{The initial values in a generic @rw{for} loop, | 2425 | @item{The initial values in a generic @rw{for} loop, |
2288 | for instance @T{for k in e1, e2, e3 do ... end} @see{for}.} | 2426 | for instance @T{for k in e1, e2, e3 do ... end} @see{for}.} |
@@ -2293,8 +2431,7 @@ the list of values from the list of expressions | |||
2293 | must be @emph{adjusted} to a specific length: | 2431 | must be @emph{adjusted} to a specific length: |
2294 | the number of parameters in a call to a non-variadic function | 2432 | the number of parameters in a call to a non-variadic function |
2295 | @see{func-def}, | 2433 | @see{func-def}, |
2296 | the number of variables in a multiple assignment or | 2434 | the number of variables in a multiple assignment or a declaration, |
2297 | a local declaration, | ||
2298 | and exactly four values for a generic @rw{for} loop. | 2435 | and exactly four values for a generic @rw{for} loop. |
2299 | The @def{adjustment} follows these rules: | 2436 | The @def{adjustment} follows these rules: |
2300 | If there are more values than needed, | 2437 | If there are more values than needed, |
@@ -2356,58 +2493,6 @@ return x,y,f() -- returns x, y, and all results from f(). | |||
2356 | 2493 | ||
2357 | } | 2494 | } |
2358 | 2495 | ||
2359 | @sect2{visibility| @title{Visibility Rules} | ||
2360 | |||
2361 | @index{visibility} | ||
2362 | Lua is a lexically scoped language. | ||
2363 | The scope of a local variable begins at the first statement after | ||
2364 | its declaration and lasts until the last non-void statement | ||
2365 | of the innermost block that includes the declaration. | ||
2366 | (@emph{Void statements} are labels and empty statements.) | ||
2367 | Consider the following example: | ||
2368 | @verbatim{ | ||
2369 | x = 10 -- global variable | ||
2370 | do -- new block | ||
2371 | local x = x -- new 'x', with value 10 | ||
2372 | print(x) --> 10 | ||
2373 | x = x+1 | ||
2374 | do -- another block | ||
2375 | local x = x+1 -- another 'x' | ||
2376 | print(x) --> 12 | ||
2377 | end | ||
2378 | print(x) --> 11 | ||
2379 | end | ||
2380 | print(x) --> 10 (the global one) | ||
2381 | } | ||
2382 | |||
2383 | Notice that, in a declaration like @T{local x = x}, | ||
2384 | the new @id{x} being declared is not in scope yet, | ||
2385 | and so the second @id{x} refers to the outside variable. | ||
2386 | |||
2387 | Because of the @x{lexical scoping} rules, | ||
2388 | local variables can be freely accessed by functions | ||
2389 | defined inside their scope. | ||
2390 | A local variable used by an inner function is called an @def{upvalue} | ||
2391 | (or @emphx{external local variable}, or simply @emphx{external variable}) | ||
2392 | inside the inner function. | ||
2393 | |||
2394 | Notice that each execution of a @Rw{local} statement | ||
2395 | defines new local variables. | ||
2396 | Consider the following example: | ||
2397 | @verbatim{ | ||
2398 | a = {} | ||
2399 | local x = 20 | ||
2400 | for i = 1, 10 do | ||
2401 | local y = 0 | ||
2402 | a[i] = function () y = y + 1; return x + y end | ||
2403 | end | ||
2404 | } | ||
2405 | The loop creates ten closures | ||
2406 | (that is, ten instances of the anonymous function). | ||
2407 | Each of these closures uses a different @id{y} variable, | ||
2408 | while all of them share the same @id{x}. | ||
2409 | |||
2410 | } | ||
2411 | 2496 | ||
2412 | } | 2497 | } |
2413 | 2498 | ||
@@ -3182,17 +3267,25 @@ when called through this function. | |||
3182 | 3267 | ||
3183 | Resets a thread, cleaning its call stack and closing all pending | 3268 | Resets a thread, cleaning its call stack and closing all pending |
3184 | to-be-closed variables. | 3269 | to-be-closed variables. |
3185 | Returns a status code: | 3270 | The parameter @id{from} represents the coroutine that is resetting @id{L}. |
3271 | If there is no such coroutine, | ||
3272 | this parameter can be @id{NULL}. | ||
3273 | |||
3274 | Unless @id{L} is equal to @id{from}, | ||
3275 | the call returns a status code: | ||
3186 | @Lid{LUA_OK} for no errors in the thread | 3276 | @Lid{LUA_OK} for no errors in the thread |
3187 | (either the original error that stopped the thread or | 3277 | (either the original error that stopped the thread or |
3188 | errors in closing methods), | 3278 | errors in closing methods), |
3189 | or an error status otherwise. | 3279 | or an error status otherwise. |
3190 | In case of error, | 3280 | In case of error, |
3191 | leaves the error object on the top of the stack. | 3281 | the error object is put on the top of the stack. |
3192 | 3282 | ||
3193 | The parameter @id{from} represents the coroutine that is resetting @id{L}. | 3283 | If @id{L} is equal to @id{from}, |
3194 | If there is no such coroutine, | 3284 | it corresponds to a thread closing itself. |
3195 | this parameter can be @id{NULL}. | 3285 | In that case, |
3286 | the call does not return; | ||
3287 | instead, the resume that (re)started the thread returns. | ||
3288 | The thread must be running inside a resume. | ||
3196 | 3289 | ||
3197 | } | 3290 | } |
3198 | 3291 | ||
@@ -3832,8 +3925,8 @@ This macro may evaluate its arguments more than once. | |||
3832 | 3925 | ||
3833 | } | 3926 | } |
3834 | 3927 | ||
3835 | @APIEntry{unsigned (lua_numbertocstring) (lua_State *L, int idx, | 3928 | @APIEntry{unsigned lua_numbertocstring (lua_State *L, int idx, |
3836 | char *buff);| | 3929 | char *buff);| |
3837 | @apii{0,0,-} | 3930 | @apii{0,0,-} |
3838 | 3931 | ||
3839 | Converts the number at acceptable index @id{idx} to a string | 3932 | Converts the number at acceptable index @id{idx} to a string |
@@ -3958,7 +4051,7 @@ This function is equivalent to @Lid{lua_pushcclosure} with no upvalues. | |||
3958 | 4051 | ||
3959 | } | 4052 | } |
3960 | 4053 | ||
3961 | @APIEntry{const char *(lua_pushexternalstring) (lua_State *L, | 4054 | @APIEntry{const char *lua_pushexternalstring (lua_State *L, |
3962 | const char *s, size_t len, lua_Alloc falloc, void *ud);| | 4055 | const char *s, size_t len, lua_Alloc falloc, void *ud);| |
3963 | @apii{0,1,m} | 4056 | @apii{0,1,m} |
3964 | 4057 | ||
@@ -3981,11 +4074,6 @@ the string @id{s} as the block, | |||
3981 | the length plus one (to account for the ending zero) as the old size, | 4074 | the length plus one (to account for the ending zero) as the old size, |
3982 | and 0 as the new size. | 4075 | and 0 as the new size. |
3983 | 4076 | ||
3984 | Lua always @x{internalizes} strings with lengths up to 40 characters. | ||
3985 | So, for strings in that range, | ||
3986 | this function will immediately internalize the string | ||
3987 | and call @id{falloc} to free the buffer. | ||
3988 | |||
3989 | Even when using an external buffer, | 4077 | Even when using an external buffer, |
3990 | Lua still has to allocate a header for the string. | 4078 | Lua still has to allocate a header for the string. |
3991 | In case of a memory-allocation error, | 4079 | In case of a memory-allocation error, |
@@ -6601,11 +6689,10 @@ It may be the string @St{b} (only @x{binary chunk}s), | |||
6601 | or @St{bt} (both binary and text). | 6689 | or @St{bt} (both binary and text). |
6602 | The default is @St{bt}. | 6690 | The default is @St{bt}. |
6603 | 6691 | ||
6604 | It is safe to load malformed binary chunks; | 6692 | Lua does not check the consistency of binary chunks. |
6605 | @id{load} signals an appropriate error. | 6693 | Maliciously crafted binary chunks can crash |
6606 | However, | 6694 | the interpreter. |
6607 | Lua does not check the consistency of the code inside binary chunks; | 6695 | You can use the @id{mode} parameter to prevent loading binary chunks. |
6608 | running maliciously crafted bytecode can crash the interpreter. | ||
6609 | 6696 | ||
6610 | } | 6697 | } |
6611 | 6698 | ||
@@ -6817,7 +6904,7 @@ and @St{userdata}. | |||
6817 | 6904 | ||
6818 | A global variable (not a function) that | 6905 | A global variable (not a function) that |
6819 | holds a string containing the running Lua version. | 6906 | holds a string containing the running Lua version. |
6820 | The current value of this variable is @St{Lua 5.4}. | 6907 | The current value of this variable is @St{Lua 5.5}. |
6821 | 6908 | ||
6822 | } | 6909 | } |
6823 | 6910 | ||
@@ -6854,18 +6941,26 @@ which come inside the table @defid{coroutine}. | |||
6854 | See @See{coroutine} for a general description of coroutines. | 6941 | See @See{coroutine} for a general description of coroutines. |
6855 | 6942 | ||
6856 | 6943 | ||
6857 | @LibEntry{coroutine.close (co)| | 6944 | @LibEntry{coroutine.close ([co])| |
6858 | 6945 | ||
6859 | Closes coroutine @id{co}, | 6946 | Closes coroutine @id{co}, |
6860 | that is, | 6947 | that is, |
6861 | closes all its pending to-be-closed variables | 6948 | closes all its pending to-be-closed variables |
6862 | and puts the coroutine in a dead state. | 6949 | and puts the coroutine in a dead state. |
6863 | The given coroutine must be dead or suspended. | 6950 | The default for @id{co} is the running coroutine. |
6864 | In case of error | 6951 | |
6952 | The given coroutine must be dead, suspended, | ||
6953 | or be the running coroutine. | ||
6954 | For the running coroutine, | ||
6955 | this function does not return. | ||
6956 | Instead, the resume that (re)started the coroutine returns. | ||
6957 | |||
6958 | For other coroutines, | ||
6959 | in case of error | ||
6865 | (either the original error that stopped the coroutine or | 6960 | (either the original error that stopped the coroutine or |
6866 | errors in closing methods), | 6961 | errors in closing methods), |
6867 | returns @false plus the error object; | 6962 | this function returns @false plus the error object; |
6868 | otherwise returns @true. | 6963 | otherwise ir returns @true. |
6869 | 6964 | ||
6870 | } | 6965 | } |
6871 | 6966 | ||
@@ -7055,7 +7150,7 @@ to search for a @N{C loader}. | |||
7055 | 7150 | ||
7056 | Lua initializes the @N{C path} @Lid{package.cpath} in the same way | 7151 | Lua initializes the @N{C path} @Lid{package.cpath} in the same way |
7057 | it initializes the Lua path @Lid{package.path}, | 7152 | it initializes the Lua path @Lid{package.path}, |
7058 | using the environment variable @defid{LUA_CPATH_5_4}, | 7153 | using the environment variable @defid{LUA_CPATH_5_5}, |
7059 | or the environment variable @defid{LUA_CPATH}, | 7154 | or the environment variable @defid{LUA_CPATH}, |
7060 | or a default path defined in @id{luaconf.h}. | 7155 | or a default path defined in @id{luaconf.h}. |
7061 | 7156 | ||
@@ -7124,7 +7219,7 @@ A string with the path used by @Lid{require} | |||
7124 | to search for a Lua loader. | 7219 | to search for a Lua loader. |
7125 | 7220 | ||
7126 | At start-up, Lua initializes this variable with | 7221 | At start-up, Lua initializes this variable with |
7127 | the value of the environment variable @defid{LUA_PATH_5_4} or | 7222 | the value of the environment variable @defid{LUA_PATH_5_5} or |
7128 | the environment variable @defid{LUA_PATH} or | 7223 | the environment variable @defid{LUA_PATH} or |
7129 | with a default path defined in @id{luaconf.h}, | 7224 | with a default path defined in @id{luaconf.h}, |
7130 | if those environment variables are not defined. | 7225 | if those environment variables are not defined. |
@@ -7495,9 +7590,9 @@ x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) | |||
7495 | end) | 7590 | end) |
7496 | -- x="4+5 = 9" | 7591 | -- x="4+5 = 9" |
7497 | 7592 | ||
7498 | local t = {name="lua", version="5.4"} | 7593 | local t = {name="lua", version="5.5"} |
7499 | x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) | 7594 | x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t) |
7500 | -- x="lua-5.4.tar.gz" | 7595 | -- x="lua-5.5.tar.gz" |
7501 | } | 7596 | } |
7502 | 7597 | ||
7503 | } | 7598 | } |
@@ -9233,7 +9328,7 @@ when the standard input (@id{stdin}) is a terminal, | |||
9233 | and as @T{lua -} otherwise. | 9328 | and as @T{lua -} otherwise. |
9234 | 9329 | ||
9235 | When called without the option @T{-E}, | 9330 | When called without the option @T{-E}, |
9236 | the interpreter checks for an environment variable @defid{LUA_INIT_5_4} | 9331 | the interpreter checks for an environment variable @defid{LUA_INIT_5_5} |
9237 | (or @defid{LUA_INIT} if the versioned name is not defined) | 9332 | (or @defid{LUA_INIT} if the versioned name is not defined) |
9238 | before running any argument. | 9333 | before running any argument. |
9239 | If the variable content has the format @T{@At@rep{filename}}, | 9334 | If the variable content has the format @T{@At@rep{filename}}, |
@@ -9408,7 +9503,12 @@ change between versions. | |||
9408 | @itemize{ | 9503 | @itemize{ |
9409 | 9504 | ||
9410 | @item{ | 9505 | @item{ |
9411 | The control variable in @Rw{for} loops are read only. | 9506 | The word @Rw{global} is a reserved word. |
9507 | Do not use it as a regular name. | ||
9508 | } | ||
9509 | |||
9510 | @item{ | ||
9511 | The control variable in @Rw{for} loops is read only. | ||
9412 | If you need to change it, | 9512 | If you need to change it, |
9413 | declare a local variable with the same name in the loop body. | 9513 | declare a local variable with the same name in the loop body. |
9414 | } | 9514 | } |
@@ -9534,13 +9634,17 @@ and @bnfNter{LiteralString}, see @See{lexical}.) | |||
9534 | @OrNL @Rw{for} namelist @Rw{in} explist @Rw{do} block @Rw{end} | 9634 | @OrNL @Rw{for} namelist @Rw{in} explist @Rw{do} block @Rw{end} |
9535 | @OrNL @Rw{function} funcname funcbody | 9635 | @OrNL @Rw{function} funcname funcbody |
9536 | @OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody | 9636 | @OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody |
9637 | @OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody | ||
9537 | @OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist} | 9638 | @OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist} |
9639 | @OrNL @Rw{global} attnamelist | ||
9640 | @OrNL @Rw{global} @bnfopt{attrib} @bnfter{*} | ||
9538 | } | 9641 | } |
9539 | 9642 | ||
9540 | @producname{attnamelist}@producbody{ | 9643 | @producname{attnamelist}@producbody{ |
9541 | @bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}} | 9644 | @bnfopt{attrib} @bnfNter{Name} @bnfopt{attrib} |
9645 | @bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}} | ||
9542 | 9646 | ||
9543 | @producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}} | 9647 | @producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}} |
9544 | 9648 | ||
9545 | @producname{retstat}@producbody{@Rw{return} | 9649 | @producname{retstat}@producbody{@Rw{return} |
9546 | @bnfopt{explist} @bnfopt{@bnfter{;}}} | 9650 | @bnfopt{explist} @bnfopt{@bnfter{;}}} |
diff --git a/testes/all.lua b/testes/all.lua index 5c7ebfa5..d3e2f123 100755 --- a/testes/all.lua +++ b/testes/all.lua | |||
@@ -2,6 +2,10 @@ | |||
2 | -- $Id: testes/all.lua $ | 2 | -- $Id: testes/all.lua $ |
3 | -- See Copyright Notice in file lua.h | 3 | -- See Copyright Notice in file lua.h |
4 | 4 | ||
5 | global <const> * | ||
6 | |||
7 | global _soft, _port, _nomsg | ||
8 | global T | ||
5 | 9 | ||
6 | local version = "Lua 5.5" | 10 | local version = "Lua 5.5" |
7 | if _VERSION ~= version then | 11 | if _VERSION ~= version then |
@@ -34,7 +38,7 @@ if usertests then | |||
34 | end | 38 | end |
35 | 39 | ||
36 | -- tests should require debug when needed | 40 | -- tests should require debug when needed |
37 | debug = nil | 41 | global debug; debug = nil |
38 | 42 | ||
39 | 43 | ||
40 | if usertests then | 44 | if usertests then |
@@ -71,7 +75,7 @@ do -- ( | |||
71 | 75 | ||
72 | -- track messages for tests not performed | 76 | -- track messages for tests not performed |
73 | local msgs = {} | 77 | local msgs = {} |
74 | function Message (m) | 78 | global function Message (m) |
75 | if not _nomsg then | 79 | if not _nomsg then |
76 | print(m) | 80 | print(m) |
77 | msgs[#msgs+1] = string.sub(m, 3, -3) | 81 | msgs[#msgs+1] = string.sub(m, 3, -3) |
diff --git a/testes/api.lua b/testes/api.lua index 49e3f9b9..b3791654 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
@@ -114,7 +114,7 @@ end | |||
114 | 114 | ||
115 | -- testing warnings | 115 | -- testing warnings |
116 | T.testC([[ | 116 | T.testC([[ |
117 | warningC "#This shold be a" | 117 | warningC "#This should be a" |
118 | warningC " single " | 118 | warningC " single " |
119 | warning "warning" | 119 | warning "warning" |
120 | warningC "#This should be " | 120 | warningC "#This should be " |
@@ -162,7 +162,7 @@ do -- test returning more results than fit in the caller stack | |||
162 | end | 162 | end |
163 | 163 | ||
164 | 164 | ||
165 | do -- testing multipe returns | 165 | do -- testing multiple returns |
166 | local function foo (n) | 166 | local function foo (n) |
167 | if n > 0 then return n, foo(n - 1) end | 167 | if n > 0 then return n, foo(n - 1) end |
168 | end | 168 | end |
@@ -902,7 +902,7 @@ F = function (x) | |||
902 | assert(T.udataval(A) == B) | 902 | assert(T.udataval(A) == B) |
903 | debug.getmetatable(A) -- just access it | 903 | debug.getmetatable(A) -- just access it |
904 | end | 904 | end |
905 | A = x -- ressurect userdata | 905 | A = x -- resurrect userdata |
906 | B = udval | 906 | B = udval |
907 | return 1,2,3 | 907 | return 1,2,3 |
908 | end | 908 | end |
diff --git a/testes/attrib.lua b/testes/attrib.lua index d8b6e0f3..f4156086 100644 --- a/testes/attrib.lua +++ b/testes/attrib.lua | |||
@@ -308,11 +308,11 @@ else | |||
308 | _ENV.x, _ENV.y = nil | 308 | _ENV.x, _ENV.y = nil |
309 | end | 309 | end |
310 | 310 | ||
311 | |||
311 | _ENV = _G | 312 | _ENV = _G |
312 | 313 | ||
313 | 314 | ||
314 | -- testing preload | 315 | -- testing preload |
315 | |||
316 | do | 316 | do |
317 | local p = package | 317 | local p = package |
318 | package = {} | 318 | package = {} |
@@ -331,6 +331,26 @@ do | |||
331 | assert(type(package.path) == "string") | 331 | assert(type(package.path) == "string") |
332 | end | 332 | end |
333 | 333 | ||
334 | |||
335 | do print("testing external strings") | ||
336 | package.cpath = DC"?" | ||
337 | local lib2 = require"lib2-v2" | ||
338 | local t = {} | ||
339 | for _, len in ipairs{0, 10, 39, 40, 41, 1000} do | ||
340 | local str = string.rep("a", len) | ||
341 | local str1 = lib2.newstr(str) | ||
342 | assert(str == str1) | ||
343 | assert(not T or T.hash(str) == T.hash(str1)) | ||
344 | t[str1] = 20; assert(t[str] == 20 and t[str1] == 20) | ||
345 | t[str] = 10; assert(t[str1] == 10) | ||
346 | local tt = {[str1] = str1} | ||
347 | assert(next(tt) == str1 and next(tt, str1) == nil) | ||
348 | assert(tt[str] == str) | ||
349 | local str2 = lib2.newstr(str1) | ||
350 | assert(str == str2 and t[str2] == 10 and tt[str2] == str) | ||
351 | end | ||
352 | end | ||
353 | |||
334 | print('+') | 354 | print('+') |
335 | 355 | ||
336 | end --] | 356 | end --] |
@@ -447,7 +467,7 @@ do | |||
447 | end | 467 | end |
448 | 468 | ||
449 | 469 | ||
450 | -- test of large float/integer indices | 470 | -- test of large float/integer indices |
451 | 471 | ||
452 | -- compute maximum integer where all bits fit in a float | 472 | -- compute maximum integer where all bits fit in a float |
453 | local maxint = math.maxinteger | 473 | local maxint = math.maxinteger |
diff --git a/testes/bwcoercion.lua b/testes/bwcoercion.lua index cd735ab0..0544944d 100644 --- a/testes/bwcoercion.lua +++ b/testes/bwcoercion.lua | |||
@@ -4,7 +4,7 @@ local strsub = string.sub | |||
4 | 4 | ||
5 | local print = print | 5 | local print = print |
6 | 6 | ||
7 | _ENV = nil | 7 | global none |
8 | 8 | ||
9 | -- Try to convert a value to an integer, without assuming any coercion. | 9 | -- Try to convert a value to an integer, without assuming any coercion. |
10 | local function toint (x) | 10 | local function toint (x) |
diff --git a/testes/calls.lua b/testes/calls.lua index 942fad72..0dacb85a 100644 --- a/testes/calls.lua +++ b/testes/calls.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/calls.lua $ | 1 | -- $Id: testes/calls.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | print("testing functions and calls") | 6 | print("testing functions and calls") |
5 | 7 | ||
6 | local debug = require "debug" | 8 | local debug = require "debug" |
@@ -22,7 +24,7 @@ assert(not pcall(type)) | |||
22 | 24 | ||
23 | 25 | ||
24 | -- testing local-function recursion | 26 | -- testing local-function recursion |
25 | fact = false | 27 | global fact = false |
26 | do | 28 | do |
27 | local res = 1 | 29 | local res = 1 |
28 | local function fact (n) | 30 | local function fact (n) |
@@ -63,7 +65,7 @@ a.b.c:f2('k', 12); assert(a.b.c.k == 12) | |||
63 | 65 | ||
64 | print('+') | 66 | print('+') |
65 | 67 | ||
66 | t = nil -- 'declare' t | 68 | global t = nil -- 'declare' t |
67 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end | 69 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end |
68 | 70 | ||
69 | f( -- this line change must be valid | 71 | f( -- this line change must be valid |
@@ -75,7 +77,7 @@ assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a') | |||
75 | 77 | ||
76 | t = nil -- delete 't' | 78 | t = nil -- delete 't' |
77 | 79 | ||
78 | function fat(x) | 80 | global function fat(x) |
79 | if x <= 1 then return 1 | 81 | if x <= 1 then return 1 |
80 | else return x*load("return fat(" .. x-1 .. ")", "")() | 82 | else return x*load("return fat(" .. x-1 .. ")", "")() |
81 | end | 83 | end |
@@ -107,7 +109,7 @@ end | |||
107 | 109 | ||
108 | _G.deep = nil -- "declaration" (used by 'all.lua') | 110 | _G.deep = nil -- "declaration" (used by 'all.lua') |
109 | 111 | ||
110 | function deep (n) | 112 | global function deep (n) |
111 | if n>0 then deep(n-1) end | 113 | if n>0 then deep(n-1) end |
112 | end | 114 | end |
113 | deep(10) | 115 | deep(10) |
@@ -352,7 +354,7 @@ assert(not load(function () return true end)) | |||
352 | 354 | ||
353 | -- small bug | 355 | -- small bug |
354 | local t = {nil, "return ", "3"} | 356 | local t = {nil, "return ", "3"} |
355 | f, msg = load(function () return table.remove(t, 1) end) | 357 | local f, msg = load(function () return table.remove(t, 1) end) |
356 | assert(f() == nil) -- should read the empty chunk | 358 | assert(f() == nil) -- should read the empty chunk |
357 | 359 | ||
358 | -- another small bug (in 5.2.1) | 360 | -- another small bug (in 5.2.1) |
@@ -388,7 +390,8 @@ assert(load("return _ENV", nil, nil, 123)() == 123) | |||
388 | 390 | ||
389 | 391 | ||
390 | -- load when _ENV is not first upvalue | 392 | -- load when _ENV is not first upvalue |
391 | local x; XX = 123 | 393 | global XX; local x |
394 | XX = 123 | ||
392 | local function h () | 395 | local function h () |
393 | local y=x -- use 'x', so that it becomes 1st upvalue | 396 | local y=x -- use 'x', so that it becomes 1st upvalue |
394 | return XX -- global name | 397 | return XX -- global name |
diff --git a/testes/closure.lua b/testes/closure.lua index d3b9f621..0c2e96c0 100644 --- a/testes/closure.lua +++ b/testes/closure.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/closure.lua $ | 1 | -- $Id: testes/closure.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | print "testing closures" | 6 | print "testing closures" |
5 | 7 | ||
6 | do -- bug in 5.4.7 | 8 | do -- bug in 5.4.7 |
diff --git a/testes/code.lua b/testes/code.lua index 111717ce..380ff70c 100644 --- a/testes/code.lua +++ b/testes/code.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/code.lua $ | 1 | -- $Id: testes/code.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | if T==nil then | 6 | if T==nil then |
5 | (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') | 7 | (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') |
6 | return | 8 | return |
@@ -405,8 +407,8 @@ do -- tests for table access in upvalues | |||
405 | end | 407 | end |
406 | 408 | ||
407 | -- de morgan | 409 | -- de morgan |
408 | checkequal(function () local a; if not (a or b) then b=a end end, | 410 | checkequal(function () local a, b; if not (a or b) then b=a end end, |
409 | function () local a; if (not a and not b) then b=a end end) | 411 | function () local a, b; if (not a and not b) then b=a end end) |
410 | 412 | ||
411 | checkequal(function (l) local a; return 0 <= a and a <= l end, | 413 | checkequal(function (l) local a; return 0 <= a and a <= l end, |
412 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) | 414 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) |
@@ -480,5 +482,23 @@ do -- basic check for SETLIST | |||
480 | assert(count == 1) | 482 | assert(count == 1) |
481 | end | 483 | end |
482 | 484 | ||
485 | |||
486 | do print("testing code for integer limits") | ||
487 | local function checkints (n) | ||
488 | local source = string.format( | ||
489 | "local a = {[true] = 0X%x}; return a[true]", n) | ||
490 | local f = assert(load(source)) | ||
491 | checkKlist(f, {n}) | ||
492 | assert(f() == n) | ||
493 | f = load(string.dump(f)) | ||
494 | assert(f() == n) | ||
495 | end | ||
496 | |||
497 | checkints(math.maxinteger) | ||
498 | checkints(math.mininteger) | ||
499 | checkints(-1) | ||
500 | |||
501 | end | ||
502 | |||
483 | print 'OK' | 503 | print 'OK' |
484 | 504 | ||
diff --git a/testes/constructs.lua b/testes/constructs.lua index 3f6d506f..94f670c7 100644 --- a/testes/constructs.lua +++ b/testes/constructs.lua | |||
@@ -60,7 +60,7 @@ assert((x>y) and x or y == 2); | |||
60 | 60 | ||
61 | assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891) | 61 | assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891) |
62 | 62 | ||
63 | do -- testing operators with diffent kinds of constants | 63 | do -- testing operators with different kinds of constants |
64 | -- operands to consider: | 64 | -- operands to consider: |
65 | -- * fit in register | 65 | -- * fit in register |
66 | -- * constant doesn't fit in register | 66 | -- * constant doesn't fit in register |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 17f6ceba..4881d964 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -156,12 +156,12 @@ do | |||
156 | st, msg = coroutine.close(co) | 156 | st, msg = coroutine.close(co) |
157 | assert(st and msg == nil) | 157 | assert(st and msg == nil) |
158 | 158 | ||
159 | local main = coroutine.running() | ||
159 | 160 | ||
160 | -- cannot close the running coroutine | 161 | -- cannot close 'main' |
161 | local st, msg = pcall(coroutine.close, coroutine.running()) | 162 | local st, msg = pcall(coroutine.close, main); |
162 | assert(not st and string.find(msg, "running")) | 163 | assert(not st and string.find(msg, "main")) |
163 | 164 | ||
164 | local main = coroutine.running() | ||
165 | 165 | ||
166 | -- cannot close a "normal" coroutine | 166 | -- cannot close a "normal" coroutine |
167 | ;(coroutine.wrap(function () | 167 | ;(coroutine.wrap(function () |
@@ -169,20 +169,19 @@ do | |||
169 | assert(not st and string.find(msg, "normal")) | 169 | assert(not st and string.find(msg, "normal")) |
170 | end))() | 170 | end))() |
171 | 171 | ||
172 | -- cannot close a coroutine while closing it | 172 | do -- close a coroutine while closing it |
173 | do | ||
174 | local co | 173 | local co |
175 | co = coroutine.create( | 174 | co = coroutine.create( |
176 | function() | 175 | function() |
177 | local x <close> = func2close(function() | 176 | local x <close> = func2close(function() |
178 | coroutine.close(co) -- try to close it again | 177 | coroutine.close(co) -- close it again |
179 | end) | 178 | end) |
180 | coroutine.yield(20) | 179 | coroutine.yield(20) |
181 | end) | 180 | end) |
182 | local st, msg = coroutine.resume(co) | 181 | local st, msg = coroutine.resume(co) |
183 | assert(st and msg == 20) | 182 | assert(st and msg == 20) |
184 | st, msg = coroutine.close(co) | 183 | st, msg = coroutine.close(co) |
185 | assert(not st and string.find(msg, "running coroutine")) | 184 | assert(st and msg == nil) |
186 | end | 185 | end |
187 | 186 | ||
188 | -- to-be-closed variables in coroutines | 187 | -- to-be-closed variables in coroutines |
@@ -289,6 +288,56 @@ do | |||
289 | end | 288 | end |
290 | 289 | ||
291 | 290 | ||
291 | do print("coroutines closing itself") | ||
292 | global <const> coroutine, string, os | ||
293 | global <const> assert, error, pcall | ||
294 | |||
295 | local X = nil | ||
296 | |||
297 | local function new () | ||
298 | return coroutine.create(function (what) | ||
299 | |||
300 | local <close>var = func2close(function (t, err) | ||
301 | if what == "yield" then | ||
302 | coroutine.yield() | ||
303 | elseif what == "error" then | ||
304 | error(200) | ||
305 | else | ||
306 | X = "Ok" | ||
307 | return X | ||
308 | end | ||
309 | end) | ||
310 | |||
311 | -- do an unprotected call so that coroutine becomes non-yieldable | ||
312 | string.gsub("a", "a", function () | ||
313 | assert(not coroutine.isyieldable()) | ||
314 | -- do protected calls while non-yieldable, to add recovery | ||
315 | -- entries (setjmp) to the stack | ||
316 | assert(pcall(pcall, function () | ||
317 | -- 'close' works even while non-yieldable | ||
318 | coroutine.close() -- close itself | ||
319 | os.exit(false) -- not reacheable | ||
320 | end)) | ||
321 | end) | ||
322 | end) | ||
323 | end | ||
324 | |||
325 | local co = new() | ||
326 | local st, msg = coroutine.resume(co, "ret") | ||
327 | assert(st and msg == nil) | ||
328 | assert(X == "Ok") | ||
329 | |||
330 | local co = new() | ||
331 | local st, msg = coroutine.resume(co, "error") | ||
332 | assert(not st and msg == 200) | ||
333 | |||
334 | local co = new() | ||
335 | local st, msg = coroutine.resume(co, "yield") | ||
336 | assert(not st and string.find(msg, "attempt to yield")) | ||
337 | |||
338 | end | ||
339 | |||
340 | |||
292 | -- yielding across C boundaries | 341 | -- yielding across C boundaries |
293 | 342 | ||
294 | local co = coroutine.wrap(function() | 343 | local co = coroutine.wrap(function() |
diff --git a/testes/db.lua b/testes/db.lua index 3c821ab7..0f174f17 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
@@ -349,8 +349,11 @@ end, "crl") | |||
349 | 349 | ||
350 | 350 | ||
351 | function f(a,b) | 351 | function f(a,b) |
352 | -- declare some globals to check that they don't interfere with 'getlocal' | ||
353 | global collectgarbage | ||
352 | collectgarbage() | 354 | collectgarbage() |
353 | local _, x = debug.getlocal(1, 1) | 355 | local _, x = debug.getlocal(1, 1) |
356 | global assert, g, string | ||
354 | local _, y = debug.getlocal(1, 2) | 357 | local _, y = debug.getlocal(1, 2) |
355 | assert(x == a and y == b) | 358 | assert(x == a and y == b) |
356 | assert(debug.setlocal(2, 3, "pera") == "AA".."AA") | 359 | assert(debug.setlocal(2, 3, "pera") == "AA".."AA") |
@@ -386,7 +389,9 @@ function g (...) | |||
386 | f(AAAA,B) | 389 | f(AAAA,B) |
387 | assert(AAAA == "pera" and B == "manga") | 390 | assert(AAAA == "pera" and B == "manga") |
388 | do | 391 | do |
392 | global * | ||
389 | local B = 13 | 393 | local B = 13 |
394 | global<const> assert | ||
390 | local x,y = debug.getlocal(1,5) | 395 | local x,y = debug.getlocal(1,5) |
391 | assert(x == 'B' and y == 13) | 396 | assert(x == 'B' and y == 13) |
392 | end | 397 | end |
@@ -431,7 +436,7 @@ do | |||
431 | assert(a == nil and not b) | 436 | assert(a == nil and not b) |
432 | end | 437 | end |
433 | 438 | ||
434 | -- testing iteraction between multiple values x hooks | 439 | -- testing interaction between multiple values x hooks |
435 | do | 440 | do |
436 | local function f(...) return 3, ... end | 441 | local function f(...) return 3, ... end |
437 | local count = 0 | 442 | local count = 0 |
@@ -587,7 +592,7 @@ t = getupvalues(foo2) | |||
587 | assert(t.a == 1 and t.b == 2 and t.c == 3) | 592 | assert(t.a == 1 and t.b == 2 and t.c == 3) |
588 | assert(debug.setupvalue(foo1, 1, "xuxu") == "b") | 593 | assert(debug.setupvalue(foo1, 1, "xuxu") == "b") |
589 | assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu") | 594 | assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu") |
590 | -- upvalues of C functions are allways "called" "" (the empty string) | 595 | -- upvalues of C functions are always named "" (the empty string) |
591 | assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "") | 596 | assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "") |
592 | 597 | ||
593 | 598 | ||
@@ -701,7 +706,7 @@ assert(debug.traceback(print, 4) == print) | |||
701 | assert(string.find(debug.traceback("hi", 4), "^hi\n")) | 706 | assert(string.find(debug.traceback("hi", 4), "^hi\n")) |
702 | assert(string.find(debug.traceback("hi"), "^hi\n")) | 707 | assert(string.find(debug.traceback("hi"), "^hi\n")) |
703 | assert(not string.find(debug.traceback("hi"), "'debug.traceback'")) | 708 | assert(not string.find(debug.traceback("hi"), "'debug.traceback'")) |
704 | assert(string.find(debug.traceback("hi", 0), "'debug.traceback'")) | 709 | assert(string.find(debug.traceback("hi", 0), "'traceback'")) |
705 | assert(string.find(debug.traceback(), "^stack traceback:\n")) | 710 | assert(string.find(debug.traceback(), "^stack traceback:\n")) |
706 | 711 | ||
707 | do -- C-function names in traceback | 712 | do -- C-function names in traceback |
@@ -829,7 +834,7 @@ end | |||
829 | 834 | ||
830 | co = coroutine.create(function (x) f(x) end) | 835 | co = coroutine.create(function (x) f(x) end) |
831 | a, b = coroutine.resume(co, 3) | 836 | a, b = coroutine.resume(co, 3) |
832 | t = {"'coroutine.yield'", "'f'", "in function <"} | 837 | t = {"'yield'", "'f'", "in function <"} |
833 | while coroutine.status(co) == "suspended" do | 838 | while coroutine.status(co) == "suspended" do |
834 | checktraceback(co, t) | 839 | checktraceback(co, t) |
835 | a, b = coroutine.resume(co) | 840 | a, b = coroutine.resume(co) |
@@ -839,7 +844,7 @@ t[1] = "'error'" | |||
839 | checktraceback(co, t) | 844 | checktraceback(co, t) |
840 | 845 | ||
841 | 846 | ||
842 | -- test acessing line numbers of a coroutine from a resume inside | 847 | -- test accessing line numbers of a coroutine from a resume inside |
843 | -- a C function (this is a known bug in Lua 5.0) | 848 | -- a C function (this is a known bug in Lua 5.0) |
844 | 849 | ||
845 | local function g(x) | 850 | local function g(x) |
@@ -966,9 +971,9 @@ local debug = require'debug' | |||
966 | local a = 12 -- a local variable | 971 | local a = 12 -- a local variable |
967 | 972 | ||
968 | local n, v = debug.getlocal(1, 1) | 973 | local n, v = debug.getlocal(1, 1) |
969 | assert(n == "(temporary)" and v == debug) -- unkown name but known value | 974 | assert(n == "(temporary)" and v == debug) -- unknown name but known value |
970 | n, v = debug.getlocal(1, 2) | 975 | n, v = debug.getlocal(1, 2) |
971 | assert(n == "(temporary)" and v == 12) -- unkown name but known value | 976 | assert(n == "(temporary)" and v == 12) -- unknown name but known value |
972 | 977 | ||
973 | -- a function with an upvalue | 978 | -- a function with an upvalue |
974 | local f = function () local x; return a end | 979 | local f = function () local x; return a end |
@@ -1018,7 +1023,7 @@ do -- bug in 5.4.0: line hooks in stripped code | |||
1018 | line = l | 1023 | line = l |
1019 | end, "l") | 1024 | end, "l") |
1020 | assert(s() == 2); debug.sethook(nil) | 1025 | assert(s() == 2); debug.sethook(nil) |
1021 | assert(line == nil) -- hook called withoug debug info for 1st instruction | 1026 | assert(line == nil) -- hook called without debug info for 1st instruction |
1022 | end | 1027 | end |
1023 | 1028 | ||
1024 | do -- tests for 'source' in binary dumps | 1029 | do -- tests for 'source' in binary dumps |
diff --git a/testes/errors.lua b/testes/errors.lua index c1c40fec..4230a352 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
@@ -303,14 +303,14 @@ do | |||
303 | local f = function (a) return a + 1 end | 303 | local f = function (a) return a + 1 end |
304 | f = assert(load(string.dump(f, true))) | 304 | f = assert(load(string.dump(f, true))) |
305 | assert(f(3) == 4) | 305 | assert(f(3) == 4) |
306 | checkerr("^%?:%-1:", f, {}) | 306 | checkerr("^%?:%?:", f, {}) |
307 | 307 | ||
308 | -- code with a move to a local var ('OP_MOV A B' with A<B) | 308 | -- code with a move to a local var ('OP_MOV A B' with A<B) |
309 | f = function () local a; a = {}; return a + 2 end | 309 | f = function () local a; a = {}; return a + 2 end |
310 | -- no debug info (so that 'a' is unknown) | 310 | -- no debug info (so that 'a' is unknown) |
311 | f = assert(load(string.dump(f, true))) | 311 | f = assert(load(string.dump(f, true))) |
312 | -- symbolic execution should not get lost | 312 | -- symbolic execution should not get lost |
313 | checkerr("^%?:%-1:.*table value", f) | 313 | checkerr("^%?:%?:.*table value", f) |
314 | end | 314 | end |
315 | 315 | ||
316 | 316 | ||
@@ -489,6 +489,14 @@ if not b then | |||
489 | end | 489 | end |
490 | end]], 5) | 490 | end]], 5) |
491 | 491 | ||
492 | lineerror([[ | ||
493 | _ENV = 1 | ||
494 | global function foo () | ||
495 | local a = 10 | ||
496 | return a | ||
497 | end | ||
498 | ]], 2) | ||
499 | |||
492 | 500 | ||
493 | -- bug in 5.4.0 | 501 | -- bug in 5.4.0 |
494 | lineerror([[ | 502 | lineerror([[ |
@@ -507,7 +515,7 @@ end | |||
507 | 515 | ||
508 | 516 | ||
509 | if not _soft then | 517 | if not _soft then |
510 | -- several tests that exaust the Lua stack | 518 | -- several tests that exhaust the Lua stack |
511 | collectgarbage() | 519 | collectgarbage() |
512 | print"testing stack overflow" | 520 | print"testing stack overflow" |
513 | local C = 0 | 521 | local C = 0 |
@@ -734,7 +742,7 @@ assert(c > 255 and string.find(b, "too many upvalues") and | |||
734 | 742 | ||
735 | -- local variables | 743 | -- local variables |
736 | s = "\nfunction foo ()\n local " | 744 | s = "\nfunction foo ()\n local " |
737 | for j = 1,300 do | 745 | for j = 1,200 do |
738 | s = s.."a"..j..", " | 746 | s = s.."a"..j..", " |
739 | end | 747 | end |
740 | s = s.."b\n" | 748 | s = s.."b\n" |
diff --git a/testes/files.lua b/testes/files.lua index 53edf314..7146ac7c 100644 --- a/testes/files.lua +++ b/testes/files.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/files.lua $ | 1 | -- $Id: testes/files.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | local debug = require "debug" | 6 | local debug = require "debug" |
5 | 7 | ||
6 | local maxint = math.maxinteger | 8 | local maxint = math.maxinteger |
@@ -478,7 +480,7 @@ do print("testing flush") | |||
478 | end | 480 | end |
479 | 481 | ||
480 | 482 | ||
481 | -- test for multipe arguments in 'lines' | 483 | -- test for multiple arguments in 'lines' |
482 | io.output(file); io.write"0123456789\n":close() | 484 | io.output(file); io.write"0123456789\n":close() |
483 | for a,b in io.lines(file, 1, 1) do | 485 | for a,b in io.lines(file, 1, 1) do |
484 | if a == "\n" then assert(not b) | 486 | if a == "\n" then assert(not b) |
@@ -713,7 +715,7 @@ do | |||
713 | end | 715 | end |
714 | 716 | ||
715 | 717 | ||
716 | if T and T.nonblock then | 718 | if T and T.nonblock and not _port then |
717 | print("testing failed write") | 719 | print("testing failed write") |
718 | 720 | ||
719 | -- unable to write anything to /dev/full | 721 | -- unable to write anything to /dev/full |
@@ -838,13 +840,13 @@ assert(os.date("!\0\0") == "\0\0") | |||
838 | local x = string.rep("a", 10000) | 840 | local x = string.rep("a", 10000) |
839 | assert(os.date(x) == x) | 841 | assert(os.date(x) == x) |
840 | local t = os.time() | 842 | local t = os.time() |
841 | D = os.date("*t", t) | 843 | global D = os.date("*t", t) |
842 | assert(os.date(string.rep("%d", 1000), t) == | 844 | assert(os.date(string.rep("%d", 1000), t) == |
843 | string.rep(os.date("%d", t), 1000)) | 845 | string.rep(os.date("%d", t), 1000)) |
844 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) | 846 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) |
845 | 847 | ||
846 | local function checkDateTable (t) | 848 | local function checkDateTable (t) |
847 | _G.D = os.date("*t", t) | 849 | D = os.date("*t", t) |
848 | assert(os.time(D) == t) | 850 | assert(os.time(D) == t) |
849 | load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and | 851 | load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and |
850 | D.hour==%H and D.min==%M and D.sec==%S and | 852 | D.hour==%H and D.min==%M and D.sec==%S and |
diff --git a/testes/gc.lua b/testes/gc.lua index 0693837c..62713dac 100644 --- a/testes/gc.lua +++ b/testes/gc.lua | |||
@@ -288,6 +288,21 @@ x,y,z=nil | |||
288 | collectgarbage() | 288 | collectgarbage() |
289 | assert(next(a) == string.rep('$', 11)) | 289 | assert(next(a) == string.rep('$', 11)) |
290 | 290 | ||
291 | do -- invalid mode | ||
292 | local a = setmetatable({}, {__mode = 34}) | ||
293 | collectgarbage() | ||
294 | end | ||
295 | |||
296 | |||
297 | if T then -- bug since 5.3: all-weak tables are not being revisited | ||
298 | T.gcstate("propagate") | ||
299 | local t = setmetatable({}, {__mode = "kv"}) | ||
300 | T.gcstate("enteratomic") -- 't' was visited | ||
301 | setmetatable(t, {__mode = "kv"}) | ||
302 | T.gcstate("pause") -- its new metatable is not being visited | ||
303 | assert(getmetatable(t).__mode == "kv") | ||
304 | end | ||
305 | |||
291 | 306 | ||
292 | -- 'bug' in 5.1 | 307 | -- 'bug' in 5.1 |
293 | a = {} | 308 | a = {} |
@@ -446,8 +461,8 @@ do -- tests for string keys in weak tables | |||
446 | local m = collectgarbage("count") -- current memory | 461 | local m = collectgarbage("count") -- current memory |
447 | local a = setmetatable({}, {__mode = "kv"}) | 462 | local a = setmetatable({}, {__mode = "kv"}) |
448 | a[string.rep("a", 2^22)] = 25 -- long string key -> number value | 463 | a[string.rep("a", 2^22)] = 25 -- long string key -> number value |
449 | a[string.rep("b", 2^22)] = {} -- long string key -> colectable value | 464 | a[string.rep("b", 2^22)] = {} -- long string key -> collectable value |
450 | a[{}] = 14 -- colectable key | 465 | a[{}] = 14 -- collectable key |
451 | collectgarbage() | 466 | collectgarbage() |
452 | local k, v = next(a) -- string key with number value preserved | 467 | local k, v = next(a) -- string key with number value preserved |
453 | assert(k == string.rep("a", 2^22) and v == 25) | 468 | assert(k == string.rep("a", 2^22) and v == 25) |
@@ -459,7 +474,7 @@ do -- tests for string keys in weak tables | |||
459 | assert(next(a) == nil) | 474 | assert(next(a) == nil) |
460 | -- make sure will not try to compare with dead key | 475 | -- make sure will not try to compare with dead key |
461 | assert(a[string.rep("b", 100)] == undef) | 476 | assert(a[string.rep("b", 100)] == undef) |
462 | assert(collectgarbage("count") <= m + 1) -- eveything collected | 477 | assert(collectgarbage("count") <= m + 1) -- everything collected |
463 | end | 478 | end |
464 | 479 | ||
465 | 480 | ||
@@ -524,7 +539,7 @@ do | |||
524 | local co = coroutine.create(f) | 539 | local co = coroutine.create(f) |
525 | assert(coroutine.resume(co, co)) | 540 | assert(coroutine.resume(co, co)) |
526 | end | 541 | end |
527 | -- Now, thread and closure are not reacheable any more. | 542 | -- Now, thread and closure are not reachable any more. |
528 | collectgarbage() | 543 | collectgarbage() |
529 | assert(collected) | 544 | assert(collected) |
530 | collectgarbage("restart") | 545 | collectgarbage("restart") |
@@ -644,7 +659,7 @@ do | |||
644 | assert(getmetatable(o) == tt) | 659 | assert(getmetatable(o) == tt) |
645 | -- create new objects during GC | 660 | -- create new objects during GC |
646 | local a = 'xuxu'..(10+3)..'joao', {} | 661 | local a = 'xuxu'..(10+3)..'joao', {} |
647 | ___Glob = o -- ressurrect object! | 662 | ___Glob = o -- resurrect object! |
648 | setmetatable({}, tt) -- creates a new one with same metatable | 663 | setmetatable({}, tt) -- creates a new one with same metatable |
649 | print(">>> closing state " .. "<<<\n") | 664 | print(">>> closing state " .. "<<<\n") |
650 | end | 665 | end |
diff --git a/testes/goto.lua b/testes/goto.lua index eca68516..3310314d 100644 --- a/testes/goto.lua +++ b/testes/goto.lua | |||
@@ -1,6 +1,12 @@ | |||
1 | -- $Id: testes/goto.lua $ | 1 | -- $Id: testes/goto.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global<const> require | ||
5 | global<const> print, load, assert, string, setmetatable | ||
6 | global<const> collectgarbage, error | ||
7 | |||
8 | print("testing goto and global declarations") | ||
9 | |||
4 | collectgarbage() | 10 | collectgarbage() |
5 | 11 | ||
6 | local function errmsg (code, m) | 12 | local function errmsg (code, m) |
@@ -17,15 +23,18 @@ errmsg([[ ::l1:: ::l1:: ]], "label 'l1'") | |||
17 | errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'") | 23 | errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'") |
18 | 24 | ||
19 | 25 | ||
20 | -- undefined label | ||
21 | errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'") | ||
22 | 26 | ||
23 | -- jumping over variable definition | 27 | -- jumping over variable declaration |
28 | errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "scope of 'aa'") | ||
29 | |||
30 | errmsg([[ goto l2; global *; ::l1:: ::l2:: print(3) ]], "scope of '*'") | ||
31 | |||
24 | errmsg([[ | 32 | errmsg([[ |
25 | do local bb, cc; goto l1; end | 33 | do local bb, cc; goto l1; end |
26 | local aa | 34 | local aa |
27 | ::l1:: print(3) | 35 | ::l1:: print(3) |
28 | ]], "local 'aa'") | 36 | ]], "scope of 'aa'") |
37 | |||
29 | 38 | ||
30 | -- jumping into a block | 39 | -- jumping into a block |
31 | errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'") | 40 | errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'") |
@@ -38,7 +47,7 @@ errmsg([[ | |||
38 | local xuxu = 10 | 47 | local xuxu = 10 |
39 | ::cont:: | 48 | ::cont:: |
40 | until xuxu < x | 49 | until xuxu < x |
41 | ]], "local 'xuxu'") | 50 | ]], "scope of 'xuxu'") |
42 | 51 | ||
43 | -- simple gotos | 52 | -- simple gotos |
44 | local x | 53 | local x |
@@ -252,6 +261,8 @@ assert(testG(5) == 10) | |||
252 | 261 | ||
253 | do -- test goto's around to-be-closed variable | 262 | do -- test goto's around to-be-closed variable |
254 | 263 | ||
264 | global * | ||
265 | |||
255 | -- set 'var' and return an object that will reset 'var' when | 266 | -- set 'var' and return an object that will reset 'var' when |
256 | -- it goes out of scope | 267 | -- it goes out of scope |
257 | local function newobj (var) | 268 | local function newobj (var) |
@@ -263,16 +274,16 @@ do -- test goto's around to-be-closed variable | |||
263 | 274 | ||
264 | goto L1 | 275 | goto L1 |
265 | 276 | ||
266 | ::L4:: assert(not X); goto L5 -- varX dead here | 277 | ::L4:: assert(not varX); goto L5 -- varX dead here |
267 | 278 | ||
268 | ::L1:: | 279 | ::L1:: |
269 | local varX <close> = newobj("X") | 280 | local varX <close> = newobj("X") |
270 | assert(X); goto L2 -- varX alive here | 281 | assert(varX); goto L2 -- varX alive here |
271 | 282 | ||
272 | ::L3:: | 283 | ::L3:: |
273 | assert(X); goto L4 -- varX alive here | 284 | assert(varX); goto L4 -- varX alive here |
274 | 285 | ||
275 | ::L2:: assert(X); goto L3 -- varX alive here | 286 | ::L2:: assert(varX); goto L3 -- varX alive here |
276 | 287 | ||
277 | ::L5:: -- return | 288 | ::L5:: -- return |
278 | end | 289 | end |
@@ -280,7 +291,146 @@ end | |||
280 | 291 | ||
281 | 292 | ||
282 | foo() | 293 | foo() |
283 | -------------------------------------------------------------------------------- | 294 | -------------------------------------------------------------------------- |
295 | |||
296 | local function checkerr (code, err) | ||
297 | local st, msg = load(code) | ||
298 | assert(not st and string.find(msg, err)) | ||
299 | end | ||
300 | |||
301 | do | ||
302 | global T<const> | ||
303 | |||
304 | -- globals must be declared, after a global declaration | ||
305 | checkerr("global none; X = 1", "variable 'X'") | ||
306 | checkerr("global none; function XX() end", "variable 'XX'") | ||
284 | 307 | ||
308 | -- global variables cannot be to-be-closed | ||
309 | checkerr("global X<close>", "cannot be") | ||
310 | checkerr("global <close> *", "cannot be") | ||
311 | |||
312 | do | ||
313 | local X = 10 | ||
314 | do global X; X = 20 end | ||
315 | assert(X == 10) -- local X | ||
316 | end | ||
317 | assert(_ENV.X == 20) -- global X | ||
318 | |||
319 | -- '_ENV' cannot be global | ||
320 | checkerr("global _ENV, a; a = 10", "variable 'a'") | ||
321 | |||
322 | -- global declarations inside functions | ||
323 | checkerr([[ | ||
324 | global none | ||
325 | local function foo () XXX = 1 end --< ERROR]], "variable 'XXX'") | ||
326 | |||
327 | if not T then -- when not in "test mode", "global" isn't reserved | ||
328 | assert(load("global = 1; return global")() == 1) | ||
329 | print " ('global' is not a reserved word)" | ||
330 | else | ||
331 | -- "global" reserved, cannot be used as a variable | ||
332 | assert(not load("global = 1; return global")) | ||
333 | end | ||
334 | |||
335 | local foo = 20 | ||
336 | do | ||
337 | global function foo (x) | ||
338 | if x == 0 then return 1 else return 2 * foo(x - 1) end | ||
339 | end | ||
340 | assert(foo == _ENV.foo and foo(4) == 16) | ||
341 | end | ||
342 | assert(_ENV.foo(4) == 16) | ||
343 | assert(foo == 20) -- local one is in context here | ||
344 | |||
345 | do | ||
346 | global foo; | ||
347 | function foo (x) return end -- Ok after declaration | ||
348 | end | ||
349 | |||
350 | checkerr([[ | ||
351 | global<const> foo; | ||
352 | function foo (x) return end -- ERROR: foo is read-only | ||
353 | ]], "assign to const variable 'foo'") | ||
354 | |||
355 | checkerr([[ | ||
356 | global foo <const>; | ||
357 | function foo (x) -- ERROR: foo is read-only | ||
358 | return | ||
359 | end | ||
360 | ]], "%:2%:") -- correct line in error message | ||
361 | |||
362 | checkerr([[ | ||
363 | global<const> *; | ||
364 | print(X) -- Ok to use | ||
365 | Y = 1 -- ERROR | ||
366 | ]], "assign to const variable 'Y'") | ||
367 | |||
368 | checkerr([[ | ||
369 | global *; | ||
370 | Y = X -- Ok to use | ||
371 | global<const> *; | ||
372 | Y = 1 -- ERROR | ||
373 | ]], "assign to const variable 'Y'") | ||
374 | |||
375 | global * | ||
376 | Y = 10 | ||
377 | assert(_ENV.Y == 10) | ||
378 | global<const> * | ||
379 | local x = Y | ||
380 | global * | ||
381 | Y = x + Y | ||
382 | assert(_ENV.Y == 20) | ||
383 | Y = nil | ||
384 | end | ||
385 | |||
386 | |||
387 | do -- Ok to declare hundreds of globals | ||
388 | global table | ||
389 | local code = {} | ||
390 | for i = 1, 1000 do | ||
391 | code[#code + 1] = ";global x" .. i | ||
392 | end | ||
393 | code[#code + 1] = "; return x990" | ||
394 | code = table.concat(code) | ||
395 | _ENV.x990 = 11 | ||
396 | assert(load(code)() == 11) | ||
397 | _ENV.x990 = nil | ||
398 | end | ||
399 | |||
400 | do -- mixing lots of global/local declarations | ||
401 | global table | ||
402 | local code = {} | ||
403 | for i = 1, 200 do | ||
404 | code[#code + 1] = ";global x" .. i | ||
405 | code[#code + 1] = ";local y" .. i .. "=" .. (2*i) | ||
406 | end | ||
407 | code[#code + 1] = "; return x200 + y200" | ||
408 | code = table.concat(code) | ||
409 | _ENV.x200 = 11 | ||
410 | assert(assert(load(code))() == 2*200 + 11) | ||
411 | _ENV.x200 = nil | ||
412 | end | ||
413 | |||
414 | do print "testing initialization in global declarations" | ||
415 | global<const> a, b, c = 10, 20, 30 | ||
416 | assert(_ENV.a == 10 and b == 20 and c == 30) | ||
417 | |||
418 | global<const> a, b, c = 10 | ||
419 | assert(_ENV.a == 10 and b == nil and c == nil) | ||
420 | |||
421 | global table | ||
422 | global a, b, c, d = table.unpack{1, 2, 3, 6, 5} | ||
423 | assert(_ENV.a == 1 and b == 2 and c == 3 and d == 6) | ||
424 | |||
425 | local a, b = 100, 200 | ||
426 | do | ||
427 | global a, b = a, b | ||
428 | end | ||
429 | assert(_ENV.a == 100 and _ENV.b == 200) | ||
430 | |||
431 | |||
432 | _ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals | ||
433 | end | ||
285 | 434 | ||
286 | print'OK' | 435 | print'OK' |
436 | |||
diff --git a/testes/libs/lib22.c b/testes/libs/lib22.c index 8e656502..b377cce5 100644 --- a/testes/libs/lib22.c +++ b/testes/libs/lib22.c | |||
@@ -1,3 +1,7 @@ | |||
1 | /* implementation for lib2-v2 */ | ||
2 | |||
3 | #include <string.h> | ||
4 | |||
1 | #include "lua.h" | 5 | #include "lua.h" |
2 | #include "lauxlib.h" | 6 | #include "lauxlib.h" |
3 | 7 | ||
@@ -8,8 +12,54 @@ static int id (lua_State *L) { | |||
8 | } | 12 | } |
9 | 13 | ||
10 | 14 | ||
15 | struct STR { | ||
16 | void *ud; | ||
17 | lua_Alloc allocf; | ||
18 | }; | ||
19 | |||
20 | |||
21 | static void *t_freestr (void *ud, void *ptr, size_t osize, size_t nsize) { | ||
22 | struct STR *blk = (struct STR*)ptr - 1; | ||
23 | blk->allocf(blk->ud, blk, sizeof(struct STR) + osize, 0); | ||
24 | return NULL; | ||
25 | } | ||
26 | |||
27 | |||
28 | static int newstr (lua_State *L) { | ||
29 | size_t len; | ||
30 | const char *str = luaL_checklstring(L, 1, &len); | ||
31 | void *ud; | ||
32 | lua_Alloc allocf = lua_getallocf(L, &ud); | ||
33 | struct STR *blk = (struct STR*)allocf(ud, NULL, 0, | ||
34 | len + 1 + sizeof(struct STR)); | ||
35 | if (blk == NULL) { /* allocation error? */ | ||
36 | lua_pushliteral(L, "not enough memory"); | ||
37 | lua_error(L); /* raise a memory error */ | ||
38 | } | ||
39 | blk->ud = ud; blk->allocf = allocf; | ||
40 | memcpy(blk + 1, str, len + 1); | ||
41 | lua_pushexternalstring(L, (char *)(blk + 1), len, t_freestr, L); | ||
42 | return 1; | ||
43 | } | ||
44 | |||
45 | |||
46 | /* | ||
47 | ** Create an external string and keep it in the registry, so that it | ||
48 | ** will test that the library code is still available (to deallocate | ||
49 | ** this string) when closing the state. | ||
50 | */ | ||
51 | static void initstr (lua_State *L) { | ||
52 | lua_pushcfunction(L, newstr); | ||
53 | lua_pushstring(L, | ||
54 | "012345678901234567890123456789012345678901234567890123456789"); | ||
55 | lua_call(L, 1, 1); /* call newstr("0123...") */ | ||
56 | luaL_ref(L, LUA_REGISTRYINDEX); /* keep string in the registry */ | ||
57 | } | ||
58 | |||
59 | |||
11 | static const struct luaL_Reg funcs[] = { | 60 | static const struct luaL_Reg funcs[] = { |
12 | {"id", id}, | 61 | {"id", id}, |
62 | {"newstr", newstr}, | ||
13 | {NULL, NULL} | 63 | {NULL, NULL} |
14 | }; | 64 | }; |
15 | 65 | ||
@@ -18,6 +68,7 @@ LUAMOD_API int luaopen_lib2 (lua_State *L) { | |||
18 | lua_settop(L, 2); | 68 | lua_settop(L, 2); |
19 | lua_setglobal(L, "y"); /* y gets 2nd parameter */ | 69 | lua_setglobal(L, "y"); /* y gets 2nd parameter */ |
20 | lua_setglobal(L, "x"); /* x gets 1st parameter */ | 70 | lua_setglobal(L, "x"); /* x gets 1st parameter */ |
71 | initstr(L); | ||
21 | luaL_newlib(L, funcs); | 72 | luaL_newlib(L, funcs); |
22 | return 1; | 73 | return 1; |
23 | } | 74 | } |
diff --git a/testes/literals.lua b/testes/literals.lua index 28995718..336ef585 100644 --- a/testes/literals.lua +++ b/testes/literals.lua | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | print('testing scanner') | 4 | print('testing scanner') |
5 | 5 | ||
6 | global <const> * | ||
7 | |||
6 | local debug = require "debug" | 8 | local debug = require "debug" |
7 | 9 | ||
8 | 10 | ||
diff --git a/testes/locals.lua b/testes/locals.lua index ccea0a14..02f41980 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/locals.lua $ | 1 | -- $Id: testes/locals.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | print('testing local variables and environments') | 6 | print('testing local variables and environments') |
5 | 7 | ||
6 | local debug = require"debug" | 8 | local debug = require"debug" |
@@ -39,9 +41,11 @@ f = nil | |||
39 | local f | 41 | local f |
40 | local x = 1 | 42 | local x = 1 |
41 | 43 | ||
42 | a = nil | 44 | do |
43 | load('local a = {}')() | 45 | global a; a = nil |
44 | assert(a == nil) | 46 | load('local a = {}')() |
47 | assert(a == nil) | ||
48 | end | ||
45 | 49 | ||
46 | function f (a) | 50 | function f (a) |
47 | local _1, _2, _3, _4, _5 | 51 | local _1, _2, _3, _4, _5 |
@@ -154,7 +158,7 @@ local _ENV = (function (...) return ... end)(_G, dummy) -- { | |||
154 | do local _ENV = {assert=assert}; assert(true) end | 158 | do local _ENV = {assert=assert}; assert(true) end |
155 | local mt = {_G = _G} | 159 | local mt = {_G = _G} |
156 | local foo,x | 160 | local foo,x |
157 | A = false -- "declare" A | 161 | global A; A = false -- "declare" A |
158 | do local _ENV = mt | 162 | do local _ENV = mt |
159 | function foo (x) | 163 | function foo (x) |
160 | A = x | 164 | A = x |
@@ -177,20 +181,27 @@ assert(x==20) | |||
177 | A = nil | 181 | A = nil |
178 | 182 | ||
179 | 183 | ||
180 | do -- constants | 184 | do print("testing local constants") |
185 | global assert<const>, load, string, X | ||
186 | X = 1 -- not a constant | ||
181 | local a<const>, b, c<const> = 10, 20, 30 | 187 | local a<const>, b, c<const> = 10, 20, 30 |
182 | b = a + c + b -- 'b' is not constant | 188 | b = a + c + b -- 'b' is not constant |
183 | assert(a == 10 and b == 60 and c == 30) | 189 | assert(a == 10 and b == 60 and c == 30) |
190 | |||
184 | local function checkro (name, code) | 191 | local function checkro (name, code) |
185 | local st, msg = load(code) | 192 | local st, msg = load(code) |
186 | local gab = string.format("attempt to assign to const variable '%s'", name) | 193 | local gab = string.format("attempt to assign to const variable '%s'", name) |
187 | assert(not st and string.find(msg, gab)) | 194 | assert(not st and string.find(msg, gab)) |
188 | end | 195 | end |
196 | |||
189 | checkro("y", "local x, y <const>, z = 10, 20, 30; x = 11; y = 12") | 197 | checkro("y", "local x, y <const>, z = 10, 20, 30; x = 11; y = 12") |
190 | checkro("x", "local x <const>, y, z <const> = 10, 20, 30; x = 11") | 198 | checkro("x", "local x <const>, y, z <const> = 10, 20, 30; x = 11") |
191 | checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11") | 199 | checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11") |
192 | checkro("foo", "local foo <const> = 10; function foo() end") | 200 | checkro("foo", "local<const> foo = 10; function foo() end") |
193 | checkro("foo", "local foo <const> = {}; function foo() end") | 201 | checkro("foo", "local<const> foo <const> = {}; function foo() end") |
202 | checkro("foo", "global<const> foo <const>; function foo() end") | ||
203 | checkro("XX", "global XX <const>; XX = 10") | ||
204 | checkro("XX", "local _ENV; global XX <const>; XX = 10") | ||
194 | 205 | ||
195 | checkro("z", [[ | 206 | checkro("z", [[ |
196 | local a, z <const>, b = 10; | 207 | local a, z <const>, b = 10; |
@@ -201,11 +212,26 @@ do -- constants | |||
201 | local a, var1 <const> = 10; | 212 | local a, var1 <const> = 10; |
202 | function foo() a = 20; z = function () var1 = 12; end end | 213 | function foo() a = 20; z = function () var1 = 12; end end |
203 | ]]) | 214 | ]]) |
215 | |||
216 | checkro("var1", [[ | ||
217 | global a, var1 <const>, z; | ||
218 | local function foo() a = 20; z = function () var1 = 12; end end | ||
219 | ]]) | ||
204 | end | 220 | end |
205 | 221 | ||
206 | 222 | ||
223 | |||
207 | print"testing to-be-closed variables" | 224 | print"testing to-be-closed variables" |
208 | 225 | ||
226 | |||
227 | do | ||
228 | local st, msg = load("local <close> a, b") | ||
229 | assert(not st and string.find(msg, "multiple")) | ||
230 | |||
231 | local st, msg = load("local a<close>, b<close>") | ||
232 | assert(not st and string.find(msg, "multiple")) | ||
233 | end | ||
234 | |||
209 | local function stack(n) n = ((n == 0) or stack(n - 1)) end | 235 | local function stack(n) n = ((n == 0) or stack(n - 1)) end |
210 | 236 | ||
211 | local function func2close (f, x, y) | 237 | local function func2close (f, x, y) |
@@ -1162,7 +1188,7 @@ do | |||
1162 | local function open (x) | 1188 | local function open (x) |
1163 | numopen = numopen + 1 | 1189 | numopen = numopen + 1 |
1164 | return | 1190 | return |
1165 | function () -- iteraction function | 1191 | function () -- iteration function |
1166 | x = x - 1 | 1192 | x = x - 1 |
1167 | if x > 0 then return x end | 1193 | if x > 0 then return x end |
1168 | end, | 1194 | end, |
diff --git a/testes/main.lua b/testes/main.lua index bf3c898e..dc48dc48 100644 --- a/testes/main.lua +++ b/testes/main.lua | |||
@@ -90,7 +90,7 @@ prepfile[[ | |||
90 | 1, a | 90 | 1, a |
91 | ) | 91 | ) |
92 | ]] | 92 | ]] |
93 | RUN('lua - < %s > %s', prog, out) | 93 | RUN('lua - -- < %s > %s', prog, out) |
94 | checkout("1\tnil\n") | 94 | checkout("1\tnil\n") |
95 | 95 | ||
96 | RUN('echo "print(10)\nprint(2)\n" | lua > %s', out) | 96 | RUN('echo "print(10)\nprint(2)\n" | lua > %s', out) |
@@ -133,7 +133,7 @@ checkout("-h\n") | |||
133 | prepfile("print(package.path)") | 133 | prepfile("print(package.path)") |
134 | 134 | ||
135 | -- test LUA_PATH | 135 | -- test LUA_PATH |
136 | RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out) | 136 | RUN('env LUA_INIT= LUA_PATH=x lua -- %s > %s', prog, out) |
137 | checkout("x\n") | 137 | checkout("x\n") |
138 | 138 | ||
139 | -- test LUA_PATH_version | 139 | -- test LUA_PATH_version |
@@ -226,7 +226,7 @@ RUN("lua -l 'str=string' '-lm=math' -e 'print(m.sin(0))' %s > %s", prog, out) | |||
226 | checkout("0.0\nALO ALO\t20\n") | 226 | checkout("0.0\nALO ALO\t20\n") |
227 | 227 | ||
228 | 228 | ||
229 | -- test module names with version sufix ("libs/lib2-v2") | 229 | -- test module names with version suffix ("libs/lib2-v2") |
230 | RUN("env LUA_CPATH='./libs/?.so' lua -l lib2-v2 -e 'print(lib2.id())' > %s", | 230 | RUN("env LUA_CPATH='./libs/?.so' lua -l lib2-v2 -e 'print(lib2.id())' > %s", |
231 | out) | 231 | out) |
232 | checkout("true\n") | 232 | checkout("true\n") |
@@ -347,7 +347,7 @@ checkout("a\n") | |||
347 | RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out) | 347 | RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out) |
348 | checkout("1\n3\n") | 348 | checkout("1\n3\n") |
349 | 349 | ||
350 | -- test iteractive mode | 350 | -- test interactive mode |
351 | prepfile[[ | 351 | prepfile[[ |
352 | (6*2-6) -- === | 352 | (6*2-6) -- === |
353 | a = | 353 | a = |
@@ -358,7 +358,7 @@ RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) | |||
358 | checkprogout("6\n10\n10\n\n") | 358 | checkprogout("6\n10\n10\n\n") |
359 | 359 | ||
360 | prepfile("a = [[b\nc\nd\ne]]\na") | 360 | prepfile("a = [[b\nc\nd\ne]]\na") |
361 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) | 361 | RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i -- < %s > %s]], prog, out) |
362 | checkprogout("b\nc\nd\ne\n\n") | 362 | checkprogout("b\nc\nd\ne\n\n") |
363 | 363 | ||
364 | -- input interrupted in continuation line | 364 | -- input interrupted in continuation line |
@@ -488,12 +488,13 @@ assert(not os.remove(out)) | |||
488 | -- invalid options | 488 | -- invalid options |
489 | NoRun("unrecognized option '-h'", "lua -h") | 489 | NoRun("unrecognized option '-h'", "lua -h") |
490 | NoRun("unrecognized option '---'", "lua ---") | 490 | NoRun("unrecognized option '---'", "lua ---") |
491 | NoRun("unrecognized option '-Ex'", "lua -Ex") | 491 | NoRun("unrecognized option '-Ex'", "lua -Ex --") |
492 | NoRun("unrecognized option '-vv'", "lua -vv") | 492 | NoRun("unrecognized option '-vv'", "lua -vv") |
493 | NoRun("unrecognized option '-iv'", "lua -iv") | 493 | NoRun("unrecognized option '-iv'", "lua -iv") |
494 | NoRun("'-e' needs argument", "lua -e") | 494 | NoRun("'-e' needs argument", "lua -e") |
495 | NoRun("syntax error", "lua -e a") | 495 | NoRun("syntax error", "lua -e a") |
496 | NoRun("'-l' needs argument", "lua -l") | 496 | NoRun("'-l' needs argument", "lua -l") |
497 | NoRun("-i", "lua -- -i") -- handles -i as a script name | ||
497 | 498 | ||
498 | 499 | ||
499 | if T then -- test library? | 500 | if T then -- test library? |
diff --git a/testes/math.lua b/testes/math.lua index bad8bc5e..0d228d09 100644 --- a/testes/math.lua +++ b/testes/math.lua | |||
@@ -3,8 +3,15 @@ | |||
3 | 3 | ||
4 | print("testing numbers and math lib") | 4 | print("testing numbers and math lib") |
5 | 5 | ||
6 | local minint <const> = math.mininteger | 6 | local math = require "math" |
7 | local maxint <const> = math.maxinteger | 7 | local string = require "string" |
8 | |||
9 | global none | ||
10 | |||
11 | global<const> print, assert, pcall, type, pairs, load | ||
12 | global<const> tonumber, tostring, select | ||
13 | |||
14 | local<const> minint, maxint = math.mininteger, math.maxinteger | ||
8 | 15 | ||
9 | local intbits <const> = math.floor(math.log(maxint, 2) + 0.5) + 1 | 16 | local intbits <const> = math.floor(math.log(maxint, 2) + 0.5) + 1 |
10 | assert((1 << intbits) == 0) | 17 | assert((1 << intbits) == 0) |
@@ -184,7 +191,7 @@ do | |||
184 | for i = -3, 3 do -- variables avoid constant folding | 191 | for i = -3, 3 do -- variables avoid constant folding |
185 | for j = -3, 3 do | 192 | for j = -3, 3 do |
186 | -- domain errors (0^(-n)) are not portable | 193 | -- domain errors (0^(-n)) are not portable |
187 | if not _port or i ~= 0 or j > 0 then | 194 | if not _ENV._port or i ~= 0 or j > 0 then |
188 | assert(eq(i^j, 1 / i^(-j))) | 195 | assert(eq(i^j, 1 / i^(-j))) |
189 | end | 196 | end |
190 | end | 197 | end |
@@ -430,7 +437,7 @@ for i = 2,36 do | |||
430 | assert(tonumber('\t10000000000\t', i) == i10) | 437 | assert(tonumber('\t10000000000\t', i) == i10) |
431 | end | 438 | end |
432 | 439 | ||
433 | if not _soft then | 440 | if not _ENV._soft then |
434 | -- tests with very long numerals | 441 | -- tests with very long numerals |
435 | assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1) | 442 | assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1) |
436 | assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1) | 443 | assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1) |
@@ -632,7 +639,7 @@ assert(maxint % -2 == -1) | |||
632 | 639 | ||
633 | -- non-portable tests because Windows C library cannot compute | 640 | -- non-portable tests because Windows C library cannot compute |
634 | -- fmod(1, huge) correctly | 641 | -- fmod(1, huge) correctly |
635 | if not _port then | 642 | if not _ENV._port then |
636 | local function anan (x) assert(isNaN(x)) end -- assert Not a Number | 643 | local function anan (x) assert(isNaN(x)) end -- assert Not a Number |
637 | anan(0.0 % 0) | 644 | anan(0.0 % 0) |
638 | anan(1.3 % 0) | 645 | anan(1.3 % 0) |
@@ -779,6 +786,7 @@ assert(a == '10' and b == '20') | |||
779 | 786 | ||
780 | do | 787 | do |
781 | print("testing -0 and NaN") | 788 | print("testing -0 and NaN") |
789 | global rawset, undef | ||
782 | local mz <const> = -0.0 | 790 | local mz <const> = -0.0 |
783 | local z <const> = 0.0 | 791 | local z <const> = 0.0 |
784 | assert(mz == z) | 792 | assert(mz == z) |
@@ -1071,9 +1079,10 @@ do | |||
1071 | assert(x == tonumber(tostring(x))) | 1079 | assert(x == tonumber(tostring(x))) |
1072 | end | 1080 | end |
1073 | 1081 | ||
1074 | -- different numbers shold print differently. | 1082 | -- different numbers should print differently. |
1075 | -- check pairs of floats with minimum detectable difference | 1083 | -- check pairs of floats with minimum detectable difference |
1076 | local p = floatbits - 1 | 1084 | local p = floatbits - 1 |
1085 | global ipairs | ||
1077 | for i = 1, maxexp - 1 do | 1086 | for i = 1, maxexp - 1 do |
1078 | for _, i in ipairs{-i, i} do | 1087 | for _, i in ipairs{-i, i} do |
1079 | local x = 2^i | 1088 | local x = 2^i |
diff --git a/testes/nextvar.lua b/testes/nextvar.lua index 031ad3fd..7e5bed56 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua | |||
@@ -1,6 +1,8 @@ | |||
1 | -- $Id: testes/nextvar.lua $ | 1 | -- $Id: testes/nextvar.lua $ |
2 | -- See Copyright Notice in file lua.h | 2 | -- See Copyright Notice in file lua.h |
3 | 3 | ||
4 | global <const> * | ||
5 | |||
4 | print('testing tables, next, and for') | 6 | print('testing tables, next, and for') |
5 | 7 | ||
6 | local function checkerror (msg, f, ...) | 8 | local function checkerror (msg, f, ...) |
@@ -227,7 +229,7 @@ for i = 1,lim do | |||
227 | end | 229 | end |
228 | 230 | ||
229 | 231 | ||
230 | -- insert and delete elements until a rehash occurr. Caller must ensure | 232 | -- insert and delete elements until a rehash occur. Caller must ensure |
231 | -- that a rehash will change the shape of the table. Must repeat because | 233 | -- that a rehash will change the shape of the table. Must repeat because |
232 | -- the insertion may collide with the deleted element, and then there is | 234 | -- the insertion may collide with the deleted element, and then there is |
233 | -- no rehash. | 235 | -- no rehash. |
@@ -343,13 +345,22 @@ do | |||
343 | end | 345 | end |
344 | end | 346 | end |
345 | 347 | ||
346 | local nofind = {} | ||
347 | 348 | ||
348 | a,b,c = 1,2,3 | 349 | do print("testing attack on table length") |
349 | a,b,c = nil | 350 | local t = {} |
351 | local lim = math.floor(math.log(math.maxinteger, 2)) - 1 | ||
352 | for i = lim, 0, -1 do | ||
353 | t[2^i] = true | ||
354 | end | ||
355 | assert(t[1 << lim]) | ||
356 | -- next loop should not take forever | ||
357 | for i = 1, #t do end | ||
358 | end | ||
359 | |||
360 | local nofind = {} | ||
350 | 361 | ||
351 | 362 | ||
352 | -- next uses always the same iteraction function | 363 | -- next uses always the same iteration function |
353 | assert(next{} == next{}) | 364 | assert(next{} == next{}) |
354 | 365 | ||
355 | local function find (name) | 366 | local function find (name) |
@@ -396,7 +407,7 @@ for i=0,10000 do | |||
396 | end | 407 | end |
397 | end | 408 | end |
398 | 409 | ||
399 | n = {n=0} | 410 | local n = {n=0} |
400 | for i,v in pairs(a) do | 411 | for i,v in pairs(a) do |
401 | n.n = n.n+1 | 412 | n.n = n.n+1 |
402 | assert(i and v and a[i] == v) | 413 | assert(i and v and a[i] == v) |
diff --git a/testes/pm.lua b/testes/pm.lua index 2a0cfb0b..720d2a35 100644 --- a/testes/pm.lua +++ b/testes/pm.lua | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | print('testing pattern matching') | 7 | print('testing pattern matching') |
8 | 8 | ||
9 | global <const> * | ||
10 | |||
9 | local function checkerror (msg, f, ...) | 11 | local function checkerror (msg, f, ...) |
10 | local s, err = pcall(f, ...) | 12 | local s, err = pcall(f, ...) |
11 | assert(not s and string.find(err, msg)) | 13 | assert(not s and string.find(err, msg)) |
@@ -23,9 +25,9 @@ a,b = string.find('alo', '') | |||
23 | assert(a == 1 and b == 0) | 25 | assert(a == 1 and b == 0) |
24 | a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position | 26 | a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position |
25 | assert(a == 1 and b == 1) | 27 | assert(a == 1 and b == 1) |
26 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle | 28 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the middle |
27 | assert(a == 5 and b == 7) | 29 | assert(a == 5 and b == 7) |
28 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle | 30 | a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the middle |
29 | assert(a == 9 and b == 11) | 31 | assert(a == 9 and b == 11) |
30 | a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end | 32 | a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end |
31 | assert(a == 9 and b == 11); | 33 | assert(a == 9 and b == 11); |
diff --git a/testes/strings.lua b/testes/strings.lua index ce28e4c5..46912d43 100644 --- a/testes/strings.lua +++ b/testes/strings.lua | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | -- ISO Latin encoding | 4 | -- ISO Latin encoding |
5 | 5 | ||
6 | global <const> * | ||
6 | 7 | ||
7 | print('testing strings and string library') | 8 | print('testing strings and string library') |
8 | 9 | ||
diff --git a/testes/tracegc.lua b/testes/tracegc.lua index 9c5c1b3f..a8c929df 100644 --- a/testes/tracegc.lua +++ b/testes/tracegc.lua | |||
@@ -6,7 +6,7 @@ local M = {} | |||
6 | local setmetatable, stderr, collectgarbage = | 6 | local setmetatable, stderr, collectgarbage = |
7 | setmetatable, io.stderr, collectgarbage | 7 | setmetatable, io.stderr, collectgarbage |
8 | 8 | ||
9 | _ENV = nil | 9 | global none |
10 | 10 | ||
11 | local active = false | 11 | local active = false |
12 | 12 | ||
diff --git a/testes/utf8.lua b/testes/utf8.lua index 0704782c..028995a4 100644 --- a/testes/utf8.lua +++ b/testes/utf8.lua | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | -- UTF-8 file | 4 | -- UTF-8 file |
5 | 5 | ||
6 | global <const> * | ||
7 | |||
6 | print "testing UTF-8 library" | 8 | print "testing UTF-8 library" |
7 | 9 | ||
8 | local utf8 = require'utf8' | 10 | local utf8 = require'utf8' |
@@ -134,7 +136,7 @@ do | |||
134 | errorcodes("\xbfinvalid") | 136 | errorcodes("\xbfinvalid") |
135 | errorcodes("αλφ\xBFα") | 137 | errorcodes("αλφ\xBFα") |
136 | 138 | ||
137 | -- calling interation function with invalid arguments | 139 | -- calling iteration function with invalid arguments |
138 | local f = utf8.codes("") | 140 | local f = utf8.codes("") |
139 | assert(f("", 2) == nil) | 141 | assert(f("", 2) == nil) |
140 | assert(f("", -1) == nil) | 142 | assert(f("", -1) == nil) |
@@ -150,11 +152,20 @@ checkerror("position out of bounds", utf8.offset, "", 1, -1) | |||
150 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) | 152 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) |
151 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) | 153 | checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) |
152 | checkerror("continuation byte", utf8.offset, "\x80", 1) | 154 | checkerror("continuation byte", utf8.offset, "\x80", 1) |
155 | checkerror("continuation byte", utf8.offset, "\x9c", -1) | ||
153 | 156 | ||
154 | -- error in indices for len | 157 | -- error in indices for len |
155 | checkerror("out of bounds", utf8.len, "abc", 0, 2) | 158 | checkerror("out of bounds", utf8.len, "abc", 0, 2) |
156 | checkerror("out of bounds", utf8.len, "abc", 1, 4) | 159 | checkerror("out of bounds", utf8.len, "abc", 1, 4) |
157 | 160 | ||
161 | do -- missing continuation bytes | ||
162 | -- get what is available | ||
163 | local p, e = utf8.offset("\xE0", 1) | ||
164 | assert(p == 1 and e == 1) | ||
165 | local p, e = utf8.offset("\xE0\x9e", -1) | ||
166 | assert(p == 1 and e == 2) | ||
167 | end | ||
168 | |||
158 | 169 | ||
159 | local s = "hello World" | 170 | local s = "hello World" |
160 | local t = {string.byte(s, 1, -1)} | 171 | local t = {string.byte(s, 1, -1)} |