Showing the changes to src (53 of 60 files). Show all
Unified · Split
| @@ -1,2 +1,2 @@ | ||
| 1 | −#define nvalue(x) 0 | |
| 1 | +#define nvalue(x) ((lua_Number)0) | |
| 2 | 2 | #define ttypenv(x) ttnov(x) |
| @@ -33,7 +33,7 @@ CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ · 32 unmodified lines | ||
| 33 | 33 | lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ |
| 34 | 34 | ltm.o lundump.o lvm.o lzio.o |
| 35 | 35 | LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ |
| 36 | − lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o | |
| 36 | + lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o | |
| 37 | 37 | BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) |
| 38 | 38 | |
| 39 | 39 | LUA_T= lua |
| @@ -152,7 +152,7 @@ lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ · 112 unmodified lines | ||
| 152 | 152 | linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h |
| 153 | 153 | liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h |
| 154 | 154 | llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \ |
| 155 | − lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h | |
| 155 | + lstate.h ltm.h lzio.h lmem.h lgc.h llex.h lparser.h lstring.h ltable.h | |
| 156 | 156 | lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h |
| 157 | 157 | lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ |
| 158 | 158 | ltm.h lzio.h lmem.h ldo.h lgc.h |
| @@ -167,8 +167,8 @@ lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ · 8 unmodified lines | ||
| 167 | 167 | lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ |
| 168 | 168 | ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \ |
| 169 | 169 | ltable.h |
| 170 | −lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ | |
| 171 | − ltm.h lzio.h lstring.h lgc.h | |
| 170 | +lstring.o: lstring.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ | |
| 171 | + llimits.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h | |
| 172 | 172 | lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h |
| 173 | 173 | ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ |
| 174 | 174 | ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h |
| @@ -180,6 +180,7 @@ luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ · 5 unmodified lines | ||
| 180 | 180 | ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h |
| 181 | 181 | lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ |
| 182 | 182 | llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h |
| 183 | +lutf8lib.o: lutf8lib.c lua.h luaconf.h lauxlib.h lualib.h | |
| 183 | 184 | lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ |
| 184 | 185 | lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h |
| 185 | 186 | lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp $ | |
| 2 | +** $Id: lapi.c,v 2.201 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Lua API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -286,7 +286,7 @@ LUA_API int lua_isstring (lua_State *L, int idx) { · 280 unmodified lines | ||
| 286 | 286 | |
| 287 | 287 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
| 288 | 288 | const TValue *o = index2addr(L, idx); |
| 289 | − return (ttisuserdata(o) || ttislightuserdata(o)); | |
| 289 | + return (ttisfulluserdata(o) || ttislightuserdata(o)); | |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 292 | |
| @@ -299,9 +299,9 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { · 6 unmodified lines | ||
| 299 | 299 | |
| 300 | 300 | LUA_API void lua_arith (lua_State *L, int op) { |
| 301 | 301 | lua_lock(L); |
| 302 | − if (op != LUA_OPUNM) /* all other operations expect two operands */ | |
| 303 | − api_checknelems(L, 2); | |
| 304 | − else { /* for unary minus, add fake 2nd operand */ | |
| 302 | + if (op != LUA_OPUNM && op != LUA_OPBNOT) | |
| 303 | + api_checknelems(L, 2); /* all other operations expect two operands */ | |
| 304 | + else { /* for unary operations, add fake 2nd operand */ | |
| 305 | 305 | api_checknelems(L, 1); |
| 306 | 306 | setobjs2s(L, L->top, L->top - 1); |
| 307 | 307 | L->top++; |
| @@ -379,20 +379,20 @@ LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) { · 71 unmodified lines | ||
| 379 | 379 | isnum = 1; |
| 380 | 380 | break; |
| 381 | 381 | } |
| 382 | − case LUA_TNUMFLT: { | |
| 383 | − const lua_Number twop = (~(lua_Unsigned)0) + cast_num(1); | |
| 384 | − lua_Number n = fltvalue(o); | |
| 382 | + case LUA_TNUMFLT: { /* compute floor(n) % 2^(numbits in an integer) */ | |
| 383 | + const lua_Number twop = cast_num(MAX_UINTEGER) + cast_num(1); /* 2^n */ | |
| 384 | + lua_Number n = fltvalue(o); /* get value */ | |
| 385 | 385 | int neg = 0; |
| 386 | − n = l_floor(n); | |
| 386 | + n = l_floor(n); /* get its floor */ | |
| 387 | 387 | if (n < 0) { |
| 388 | 388 | neg = 1; |
| 389 | − n = -n; | |
| 389 | + n = -n; /* make 'n' positive, so that 'fmod' is the same as '%' */ | |
| 390 | 390 | } |
| 391 | − n = l_mathop(fmod)(n, twop); | |
| 392 | − if (luai_numisnan(L,n)) /* not a number? */ | |
| 391 | + n = l_mathop(fmod)(n, twop); /* n = n % 2^(numbits in an integer) */ | |
| 392 | + if (luai_numisnan(n)) /* not a number? */ | |
| 393 | 393 | break; /* not an integer, too */ |
| 394 | − res = cast_unsigned(n); | |
| 395 | − if (neg) res = 0u - res; | |
| 394 | + res = cast_unsigned(n); /* 'n' now must fit in an unsigned */ | |
| 395 | + if (neg) res = 0u - res; /* back to negative, if needed */ | |
| 396 | 396 | isnum = 1; |
| 397 | 397 | break; |
| 398 | 398 | } |
| @@ -586,8 +586,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { · 187 unmodified lines | ||
| 586 | 586 | cl = luaF_newCclosure(L, n); |
| 587 | 587 | cl->c.f = fn; |
| 588 | 588 | L->top -= n; |
| 589 | − while (n--) | |
| 589 | + while (n--) { | |
| 590 | 590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); |
| 591 | + /* does not need barrier because closure is white */ | |
| 592 | + } | |
| 591 | 593 | setclCvalue(L, L->top, cl); |
| 592 | 594 | } |
| 593 | 595 | api_incr_top(L); |
| @@ -626,7 +628,7 @@ LUA_API int lua_pushthread (lua_State *L) { · 32 unmodified lines | ||
| 626 | 628 | */ |
| 627 | 629 | |
| 628 | 630 | |
| 629 | −LUA_API void lua_getglobal (lua_State *L, const char *var) { | |
| 631 | +LUA_API int lua_getglobal (lua_State *L, const char *var) { | |
| 630 | 632 | Table *reg = hvalue(&G(L)->l_registry); |
| 631 | 633 | const TValue *gt; /* global table */ |
| 632 | 634 | lua_lock(L); |
| @@ -634,19 +636,21 @@ LUA_API void lua_getglobal (lua_State *L, const char *var) { · 1 unmodified line | ||
| 634 | 636 | setsvalue2s(L, L->top++, luaS_new(L, var)); |
| 635 | 637 | luaV_gettable(L, gt, L->top - 1, L->top - 1); |
| 636 | 638 | lua_unlock(L); |
| 639 | + return ttnov(L->top - 1); | |
| 637 | 640 | } |
| 638 | 641 | |
| 639 | 642 | |
| 640 | −LUA_API void lua_gettable (lua_State *L, int idx) { | |
| 643 | +LUA_API int lua_gettable (lua_State *L, int idx) { | |
| 641 | 644 | StkId t; |
| 642 | 645 | lua_lock(L); |
| 643 | 646 | t = index2addr(L, idx); |
| 644 | 647 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
| 645 | 648 | lua_unlock(L); |
| 649 | + return ttnov(L->top - 1); | |
| 646 | 650 | } |
| 647 | 651 | |
| 648 | 652 | |
| 649 | −LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | |
| 653 | +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { | |
| 650 | 654 | StkId t; |
| 651 | 655 | lua_lock(L); |
| 652 | 656 | t = index2addr(L, idx); |
| @@ -654,20 +658,22 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { · 1 unmodified line | ||
| 654 | 658 | api_incr_top(L); |
| 655 | 659 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
| 656 | 660 | lua_unlock(L); |
| 661 | + return ttnov(L->top - 1); | |
| 657 | 662 | } |
| 658 | 663 | |
| 659 | 664 | |
| 660 | −LUA_API void lua_rawget (lua_State *L, int idx) { | |
| 665 | +LUA_API int lua_rawget (lua_State *L, int idx) { | |
| 661 | 666 | StkId t; |
| 662 | 667 | lua_lock(L); |
| 663 | 668 | t = index2addr(L, idx); |
| 664 | 669 | api_check(L, ttistable(t), "table expected"); |
| 665 | 670 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); |
| 666 | 671 | lua_unlock(L); |
| 672 | + return ttnov(L->top - 1); | |
| 667 | 673 | } |
| 668 | 674 | |
| 669 | 675 | |
| 670 | −LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | |
| 676 | +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | |
| 671 | 677 | StkId t; |
| 672 | 678 | lua_lock(L); |
| 673 | 679 | t = index2addr(L, idx); |
| @@ -675,10 +681,11 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) { · 1 unmodified line | ||
| 675 | 681 | setobj2s(L, L->top, luaH_getint(hvalue(t), n)); |
| 676 | 682 | api_incr_top(L); |
| 677 | 683 | lua_unlock(L); |
| 684 | + return ttnov(L->top - 1); | |
| 678 | 685 | } |
| 679 | 686 | |
| 680 | 687 | |
| 681 | −LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { | |
| 688 | +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { | |
| 682 | 689 | StkId t; |
| 683 | 690 | TValue k; |
| 684 | 691 | lua_lock(L); |
| @@ -688,6 +695,7 @@ LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { · 3 unmodified lines | ||
| 688 | 695 | setobj2s(L, L->top, luaH_get(hvalue(t), &k)); |
| 689 | 696 | api_incr_top(L); |
| 690 | 697 | lua_unlock(L); |
| 698 | + return ttnov(L->top - 1); | |
| 691 | 699 | } |
| 692 | 700 | |
| 693 | 701 | |
| @@ -737,11 +745,8 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) { · 43 unmodified lines | ||
| 737 | 745 | StkId o; |
| 738 | 746 | lua_lock(L); |
| 739 | 747 | o = index2addr(L, idx); |
| 740 | − api_check(L, ttisuserdata(o), "userdata expected"); | |
| 741 | − if (uvalue(o)->env) { | |
| 742 | − sethvalue(L, L->top, uvalue(o)->env); | |
| 743 | − } else | |
| 744 | − setnilvalue(L->top); | |
| 748 | + api_check(L, ttisfulluserdata(o), "full userdata expected"); | |
| 749 | + getuservalue(L, rawuvalue(o), L->top); | |
| 745 | 750 | api_incr_top(L); |
| 746 | 751 | lua_unlock(L); |
| 747 | 752 | } |
| @@ -846,7 +851,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { · 98 unmodified lines | ||
| 846 | 851 | case LUA_TTABLE: { |
| 847 | 852 | hvalue(obj)->metatable = mt; |
| 848 | 853 | if (mt) { |
| 849 | − luaC_objbarrierback(L, gcvalue(obj), mt); | |
| 854 | + luaC_objbarrier(L, gcvalue(obj), mt); | |
| 850 | 855 | luaC_checkfinalizer(L, gcvalue(obj), mt); |
| 851 | 856 | } |
| 852 | 857 | break; |
| @@ -875,14 +880,9 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { · 22 unmodified lines | ||
| 875 | 880 | lua_lock(L); |
| 876 | 881 | api_checknelems(L, 1); |
| 877 | 882 | o = index2addr(L, idx); |
| 878 | − api_check(L, ttisuserdata(o), "userdata expected"); | |
| 879 | − if (ttisnil(L->top - 1)) | |
| 880 | − uvalue(o)->env = NULL; | |
| 881 | − else { | |
| 882 | − api_check(L, ttistable(L->top - 1), "table expected"); | |
| 883 | − uvalue(o)->env = hvalue(L->top - 1); | |
| 884 | − luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | |
| 885 | − } | |
| 883 | + api_check(L, ttisfulluserdata(o), "full userdata expected"); | |
| 884 | + setuservalue(L, rawuvalue(o), L->top - 1); | |
| 885 | + luaC_barrier(L, gcvalue(o), L->top - 1); | |
| 886 | 886 | L->top--; |
| 887 | 887 | lua_unlock(L); |
| 888 | 888 | } |
| @@ -1015,14 +1015,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, · 126 unmodified lines | ||
| 1015 | 1015 | } |
| 1016 | 1016 | |
| 1017 | 1017 | |
| 1018 | −LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |
| 1018 | +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { | |
| 1019 | 1019 | int status; |
| 1020 | 1020 | TValue *o; |
| 1021 | 1021 | lua_lock(L); |
| 1022 | 1022 | api_checknelems(L, 1); |
| 1023 | 1023 | o = L->top - 1; |
| 1024 | 1024 | if (isLfunction(o)) |
| 1025 | − status = luaU_dump(L, getproto(o), writer, data, 0); | |
| 1025 | + status = luaU_dump(L, getproto(o), writer, data, strip); | |
| 1026 | 1026 | else |
| 1027 | 1027 | status = 1; |
| 1028 | 1028 | lua_unlock(L); |
| @@ -1068,19 +1068,21 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 39 unmodified lines | ||
| 1068 | 1068 | break; |
| 1069 | 1069 | } |
| 1070 | 1070 | case LUA_GCSTEP: { |
| 1071 | − if (g->gckind == KGC_GEN) { /* generational mode? */ | |
| 1072 | − res = (g->GCestimate == 0); /* true if it will do major collection */ | |
| 1073 | − luaC_forcestep(L); /* do a single step */ | |
| 1071 | + l_mem debt = 1; /* =1 to signal that it did an actual step */ | |
| 1072 | + int oldrunning = g->gcrunning; | |
| 1073 | + g->gcrunning = 1; /* force GC to run */ | |
| 1074 | + if (data == 0) { | |
| 1075 | + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ | |
| 1076 | + luaC_step(L); | |
| 1074 | 1077 | } |
| 1075 | − else { | |
| 1076 | − lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; | |
| 1077 | − if (g->gcrunning) | |
| 1078 | − debt += g->GCdebt; /* include current debt */ | |
| 1079 | − luaE_setdebt(g, debt); | |
| 1080 | − luaC_forcestep(L); | |
| 1081 | − if (g->gcstate == GCSpause) /* end of cycle? */ | |
| 1082 | − res = 1; /* signal it */ | |
| 1078 | + else { /* add 'data' to total debt */ | |
| 1079 | + debt = cast(l_mem, data) * 1024 + g->GCdebt; | |
| 1080 | + luaE_setdebt(g, debt); | |
| 1081 | + luaC_checkGC(L); | |
| 1083 | 1082 | } |
| 1083 | + g->gcrunning = oldrunning; /* restore previous state */ | |
| 1084 | + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ | |
| 1085 | + res = 1; /* signal it */ | |
| 1084 | 1086 | break; |
| 1085 | 1087 | } |
| 1086 | 1088 | case LUA_GCSETPAUSE: { |
| @@ -1088,13 +1090,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 1 unmodified line | ||
| 1088 | 1090 | g->gcpause = data; |
| 1089 | 1091 | break; |
| 1090 | 1092 | } |
| 1091 | − case LUA_GCSETMAJORINC: { | |
| 1092 | − res = g->gcmajorinc; | |
| 1093 | − g->gcmajorinc = data; | |
| 1094 | − break; | |
| 1095 | − } | |
| 1096 | 1093 | case LUA_GCSETSTEPMUL: { |
| 1097 | 1094 | res = g->gcstepmul; |
| 1095 | + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ | |
| 1098 | 1096 | g->gcstepmul = data; |
| 1099 | 1097 | break; |
| 1100 | 1098 | } |
| @@ -1102,14 +1100,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 1 unmodified line | ||
| 1102 | 1100 | res = g->gcrunning; |
| 1103 | 1101 | break; |
| 1104 | 1102 | } |
| 1105 | − case LUA_GCGEN: { /* change collector to generational mode */ | |
| 1106 | − luaC_changemode(L, KGC_GEN); | |
| 1107 | − break; | |
| 1108 | − } | |
| 1109 | − case LUA_GCINC: { /* change collector to incremental mode */ | |
| 1110 | − luaC_changemode(L, KGC_NORMAL); | |
| 1111 | − break; | |
| 1112 | − } | |
| 1113 | 1103 | default: res = -1; /* invalid option */ |
| 1114 | 1104 | } |
| 1115 | 1105 | lua_unlock(L); |
| @@ -1197,7 +1187,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { · 81 unmodified lines | ||
| 1197 | 1187 | Udata *u; |
| 1198 | 1188 | lua_lock(L); |
| 1199 | 1189 | luaC_checkGC(L); |
| 1200 | − u = luaS_newudata(L, size, NULL); | |
| 1190 | + u = luaS_newudata(L, size); | |
| 1201 | 1191 | setuvalue(L, L->top, u); |
| 1202 | 1192 | api_incr_top(L); |
| 1203 | 1193 | lua_unlock(L); |
| @@ -1207,7 +1197,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { · 3 unmodified lines | ||
| 1207 | 1197 | |
| 1208 | 1198 | |
| 1209 | 1199 | static const char *aux_upvalue (StkId fi, int n, TValue **val, |
| 1210 | − GCObject **owner) { | |
| 1200 | + GCObject **owner, UpVal **uv) { | |
| 1211 | 1201 | switch (ttype(fi)) { |
| 1212 | 1202 | case LUA_TCCL: { /* C closure */ |
| 1213 | 1203 | CClosure *f = clCvalue(fi); |
| @@ -1222,9 +1212,9 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, · 8 unmodified lines | ||
| 1222 | 1212 | Proto *p = f->p; |
| 1223 | 1213 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
| 1224 | 1214 | *val = f->upvals[n-1]->v; |
| 1225 | − if (owner) *owner = obj2gco(f->upvals[n - 1]); | |
| 1215 | + if (uv) *uv = f->upvals[n - 1]; | |
| 1226 | 1216 | name = p->upvalues[n-1].name; |
| 1227 | − return (name == NULL) ? "" : getstr(name); | |
| 1217 | + return (name == NULL) ? "(*no name)" : getstr(name); | |
| 1228 | 1218 | } |
| 1229 | 1219 | default: return NULL; /* not a closure */ |
| 1230 | 1220 | } |
| @@ -1235,7 +1225,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { · 4 unmodified lines | ||
| 1235 | 1225 | const char *name; |
| 1236 | 1226 | TValue *val = NULL; /* to avoid warnings */ |
| 1237 | 1227 | lua_lock(L); |
| 1238 | − name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); | |
| 1228 | + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); | |
| 1239 | 1229 | if (name) { |
| 1240 | 1230 | setobj2s(L, L->top, val); |
| 1241 | 1231 | api_incr_top(L); |
| @@ -1248,16 +1238,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { · 6 unmodified lines | ||
| 1248 | 1238 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
| 1249 | 1239 | const char *name; |
| 1250 | 1240 | TValue *val = NULL; /* to avoid warnings */ |
| 1251 | − GCObject *owner = NULL; /* to avoid warnings */ | |
| 1241 | + GCObject *owner = NULL; | |
| 1242 | + UpVal *uv = NULL; | |
| 1252 | 1243 | StkId fi; |
| 1253 | 1244 | lua_lock(L); |
| 1254 | 1245 | fi = index2addr(L, funcindex); |
| 1255 | 1246 | api_checknelems(L, 1); |
| 1256 | − name = aux_upvalue(fi, n, &val, &owner); | |
| 1247 | + name = aux_upvalue(fi, n, &val, &owner, &uv); | |
| 1257 | 1248 | if (name) { |
| 1258 | 1249 | L->top--; |
| 1259 | 1250 | setobj(L, val, L->top); |
| 1260 | − luaC_barrier(L, owner, L->top); | |
| 1251 | + if (owner) { luaC_barrier(L, owner, L->top); } | |
| 1252 | + else if (uv) { luaC_upvalbarrier(L, uv); } | |
| 1261 | 1253 | } |
| 1262 | 1254 | lua_unlock(L); |
| 1263 | 1255 | return name; |
| @@ -1299,7 +1291,11 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, · 35 unmodified lines | ||
| 1299 | 1291 | LClosure *f1; |
| 1300 | 1292 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
| 1301 | 1293 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
| 1294 | + luaC_upvdeccount(L, *up1); | |
| 1302 | 1295 | *up1 = *up2; |
| 1303 | − luaC_objbarrier(L, f1, *up2); | |
| 1296 | + (*up1)->refcount++; | |
| 1297 | + if (upisopen(*up1)) (*up1)->u.open.touched = 1; | |
| 1298 | + luaC_upvalbarrier(L, *up1); | |
| 1304 | 1299 | } |
| 1305 | 1300 | |
| 1301 | + | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lauxlib.c,v 1.255 2013/06/27 18:32:33 roberto Exp $ | |
| 2 | +** $Id: lauxlib.c,v 1.260 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -150,33 +150,40 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, · 144 unmodified lines | ||
| 150 | 150 | ** ======================================================= |
| 151 | 151 | */ |
| 152 | 152 | |
| 153 | −LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { | |
| 153 | +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { | |
| 154 | 154 | lua_Debug ar; |
| 155 | 155 | if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ |
| 156 | − return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); | |
| 156 | + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); | |
| 157 | 157 | lua_getinfo(L, "n", &ar); |
| 158 | 158 | if (strcmp(ar.namewhat, "method") == 0) { |
| 159 | − narg--; /* do not count `self' */ | |
| 160 | − if (narg == 0) /* error is in the self argument itself? */ | |
| 159 | + arg--; /* do not count `self' */ | |
| 160 | + if (arg == 0) /* error is in the self argument itself? */ | |
| 161 | 161 | return luaL_error(L, "calling " LUA_QS " on bad self (%s)", |
| 162 | 162 | ar.name, extramsg); |
| 163 | 163 | } |
| 164 | 164 | if (ar.name == NULL) |
| 165 | 165 | ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; |
| 166 | 166 | return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", |
| 167 | − narg, ar.name, extramsg); | |
| 167 | + arg, ar.name, extramsg); | |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | |
| 171 | −static int typeerror (lua_State *L, int narg, const char *tname) { | |
| 172 | − const char *msg = lua_pushfstring(L, "%s expected, got %s", | |
| 173 | − tname, luaL_typename(L, narg)); | |
| 174 | − return luaL_argerror(L, narg, msg); | |
| 171 | +static int typeerror (lua_State *L, int arg, const char *tname) { | |
| 172 | + const char *msg; | |
| 173 | + const char *typearg = luaL_typename(L, arg); | |
| 174 | + if (lua_getmetatable(L, arg)) { | |
| 175 | + if (lua_getfield(L, -1, "__name") == LUA_TSTRING) | |
| 176 | + typearg = lua_tostring(L, -1); | |
| 177 | + } | |
| 178 | + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) | |
| 179 | + typearg = "light userdata"; | |
| 180 | + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); | |
| 181 | + return luaL_argerror(L, arg, msg); | |
| 175 | 182 | } |
| 176 | 183 | |
| 177 | 184 | |
| 178 | −static void tag_error (lua_State *L, int narg, int tag) { | |
| 179 | − typeerror(L, narg, lua_typename(L, tag)); | |
| 185 | +static void tag_error (lua_State *L, int arg, int tag) { | |
| 186 | + typeerror(L, arg, lua_typename(L, tag)); | |
| 180 | 187 | } |
| 181 | 188 | |
| 182 | 189 | |
| @@ -275,6 +282,8 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { · 92 unmodified lines | ||
| 275 | 282 | return 0; /* leave previous value on top, but return 0 */ |
| 276 | 283 | lua_pop(L, 1); |
| 277 | 284 | lua_newtable(L); /* create metatable */ |
| 285 | + lua_pushstring(L, tname); | |
| 286 | + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ | |
| 278 | 287 | lua_pushvalue(L, -1); |
| 279 | 288 | lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ |
| 280 | 289 | return 1; |
| @@ -317,15 +326,15 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { · 36 unmodified lines | ||
| 317 | 326 | ** ======================================================= |
| 318 | 327 | */ |
| 319 | 328 | |
| 320 | −LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, | |
| 329 | +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, | |
| 321 | 330 | const char *const lst[]) { |
| 322 | − const char *name = (def) ? luaL_optstring(L, narg, def) : | |
| 323 | − luaL_checkstring(L, narg); | |
| 331 | + const char *name = (def) ? luaL_optstring(L, arg, def) : | |
| 332 | + luaL_checkstring(L, arg); | |
| 324 | 333 | int i; |
| 325 | 334 | for (i=0; lst[i]; i++) |
| 326 | 335 | if (strcmp(lst[i], name) == 0) |
| 327 | 336 | return i; |
| 328 | − return luaL_argerror(L, narg, | |
| 337 | + return luaL_argerror(L, arg, | |
| 329 | 338 | lua_pushfstring(L, "invalid option " LUA_QS, name)); |
| 330 | 339 | } |
| 331 | 340 | |
| @@ -342,86 +351,86 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { · 10 unmodified lines | ||
| 342 | 351 | } |
| 343 | 352 | |
| 344 | 353 | |
| 345 | −LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { | |
| 346 | − if (lua_type(L, narg) != t) | |
| 347 | − tag_error(L, narg, t); | |
| 354 | +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { | |
| 355 | + if (lua_type(L, arg) != t) | |
| 356 | + tag_error(L, arg, t); | |
| 348 | 357 | } |
| 349 | 358 | |
| 350 | 359 | |
| 351 | −LUALIB_API void luaL_checkany (lua_State *L, int narg) { | |
| 352 | − if (lua_type(L, narg) == LUA_TNONE) | |
| 353 | − luaL_argerror(L, narg, "value expected"); | |
| 360 | +LUALIB_API void luaL_checkany (lua_State *L, int arg) { | |
| 361 | + if (lua_type(L, arg) == LUA_TNONE) | |
| 362 | + luaL_argerror(L, arg, "value expected"); | |
| 354 | 363 | } |
| 355 | 364 | |
| 356 | 365 | |
| 357 | −LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { | |
| 358 | − const char *s = lua_tolstring(L, narg, len); | |
| 359 | − if (!s) tag_error(L, narg, LUA_TSTRING); | |
| 366 | +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { | |
| 367 | + const char *s = lua_tolstring(L, arg, len); | |
| 368 | + if (!s) tag_error(L, arg, LUA_TSTRING); | |
| 360 | 369 | return s; |
| 361 | 370 | } |
| 362 | 371 | |
| 363 | 372 | |
| 364 | −LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, | |
| 373 | +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, | |
| 365 | 374 | const char *def, size_t *len) { |
| 366 | − if (lua_isnoneornil(L, narg)) { | |
| 375 | + if (lua_isnoneornil(L, arg)) { | |
| 367 | 376 | if (len) |
| 368 | 377 | *len = (def ? strlen(def) : 0); |
| 369 | 378 | return def; |
| 370 | 379 | } |
| 371 | − else return luaL_checklstring(L, narg, len); | |
| 380 | + else return luaL_checklstring(L, arg, len); | |
| 372 | 381 | } |
| 373 | 382 | |
| 374 | 383 | |
| 375 | −LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { | |
| 384 | +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { | |
| 376 | 385 | int isnum; |
| 377 | − lua_Number d = lua_tonumberx(L, narg, &isnum); | |
| 386 | + lua_Number d = lua_tonumberx(L, arg, &isnum); | |
| 378 | 387 | if (!isnum) |
| 379 | − tag_error(L, narg, LUA_TNUMBER); | |
| 388 | + tag_error(L, arg, LUA_TNUMBER); | |
| 380 | 389 | return d; |
| 381 | 390 | } |
| 382 | 391 | |
| 383 | 392 | |
| 384 | −LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { | |
| 385 | − return luaL_opt(L, luaL_checknumber, narg, def); | |
| 393 | +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { | |
| 394 | + return luaL_opt(L, luaL_checknumber, arg, def); | |
| 386 | 395 | } |
| 387 | 396 | |
| 388 | 397 | |
| 389 | −static void interror (lua_State *L, int narg) { | |
| 390 | − if (lua_type(L, narg) == LUA_TNUMBER) | |
| 391 | − luaL_argerror(L, narg, "float value out of range"); | |
| 398 | +static void interror (lua_State *L, int arg) { | |
| 399 | + if (lua_type(L, arg) == LUA_TNUMBER) | |
| 400 | + luaL_argerror(L, arg, "float value out of range"); | |
| 392 | 401 | else |
| 393 | − tag_error(L, narg, LUA_TNUMBER); | |
| 402 | + tag_error(L, arg, LUA_TNUMBER); | |
| 394 | 403 | } |
| 395 | 404 | |
| 396 | 405 | |
| 397 | −LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { | |
| 406 | +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { | |
| 398 | 407 | int isnum; |
| 399 | − lua_Integer d = lua_tointegerx(L, narg, &isnum); | |
| 408 | + lua_Integer d = lua_tointegerx(L, arg, &isnum); | |
| 400 | 409 | if (!isnum) { |
| 401 | − interror(L, narg); | |
| 410 | + interror(L, arg); | |
| 402 | 411 | } |
| 403 | 412 | return d; |
| 404 | 413 | } |
| 405 | 414 | |
| 406 | 415 | |
| 407 | −LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { | |
| 416 | +LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int arg) { | |
| 408 | 417 | int isnum; |
| 409 | − lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); | |
| 418 | + lua_Unsigned d = lua_tounsignedx(L, arg, &isnum); | |
| 410 | 419 | if (!isnum) |
| 411 | − interror(L, narg); | |
| 420 | + interror(L, arg); | |
| 412 | 421 | return d; |
| 413 | 422 | } |
| 414 | 423 | |
| 415 | 424 | |
| 416 | −LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, | |
| 425 | +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, | |
| 417 | 426 | lua_Integer def) { |
| 418 | − return luaL_opt(L, luaL_checkinteger, narg, def); | |
| 427 | + return luaL_opt(L, luaL_checkinteger, arg, def); | |
| 419 | 428 | } |
| 420 | 429 | |
| 421 | 430 | |
| 422 | −LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, | |
| 431 | +LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int arg, | |
| 423 | 432 | lua_Unsigned def) { |
| 424 | − return luaL_opt(L, luaL_checkunsigned, narg, def); | |
| 433 | + return luaL_opt(L, luaL_checkunsigned, arg, def); | |
| 425 | 434 | } |
| 426 | 435 | |
| 427 | 436 | /* }====================================================== */ |
| @@ -709,8 +718,7 @@ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { · 281 unmodified lines | ||
| 709 | 718 | if (!lua_getmetatable(L, obj)) /* no metatable? */ |
| 710 | 719 | return 0; |
| 711 | 720 | lua_pushstring(L, event); |
| 712 | − lua_rawget(L, -2); | |
| 713 | − if (lua_isnil(L, -1)) { | |
| 721 | + if (lua_rawget(L, -2) == LUA_TNIL) { /* is metafield nil? */ | |
| 714 | 722 | lua_pop(L, 2); /* remove metatable and metafield */ |
| 715 | 723 | return 0; |
| 716 | 724 | } |
| @@ -746,10 +754,16 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { · 29 unmodified lines | ||
| 746 | 754 | LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { |
| 747 | 755 | if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ |
| 748 | 756 | switch (lua_type(L, idx)) { |
| 749 | − case LUA_TNUMBER: { /* concatenate with empty string to convert */ | |
| 750 | − lua_pushvalue(L, idx); | |
| 751 | − lua_pushliteral(L, ""); | |
| 752 | − lua_concat(L, 2); | |
| 757 | + case LUA_TNUMBER: { | |
| 758 | + if (lua_isinteger(L, idx)) | |
| 759 | + lua_pushfstring(L, "%I", lua_tointeger(L, idx)); | |
| 760 | + else { | |
| 761 | + const char *s = lua_pushfstring(L, "%f", lua_tonumber(L, idx)); | |
| 762 | + if (s[strspn(s, "-0123456789")] == '\0') { /* looks like an int? */ | |
| 763 | + lua_pushliteral(L, ".0"); /* add a '.0' to result */ | |
| 764 | + lua_concat(L, 2); | |
| 765 | + } | |
| 766 | + } | |
| 753 | 767 | break; |
| 754 | 768 | } |
| 755 | 769 | case LUA_TSTRING: |
| @@ -786,8 +800,7 @@ static const char *luaL_findtable (lua_State *L, int idx, · 30 unmodified lines | ||
| 786 | 800 | e = strchr(fname, '.'); |
| 787 | 801 | if (e == NULL) e = fname + strlen(fname); |
| 788 | 802 | lua_pushlstring(L, fname, e - fname); |
| 789 | − lua_rawget(L, -2); | |
| 790 | − if (lua_isnil(L, -1)) { /* no such field? */ | |
| 803 | + if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ | |
| 791 | 804 | lua_pop(L, 1); /* remove this nil */ |
| 792 | 805 | lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ |
| 793 | 806 | lua_pushlstring(L, fname, e - fname); |
| @@ -824,8 +837,7 @@ static int libsize (const luaL_Reg *l) { · 30 unmodified lines | ||
| 824 | 837 | LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, |
| 825 | 838 | int sizehint) { |
| 826 | 839 | luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ |
| 827 | − lua_getfield(L, -1, modname); /* get _LOADED[modname] */ | |
| 828 | − if (!lua_istable(L, -1)) { /* not found? */ | |
| 840 | + if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no _LOADED[modname]? */ | |
| 829 | 841 | lua_pop(L, 1); /* remove previous result */ |
| 830 | 842 | /* try global variable (and create one if it does not exist) */ |
| 831 | 843 | lua_pushglobaltable(L); |
| @@ -877,8 +889,8 @@ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { · 45 unmodified lines | ||
| 877 | 889 | ** into the stack |
| 878 | 890 | */ |
| 879 | 891 | LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { |
| 880 | − lua_getfield(L, idx, fname); | |
| 881 | − if (lua_istable(L, -1)) return 1; /* table already there */ | |
| 892 | + if (lua_getfield(L, idx, fname) == LUA_TTABLE) | |
| 893 | + return 1; /* table already there */ | |
| 882 | 894 | else { |
| 883 | 895 | lua_pop(L, 1); /* remove previous result */ |
| 884 | 896 | idx = lua_absindex(L, idx); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lauxlib.h,v 1.122 2013/06/27 18:32:33 roberto Exp $ | |
| 2 | +** $Id: lauxlib.h,v 1.123 2014/01/05 14:04:46 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -35,24 +35,24 @@ LUALIB_API void (luaL_checkversion_) (lua_State *L, int ver, size_t sz); · 29 unmodified lines | ||
| 35 | 35 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); |
| 36 | 36 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); |
| 37 | 37 | LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); |
| 38 | −LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); | |
| 39 | −LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, | |
| 38 | +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); | |
| 39 | +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, | |
| 40 | 40 | size_t *l); |
| 41 | −LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, | |
| 41 | +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, | |
| 42 | 42 | const char *def, size_t *l); |
| 43 | −LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); | |
| 44 | −LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); | |
| 43 | +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); | |
| 44 | +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); | |
| 45 | 45 | |
| 46 | −LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); | |
| 47 | −LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, | |
| 46 | +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); | |
| 47 | +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, | |
| 48 | 48 | lua_Integer def); |
| 49 | −LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); | |
| 50 | −LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, | |
| 49 | +LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int arg); | |
| 50 | +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int arg, | |
| 51 | 51 | lua_Unsigned def); |
| 52 | 52 | |
| 53 | 53 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); |
| 54 | −LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); | |
| 55 | −LUALIB_API void (luaL_checkany) (lua_State *L, int narg); | |
| 54 | +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); | |
| 55 | +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); | |
| 56 | 56 | |
| 57 | 57 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); |
| 58 | 58 | LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); |
| @@ -62,7 +62,7 @@ LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); · 3 unmodified lines | ||
| 62 | 62 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); |
| 63 | 63 | LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); |
| 64 | 64 | |
| 65 | −LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, | |
| 65 | +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, | |
| 66 | 66 | const char *const lst[]); |
| 67 | 67 | |
| 68 | 68 | LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); |
| @@ -114,8 +114,8 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, · 45 unmodified lines | ||
| 114 | 114 | #define luaL_newlib(L,l) \ |
| 115 | 115 | (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) |
| 116 | 116 | |
| 117 | −#define luaL_argcheck(L, cond,numarg,extramsg) \ | |
| 118 | − ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) | |
| 117 | +#define luaL_argcheck(L, cond,arg,extramsg) \ | |
| 118 | + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) | |
| 119 | 119 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) |
| 120 | 120 | #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) |
| 121 | 121 | #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lbaselib.c,v 1.279 2013/07/05 14:39:15 roberto Exp $ | |
| 2 | +** $Id: lbaselib.c,v 1.285 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Basic library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -63,7 +63,7 @@ static int b_str2int (const char *s, const char *e, int base, lua_Integer *pn) { · 57 unmodified lines | ||
| 63 | 63 | s += strspn(s, SPACECHARS); /* skip trailing spaces */ |
| 64 | 64 | if (s != e) /* invalid trailing characters? */ |
| 65 | 65 | return 0; |
| 66 | − *pn = (neg) ? -(lua_Integer)n : (lua_Integer)n; | |
| 66 | + *pn = (lua_Integer)((neg) ? (0u - n) : n); | |
| 67 | 67 | return 1; |
| 68 | 68 | } |
| 69 | 69 | |
| @@ -175,19 +175,18 @@ static int luaB_rawset (lua_State *L) { · 105 unmodified lines | ||
| 175 | 175 | static int luaB_collectgarbage (lua_State *L) { |
| 176 | 176 | static const char *const opts[] = {"stop", "restart", "collect", |
| 177 | 177 | "count", "step", "setpause", "setstepmul", |
| 178 | − "setmajorinc", "isrunning", "generational", "incremental", NULL}; | |
| 178 | + "isrunning", NULL}; | |
| 179 | 179 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
| 180 | 180 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
| 181 | − LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; | |
| 181 | + LUA_GCISRUNNING}; | |
| 182 | 182 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
| 183 | 183 | int ex = luaL_optint(L, 2, 0); |
| 184 | 184 | int res = lua_gc(L, o, ex); |
| 185 | 185 | switch (o) { |
| 186 | 186 | case LUA_GCCOUNT: { |
| 187 | 187 | int b = lua_gc(L, LUA_GCCOUNTB, 0); |
| 188 | − lua_pushnumber(L, res + ((lua_Number)b/1024)); | |
| 189 | − lua_pushinteger(L, b); | |
| 190 | − return 2; | |
| 188 | + lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); | |
| 189 | + return 1; | |
| 191 | 190 | } |
| 192 | 191 | case LUA_GCSTEP: case LUA_GCISRUNNING: { |
| 193 | 192 | lua_pushboolean(L, res); |
| @@ -247,8 +246,7 @@ static int ipairsaux (lua_State *L) { · 53 unmodified lines | ||
| 247 | 246 | luaL_checktype(L, 1, LUA_TTABLE); |
| 248 | 247 | i++; /* next value */ |
| 249 | 248 | lua_pushinteger(L, i); |
| 250 | − lua_rawgeti(L, 1, i); | |
| 251 | − return (lua_isnil(L, -1)) ? 1 : 2; | |
| 249 | + return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2; | |
| 252 | 250 | } |
| 253 | 251 | |
| 254 | 252 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lbitlib.c,v 1.20 2013/06/21 17:27:24 roberto Exp $ | |
| 2 | +** $Id: lbitlib.c,v 1.25 2014/03/20 19:22:16 roberto Exp $ | |
| 3 | 3 | ** Standard library for bitwise operations |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -13,17 +13,21 @@ · 7 unmodified lines | ||
| 13 | 13 | #include "lualib.h" |
| 14 | 14 | |
| 15 | 15 | |
| 16 | +#if defined(LUA_COMPAT_BITLIB) /* { */ | |
| 17 | + | |
| 18 | + | |
| 16 | 19 | /* number of bits to consider in a number */ |
| 17 | 20 | #if !defined(LUA_NBITS) |
| 18 | 21 | #define LUA_NBITS 32 |
| 19 | 22 | #endif |
| 20 | 23 | |
| 21 | 24 | |
| 22 | −/* type with (at least) LUA_NBITS bits */ | |
| 23 | −typedef unsigned long b_uint; | |
| 24 | − | |
| 25 | − | |
| 26 | −#define ALLONES (~(((~(b_uint)0) << (LUA_NBITS - 1)) << 1)) | |
| 25 | +/* | |
| 26 | +** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must | |
| 27 | +** be made in two parts to avoid problems when LUA_NBITS is equal to the | |
| 28 | +** number of bits in a lua_Unsigned.) | |
| 29 | +*/ | |
| 30 | +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) | |
| 27 | 31 | |
| 28 | 32 | |
| 29 | 33 | /* macro to trim extra bits */ |
| @@ -35,9 +39,9 @@ typedef unsigned long b_uint; · 5 unmodified lines | ||
| 35 | 39 | |
| 36 | 40 | |
| 37 | 41 | |
| 38 | −static b_uint andaux (lua_State *L) { | |
| 42 | +static lua_Unsigned andaux (lua_State *L) { | |
| 39 | 43 | int i, n = lua_gettop(L); |
| 40 | − b_uint r = ~(b_uint)0; | |
| 44 | + lua_Unsigned r = ~(lua_Unsigned)0; | |
| 41 | 45 | for (i = 1; i <= n; i++) |
| 42 | 46 | r &= luaL_checkunsigned(L, i); |
| 43 | 47 | return trim(r); |
| @@ -45,14 +49,14 @@ static b_uint andaux (lua_State *L) { · 1 unmodified line | ||
| 45 | 49 | |
| 46 | 50 | |
| 47 | 51 | static int b_and (lua_State *L) { |
| 48 | − b_uint r = andaux(L); | |
| 52 | + lua_Unsigned r = andaux(L); | |
| 49 | 53 | lua_pushunsigned(L, r); |
| 50 | 54 | return 1; |
| 51 | 55 | } |
| 52 | 56 | |
| 53 | 57 | |
| 54 | 58 | static int b_test (lua_State *L) { |
| 55 | − b_uint r = andaux(L); | |
| 59 | + lua_Unsigned r = andaux(L); | |
| 56 | 60 | lua_pushboolean(L, r != 0); |
| 57 | 61 | return 1; |
| 58 | 62 | } |
| @@ -60,7 +64,7 @@ static int b_test (lua_State *L) { · 1 unmodified line | ||
| 60 | 64 | |
| 61 | 65 | static int b_or (lua_State *L) { |
| 62 | 66 | int i, n = lua_gettop(L); |
| 63 | − b_uint r = 0; | |
| 67 | + lua_Unsigned r = 0; | |
| 64 | 68 | for (i = 1; i <= n; i++) |
| 65 | 69 | r |= luaL_checkunsigned(L, i); |
| 66 | 70 | lua_pushunsigned(L, trim(r)); |
| @@ -70,7 +74,7 @@ static int b_or (lua_State *L) { · 3 unmodified lines | ||
| 70 | 74 | |
| 71 | 75 | static int b_xor (lua_State *L) { |
| 72 | 76 | int i, n = lua_gettop(L); |
| 73 | − b_uint r = 0; | |
| 77 | + lua_Unsigned r = 0; | |
| 74 | 78 | for (i = 1; i <= n; i++) |
| 75 | 79 | r ^= luaL_checkunsigned(L, i); |
| 76 | 80 | lua_pushunsigned(L, trim(r)); |
| @@ -79,13 +83,13 @@ static int b_xor (lua_State *L) { · 2 unmodified lines | ||
| 79 | 83 | |
| 80 | 84 | |
| 81 | 85 | static int b_not (lua_State *L) { |
| 82 | − b_uint r = ~luaL_checkunsigned(L, 1); | |
| 86 | + lua_Unsigned r = ~luaL_checkunsigned(L, 1); | |
| 83 | 87 | lua_pushunsigned(L, trim(r)); |
| 84 | 88 | return 1; |
| 85 | 89 | } |
| 86 | 90 | |
| 87 | 91 | |
| 88 | −static int b_shift (lua_State *L, b_uint r, int i) { | |
| 92 | +static int b_shift (lua_State *L, lua_Unsigned r, int i) { | |
| 89 | 93 | if (i < 0) { /* shift right? */ |
| 90 | 94 | i = -i; |
| 91 | 95 | r = trim(r); |
| @@ -113,14 +117,14 @@ static int b_rshift (lua_State *L) { · 21 unmodified lines | ||
| 113 | 117 | |
| 114 | 118 | |
| 115 | 119 | static int b_arshift (lua_State *L) { |
| 116 | − b_uint r = luaL_checkunsigned(L, 1); | |
| 120 | + lua_Unsigned r = luaL_checkunsigned(L, 1); | |
| 117 | 121 | int i = luaL_checkint(L, 2); |
| 118 | − if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) | |
| 122 | + if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) | |
| 119 | 123 | return b_shift(L, r, -i); |
| 120 | 124 | else { /* arithmetic shift for 'negative' number */ |
| 121 | 125 | if (i >= LUA_NBITS) r = ALLONES; |
| 122 | 126 | else |
| 123 | − r = trim((r >> i) | ~(trim(~(b_uint)0) >> i)); /* add signal bit */ | |
| 127 | + r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ | |
| 124 | 128 | lua_pushunsigned(L, r); |
| 125 | 129 | return 1; |
| 126 | 130 | } |
| @@ -128,10 +132,11 @@ static int b_arshift (lua_State *L) { · 1 unmodified line | ||
| 128 | 132 | |
| 129 | 133 | |
| 130 | 134 | static int b_rot (lua_State *L, int i) { |
| 131 | − b_uint r = luaL_checkunsigned(L, 1); | |
| 135 | + lua_Unsigned r = luaL_checkunsigned(L, 1); | |
| 132 | 136 | i &= (LUA_NBITS - 1); /* i = i % NBITS */ |
| 133 | 137 | r = trim(r); |
| 134 | − r = (r << i) | (r >> (LUA_NBITS - i)); | |
| 138 | + if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ | |
| 139 | + r = (r << i) | (r >> (LUA_NBITS - i)); | |
| 135 | 140 | lua_pushunsigned(L, trim(r)); |
| 136 | 141 | return 1; |
| 137 | 142 | } |
| @@ -167,7 +172,7 @@ static int fieldargs (lua_State *L, int farg, int *width) { · 29 unmodified lines | ||
| 167 | 172 | |
| 168 | 173 | static int b_extract (lua_State *L) { |
| 169 | 174 | int w; |
| 170 | − b_uint r = trim(luaL_checkunsigned(L, 1)); | |
| 175 | + lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); | |
| 171 | 176 | int f = fieldargs(L, 2, &w); |
| 172 | 177 | r = (r >> f) & mask(w); |
| 173 | 178 | lua_pushunsigned(L, r); |
| @@ -177,8 +182,8 @@ static int b_extract (lua_State *L) { · 3 unmodified lines | ||
| 177 | 182 | |
| 178 | 183 | static int b_replace (lua_State *L) { |
| 179 | 184 | int w; |
| 180 | − b_uint r = trim(luaL_checkunsigned(L, 1)); | |
| 181 | − b_uint v = luaL_checkunsigned(L, 2); | |
| 185 | + lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); | |
| 186 | + lua_Unsigned v = luaL_checkunsigned(L, 2); | |
| 182 | 187 | int f = fieldargs(L, 3, &w); |
| 183 | 188 | int m = mask(w); |
| 184 | 189 | v &= m; /* erase bits outside given width */ |
| @@ -211,3 +216,13 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) { · 26 unmodified lines | ||
| 211 | 216 | return 1; |
| 212 | 217 | } |
| 213 | 218 | |
| 219 | + | |
| 220 | +#else /* }{ */ | |
| 221 | + | |
| 222 | + | |
| 223 | +LUAMOD_API int luaopen_bit32 (lua_State *L) { | |
| 224 | + lua_pushnil(L); | |
| 225 | + return 1; | |
| 226 | +} | |
| 227 | + | |
| 228 | +#endif /* } */ | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp $ | |
| 2 | +** $Id: lcode.c,v 2.85 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -307,17 +307,21 @@ static void freeexp (FuncState *fs, expdesc *e) { · 301 unmodified lines | ||
| 307 | 307 | } |
| 308 | 308 | |
| 309 | 309 | |
| 310 | +/* | |
| 311 | +** Use scanner's table to cache position of constants in constant list | |
| 312 | +** and try to reuse constants | |
| 313 | +*/ | |
| 310 | 314 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
| 311 | 315 | lua_State *L = fs->ls->L; |
| 312 | − TValue *idx = luaH_set(L, fs->h, key); | |
| 313 | 316 | Proto *f = fs->f; |
| 317 | + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ | |
| 314 | 318 | int k, oldsize; |
| 315 | − if (ttisinteger(idx)) { | |
| 319 | + if (ttisinteger(idx)) { /* is there an index there? */ | |
| 316 | 320 | k = ivalue(idx); |
| 317 | − if (luaV_rawequalobj(&f->k[k], v)) | |
| 318 | − return k; | |
| 319 | − /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); | |
| 320 | − go through and create a new entry for this value */ | |
| 321 | + /* correct value? (warning: must distinguish floats from integers!) */ | |
| 322 | + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && | |
| 323 | + luaV_rawequalobj(&f->k[k], v)) | |
| 324 | + return k; /* reuse index */ | |
| 321 | 325 | } |
| 322 | 326 | /* constant not found; create a new entry */ |
| 323 | 327 | oldsize = f->sizek; |
| @@ -360,7 +364,7 @@ int luaK_intK (FuncState *fs, lua_Integer n) { · 36 unmodified lines | ||
| 360 | 364 | */ |
| 361 | 365 | static int luaK_numberK (FuncState *fs, lua_Number r) { |
| 362 | 366 | TValue o; |
| 363 | − lua_assert(!luai_numisnan(NULL, r) && !isminuszero(r)); | |
| 367 | + lua_assert(!luai_numisnan(r) && !isminuszero(r)); | |
| 364 | 368 | setnvalue(&o, r); |
| 365 | 369 | return addk(fs, &o, &o); |
| 366 | 370 | } |
| @@ -377,7 +381,7 @@ static int nilK (FuncState *fs) { · 10 unmodified lines | ||
| 377 | 381 | TValue k, v; |
| 378 | 382 | setnilvalue(&v); |
| 379 | 383 | /* cannot use nil as key; instead use table itself to represent nil */ |
| 380 | − sethvalue(fs->ls->L, &k, fs->h); | |
| 384 | + sethvalue(fs->ls->L, &k, fs->ls->h); | |
| 381 | 385 | return addk(fs, &k, &v); |
| 382 | 386 | } |
| 383 | 387 | |
| @@ -746,24 +750,46 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { · 362 unmodified lines | ||
| 746 | 750 | } |
| 747 | 751 | |
| 748 | 752 | |
| 749 | −static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |
| 750 | − TValue v1, v2, res; | |
| 753 | +/* | |
| 754 | +** return false if folding can raise an error | |
| 755 | +*/ | |
| 756 | +static int validop (int op, TValue *v1, TValue *v2) { | |
| 757 | + lua_Number a, b; | |
| 751 | 758 | lua_Integer i; |
| 752 | − if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) | |
| 759 | + cast_void(a); cast_void(b); /* macro may not use its arguments */ | |
| 760 | + if (luai_numinvalidop(op, (cast_void(tonumber(v1, &a)), a), | |
| 761 | + (cast_void(tonumber(v2, &b)), b))) | |
| 753 | 762 | return 0; |
| 754 | − if (op == OP_IDIV && | |
| 755 | − (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) | |
| 756 | − return 0; /* avoid division by 0 and conversion errors */ | |
| 757 | − if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0) | |
| 758 | − return 0; /* avoid module by 0 at compile time */ | |
| 759 | − luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); | |
| 763 | + switch (op) { | |
| 764 | + case LUA_OPIDIV: /* division by 0 and conversion errors */ | |
| 765 | + return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0); | |
| 766 | + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: | |
| 767 | + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: /* conversion errors */ | |
| 768 | + return (tointeger(v1, &i) && tointeger(v2, &i)); | |
| 769 | + case LUA_OPMOD: /* integer module by 0 */ | |
| 770 | + return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0); | |
| 771 | + case LUA_OPPOW: /* negative integer exponentiation */ | |
| 772 | + return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) < 0); | |
| 773 | + default: return 1; /* everything else is valid */ | |
| 774 | + } | |
| 775 | +} | |
| 776 | + | |
| 777 | + | |
| 778 | +/* | |
| 779 | +** Try to "constant-fold" an operation; return 1 iff successful | |
| 780 | +*/ | |
| 781 | +static int constfolding (FuncState *fs, int op, expdesc *e1, expdesc *e2) { | |
| 782 | + TValue v1, v2, res; | |
| 783 | + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) | |
| 784 | + return 0; /* non-numeric operands or not safe to fold */ | |
| 785 | + luaO_arith(fs->ls->L, op, &v1, &v2, &res); | |
| 760 | 786 | if (ttisinteger(&res)) { |
| 761 | 787 | e1->k = VKINT; |
| 762 | 788 | e1->u.ival = ivalue(&res); |
| 763 | 789 | } |
| 764 | 790 | else { |
| 765 | 791 | lua_Number n = fltvalue(&res); |
| 766 | − if (luai_numisnan(NULL, n) || isminuszero(n)) | |
| 792 | + if (luai_numisnan(n) || isminuszero(n)) | |
| 767 | 793 | return 0; /* folds neither NaN nor -0 */ |
| 768 | 794 | e1->k = VKFLT; |
| 769 | 795 | e1->u.nval = n; |
| @@ -774,9 +800,16 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { · 4 unmodified lines | ||
| 774 | 800 | |
| 775 | 801 | static void codearith (FuncState *fs, OpCode op, |
| 776 | 802 | expdesc *e1, expdesc *e2, int line) { |
| 777 | − if (!constfolding(op, e1, e2)) { /* could not fold operation? */ | |
| 778 | − int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; | |
| 779 | − int o1 = luaK_exp2RK(fs, e1); | |
| 803 | + if (!constfolding(fs, op - OP_ADD + LUA_OPADD, e1, e2)) { | |
| 804 | + int o1, o2; | |
| 805 | + if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) { | |
| 806 | + o2 = 0; | |
| 807 | + o1 = luaK_exp2anyreg(fs, e1); /* cannot operate on constants */ | |
| 808 | + } | |
| 809 | + else { /* regular case (binary operators) */ | |
| 810 | + o2 = luaK_exp2RK(fs, e2); | |
| 811 | + o1 = luaK_exp2RK(fs, e1); | |
| 812 | + } | |
| 780 | 813 | if (o1 > o2) { |
| 781 | 814 | freeexp(fs, e1); |
| 782 | 815 | freeexp(fs, e2); |
| @@ -810,21 +843,13 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, · 27 unmodified lines | ||
| 810 | 843 | |
| 811 | 844 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
| 812 | 845 | expdesc e2; |
| 813 | − e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; | |
| 846 | + e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0; | |
| 814 | 847 | switch (op) { |
| 815 | − case OPR_MINUS: { | |
| 816 | − if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */ | |
| 817 | − luaK_exp2anyreg(fs, e); | |
| 818 | − codearith(fs, OP_UNM, e, &e2, line); | |
| 819 | − } | |
| 848 | + case OPR_MINUS: case OPR_BNOT: case OPR_LEN: { | |
| 849 | + codearith(fs, cast(OpCode, (op - OPR_MINUS) + OP_UNM), e, &e2, line); | |
| 820 | 850 | break; |
| 821 | 851 | } |
| 822 | 852 | case OPR_NOT: codenot(fs, e); break; |
| 823 | − case OPR_LEN: { | |
| 824 | − luaK_exp2anyreg(fs, e); /* cannot operate on constants */ | |
| 825 | − codearith(fs, OP_LEN, e, &e2, line); | |
| 826 | − break; | |
| 827 | − } | |
| 828 | 853 | default: lua_assert(0); |
| 829 | 854 | } |
| 830 | 855 | } |
| @@ -846,7 +871,9 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { · 15 unmodified lines | ||
| 846 | 871 | } |
| 847 | 872 | case OPR_ADD: case OPR_SUB: |
| 848 | 873 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: |
| 849 | − case OPR_MOD: case OPR_POW: { | |
| 874 | + case OPR_MOD: case OPR_POW: | |
| 875 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: | |
| 876 | + case OPR_SHL: case OPR_SHR: { | |
| 850 | 877 | if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v); |
| 851 | 878 | break; |
| 852 | 879 | } |
| @@ -890,8 +917,10 @@ void luaK_posfix (FuncState *fs, BinOpr op, · 37 unmodified lines | ||
| 890 | 917 | break; |
| 891 | 918 | } |
| 892 | 919 | case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: |
| 893 | − case OPR_IDIV: case OPR_MOD: case OPR_POW: { | |
| 894 | − codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); | |
| 920 | + case OPR_IDIV: case OPR_MOD: case OPR_POW: | |
| 921 | + case OPR_BAND: case OPR_BOR: case OPR_BXOR: | |
| 922 | + case OPR_SHL: case OPR_SHR: { | |
| 923 | + codearith(fs, cast(OpCode, (op - OPR_ADD) + OP_ADD), e1, e2, line); | |
| 895 | 924 | break; |
| 896 | 925 | } |
| 897 | 926 | case OPR_EQ: case OPR_LT: case OPR_LE: { |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lcode.h,v 1.60 2013/04/26 13:07:53 roberto Exp $ | |
| 2 | +** $Id: lcode.h,v 1.63 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Code generator for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -24,7 +24,11 @@ · 18 unmodified lines | ||
| 24 | 24 | ** grep "ORDER OPR" if you change these enums (ORDER OP) |
| 25 | 25 | */ |
| 26 | 26 | typedef enum BinOpr { |
| 27 | − OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_IDIV, OPR_MOD, OPR_POW, | |
| 27 | + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, | |
| 28 | + OPR_DIV, | |
| 29 | + OPR_IDIV, | |
| 30 | + OPR_BAND, OPR_BOR, OPR_BXOR, | |
| 31 | + OPR_SHL, OPR_SHR, | |
| 28 | 32 | OPR_CONCAT, |
| 29 | 33 | OPR_EQ, OPR_LT, OPR_LE, |
| 30 | 34 | OPR_NE, OPR_GT, OPR_GE, |
| @@ -33,7 +37,7 @@ typedef enum BinOpr { · 2 unmodified lines | ||
| 33 | 37 | } BinOpr; |
| 34 | 38 | |
| 35 | 39 | |
| 36 | −typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; | |
| 40 | +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; | |
| 37 | 41 | |
| 38 | 42 | |
| 39 | 43 | #define getcode(fs,e) ((fs)->f->code[(e)->u.info]) |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldblib.c,v 1.133 2013/06/25 19:37:00 roberto Exp $ | |
| 2 | +** $Id: ldblib.c,v 1.137 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Interface from Lua to its debug API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -69,11 +69,8 @@ static int db_getuservalue (lua_State *L) { · 63 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | |
| 71 | 71 | static int db_setuservalue (lua_State *L) { |
| 72 | − if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) | |
| 73 | − luaL_argerror(L, 1, "full userdata expected, got light userdata"); | |
| 74 | 72 | luaL_checktype(L, 1, LUA_TUSERDATA); |
| 75 | − if (!lua_isnoneornil(L, 2)) | |
| 76 | − luaL_checktype(L, 2, LUA_TTABLE); | |
| 73 | + luaL_checkany(L, 2); | |
| 77 | 74 | lua_settop(L, 2); |
| 78 | 75 | lua_setuservalue(L, 1); |
| 79 | 76 | return 1; |
| @@ -273,8 +270,7 @@ static void hookf (lua_State *L, lua_Debug *ar) { · 193 unmodified lines | ||
| 273 | 270 | {"call", "return", "line", "count", "tail call"}; |
| 274 | 271 | gethooktable(L); |
| 275 | 272 | lua_pushthread(L); |
| 276 | − lua_rawget(L, -2); | |
| 277 | − if (lua_isfunction(L, -1)) { | |
| 273 | + if (lua_rawget(L, -2) == LUA_TFUNCTION) { | |
| 278 | 274 | lua_pushstring(L, hooknames[(int)ar->event]); |
| 279 | 275 | if (ar->currentline >= 0) |
| 280 | 276 | lua_pushinteger(L, ar->currentline); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldebug.c,v 2.95 2013/05/06 17:21:59 roberto Exp $ | |
| 2 | +** $Id: ldebug.c,v 2.97 2013/12/09 14:21:10 roberto Exp $ | |
| 3 | 3 | ** Debug Interface |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -50,7 +50,7 @@ static int currentline (CallInfo *ci) { · 44 unmodified lines | ||
| 50 | 50 | /* |
| 51 | 51 | ** this function can be called asynchronous (e.g. during a signal) |
| 52 | 52 | */ |
| 53 | −LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |
| 53 | +LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |
| 54 | 54 | if (func == NULL || mask == 0) { /* turn off hooks? */ |
| 55 | 55 | mask = 0; |
| 56 | 56 | func = NULL; |
| @@ -61,7 +61,6 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { · 4 unmodified lines | ||
| 61 | 61 | L->basehookcount = count; |
| 62 | 62 | resethookcount(L); |
| 63 | 63 | L->hookmask = cast_byte(mask); |
| 64 | − return 1; | |
| 65 | 64 | } |
| 66 | 65 | |
| 67 | 66 | |
| @@ -327,12 +326,20 @@ static void kname (Proto *p, int pc, int c, const char **name) { · 259 unmodified lines | ||
| 327 | 326 | } |
| 328 | 327 | |
| 329 | 328 | |
| 329 | +static int filterpc (int pc, int jmptarget) { | |
| 330 | + if (pc < jmptarget) /* is code conditional (inside a jump)? */ | |
| 331 | + return -1; /* cannot know who sets that register */ | |
| 332 | + else return pc; /* current position sets that register */ | |
| 333 | +} | |
| 334 | + | |
| 335 | + | |
| 330 | 336 | /* |
| 331 | 337 | ** try to find last instruction before 'lastpc' that modified register 'reg' |
| 332 | 338 | */ |
| 333 | 339 | static int findsetreg (Proto *p, int lastpc, int reg) { |
| 334 | 340 | int pc; |
| 335 | 341 | int setreg = -1; /* keep last instruction that changed 'reg' */ |
| 342 | + int jmptarget = 0; /* any code before this address is conditional */ | |
| 336 | 343 | for (pc = 0; pc < lastpc; pc++) { |
| 337 | 344 | Instruction i = p->code[pc]; |
| 338 | 345 | OpCode op = GET_OPCODE(i); |
| @@ -341,33 +348,33 @@ static int findsetreg (Proto *p, int lastpc, int reg) { · 2 unmodified lines | ||
| 341 | 348 | case OP_LOADNIL: { |
| 342 | 349 | int b = GETARG_B(i); |
| 343 | 350 | if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ |
| 344 | − setreg = pc; | |
| 351 | + setreg = filterpc(pc, jmptarget); | |
| 345 | 352 | break; |
| 346 | 353 | } |
| 347 | 354 | case OP_TFORCALL: { |
| 348 | − if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ | |
| 355 | + if (reg >= a + 2) /* affect all regs above its base */ | |
| 356 | + setreg = filterpc(pc, jmptarget); | |
| 349 | 357 | break; |
| 350 | 358 | } |
| 351 | 359 | case OP_CALL: |
| 352 | 360 | case OP_TAILCALL: { |
| 353 | − if (reg >= a) setreg = pc; /* affect all registers above base */ | |
| 361 | + if (reg >= a) /* affect all registers above base */ | |
| 362 | + setreg = filterpc(pc, jmptarget); | |
| 354 | 363 | break; |
| 355 | 364 | } |
| 356 | 365 | case OP_JMP: { |
| 357 | 366 | int b = GETARG_sBx(i); |
| 358 | 367 | int dest = pc + 1 + b; |
| 359 | 368 | /* jump is forward and do not skip `lastpc'? */ |
| 360 | − if (pc < dest && dest <= lastpc) | |
| 361 | − pc += b; /* do the jump */ | |
| 362 | − break; | |
| 363 | − } | |
| 364 | − case OP_TEST: { | |
| 365 | − if (reg == a) setreg = pc; /* jumped code can change 'a' */ | |
| 369 | + if (pc < dest && dest <= lastpc) { | |
| 370 | + if (dest > jmptarget) | |
| 371 | + jmptarget = dest; /* update 'jmptarget' */ | |
| 372 | + } | |
| 366 | 373 | break; |
| 367 | 374 | } |
| 368 | 375 | default: |
| 369 | 376 | if (testAMode(op) && reg == a) /* any instruction that set A */ |
| 370 | − setreg = pc; | |
| 377 | + setreg = filterpc(pc, jmptarget); | |
| 371 | 378 | break; |
| 372 | 379 | } |
| 373 | 380 | } |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldebug.h,v 2.10 2013/05/06 17:19:11 roberto Exp $ | |
| 2 | +** $Id: ldebug.h,v 2.11 2014/02/25 14:31:16 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions from Debug Interface module |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -13,7 +13,7 @@ · 7 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) |
| 15 | 15 | |
| 16 | −#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) | |
| 16 | +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) | |
| 17 | 17 | |
| 18 | 18 | #define resethookcount(L) (L->hookcount = L->basehookcount) |
| 19 | 19 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldo.c,v 2.109 2013/04/19 21:05:04 roberto Exp $ | |
| 2 | +** $Id: ldo.c,v 2.115 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Stack and Call structure of Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -46,30 +46,33 @@ · 40 unmodified lines | ||
| 46 | 46 | ** C++ code, with _longjmp/_setjmp when asked to use them, and with |
| 47 | 47 | ** longjmp/setjmp otherwise. |
| 48 | 48 | */ |
| 49 | −#if !defined(LUAI_THROW) | |
| 49 | +#if !defined(LUAI_THROW) /* { */ | |
| 50 | + | |
| 51 | +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ | |
| 50 | 52 | |
| 51 | −#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) | |
| 52 | 53 | /* C++ exceptions */ |
| 53 | 54 | #define LUAI_THROW(L,c) throw(c) |
| 54 | 55 | #define LUAI_TRY(L,c,a) \ |
| 55 | 56 | try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } |
| 56 | 57 | #define luai_jmpbuf int /* dummy variable */ |
| 57 | 58 | |
| 58 | −#elif defined(LUA_USE_ULONGJMP) | |
| 59 | −/* in Unix, try _longjmp/_setjmp (more efficient) */ | |
| 59 | +#elif defined(LUA_USE_POSIX) /* }{ */ | |
| 60 | + | |
| 61 | +/* in POSIX, try _longjmp/_setjmp (more efficient) */ | |
| 60 | 62 | #define LUAI_THROW(L,c) _longjmp((c)->b, 1) |
| 61 | 63 | #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } |
| 62 | 64 | #define luai_jmpbuf jmp_buf |
| 63 | 65 | |
| 64 | −#else | |
| 65 | −/* default handling with long jumps */ | |
| 66 | +#else /* }{ */ | |
| 67 | + | |
| 68 | +/* ANSI handling with long jumps */ | |
| 66 | 69 | #define LUAI_THROW(L,c) longjmp((c)->b, 1) |
| 67 | 70 | #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } |
| 68 | 71 | #define luai_jmpbuf jmp_buf |
| 69 | 72 | |
| 70 | −#endif | |
| 73 | +#endif /* } */ | |
| 71 | 74 | |
| 72 | −#endif | |
| 75 | +#endif /* } */ | |
| 73 | 76 | |
| 74 | 77 | |
| 75 | 78 | |
| @@ -141,10 +144,10 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { · 65 unmodified lines | ||
| 141 | 144 | |
| 142 | 145 | static void correctstack (lua_State *L, TValue *oldstack) { |
| 143 | 146 | CallInfo *ci; |
| 144 | − GCObject *up; | |
| 147 | + UpVal *up; | |
| 145 | 148 | L->top = (L->top - oldstack) + L->stack; |
| 146 | − for (up = L->openupval; up != NULL; up = up->gch.next) | |
| 147 | − gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; | |
| 149 | + for (up = L->openupval; up != NULL; up = up->u.open.next) | |
| 150 | + up->v = (up->v - oldstack) + L->stack; | |
| 148 | 151 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
| 149 | 152 | ci->top = (ci->top - oldstack) + L->stack; |
| 150 | 153 | ci->func = (ci->func - oldstack) + L->stack; |
| @@ -206,7 +209,11 @@ void luaD_shrinkstack (lua_State *L) { · 55 unmodified lines | ||
| 206 | 209 | int inuse = stackinuse(L); |
| 207 | 210 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; |
| 208 | 211 | if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; |
| 209 | − if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ | |
| 212 | + if (L->stacksize > LUAI_MAXSTACK) /* was handling stack overflow? */ | |
| 213 | + luaE_freeCI(L); /* free all CIs (list grew because of an error) */ | |
| 214 | + else | |
| 215 | + luaE_shrinkCI(L); /* shrink list */ | |
| 216 | + if (inuse > LUAI_MAXSTACK || /* still handling stack overflow? */ | |
| 210 | 217 | goodsize >= L->stacksize) /* would grow instead of shrink? */ |
| 211 | 218 | condmovestack(L); /* don't change stack (change only for debugging) */ |
| 212 | 219 | else |
| @@ -534,6 +541,7 @@ static void resume (lua_State *L, void *ud) { · 321 unmodified lines | ||
| 534 | 541 | |
| 535 | 542 | LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { |
| 536 | 543 | int status; |
| 544 | + int oldnny = L->nny; /* save 'nny' */ | |
| 537 | 545 | lua_lock(L); |
| 538 | 546 | luai_userstateresume(L, nargs); |
| 539 | 547 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; |
| @@ -555,7 +563,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { · 15 unmodified lines | ||
| 555 | 563 | } |
| 556 | 564 | lua_assert(status == L->status); |
| 557 | 565 | } |
| 558 | − L->nny = 1; /* do not allow yields */ | |
| 566 | + L->nny = oldnny; /* restore 'nny' */ | |
| 559 | 567 | L->nCcalls--; |
| 560 | 568 | lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); |
| 561 | 569 | lua_unlock(L); |
| @@ -637,7 +645,6 @@ static void checkmode (lua_State *L, const char *mode, const char *x) { · 75 unmodified lines | ||
| 637 | 645 | |
| 638 | 646 | |
| 639 | 647 | static void f_parser (lua_State *L, void *ud) { |
| 640 | − int i; | |
| 641 | 648 | Closure *cl; |
| 642 | 649 | struct SParser *p = cast(struct SParser *, ud); |
| 643 | 650 | int c = zgetc(p->z); /* read first character */ |
| @@ -650,11 +657,7 @@ static void f_parser (lua_State *L, void *ud) { · 6 unmodified lines | ||
| 650 | 657 | cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); |
| 651 | 658 | } |
| 652 | 659 | lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); |
| 653 | − for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ | |
| 654 | − UpVal *up = luaF_newupval(L); | |
| 655 | − cl->l.upvals[i] = up; | |
| 656 | − luaC_objbarrier(L, cl, up); | |
| 657 | − } | |
| 660 | + luaF_initupvals(L, &cl->l); | |
| 658 | 661 | } |
| 659 | 662 | |
| 660 | 663 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ldump.c,v 2.19 2013/04/26 18:48:35 roberto Exp $ | |
| 2 | +** $Id: ldump.c,v 2.27 2014/03/11 18:56:27 roberto Exp $ | |
| 3 | 3 | ** save precompiled Lua chunks |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -15,167 +15,188 @@ · 9 unmodified lines | ||
| 15 | 15 | #include "lstate.h" |
| 16 | 16 | #include "lundump.h" |
| 17 | 17 | |
| 18 | + | |
| 18 | 19 | typedef struct { |
| 19 | − lua_State* L; | |
| 20 | − lua_Writer writer; | |
| 21 | − void* data; | |
| 22 | − int strip; | |
| 23 | − int status; | |
| 20 | + lua_State *L; | |
| 21 | + lua_Writer writer; | |
| 22 | + void *data; | |
| 23 | + int strip; | |
| 24 | + int status; | |
| 24 | 25 | } DumpState; |
| 25 | 26 | |
| 26 | −#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) | |
| 27 | −#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) | |
| 28 | − | |
| 29 | −static void DumpBlock(const void* b, size_t size, DumpState* D) | |
| 30 | −{ | |
| 31 | − if (D->status==0) | |
| 32 | − { | |
| 33 | − lua_unlock(D->L); | |
| 34 | − D->status=(*D->writer)(D->L,b,size,D->data); | |
| 35 | − lua_lock(D->L); | |
| 36 | − } | |
| 27 | + | |
| 28 | +/* | |
| 29 | +** All high-level dumps go through DumpVector; you can change it to | |
| 30 | +** change the endianess of the result | |
| 31 | +*/ | |
| 32 | +#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) | |
| 33 | + | |
| 34 | +#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) | |
| 35 | + | |
| 36 | + | |
| 37 | +static void DumpBlock (const void *b, size_t size, DumpState *D) { | |
| 38 | + if (D->status == 0) { | |
| 39 | + lua_unlock(D->L); | |
| 40 | + D->status = (*D->writer)(D->L, b, size, D->data); | |
| 41 | + lua_lock(D->L); | |
| 42 | + } | |
| 37 | 43 | } |
| 38 | 44 | |
| 39 | −static void DumpChar(int y, DumpState* D) | |
| 40 | −{ | |
| 41 | − char x=(char)y; | |
| 42 | − DumpVar(x,D); | |
| 45 | + | |
| 46 | +#define DumpVar(x,D) DumpVector(&x,1,D) | |
| 47 | + | |
| 48 | + | |
| 49 | +static void DumpByte (int y, DumpState *D) { | |
| 50 | + lu_byte x = (lu_byte)y; | |
| 51 | + DumpVar(x, D); | |
| 43 | 52 | } |
| 44 | 53 | |
| 45 | −static void DumpInt(int x, DumpState* D) | |
| 46 | −{ | |
| 47 | − DumpVar(x,D); | |
| 54 | + | |
| 55 | +static void DumpInt (int x, DumpState *D) { | |
| 56 | + DumpVar(x, D); | |
| 48 | 57 | } |
| 49 | 58 | |
| 50 | −static void DumpNumber(lua_Number x, DumpState* D) | |
| 51 | −{ | |
| 52 | − DumpVar(x,D); | |
| 59 | + | |
| 60 | +static void DumpNumber (lua_Number x, DumpState *D) { | |
| 61 | + DumpVar(x, D); | |
| 53 | 62 | } |
| 54 | 63 | |
| 55 | −static void DumpInteger(lua_Integer x, DumpState* D) | |
| 56 | −{ | |
| 57 | − DumpVar(x,D); | |
| 64 | + | |
| 65 | +static void DumpInteger (lua_Integer x, DumpState *D) { | |
| 66 | + DumpVar(x, D); | |
| 58 | 67 | } |
| 59 | 68 | |
| 60 | −static void DumpVector(const void* b, int n, size_t size, DumpState* D) | |
| 61 | −{ | |
| 62 | − DumpInt(n,D); | |
| 63 | − DumpMem(b,n,size,D); | |
| 69 | + | |
| 70 | +static void DumpString (const TString *s, DumpState *D) { | |
| 71 | + if (s == NULL) | |
| 72 | + DumpByte(0, D); | |
| 73 | + else { | |
| 74 | + size_t size = s->tsv.len + 1; /* include trailing '\0' */ | |
| 75 | + if (size < 0xFF) | |
| 76 | + DumpByte(size, D); | |
| 77 | + else { | |
| 78 | + DumpByte(0xFF, D); | |
| 79 | + DumpVar(size, D); | |
| 80 | + } | |
| 81 | + DumpVector(getstr(s), size - 1, D); /* no need to save '\0' */ | |
| 82 | + } | |
| 64 | 83 | } |
| 65 | 84 | |
| 66 | −static void DumpString(const TString* s, DumpState* D) | |
| 67 | −{ | |
| 68 | − if (s==NULL) | |
| 69 | − { | |
| 70 | − size_t size=0; | |
| 71 | − DumpVar(size,D); | |
| 72 | − } | |
| 73 | − else | |
| 74 | − { | |
| 75 | − size_t size=s->tsv.len+1; /* include trailing '\0' */ | |
| 76 | − DumpVar(size,D); | |
| 77 | − DumpBlock(getstr(s),size*sizeof(char),D); | |
| 78 | − } | |
| 85 | + | |
| 86 | +static void DumpCode (const Proto *f, DumpState *D) { | |
| 87 | + DumpInt(f->sizecode, D); | |
| 88 | + DumpVector(f->code, f->sizecode, D); | |
| 79 | 89 | } |
| 80 | 90 | |
| 81 | −#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) | |
| 82 | − | |
| 83 | −static void DumpFunction(const Proto* f, DumpState* D); | |
| 84 | − | |
| 85 | −static void DumpConstants(const Proto* f, DumpState* D) | |
| 86 | −{ | |
| 87 | − int i,n=f->sizek; | |
| 88 | − DumpInt(n,D); | |
| 89 | − for (i=0; i<n; i++) | |
| 90 | − { | |
| 91 | − const TValue* o=&f->k[i]; | |
| 92 | − DumpChar(ttype(o),D); | |
| 93 | − switch (ttype(o)) | |
| 94 | − { | |
| 95 | − case LUA_TNIL: | |
| 96 | − break; | |
| 97 | − case LUA_TBOOLEAN: | |
| 98 | − DumpChar(bvalue(o),D); | |
| 99 | − break; | |
| 100 | − case LUA_TNUMFLT: | |
| 101 | − DumpNumber(fltvalue(o),D); | |
| 102 | − break; | |
| 103 | − case LUA_TNUMINT: | |
| 104 | − DumpInteger(ivalue(o),D); | |
| 105 | − break; | |
| 106 | − case LUA_TSHRSTR: case LUA_TLNGSTR: | |
| 107 | − DumpString(rawtsvalue(o),D); | |
| 108 | − break; | |
| 109 | − default: lua_assert(0); | |
| 91 | + | |
| 92 | +static void DumpFunction(const Proto *f, DumpState *D); | |
| 93 | + | |
| 94 | +static void DumpConstants (const Proto *f, DumpState *D) { | |
| 95 | + int i; | |
| 96 | + int n = f->sizek; | |
| 97 | + DumpInt(n, D); | |
| 98 | + for (i = 0; i < n; i++) { | |
| 99 | + const TValue *o = &f->k[i]; | |
| 100 | + DumpByte(ttype(o), D); | |
| 101 | + switch (ttype(o)) { | |
| 102 | + case LUA_TNIL: | |
| 103 | + break; | |
| 104 | + case LUA_TBOOLEAN: | |
| 105 | + DumpByte(bvalue(o), D); | |
| 106 | + break; | |
| 107 | + case LUA_TNUMFLT: | |
| 108 | + DumpNumber(fltvalue(o), D); | |
| 109 | + break; | |
| 110 | + case LUA_TNUMINT: | |
| 111 | + DumpInteger(ivalue(o), D); | |
| 112 | + break; | |
| 113 | + case LUA_TSHRSTR: | |
| 114 | + case LUA_TLNGSTR: | |
| 115 | + DumpString(rawtsvalue(o), D); | |
| 116 | + break; | |
| 117 | + default: | |
| 118 | + lua_assert(0); | |
| 119 | + } | |
| 110 | 120 | } |
| 111 | − } | |
| 112 | − n=f->sizep; | |
| 113 | − DumpInt(n,D); | |
| 114 | − for (i=0; i<n; i++) DumpFunction(f->p[i],D); | |
| 121 | + n = f->sizep; | |
| 122 | + DumpInt(n, D); | |
| 123 | + for (i = 0; i < n; i++) | |
| 124 | + DumpFunction(f->p[i], D); | |
| 115 | 125 | } |
| 116 | 126 | |
| 117 | −static void DumpUpvalues(const Proto* f, DumpState* D) | |
| 118 | −{ | |
| 119 | − int i,n=f->sizeupvalues; | |
| 120 | − DumpInt(n,D); | |
| 121 | − for (i=0; i<n; i++) | |
| 122 | − { | |
| 123 | − DumpChar(f->upvalues[i].instack,D); | |
| 124 | − DumpChar(f->upvalues[i].idx,D); | |
| 125 | − } | |
| 127 | + | |
| 128 | +static void DumpUpvalues (const Proto *f, DumpState *D) { | |
| 129 | + int i, n = f->sizeupvalues; | |
| 130 | + DumpInt(n, D); | |
| 131 | + for (i = 0; i < n; i++) { | |
| 132 | + DumpByte(f->upvalues[i].instack, D); | |
| 133 | + DumpByte(f->upvalues[i].idx, D); | |
| 134 | + } | |
| 126 | 135 | } |
| 127 | 136 | |
| 128 | −static void DumpDebug(const Proto* f, DumpState* D) | |
| 129 | −{ | |
| 130 | − int i,n; | |
| 131 | − DumpString((D->strip) ? NULL : f->source,D); | |
| 132 | − n= (D->strip) ? 0 : f->sizelineinfo; | |
| 133 | − DumpVector(f->lineinfo,n,sizeof(int),D); | |
| 134 | − n= (D->strip) ? 0 : f->sizelocvars; | |
| 135 | − DumpInt(n,D); | |
| 136 | − for (i=0; i<n; i++) | |
| 137 | − { | |
| 138 | − DumpString(f->locvars[i].varname,D); | |
| 139 | − DumpInt(f->locvars[i].startpc,D); | |
| 140 | − DumpInt(f->locvars[i].endpc,D); | |
| 141 | − } | |
| 142 | − n= (D->strip) ? 0 : f->sizeupvalues; | |
| 143 | − DumpInt(n,D); | |
| 144 | − for (i=0; i<n; i++) DumpString(f->upvalues[i].name,D); | |
| 137 | + | |
| 138 | +static void DumpDebug (const Proto *f, DumpState *D) { | |
| 139 | + int i, n; | |
| 140 | + DumpString((D->strip) ? NULL : f->source, D); | |
| 141 | + n = (D->strip) ? 0 : f->sizelineinfo; | |
| 142 | + DumpInt(n, D); | |
| 143 | + DumpVector(f->lineinfo, n, D); | |
| 144 | + n = (D->strip) ? 0 : f->sizelocvars; | |
| 145 | + DumpInt(n, D); | |
| 146 | + for (i = 0; i < n; i++) { | |
| 147 | + DumpString(f->locvars[i].varname, D); | |
| 148 | + DumpInt(f->locvars[i].startpc, D); | |
| 149 | + DumpInt(f->locvars[i].endpc, D); | |
| 150 | + } | |
| 151 | + n = (D->strip) ? 0 : f->sizeupvalues; | |
| 152 | + DumpInt(n, D); | |
| 153 | + for (i = 0; i < n; i++) | |
| 154 | + DumpString(f->upvalues[i].name, D); | |
| 145 | 155 | } |
| 146 | 156 | |
| 147 | −static void DumpFunction(const Proto* f, DumpState* D) | |
| 148 | −{ | |
| 149 | − DumpInt(f->linedefined,D); | |
| 150 | − DumpInt(f->lastlinedefined,D); | |
| 151 | − DumpChar(f->numparams,D); | |
| 152 | − DumpChar(f->is_vararg,D); | |
| 153 | − DumpChar(f->maxstacksize,D); | |
| 154 | − DumpCode(f,D); | |
| 155 | − DumpConstants(f,D); | |
| 156 | − DumpUpvalues(f,D); | |
| 157 | − DumpDebug(f,D); | |
| 157 | + | |
| 158 | +static void DumpFunction (const Proto *f, DumpState *D) { | |
| 159 | + DumpInt(f->linedefined, D); | |
| 160 | + DumpInt(f->lastlinedefined, D); | |
| 161 | + DumpByte(f->numparams, D); | |
| 162 | + DumpByte(f->is_vararg, D); | |
| 163 | + DumpByte(f->maxstacksize, D); | |
| 164 | + DumpCode(f, D); | |
| 165 | + DumpConstants(f, D); | |
| 166 | + DumpUpvalues(f, D); | |
| 167 | + DumpDebug(f, D); | |
| 158 | 168 | } |
| 159 | 169 | |
| 160 | −static void DumpHeader(DumpState* D) | |
| 161 | −{ | |
| 162 | − lu_byte h[LUAC_HEADERSIZE]; | |
| 163 | − luaU_header(h); | |
| 164 | − DumpBlock(h,LUAC_HEADERSIZE,D); | |
| 170 | + | |
| 171 | +static void DumpHeader (DumpState *D) { | |
| 172 | + DumpLiteral(LUA_SIGNATURE, D); | |
| 173 | + DumpByte(LUAC_VERSION, D); | |
| 174 | + DumpByte(LUAC_FORMAT, D); | |
| 175 | + DumpLiteral(LUAC_DATA, D); | |
| 176 | + DumpByte(sizeof(int), D); | |
| 177 | + DumpByte(sizeof(size_t), D); | |
| 178 | + DumpByte(sizeof(Instruction), D); | |
| 179 | + DumpByte(sizeof(lua_Integer), D); | |
| 180 | + DumpByte(sizeof(lua_Number), D); | |
| 181 | + DumpInteger(LUAC_INT, D); | |
| 182 | + DumpNumber(LUAC_NUM, D); | |
| 165 | 183 | } |
| 166 | 184 | |
| 185 | + | |
| 167 | 186 | /* |
| 168 | 187 | ** dump Lua function as precompiled chunk |
| 169 | 188 | */ |
| 170 | −int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) | |
| 171 | −{ | |
| 172 | − DumpState D; | |
| 173 | − D.L=L; | |
| 174 | − D.writer=w; | |
| 175 | − D.data=data; | |
| 176 | − D.strip=strip; | |
| 177 | − D.status=0; | |
| 178 | − DumpHeader(&D); | |
| 179 | − DumpFunction(f,&D); | |
| 180 | − return D.status; | |
| 189 | +int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, | |
| 190 | + int strip) { | |
| 191 | + DumpState D; | |
| 192 | + D.L = L; | |
| 193 | + D.writer = w; | |
| 194 | + D.data = data; | |
| 195 | + D.strip = strip; | |
| 196 | + D.status = 0; | |
| 197 | + DumpHeader(&D); | |
| 198 | + DumpByte(f->sizeupvalues, &D); | |
| 199 | + DumpFunction(f, &D); | |
| 200 | + return D.status; | |
| 181 | 201 | } |
| 202 | + | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp $ | |
| 2 | +** $Id: lfunc.c,v 2.41 2014/02/18 13:39:37 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -21,94 +21,79 @@ · 15 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | |
| 23 | 23 | Closure *luaF_newCclosure (lua_State *L, int n) { |
| 24 | − Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; | |
| 24 | + Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n))->cl; | |
| 25 | 25 | c->c.nupvalues = cast_byte(n); |
| 26 | 26 | return c; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | |
| 30 | 30 | Closure *luaF_newLclosure (lua_State *L, int n) { |
| 31 | − Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; | |
| 31 | + Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n))->cl; | |
| 32 | 32 | c->l.p = NULL; |
| 33 | 33 | c->l.nupvalues = cast_byte(n); |
| 34 | 34 | while (n--) c->l.upvals[n] = NULL; |
| 35 | 35 | return c; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | − | |
| 39 | −UpVal *luaF_newupval (lua_State *L) { | |
| 40 | − UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; | |
| 41 | − uv->v = &uv->u.value; | |
| 42 | − setnilvalue(uv->v); | |
| 43 | − return uv; | |
| 38 | +/* | |
| 39 | +** fill a closure with new closed upvalues | |
| 40 | +*/ | |
| 41 | +void luaF_initupvals (lua_State *L, LClosure *cl) { | |
| 42 | + int i; | |
| 43 | + for (i = 0; i < cl->nupvalues; i++) { | |
| 44 | + UpVal *uv = luaM_new(L, UpVal); | |
| 45 | + uv->refcount = 1; | |
| 46 | + uv->v = &uv->u.value; /* make it closed */ | |
| 47 | + setnilvalue(uv->v); | |
| 48 | + cl->upvals[i] = uv; | |
| 49 | + } | |
| 44 | 50 | } |
| 45 | 51 | |
| 46 | 52 | |
| 47 | 53 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
| 48 | − global_State *g = G(L); | |
| 49 | − GCObject **pp = &L->openupval; | |
| 54 | + UpVal **pp = &L->openupval; | |
| 50 | 55 | UpVal *p; |
| 51 | 56 | UpVal *uv; |
| 52 | − while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { | |
| 53 | − GCObject *o = obj2gco(p); | |
| 54 | − lua_assert(p->v != &p->u.value); | |
| 55 | − lua_assert(!isold(o) || isold(obj2gco(L))); | |
| 56 | − if (p->v == level) { /* found a corresponding upvalue? */ | |
| 57 | − if (isdead(g, o)) /* is it dead? */ | |
| 58 | − changewhite(o); /* resurrect it */ | |
| 59 | − return p; | |
| 60 | − } | |
| 61 | − pp = &p->next; | |
| 57 | + lua_assert(isintwups(L) || L->openupval == NULL); | |
| 58 | + while (*pp != NULL && (p = *pp)->v >= level) { | |
| 59 | + lua_assert(upisopen(p)); | |
| 60 | + if (p->v == level) /* found a corresponding upvalue? */ | |
| 61 | + return p; /* return it */ | |
| 62 | + pp = &p->u.open.next; | |
| 62 | 63 | } |
| 63 | − /* not found: create a new one */ | |
| 64 | − uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; | |
| 64 | + /* not found: create a new upvalue */ | |
| 65 | + uv = luaM_new(L, UpVal); | |
| 66 | + uv->refcount = 0; | |
| 67 | + uv->u.open.next = *pp; /* link it to list of open upvalues */ | |
| 68 | + uv->u.open.touched = 1; | |
| 69 | + *pp = uv; | |
| 65 | 70 | uv->v = level; /* current value lives in the stack */ |
| 66 | − uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ | |
| 67 | − uv->u.l.next = g->uvhead.u.l.next; | |
| 68 | − uv->u.l.next->u.l.prev = uv; | |
| 69 | − g->uvhead.u.l.next = uv; | |
| 70 | − lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | |
| 71 | + if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ | |
| 72 | + L->twups = G(L)->twups; /* link it to the list */ | |
| 73 | + G(L)->twups = L; | |
| 74 | + } | |
| 71 | 75 | return uv; |
| 72 | 76 | } |
| 73 | 77 | |
| 74 | 78 | |
| 75 | −static void unlinkupval (UpVal *uv) { | |
| 76 | − lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); | |
| 77 | − uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ | |
| 78 | − uv->u.l.prev->u.l.next = uv->u.l.next; | |
| 79 | −} | |
| 80 | − | |
| 81 | − | |
| 82 | −void luaF_freeupval (lua_State *L, UpVal *uv) { | |
| 83 | − if (uv->v != &uv->u.value) /* is it open? */ | |
| 84 | − unlinkupval(uv); /* remove from open list */ | |
| 85 | − luaM_free(L, uv); /* free upvalue */ | |
| 86 | −} | |
| 87 | − | |
| 88 | − | |
| 89 | 79 | void luaF_close (lua_State *L, StkId level) { |
| 90 | 80 | UpVal *uv; |
| 91 | − global_State *g = G(L); | |
| 92 | − while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { | |
| 93 | − GCObject *o = obj2gco(uv); | |
| 94 | − lua_assert(!isblack(o) && uv->v != &uv->u.value); | |
| 95 | − L->openupval = uv->next; /* remove from `open' list */ | |
| 96 | − if (isdead(g, o)) | |
| 97 | − luaF_freeupval(L, uv); /* free upvalue */ | |
| 81 | + while (L->openupval != NULL && (uv = L->openupval)->v >= level) { | |
| 82 | + lua_assert(upisopen(uv)); | |
| 83 | + L->openupval = uv->u.open.next; /* remove from `open' list */ | |
| 84 | + if (uv->refcount == 0) /* no references? */ | |
| 85 | + luaM_free(L, uv); /* free upvalue */ | |
| 98 | 86 | else { |
| 99 | − unlinkupval(uv); /* remove upvalue from 'uvhead' list */ | |
| 100 | 87 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ |
| 101 | 88 | uv->v = &uv->u.value; /* now current value lives here */ |
| 102 | − gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ | |
| 103 | − g->allgc = o; | |
| 104 | − luaC_checkupvalcolor(g, uv); | |
| 89 | + luaC_upvalbarrier(L, uv); | |
| 105 | 90 | } |
| 106 | 91 | } |
| 107 | 92 | } |
| 108 | 93 | |
| 109 | 94 | |
| 110 | 95 | Proto *luaF_newproto (lua_State *L) { |
| 111 | − Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; | |
| 96 | + Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p; | |
| 112 | 97 | f->k = NULL; |
| 113 | 98 | f->sizek = 0; |
| 114 | 99 | f->p = NULL; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $ | |
| 2 | +** $Id: lfunc.h,v 2.13 2014/02/18 13:39:37 roberto Exp $ | |
| 3 | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -18,14 +18,35 @@ · 12 unmodified lines | ||
| 18 | 18 | cast(int, sizeof(TValue *)*((n)-1))) |
| 19 | 19 | |
| 20 | 20 | |
| 21 | +/* test whether thread is in 'twups' list */ | |
| 22 | +#define isintwups(L) (L->twups != L) | |
| 23 | + | |
| 24 | + | |
| 25 | +/* | |
| 26 | +** Upvalues for Lua closures | |
| 27 | +*/ | |
| 28 | +struct UpVal { | |
| 29 | + TValue *v; /* points to stack or to its own value */ | |
| 30 | + lu_mem refcount; /* reference counter */ | |
| 31 | + union { | |
| 32 | + struct { /* (when open) */ | |
| 33 | + UpVal *next; /* linked list */ | |
| 34 | + int touched; /* mark to avoid cycles with dead threads */ | |
| 35 | + } open; | |
| 36 | + TValue value; /* the value (when closed) */ | |
| 37 | + } u; | |
| 38 | +}; | |
| 39 | + | |
| 40 | +#define upisopen(up) ((up)->v != &(up)->u.value) | |
| 41 | + | |
| 42 | + | |
| 21 | 43 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); |
| 22 | 44 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); |
| 23 | 45 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); |
| 24 | −LUAI_FUNC UpVal *luaF_newupval (lua_State *L); | |
| 46 | +LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); | |
| 25 | 47 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); |
| 26 | 48 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); |
| 27 | 49 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); |
| 28 | −LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); | |
| 29 | 50 | LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, |
| 30 | 51 | int pc); |
| 31 | 52 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 roberto Exp $ | |
| 2 | +** $Id: lgc.c,v 2.179 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Garbage Collector |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -23,6 +23,11 @@ · 17 unmodified lines | ||
| 23 | 23 | #include "ltm.h" |
| 24 | 24 | |
| 25 | 25 | |
| 26 | +/* | |
| 27 | +** internal state for collector while inside the atomic phase. The | |
| 28 | +** collector should never be in this state while running regular code. | |
| 29 | +*/ | |
| 30 | +#define GCSinsideatomic (GCSpause + 1) | |
| 26 | 31 | |
| 27 | 32 | /* |
| 28 | 33 | ** cost of sweeping one element (the size of a small object divided |
| @@ -33,8 +38,8 @@ · 4 unmodified lines | ||
| 33 | 38 | /* maximum number of elements to sweep in each single step */ |
| 34 | 39 | #define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) |
| 35 | 40 | |
| 36 | −/* maximum number of finalizers to call in each GC step */ | |
| 37 | −#define GCFINALIZENUM 4 | |
| 41 | +/* cost of calling one finalizer */ | |
| 42 | +#define GCFINALIZECOST GCSWEEPCOST | |
| 38 | 43 | |
| 39 | 44 | |
| 40 | 45 | /* |
| @@ -52,10 +57,10 @@ · 11 unmodified lines | ||
| 52 | 57 | |
| 53 | 58 | |
| 54 | 59 | /* |
| 55 | −** 'makewhite' erases all color bits plus the old bit and then | |
| 56 | −** sets only the current white bit | |
| 60 | +** 'makewhite' erases all color bits then sets only the current white | |
| 61 | +** bit | |
| 57 | 62 | */ |
| 58 | −#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) | |
| 63 | +#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) | |
| 59 | 64 | #define makewhite(g,x) \ |
| 60 | 65 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) |
| 61 | 66 | |
| @@ -63,7 +68,7 @@ · 1 unmodified line | ||
| 63 | 68 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) |
| 64 | 69 | |
| 65 | 70 | |
| 66 | −#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) | |
| 71 | +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) | |
| 67 | 72 | |
| 68 | 73 | #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) |
| 69 | 74 | |
| @@ -75,8 +80,8 @@ · 5 unmodified lines | ||
| 75 | 80 | #define markvalue(g,o) { checkconsistency(o); \ |
| 76 | 81 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
| 77 | 82 | |
| 78 | −#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ | |
| 79 | − reallymarkobject(g, obj2gco(t)); } | |
| 83 | +#define markobject(g,t) \ | |
| 84 | + { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } | |
| 80 | 85 | |
| 81 | 86 | static void reallymarkobject (global_State *g, GCObject *o); |
| 82 | 87 | |
| @@ -136,8 +141,8 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { · 53 unmodified lines | ||
| 136 | 141 | global_State *g = G(L); |
| 137 | 142 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
| 138 | 143 | lua_assert(g->gcstate != GCSpause); |
| 139 | − lua_assert(gch(o)->tt != LUA_TTABLE); | |
| 140 | − if (keepinvariantout(g)) /* must keep invariant? */ | |
| 144 | + lua_assert(gch(o)->tt != LUA_TTABLE); /* tables use a back barrier */ | |
| 145 | + if (keepinvariant(g)) /* must keep invariant? */ | |
| 141 | 146 | reallymarkobject(g, v); /* restore invariant */ |
| 142 | 147 | else { /* sweep phase */ |
| 143 | 148 | lua_assert(issweepphase(g)); |
| @@ -162,64 +167,41 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) { · 18 unmodified lines | ||
| 162 | 167 | |
| 163 | 168 | |
| 164 | 169 | /* |
| 165 | −** barrier for prototypes. When creating first closure (cache is | |
| 166 | −** NULL), use a forward barrier; this may be the only closure of the | |
| 167 | −** prototype (if it is a "regular" function, with a single instance) | |
| 168 | −** and the prototype may be big, so it is better to avoid traversing | |
| 169 | −** it again. Otherwise, use a backward barrier, to avoid marking all | |
| 170 | −** possible instances. | |
| 170 | +** barrier for assignments to closed upvalues. Because upvalues are | |
| 171 | +** shared among closures, it is impossible to know the color of all | |
| 172 | +** closures pointing to it. So, we assume that the object being assigned | |
| 173 | +** must be marked. | |
| 171 | 174 | */ |
| 172 | −LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { | |
| 175 | +LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |
| 173 | 176 | global_State *g = G(L); |
| 174 | − lua_assert(isblack(obj2gco(p))); | |
| 175 | − if (p->cache == NULL) { /* first time? */ | |
| 176 | − luaC_objbarrier(L, p, c); | |
| 177 | − } | |
| 178 | − else { /* use a backward barrier */ | |
| 179 | − black2gray(obj2gco(p)); /* make prototype gray (again) */ | |
| 180 | − p->gclist = g->grayagain; | |
| 181 | − g->grayagain = obj2gco(p); | |
| 182 | − } | |
| 177 | + GCObject *o = gcvalue(uv->v); | |
| 178 | + lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ | |
| 179 | + if (keepinvariant(g)) | |
| 180 | + markobject(g, o); | |
| 183 | 181 | } |
| 184 | 182 | |
| 185 | 183 | |
| 186 | −/* | |
| 187 | −** check color (and invariants) for an upvalue that was closed, | |
| 188 | −** i.e., moved into the 'allgc' list | |
| 189 | −*/ | |
| 190 | −void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | |
| 191 | − GCObject *o = obj2gco(uv); | |
| 192 | − lua_assert(!isblack(o)); /* open upvalues are never black */ | |
| 193 | − if (isgray(o)) { | |
| 194 | − if (keepinvariant(g)) { | |
| 195 | − resetoldbit(o); /* see MOVE OLD rule */ | |
| 196 | − gray2black(o); /* it is being visited now */ | |
| 197 | − markvalue(g, uv->v); | |
| 198 | − } | |
| 199 | − else { | |
| 200 | − lua_assert(issweepphase(g)); | |
| 201 | − makewhite(g, o); | |
| 202 | − } | |
| 203 | − } | |
| 184 | +void luaC_fix (lua_State *L, GCObject *o) { | |
| 185 | + global_State *g = G(L); | |
| 186 | + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ | |
| 187 | + white2gray(o); /* they will be gray forever */ | |
| 188 | + g->allgc = o->gch.next; /* remove object from 'allgc' list */ | |
| 189 | + o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ | |
| 190 | + g->fixedgc = o; | |
| 204 | 191 | } |
| 205 | 192 | |
| 206 | 193 | |
| 207 | 194 | /* |
| 208 | 195 | ** create a new collectable object (with given type and size) and link |
| 209 | −** it to '*list'. 'offset' tells how many bytes to allocate before the | |
| 210 | −** object itself (used only by states). | |
| 196 | +** it to 'allgc' list. | |
| 211 | 197 | */ |
| 212 | −GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, | |
| 213 | − int offset) { | |
| 198 | +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | |
| 214 | 199 | global_State *g = G(L); |
| 215 | − char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); | |
| 216 | − GCObject *o = obj2gco(raw + offset); | |
| 217 | − if (list == NULL) | |
| 218 | − list = &g->allgc; /* standard list for collectable objects */ | |
| 200 | + GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); | |
| 219 | 201 | gch(o)->marked = luaC_white(g); |
| 220 | 202 | gch(o)->tt = tt; |
| 221 | − gch(o)->next = *list; | |
| 222 | − *list = o; | |
| 203 | + gch(o)->next = g->allgc; | |
| 204 | + g->allgc = o; | |
| 223 | 205 | return o; |
| 224 | 206 | } |
| 225 | 207 | |
| @@ -241,57 +223,53 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, · 15 unmodified lines | ||
| 241 | 223 | ** upvalues are already linked in 'headuv' list.) |
| 242 | 224 | */ |
| 243 | 225 | static void reallymarkobject (global_State *g, GCObject *o) { |
| 244 | − lu_mem size; | |
| 226 | + reentry: | |
| 245 | 227 | white2gray(o); |
| 246 | 228 | switch (gch(o)->tt) { |
| 247 | 229 | case LUA_TSHRSTR: |
| 248 | 230 | case LUA_TLNGSTR: { |
| 249 | − size = sizestring(gco2ts(o)); | |
| 250 | − break; /* nothing else to mark; make it black */ | |
| 251 | − } | |
| 252 | − case LUA_TUSERDATA: { | |
| 253 | − Table *mt = gco2u(o)->metatable; | |
| 254 | − markobject(g, mt); | |
| 255 | − markobject(g, gco2u(o)->env); | |
| 256 | − size = sizeudata(gco2u(o)); | |
| 231 | + gray2black(o); | |
| 232 | + g->GCmemtrav += sizestring(gco2ts(o)); | |
| 257 | 233 | break; |
| 258 | 234 | } |
| 259 | − case LUA_TUPVAL: { | |
| 260 | − UpVal *uv = gco2uv(o); | |
| 261 | − markvalue(g, uv->v); | |
| 262 | − if (uv->v != &uv->u.value) /* open? */ | |
| 263 | − return; /* open upvalues remain gray */ | |
| 264 | − size = sizeof(UpVal); | |
| 235 | + case LUA_TUSERDATA: { | |
| 236 | + TValue uvalue; | |
| 237 | + markobject(g, gco2u(o)->metatable); /* mark its metatable */ | |
| 238 | + gray2black(o); | |
| 239 | + g->GCmemtrav += sizeudata(gco2u(o)); | |
| 240 | + getuservalue(g->mainthread, rawgco2u(o), &uvalue); | |
| 241 | + if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ | |
| 242 | + o = gcvalue(&uvalue); | |
| 243 | + goto reentry; | |
| 244 | + } | |
| 265 | 245 | break; |
| 266 | 246 | } |
| 267 | 247 | case LUA_TLCL: { |
| 268 | 248 | gco2lcl(o)->gclist = g->gray; |
| 269 | 249 | g->gray = o; |
| 270 | − return; | |
| 250 | + break; | |
| 271 | 251 | } |
| 272 | 252 | case LUA_TCCL: { |
| 273 | 253 | gco2ccl(o)->gclist = g->gray; |
| 274 | 254 | g->gray = o; |
| 275 | − return; | |
| 255 | + break; | |
| 276 | 256 | } |
| 277 | 257 | case LUA_TTABLE: { |
| 278 | 258 | linktable(gco2t(o), &g->gray); |
| 279 | − return; | |
| 259 | + break; | |
| 280 | 260 | } |
| 281 | 261 | case LUA_TTHREAD: { |
| 282 | 262 | gco2th(o)->gclist = g->gray; |
| 283 | 263 | g->gray = o; |
| 284 | − return; | |
| 264 | + break; | |
| 285 | 265 | } |
| 286 | 266 | case LUA_TPROTO: { |
| 287 | 267 | gco2p(o)->gclist = g->gray; |
| 288 | 268 | g->gray = o; |
| 289 | − return; | |
| 269 | + break; | |
| 290 | 270 | } |
| 291 | − default: lua_assert(0); return; | |
| 271 | + default: lua_assert(0); break; | |
| 292 | 272 | } |
| 293 | − gray2black(o); | |
| 294 | − g->GCmemtrav += size; | |
| 295 | 273 | } |
| 296 | 274 | |
| 297 | 275 | |
| @@ -310,29 +288,41 @@ static void markmt (global_State *g) { · 12 unmodified lines | ||
| 310 | 288 | */ |
| 311 | 289 | static void markbeingfnz (global_State *g) { |
| 312 | 290 | GCObject *o; |
| 313 | − for (o = g->tobefnz; o != NULL; o = gch(o)->next) { | |
| 314 | − makewhite(g, o); | |
| 315 | − reallymarkobject(g, o); | |
| 316 | − } | |
| 291 | + for (o = g->tobefnz; o != NULL; o = gch(o)->next) | |
| 292 | + markobject(g, o); | |
| 317 | 293 | } |
| 318 | 294 | |
| 319 | 295 | |
| 320 | 296 | /* |
| 321 | −** mark all values stored in marked open upvalues. (See comment in | |
| 322 | −** 'lstate.h'.) | |
| 297 | +** Mark all values stored in marked open upvalues from non-marked threads. | |
| 298 | +** (Values from marked threads were already marked when traversing the | |
| 299 | +** thread.) Remove from the list threads that no longer have upvalues and | |
| 300 | +** not-marked threads. | |
| 323 | 301 | */ |
| 324 | 302 | static void remarkupvals (global_State *g) { |
| 325 | − UpVal *uv; | |
| 326 | − for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { | |
| 327 | − if (isgray(obj2gco(uv))) | |
| 328 | − markvalue(g, uv->v); | |
| 303 | + lua_State *thread; | |
| 304 | + lua_State **p = &g->twups; | |
| 305 | + while ((thread = *p) != NULL) { | |
| 306 | + lua_assert(!isblack(obj2gco(thread))); /* threads are never black */ | |
| 307 | + if (isgray(obj2gco(thread)) && thread->openupval != NULL) | |
| 308 | + p = &thread->twups; /* keep marked thread with upvalues in the list */ | |
| 309 | + else { /* thread is not marked or without upvalues */ | |
| 310 | + UpVal *uv; | |
| 311 | + *p = thread->twups; /* remove thread from the list */ | |
| 312 | + thread->twups = thread; /* mark that it is out of list */ | |
| 313 | + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { | |
| 314 | + if (uv->u.open.touched) { | |
| 315 | + markvalue(g, uv->v); /* remark upvalue's value */ | |
| 316 | + uv->u.open.touched = 0; | |
| 317 | + } | |
| 318 | + } | |
| 319 | + } | |
| 329 | 320 | } |
| 330 | 321 | } |
| 331 | 322 | |
| 332 | 323 | |
| 333 | 324 | /* |
| 334 | −** mark root set and reset all gray lists, to start a new | |
| 335 | −** incremental (or full) collection | |
| 325 | +** mark root set and reset all gray lists, to start a new collection | |
| 336 | 326 | */ |
| 337 | 327 | static void restartcollection (global_State *g) { |
| 338 | 328 | g->gray = g->grayagain = NULL; |
| @@ -483,11 +473,24 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) { · 144 unmodified lines | ||
| 483 | 473 | return sizeCclosure(cl->nupvalues); |
| 484 | 474 | } |
| 485 | 475 | |
| 476 | +/* | |
| 477 | +** open upvalues point to values in a thread, so those values should | |
| 478 | +** be marked when the thread is traversed except in the atomic phase | |
| 479 | +** (because then the value cannot be changed by the thread and the | |
| 480 | +** thread may not be traversed again) | |
| 481 | +*/ | |
| 486 | 482 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { |
| 487 | 483 | int i; |
| 488 | 484 | markobject(g, cl->p); /* mark its prototype */ |
| 489 | − for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | |
| 490 | − markobject(g, cl->upvals[i]); | |
| 485 | + for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ | |
| 486 | + UpVal *uv = cl->upvals[i]; | |
| 487 | + if (uv != NULL) { | |
| 488 | + if (upisopen(uv) && g->gcstate != GCSinsideatomic) | |
| 489 | + uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ | |
| 490 | + else | |
| 491 | + markvalue(g, uv->v); | |
| 492 | + } | |
| 493 | + } | |
| 491 | 494 | return sizeLclosure(cl->nupvalues); |
| 492 | 495 | } |
| 493 | 496 | |
| @@ -497,17 +500,27 @@ static lu_mem traversestack (global_State *g, lua_State *th) { · 3 unmodified lines | ||
| 497 | 500 | StkId o = th->stack; |
| 498 | 501 | if (o == NULL) |
| 499 | 502 | return 1; /* stack not completely built yet */ |
| 503 | + lua_assert(g->gcstate == GCSinsideatomic || | |
| 504 | + th->openupval == NULL || isintwups(th)); | |
| 500 | 505 | for (; o < th->top; o++) /* mark live elements in the stack */ |
| 501 | 506 | markvalue(g, o); |
| 502 | − if (g->gcstate == GCSatomic) { /* final traversal? */ | |
| 507 | + if (g->gcstate == GCSinsideatomic) { /* final traversal? */ | |
| 503 | 508 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
| 504 | 509 | for (; o < lim; o++) /* clear not-marked stack slice */ |
| 505 | 510 | setnilvalue(o); |
| 511 | + /* 'remarkupvals' may have removed thread from 'twups' list */ | |
| 512 | + if (!isintwups(th) && th->openupval != NULL) { | |
| 513 | + th->twups = g->twups; /* link it back to the list */ | |
| 514 | + g->twups = th; | |
| 515 | + } | |
| 506 | 516 | } |
| 507 | − else { /* count call infos to compute size */ | |
| 517 | + else { | |
| 508 | 518 | CallInfo *ci; |
| 509 | 519 | for (ci = &th->base_ci; ci != th->ci; ci = ci->next) |
| 510 | − n++; | |
| 520 | + n++; /* count call infos to compute size */ | |
| 521 | + /* should not change the stack during an emergency gc cycle */ | |
| 522 | + if (g->gckind != KGC_EMERGENCY) | |
| 523 | + luaD_shrinkstack(th); | |
| 511 | 524 | } |
| 512 | 525 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + |
| 513 | 526 | sizeof(CallInfo) * n; |
| @@ -660,23 +673,41 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) { · 146 unmodified lines | ||
| 660 | 673 | } |
| 661 | 674 | |
| 662 | 675 | |
| 676 | +void luaC_upvdeccount (lua_State *L, UpVal *uv) { | |
| 677 | + lua_assert(uv->refcount > 0); | |
| 678 | + uv->refcount--; | |
| 679 | + if (uv->refcount == 0 && !upisopen(uv)) | |
| 680 | + luaM_free(L, uv); | |
| 681 | +} | |
| 682 | + | |
| 683 | + | |
| 684 | +static void freeLclosure (lua_State *L, LClosure *cl) { | |
| 685 | + int i; | |
| 686 | + for (i = 0; i < cl->nupvalues; i++) { | |
| 687 | + UpVal *uv = cl->upvals[i]; | |
| 688 | + if (uv) | |
| 689 | + luaC_upvdeccount(L, uv); | |
| 690 | + } | |
| 691 | + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); | |
| 692 | +} | |
| 693 | + | |
| 694 | + | |
| 663 | 695 | static void freeobj (lua_State *L, GCObject *o) { |
| 664 | 696 | switch (gch(o)->tt) { |
| 665 | 697 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
| 666 | 698 | case LUA_TLCL: { |
| 667 | − luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); | |
| 699 | + freeLclosure(L, gco2lcl(o)); | |
| 668 | 700 | break; |
| 669 | 701 | } |
| 670 | 702 | case LUA_TCCL: { |
| 671 | 703 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); |
| 672 | 704 | break; |
| 673 | 705 | } |
| 674 | − case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; | |
| 675 | 706 | case LUA_TTABLE: luaH_free(L, gco2t(o)); break; |
| 676 | 707 | case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; |
| 677 | 708 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; |
| 678 | 709 | case LUA_TSHRSTR: |
| 679 | − G(L)->strt.nuse--; | |
| 710 | + luaS_remove(L, rawgco2ts(o)); /* remove it from hash table */ | |
| 680 | 711 | /* go through */ |
| 681 | 712 | case LUA_TLNGSTR: { |
| 682 | 713 | luaM_freemem(L, o, sizestring(gco2ts(o))); |
| @@ -691,46 +722,17 @@ static void freeobj (lua_State *L, GCObject *o) { · 8 unmodified lines | ||
| 691 | 722 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); |
| 692 | 723 | |
| 693 | 724 | |
| 694 | −/* | |
| 695 | −** sweep the (open) upvalues of a thread and resize its stack and | |
| 696 | −** list of call-info structures. | |
| 697 | −*/ | |
| 698 | −static void sweepthread (lua_State *L, lua_State *L1) { | |
| 699 | − if (L1->stack == NULL) return; /* stack not completely built yet */ | |
| 700 | − sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ | |
| 701 | − luaE_freeCI(L1); /* free extra CallInfo slots */ | |
| 702 | − /* should not change the stack during an emergency gc cycle */ | |
| 703 | − if (G(L)->gckind != KGC_EMERGENCY) | |
| 704 | − luaD_shrinkstack(L1); | |
| 705 | −} | |
| 706 | − | |
| 707 | − | |
| 708 | 725 | /* |
| 709 | 726 | ** sweep at most 'count' elements from a list of GCObjects erasing dead |
| 710 | 727 | ** objects, where a dead (not alive) object is one marked with the "old" |
| 711 | −** (non current) white and not fixed. | |
| 712 | −** In non-generational mode, change all non-dead objects back to white, | |
| 713 | −** preparing for next collection cycle. | |
| 714 | −** In generational mode, keep black objects black, and also mark them as | |
| 715 | −** old; stop when hitting an old object, as all objects after that | |
| 716 | −** one will be old too. | |
| 728 | +** (non current) white and not fixed; change all non-dead objects back | |
| 729 | +** to white, preparing for next collection cycle. | |
| 717 | 730 | ** When object is a thread, sweep its list of open upvalues too. |
| 718 | 731 | */ |
| 719 | 732 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
| 720 | 733 | global_State *g = G(L); |
| 721 | 734 | int ow = otherwhite(g); |
| 722 | − int toclear, toset; /* bits to clear and to set in all live objects */ | |
| 723 | − int tostop; /* stop sweep when this is true */ | |
| 724 | − if (isgenerational(g)) { /* generational mode? */ | |
| 725 | − toclear = ~0; /* clear nothing */ | |
| 726 | − toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ | |
| 727 | − tostop = bitmask(OLDBIT); /* do not sweep old generation */ | |
| 728 | − } | |
| 729 | − else { /* normal mode */ | |
| 730 | − toclear = maskcolors; /* clear all color bits + old bit */ | |
| 731 | − toset = luaC_white(g); /* make object white */ | |
| 732 | − tostop = 0; /* do not stop */ | |
| 733 | − } | |
| 735 | + int white = luaC_white(g); /* current white */ | |
| 734 | 736 | while (*p != NULL && count-- > 0) { |
| 735 | 737 | GCObject *curr = *p; |
| 736 | 738 | int marked = gch(curr)->marked; |
| @@ -738,13 +740,8 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { · 1 unmodified line | ||
| 738 | 740 | *p = gch(curr)->next; /* remove 'curr' from list */ |
| 739 | 741 | freeobj(L, curr); /* erase 'curr' */ |
| 740 | 742 | } |
| 741 | − else { | |
| 742 | − if (testbits(marked, tostop)) | |
| 743 | − return NULL; /* stop sweeping this list */ | |
| 744 | − if (gch(curr)->tt == LUA_TTHREAD) | |
| 745 | − sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | |
| 746 | − /* update marks */ | |
| 747 | − gch(curr)->marked = cast_byte((marked & toclear) | toset); | |
| 743 | + else { /* update marks */ | |
| 744 | + gch(curr)->marked = cast_byte((marked & maskcolors) | white); | |
| 748 | 745 | p = &gch(curr)->next; /* go to next element */ |
| 749 | 746 | } |
| 750 | 747 | } |
| @@ -756,7 +753,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { · 5 unmodified lines | ||
| 756 | 753 | ** sweep a list until a live object (or end of list) |
| 757 | 754 | */ |
| 758 | 755 | static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { |
| 759 | − GCObject ** old = p; | |
| 756 | + GCObject **old = p; | |
| 760 | 757 | int i = 0; |
| 761 | 758 | do { |
| 762 | 759 | i++; |
| @@ -775,26 +772,26 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { · 12 unmodified lines | ||
| 775 | 772 | ** ======================================================= |
| 776 | 773 | */ |
| 777 | 774 | |
| 778 | −static void checkSizes (lua_State *L) { | |
| 779 | − global_State *g = G(L); | |
| 780 | − if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ | |
| 781 | − int hs = g->strt.size / 2; /* half the size of the string table */ | |
| 782 | − if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ | |
| 783 | − luaS_resize(L, hs); /* halve its size */ | |
| 775 | +/* | |
| 776 | +** If possible, free concatenation buffer and shrink string table | |
| 777 | +*/ | |
| 778 | +static void checkSizes (lua_State *L, global_State *g) { | |
| 779 | + if (g->gckind != KGC_EMERGENCY) { | |
| 784 | 780 | luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ |
| 781 | + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ | |
| 782 | + luaS_resize(L, g->strt.size / 2); /* shrink it a little */ | |
| 785 | 783 | } |
| 786 | 784 | } |
| 787 | 785 | |
| 788 | 786 | |
| 789 | 787 | static GCObject *udata2finalize (global_State *g) { |
| 790 | 788 | GCObject *o = g->tobefnz; /* get first element */ |
| 791 | − lua_assert(isfinalized(o)); | |
| 789 | + lua_assert(tofinalize(o)); | |
| 792 | 790 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
| 793 | 791 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
| 794 | 792 | g->allgc = o; |
| 795 | − resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ | |
| 796 | − lua_assert(!isold(o)); /* see MOVE OLD rule */ | |
| 797 | − if (!keepinvariantout(g)) /* not keeping invariant? */ | |
| 793 | + resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ | |
| 794 | + if (issweepphase(g)) | |
| 798 | 795 | makewhite(g, o); /* "sweep" object */ |
| 799 | 796 | return o; |
| 800 | 797 | } |
| @@ -839,25 +836,39 @@ static void GCTM (lua_State *L, int propagateerrors) { · 38 unmodified lines | ||
| 839 | 836 | |
| 840 | 837 | |
| 841 | 838 | /* |
| 842 | −** move all unreachable objects (or 'all' objects) that need | |
| 843 | −** finalization from list 'finobj' to list 'tobefnz' (to be finalized) | |
| 839 | +** call all pending finalizers | |
| 844 | 840 | */ |
| 845 | −static void separatetobefnz (lua_State *L, int all) { | |
| 841 | +static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | |
| 846 | 842 | global_State *g = G(L); |
| 847 | − GCObject **p = &g->finobj; | |
| 843 | + while (g->tobefnz) | |
| 844 | + GCTM(L, propagateerrors); | |
| 845 | +} | |
| 846 | + | |
| 847 | + | |
| 848 | +/* | |
| 849 | +** find last 'next' field in list 'p' list (to add elements in its end) | |
| 850 | +*/ | |
| 851 | +static GCObject **findlast (GCObject **p) { | |
| 852 | + while (*p != NULL) | |
| 853 | + p = &gch(*p)->next; | |
| 854 | + return p; | |
| 855 | +} | |
| 856 | + | |
| 857 | + | |
| 858 | +/* | |
| 859 | +** move all unreachable objects (or 'all' objects) that need | |
| 860 | +** finalization from list 'p' to list 'tobefnz' (to be finalized) | |
| 861 | +*/ | |
| 862 | +static void separatetobefnz (global_State *g, int all) { | |
| 848 | 863 | GCObject *curr; |
| 849 | − GCObject **lastnext = &g->tobefnz; | |
| 850 | − /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ | |
| 851 | − while (*lastnext != NULL) | |
| 852 | − lastnext = &gch(*lastnext)->next; | |
| 864 | + GCObject **p = &g->finobj; | |
| 865 | + GCObject **lastnext = findlast(&g->tobefnz); | |
| 853 | 866 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
| 854 | − lua_assert(!isfinalized(curr)); | |
| 855 | − lua_assert(testbit(gch(curr)->marked, SEPARATED)); | |
| 867 | + lua_assert(tofinalize(curr)); | |
| 856 | 868 | if (!(iswhite(curr) || all)) /* not being collected? */ |
| 857 | 869 | p = &gch(curr)->next; /* don't bother with it */ |
| 858 | 870 | else { |
| 859 | − l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | |
| 860 | − *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ | |
| 871 | + *p = gch(curr)->next; /* remove 'curr' from "fin" list */ | |
| 861 | 872 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
| 862 | 873 | *lastnext = curr; |
| 863 | 874 | lastnext = &gch(curr)->next; |
| @@ -872,33 +883,30 @@ static void separatetobefnz (lua_State *L, int all) { · 8 unmodified lines | ||
| 872 | 883 | */ |
| 873 | 884 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { |
| 874 | 885 | global_State *g = G(L); |
| 875 | − if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ | |
| 876 | − isfinalized(o) || /* ... or is finalized... */ | |
| 877 | − gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ | |
| 886 | + if (tofinalize(o) || /* obj. is already marked... */ | |
| 887 | + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ | |
| 878 | 888 | return; /* nothing to be done */ |
| 879 | 889 | else { /* move 'o' to 'finobj' list */ |
| 880 | 890 | GCObject **p; |
| 881 | − GCheader *ho = gch(o); | |
| 882 | − if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ | |
| 891 | + if (g->sweepgc == &o->gch.next) { /* avoid removing current sweep object */ | |
| 883 | 892 | lua_assert(issweepphase(g)); |
| 884 | 893 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); |
| 885 | 894 | } |
| 886 | 895 | /* search for pointer pointing to 'o' */ |
| 887 | 896 | for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } |
| 888 | − *p = ho->next; /* remove 'o' from root list */ | |
| 889 | − ho->next = g->finobj; /* link it in list 'finobj' */ | |
| 897 | + *p = o->gch.next; /* remove 'o' from its list */ | |
| 898 | + o->gch.next = g->finobj; /* link it in "fin" list */ | |
| 890 | 899 | g->finobj = o; |
| 891 | − l_setbit(ho->marked, SEPARATED); /* mark it as such */ | |
| 892 | − if (!keepinvariantout(g)) /* not keeping invariant? */ | |
| 900 | + l_setbit(o->gch.marked, FINALIZEDBIT); /* mark it as such */ | |
| 901 | + if (issweepphase(g)) | |
| 893 | 902 | makewhite(g, o); /* "sweep" object */ |
| 894 | − else | |
| 895 | − resetoldbit(o); /* see MOVE OLD rule */ | |
| 896 | 903 | } |
| 897 | 904 | } |
| 898 | 905 | |
| 899 | 906 | /* }====================================================== */ |
| 900 | 907 | |
| 901 | 908 | |
| 909 | + | |
| 902 | 910 | /* |
| 903 | 911 | ** {====================================================== |
| 904 | 912 | ** GC control |
| @@ -911,87 +919,45 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { · 6 unmodified lines | ||
| 911 | 919 | ** cycle will start when memory use hits threshold |
| 912 | 920 | */ |
| 913 | 921 | static void setpause (global_State *g, l_mem estimate) { |
| 914 | − l_mem debt, threshold; | |
| 922 | + l_mem threshold, debt; | |
| 915 | 923 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ |
| 916 | 924 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ |
| 917 | 925 | ? estimate * g->gcpause /* no overflow */ |
| 918 | 926 | : MAX_LMEM; /* overflow; truncate to maximum */ |
| 919 | − debt = -cast(l_mem, threshold - gettotalbytes(g)); | |
| 927 | + debt = gettotalbytes(g) - threshold; | |
| 920 | 928 | luaE_setdebt(g, debt); |
| 921 | 929 | } |
| 922 | 930 | |
| 923 | 931 | |
| 924 | −#define sweepphases \ | |
| 925 | − (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) | |
| 926 | − | |
| 927 | − | |
| 928 | 932 | /* |
| 929 | −** enter first sweep phase (strings) and prepare pointers for other | |
| 930 | −** sweep phases. The calls to 'sweeptolive' make pointers point to an | |
| 931 | −** object inside the list (instead of to the header), so that the real | |
| 932 | −** sweep do not need to skip objects created between "now" and the start | |
| 933 | −** of the real sweep. | |
| 933 | +** Enter first sweep phase. | |
| 934 | +** The call to 'sweeptolive' makes pointer point to an object inside | |
| 935 | +** the list (instead of to the header), so that the real sweep do not | |
| 936 | +** need to skip objects created between "now" and the start of the real | |
| 937 | +** sweep. | |
| 934 | 938 | ** Returns how many objects it swept. |
| 935 | 939 | */ |
| 936 | 940 | static int entersweep (lua_State *L) { |
| 937 | 941 | global_State *g = G(L); |
| 938 | 942 | int n = 0; |
| 939 | − g->gcstate = GCSsweepstring; | |
| 940 | − lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); | |
| 941 | − /* prepare to sweep strings, finalizable objects, and regular objects */ | |
| 942 | − g->sweepstrgc = 0; | |
| 943 | − g->sweepfin = sweeptolive(L, &g->finobj, &n); | |
| 943 | + g->gcstate = GCSswpallgc; | |
| 944 | + lua_assert(g->sweepgc == NULL); | |
| 944 | 945 | g->sweepgc = sweeptolive(L, &g->allgc, &n); |
| 945 | 946 | return n; |
| 946 | 947 | } |
| 947 | 948 | |
| 948 | 949 | |
| 949 | −/* | |
| 950 | −** change GC mode | |
| 951 | −*/ | |
| 952 | −void luaC_changemode (lua_State *L, int mode) { | |
| 953 | − global_State *g = G(L); | |
| 954 | − if (mode == g->gckind) return; /* nothing to change */ | |
| 955 | − if (mode == KGC_GEN) { /* change to generational mode */ | |
| 956 | − /* make sure gray lists are consistent */ | |
| 957 | − luaC_runtilstate(L, bitmask(GCSpropagate)); | |
| 958 | − g->GCestimate = gettotalbytes(g); | |
| 959 | − g->gckind = KGC_GEN; | |
| 960 | − } | |
| 961 | − else { /* change to incremental mode */ | |
| 962 | − /* sweep all objects to turn them back to white | |
| 963 | − (as white has not changed, nothing extra will be collected) */ | |
| 964 | − g->gckind = KGC_NORMAL; | |
| 965 | − entersweep(L); | |
| 966 | − luaC_runtilstate(L, ~sweepphases); | |
| 967 | − } | |
| 968 | −} | |
| 969 | − | |
| 970 | − | |
| 971 | −/* | |
| 972 | −** call all pending finalizers | |
| 973 | −*/ | |
| 974 | −static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | |
| 975 | − global_State *g = G(L); | |
| 976 | − while (g->tobefnz) { | |
| 977 | − resetoldbit(g->tobefnz); | |
| 978 | − GCTM(L, propagateerrors); | |
| 979 | − } | |
| 980 | −} | |
| 981 | − | |
| 982 | − | |
| 983 | 950 | void luaC_freeallobjects (lua_State *L) { |
| 984 | 951 | global_State *g = G(L); |
| 985 | − int i; | |
| 986 | − separatetobefnz(L, 1); /* separate all objects with finalizers */ | |
| 952 | + separatetobefnz(g, 1); /* separate all objects with finalizers */ | |
| 987 | 953 | lua_assert(g->finobj == NULL); |
| 988 | 954 | callallpendingfinalizers(L, 0); |
| 955 | + lua_assert(g->tobefnz == NULL); | |
| 989 | 956 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
| 990 | 957 | g->gckind = KGC_NORMAL; |
| 991 | − sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | |
| 958 | + sweepwholelist(L, &g->finobj); | |
| 992 | 959 | sweepwholelist(L, &g->allgc); |
| 993 | − for (i = 0; i < g->strt.size; i++) /* free all string lists */ | |
| 994 | − sweepwholelist(L, &g->strt.hash[i]); | |
| 960 | + sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | |
| 995 | 961 | lua_assert(g->strt.nuse == 0); |
| 996 | 962 | } |
| 997 | 963 | |
| @@ -1001,6 +967,7 @@ static l_mem atomic (lua_State *L) { · 3 unmodified lines | ||
| 1001 | 967 | l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ |
| 1002 | 968 | GCObject *origweak, *origall; |
| 1003 | 969 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
| 970 | + g->gcstate = GCSinsideatomic; | |
| 1004 | 971 | markobject(g, L); /* mark running thread */ |
| 1005 | 972 | /* registry and global metatables may be changed by API */ |
| 1006 | 973 | markvalue(g, &g->l_registry); |
| @@ -1014,14 +981,15 @@ static l_mem atomic (lua_State *L) { · 7 unmodified lines | ||
| 1014 | 981 | work -= g->GCmemtrav; /* restart counting */ |
| 1015 | 982 | convergeephemerons(g); |
| 1016 | 983 | /* at this point, all strongly accessible objects are marked. */ |
| 1017 | − /* clear values from weak tables, before checking finalizers */ | |
| 984 | + /* Clear values from weak tables, before checking finalizers */ | |
| 1018 | 985 | clearvalues(g, g->weak, NULL); |
| 1019 | 986 | clearvalues(g, g->allweak, NULL); |
| 1020 | 987 | origweak = g->weak; origall = g->allweak; |
| 1021 | 988 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ |
| 1022 | − separatetobefnz(L, 0); /* separate objects to be finalized */ | |
| 989 | + separatetobefnz(g, 0); /* separate objects to be finalized */ | |
| 990 | + g->gcfinnum = 1; /* there may be objects to be finalized */ | |
| 1023 | 991 | markbeingfnz(g); /* mark objects that will be finalized */ |
| 1024 | − propagateall(g); /* remark, to propagate `preserveness' */ | |
| 992 | + propagateall(g); /* remark, to propagate 'resurrection' */ | |
| 1025 | 993 | work -= g->GCmemtrav; /* restart counting */ |
| 1026 | 994 | convergeephemerons(g); |
| 1027 | 995 | /* at this point, all resurrected objects are marked. */ |
| @@ -1037,66 +1005,67 @@ static l_mem atomic (lua_State *L) { · 9 unmodified lines | ||
| 1037 | 1005 | } |
| 1038 | 1006 | |
| 1039 | 1007 | |
| 1008 | +static lu_mem sweepstep (lua_State *L, global_State *g, | |
| 1009 | + int nextstate, GCObject **nextlist) { | |
| 1010 | + if (g->sweepgc) { | |
| 1011 | + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | |
| 1012 | + if (g->sweepgc) /* is there still something to sweep? */ | |
| 1013 | + return (GCSWEEPMAX * GCSWEEPCOST); | |
| 1014 | + } | |
| 1015 | + /* else enter next state */ | |
| 1016 | + g->gcstate = nextstate; | |
| 1017 | + g->sweepgc = nextlist; | |
| 1018 | + return 0; | |
| 1019 | +} | |
| 1020 | + | |
| 1021 | + | |
| 1040 | 1022 | static lu_mem singlestep (lua_State *L) { |
| 1041 | 1023 | global_State *g = G(L); |
| 1042 | 1024 | switch (g->gcstate) { |
| 1043 | 1025 | case GCSpause: { |
| 1044 | 1026 | /* start to count memory traversed */ |
| 1045 | 1027 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); |
| 1046 | − lua_assert(!isgenerational(g)); | |
| 1047 | 1028 | restartcollection(g); |
| 1048 | 1029 | g->gcstate = GCSpropagate; |
| 1049 | 1030 | return g->GCmemtrav; |
| 1050 | 1031 | } |
| 1051 | 1032 | case GCSpropagate: { |
| 1052 | − if (g->gray) { | |
| 1053 | − lu_mem oldtrav = g->GCmemtrav; | |
| 1054 | − propagatemark(g); | |
| 1055 | − return g->GCmemtrav - oldtrav; /* memory traversed in this step */ | |
| 1056 | − } | |
| 1057 | − else { /* no more `gray' objects */ | |
| 1058 | − lu_mem work; | |
| 1059 | − int sw; | |
| 1060 | − g->gcstate = GCSatomic; /* finish mark phase */ | |
| 1061 | − g->GCestimate = g->GCmemtrav; /* save what was counted */; | |
| 1062 | − work = atomic(L); /* add what was traversed by 'atomic' */ | |
| 1063 | − g->GCestimate += work; /* estimate of total memory traversed */ | |
| 1064 | − sw = entersweep(L); | |
| 1065 | − return work + sw * GCSWEEPCOST; | |
| 1066 | − } | |
| 1033 | + lu_mem oldtrav = g->GCmemtrav; | |
| 1034 | + lua_assert(g->gray); | |
| 1035 | + propagatemark(g); | |
| 1036 | + if (g->gray == NULL) /* no more `gray' objects? */ | |
| 1037 | + g->gcstate = GCSatomic; /* finish propagate phase */ | |
| 1038 | + return g->GCmemtrav - oldtrav; /* memory traversed in this step */ | |
| 1067 | 1039 | } |
| 1068 | − case GCSsweepstring: { | |
| 1069 | − int i; | |
| 1070 | − for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) | |
| 1071 | − sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); | |
| 1072 | − g->sweepstrgc += i; | |
| 1073 | − if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ | |
| 1074 | − g->gcstate = GCSsweepudata; | |
| 1075 | − return i * GCSWEEPCOST; | |
| 1040 | + case GCSatomic: { | |
| 1041 | + lu_mem work; | |
| 1042 | + int sw; | |
| 1043 | + propagateall(g); /* make sure gray list is empty */ | |
| 1044 | + g->GCestimate = g->GCmemtrav; /* save what was counted */; | |
| 1045 | + work = atomic(L); /* work is what was traversed by 'atomic' */ | |
| 1046 | + g->GCestimate += work; /* estimate of total memory traversed */ | |
| 1047 | + sw = entersweep(L); | |
| 1048 | + return work + sw * GCSWEEPCOST; | |
| 1076 | 1049 | } |
| 1077 | − case GCSsweepudata: { | |
| 1078 | − if (g->sweepfin) { | |
| 1079 | − g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); | |
| 1080 | − return GCSWEEPMAX*GCSWEEPCOST; | |
| 1081 | − } | |
| 1082 | − else { | |
| 1083 | − g->gcstate = GCSsweep; | |
| 1084 | − return 0; | |
| 1085 | − } | |
| 1050 | + case GCSswpallgc: { /* sweep "regular" objects */ | |
| 1051 | + return sweepstep(L, g, GCSswpfinobj, &g->finobj); | |
| 1086 | 1052 | } |
| 1087 | − case GCSsweep: { | |
| 1088 | − if (g->sweepgc) { | |
| 1089 | − g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | |
| 1090 | − return GCSWEEPMAX*GCSWEEPCOST; | |
| 1091 | − } | |
| 1092 | − else { | |
| 1093 | − /* sweep main thread */ | |
| 1094 | − GCObject *mt = obj2gco(g->mainthread); | |
| 1095 | − sweeplist(L, &mt, 1); | |
| 1096 | − checkSizes(L); | |
| 1097 | − g->gcstate = GCSpause; /* finish collection */ | |
| 1098 | − return GCSWEEPCOST; | |
| 1099 | − } | |
| 1053 | + case GCSswpfinobj: { /* sweep objects with finalizers */ | |
| 1054 | + return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); | |
| 1055 | + } | |
| 1056 | + case GCSswptobefnz: { /* sweep objects to be finalized */ | |
| 1057 | + return sweepstep(L, g, GCSswpend, NULL); | |
| 1058 | + } | |
| 1059 | + case GCSswpend: { /* finish sweeps */ | |
| 1060 | + makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ | |
| 1061 | + checkSizes(L, g); | |
| 1062 | + g->gcstate = GCScallfin; | |
| 1063 | + return 0; | |
| 1064 | + } | |
| 1065 | + case GCScallfin: { /* state to finish calling finalizers */ | |
| 1066 | + /* do nothing here; should be handled by 'luaC_forcestep' */ | |
| 1067 | + g->gcstate = GCSpause; /* finish collection */ | |
| 1068 | + return 0; | |
| 1100 | 1069 | } |
| 1101 | 1070 | default: lua_assert(0); return 0; |
| 1102 | 1071 | } |
| @@ -1114,88 +1083,74 @@ void luaC_runtilstate (lua_State *L, int statesmask) { · 11 unmodified lines | ||
| 1114 | 1083 | } |
| 1115 | 1084 | |
| 1116 | 1085 | |
| 1117 | −static void generationalcollection (lua_State *L) { | |
| 1086 | +/* | |
| 1087 | +** run a few (up to 'g->gcfinnum') finalizers | |
| 1088 | +*/ | |
| 1089 | +static int runafewfinalizers (lua_State *L) { | |
| 1118 | 1090 | global_State *g = G(L); |
| 1119 | − lua_assert(g->gcstate == GCSpropagate); | |
| 1120 | − if (g->GCestimate == 0) { /* signal for another major collection? */ | |
| 1121 | − luaC_fullgc(L, 0); /* perform a full regular collection */ | |
| 1122 | − g->GCestimate = gettotalbytes(g); /* update control */ | |
| 1123 | − } | |
| 1124 | − else { | |
| 1125 | − lu_mem estimate = g->GCestimate; | |
| 1126 | − luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ | |
| 1127 | − g->gcstate = GCSpropagate; /* skip restart */ | |
| 1128 | − if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) | |
| 1129 | − g->GCestimate = 0; /* signal for a major collection */ | |
| 1130 | − else | |
| 1131 | − g->GCestimate = estimate; /* keep estimate from last major coll. */ | |
| 1132 | − | |
| 1133 | − } | |
| 1134 | − setpause(g, gettotalbytes(g)); | |
| 1135 | − lua_assert(g->gcstate == GCSpropagate); | |
| 1091 | + unsigned int i; | |
| 1092 | + lua_assert(!g->tobefnz || g->gcfinnum > 0); | |
| 1093 | + for (i = 0; g->tobefnz && i < g->gcfinnum; i++) | |
| 1094 | + GCTM(L, 1); /* call one finalizer */ | |
| 1095 | + g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ | |
| 1096 | + : g->gcfinnum * 2; /* else call a few more next time */ | |
| 1097 | + return i; | |
| 1136 | 1098 | } |
| 1137 | 1099 | |
| 1138 | 1100 | |
| 1139 | −static void incstep (lua_State *L) { | |
| 1140 | − global_State *g = G(L); | |
| 1101 | +/* | |
| 1102 | +** get GC debt and convert it from Kb to 'work units' (avoid zero debt | |
| 1103 | +** and overflows) | |
| 1104 | +*/ | |
| 1105 | +static l_mem getdebt (global_State *g) { | |
| 1141 | 1106 | l_mem debt = g->GCdebt; |
| 1142 | 1107 | int stepmul = g->gcstepmul; |
| 1143 | − if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ | |
| 1144 | − /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ | |
| 1145 | 1108 | debt = (debt / STEPMULADJ) + 1; |
| 1146 | 1109 | debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; |
| 1147 | − do { /* always perform at least one single step */ | |
| 1148 | − lu_mem work = singlestep(L); /* do some work */ | |
| 1149 | − debt -= work; | |
| 1150 | − } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); | |
| 1151 | − if (g->gcstate == GCSpause) | |
| 1152 | − setpause(g, g->GCestimate); /* pause until next cycle */ | |
| 1153 | − else { | |
| 1154 | − debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ | |
| 1155 | − luaE_setdebt(g, debt); | |
| 1156 | − } | |
| 1110 | + return debt; | |
| 1157 | 1111 | } |
| 1158 | 1112 | |
| 1159 | − | |
| 1160 | 1113 | /* |
| 1161 | −** performs a basic GC step | |
| 1162 | −*/ | |
| 1163 | −void luaC_forcestep (lua_State *L) { | |
| 1164 | − global_State *g = G(L); | |
| 1165 | − int i; | |
| 1166 | − if (isgenerational(g)) generationalcollection(L); | |
| 1167 | − else incstep(L); | |
| 1168 | − /* run a few finalizers (or all of them at the end of a collect cycle) */ | |
| 1169 | − for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) | |
| 1170 | − GCTM(L, 1); /* call one finalizer */ | |
| 1171 | −} | |
| 1172 | − | |
| 1173 | − | |
| 1174 | −/* | |
| 1175 | −** performs a basic GC step only if collector is running | |
| 1114 | +** performs a basic GC step when collector is running | |
| 1176 | 1115 | */ |
| 1177 | 1116 | void luaC_step (lua_State *L) { |
| 1178 | 1117 | global_State *g = G(L); |
| 1179 | − if (g->gcrunning) luaC_forcestep(L); | |
| 1180 | − else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ | |
| 1118 | + l_mem debt = getdebt(g); | |
| 1119 | + if (!g->gcrunning) { /* not running? */ | |
| 1120 | + luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ | |
| 1121 | + return; | |
| 1122 | + } | |
| 1123 | + do { | |
| 1124 | + if (g->gcstate == GCScallfin && g->tobefnz) { | |
| 1125 | + unsigned int n = runafewfinalizers(L); | |
| 1126 | + debt -= (n * GCFINALIZECOST); | |
| 1127 | + } | |
| 1128 | + else { /* perform one single step */ | |
| 1129 | + lu_mem work = singlestep(L); | |
| 1130 | + debt -= work; | |
| 1131 | + } | |
| 1132 | + } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); | |
| 1133 | + if (g->gcstate == GCSpause) | |
| 1134 | + setpause(g, g->GCestimate); /* pause until next cycle */ | |
| 1135 | + else { | |
| 1136 | + debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ | |
| 1137 | + luaE_setdebt(g, debt); | |
| 1138 | + runafewfinalizers(L); | |
| 1139 | + } | |
| 1181 | 1140 | } |
| 1182 | 1141 | |
| 1183 | 1142 | |
| 1184 | − | |
| 1185 | 1143 | /* |
| 1186 | 1144 | ** performs a full GC cycle; if "isemergency", does not call |
| 1187 | 1145 | ** finalizers (which could change stack positions) |
| 1188 | 1146 | */ |
| 1189 | 1147 | void luaC_fullgc (lua_State *L, int isemergency) { |
| 1190 | 1148 | global_State *g = G(L); |
| 1191 | − int origkind = g->gckind; | |
| 1192 | − lua_assert(origkind != KGC_EMERGENCY); | |
| 1149 | + lua_assert(g->gckind == KGC_NORMAL); | |
| 1193 | 1150 | if (isemergency) /* do not run finalizers during emergency GC */ |
| 1194 | 1151 | g->gckind = KGC_EMERGENCY; |
| 1195 | − else { | |
| 1196 | − g->gckind = KGC_NORMAL; | |
| 1152 | + else | |
| 1197 | 1153 | callallpendingfinalizers(L, 1); |
| 1198 | − } | |
| 1199 | 1154 | if (keepinvariant(g)) { /* may there be some black objects? */ |
| 1200 | 1155 | /* must sweep all objects to turn them back to white |
| 1201 | 1156 | (as white has not changed, nothing will be collected) */ |
| @@ -1205,11 +1160,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { · 3 unmodified lines | ||
| 1205 | 1160 | luaC_runtilstate(L, bitmask(GCSpause)); |
| 1206 | 1161 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ |
| 1207 | 1162 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ |
| 1208 | − if (origkind == KGC_GEN) { /* generational mode? */ | |
| 1209 | − /* generational mode must be kept in propagate phase */ | |
| 1210 | − luaC_runtilstate(L, bitmask(GCSpropagate)); | |
| 1211 | − } | |
| 1212 | − g->gckind = origkind; | |
| 1163 | + g->gckind = KGC_NORMAL; | |
| 1213 | 1164 | setpause(g, gettotalbytes(g)); |
| 1214 | 1165 | if (!isemergency) /* do not run finalizers during emergency GC */ |
| 1215 | 1166 | callallpendingfinalizers(L, 1); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lgc.h,v 2.58 2012/09/11 12:53:08 roberto Exp $ | |
| 2 | +** $Id: lgc.h,v 2.82 2014/03/19 18:51:16 roberto Exp $ | |
| 3 | 3 | ** Garbage Collector |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -38,36 +38,27 @@ · 32 unmodified lines | ||
| 38 | 38 | */ |
| 39 | 39 | #define GCSpropagate 0 |
| 40 | 40 | #define GCSatomic 1 |
| 41 | −#define GCSsweepstring 2 | |
| 42 | −#define GCSsweepudata 3 | |
| 43 | −#define GCSsweep 4 | |
| 44 | −#define GCSpause 5 | |
| 41 | +#define GCSswpallgc 2 | |
| 42 | +#define GCSswpfinobj 3 | |
| 43 | +#define GCSswptobefnz 4 | |
| 44 | +#define GCSswpend 5 | |
| 45 | +#define GCScallfin 6 | |
| 46 | +#define GCSpause 7 | |
| 45 | 47 | |
| 46 | 48 | |
| 47 | 49 | #define issweepphase(g) \ |
| 48 | − (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | |
| 50 | + (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) | |
| 49 | 51 | |
| 50 | −#define isgenerational(g) ((g)->gckind == KGC_GEN) | |
| 51 | 52 | |
| 52 | 53 | /* |
| 53 | −** macros to tell when main invariant (white objects cannot point to black | |
| 54 | −** ones) must be kept. During a non-generational collection, the sweep | |
| 54 | +** macro to tell when main invariant (white objects cannot point to black | |
| 55 | +** ones) must be kept. During a collection, the sweep | |
| 55 | 56 | ** phase may break the invariant, as objects turned white may point to |
| 56 | 57 | ** still-black objects. The invariant is restored when sweep ends and |
| 57 | −** all objects are white again. During a generational collection, the | |
| 58 | −** invariant must be kept all times. | |
| 58 | +** all objects are white again. | |
| 59 | 59 | */ |
| 60 | 60 | |
| 61 | −#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) | |
| 62 | − | |
| 63 | − | |
| 64 | −/* | |
| 65 | −** Outside the collector, the state in generational mode is kept in | |
| 66 | −** 'propagate', so 'keepinvariant' is always true. | |
| 67 | −*/ | |
| 68 | −#define keepinvariantout(g) \ | |
| 69 | − check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ | |
| 70 | − g->gcstate <= GCSatomic) | |
| 61 | +#define keepinvariant(g) ((g)->gcstate <= GCSatomic) | |
| 71 | 62 | |
| 72 | 63 | |
| 73 | 64 | /* |
| @@ -87,10 +78,7 @@ · 13 unmodified lines | ||
| 87 | 78 | #define WHITE0BIT 0 /* object is white (type 0) */ |
| 88 | 79 | #define WHITE1BIT 1 /* object is white (type 1) */ |
| 89 | 80 | #define BLACKBIT 2 /* object is black */ |
| 90 | −#define FINALIZEDBIT 3 /* object has been separated for finalization */ | |
| 91 | −#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ | |
| 92 | −#define FIXEDBIT 5 /* object is fixed (should not be collected) */ | |
| 93 | −#define OLDBIT 6 /* object is old (only in generational mode) */ | |
| 81 | +#define FINALIZEDBIT 3 /* object has been marked for finalization */ | |
| 94 | 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ |
| 95 | 83 | |
| 96 | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
| @@ -101,21 +89,15 @@ · 4 unmodified lines | ||
| 101 | 89 | #define isgray(x) /* neither white nor black */ \ |
| 102 | 90 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) |
| 103 | 91 | |
| 104 | −#define isold(x) testbit((x)->gch.marked, OLDBIT) | |
| 92 | +#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) | |
| 105 | 93 | |
| 106 | −/* MOVE OLD rule: whenever an object is moved to the beginning of | |
| 107 | − a GC list, its old bit must be cleared */ | |
| 108 | −#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) | |
| 109 | − | |
| 110 | −#define otherwhite(g) (g->currentwhite ^ WHITEBITS) | |
| 94 | +#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) | |
| 111 | 95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) |
| 112 | 96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) |
| 113 | 97 | |
| 114 | 98 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
| 115 | 99 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) |
| 116 | 100 | |
| 117 | −#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) | |
| 118 | − | |
| 119 | 101 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
| 120 | 102 | |
| 121 | 103 | |
| @@ -124,34 +106,33 @@ · 2 unmodified lines | ||
| 124 | 106 | #define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) |
| 125 | 107 | |
| 126 | 108 | |
| 127 | −#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | |
| 109 | +#define luaC_barrier(L,p,v) { \ | |
| 110 | + if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ | |
| 128 | 111 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } |
| 129 | 112 | |
| 130 | −#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | |
| 131 | − luaC_barrierback_(L,p); } | |
| 113 | +#define luaC_barrierback(L,p,v) { \ | |
| 114 | + if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ | |
| 115 | + luaC_barrierback_(L,obj2gco(p)); } | |
| 132 | 116 | |
| 133 | −#define luaC_objbarrier(L,p,o) \ | |
| 134 | − { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ | |
| 117 | +#define luaC_objbarrier(L,p,o) { \ | |
| 118 | + if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ | |
| 135 | 119 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } |
| 136 | 120 | |
| 137 | −#define luaC_objbarrierback(L,p,o) \ | |
| 138 | − { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } | |
| 139 | − | |
| 140 | −#define luaC_barrierproto(L,p,c) \ | |
| 141 | − { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } | |
| 121 | +#define luaC_upvalbarrier(L,uv) \ | |
| 122 | + { if (iscollectable((uv)->v) && !upisopen(uv)) \ | |
| 123 | + luaC_upvalbarrier_(L,uv); } | |
| 142 | 124 | |
| 125 | +LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); | |
| 143 | 126 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
| 144 | 127 | LUAI_FUNC void luaC_step (lua_State *L); |
| 145 | −LUAI_FUNC void luaC_forcestep (lua_State *L); | |
| 146 | 128 | LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); |
| 147 | 129 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
| 148 | −LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | |
| 149 | − GCObject **list, int offset); | |
| 130 | +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); | |
| 150 | 131 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); |
| 151 | 132 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); |
| 152 | −LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); | |
| 133 | +LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); | |
| 153 | 134 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
| 154 | −LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | |
| 155 | −LUAI_FUNC void luaC_changemode (lua_State *L, int mode); | |
| 135 | +LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); | |
| 136 | + | |
| 156 | 137 | |
| 157 | 138 | #endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $ | |
| 2 | +** $Id: linit.c,v 1.33 2014/02/06 17:32:33 roberto Exp $ | |
| 3 | 3 | ** Initialization of libraries for lua.c and other clients |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -34,6 +34,7 @@ static const luaL_Reg loadedlibs[] = { · 28 unmodified lines | ||
| 34 | 34 | {LUA_IOLIBNAME, luaopen_io}, |
| 35 | 35 | {LUA_OSLIBNAME, luaopen_os}, |
| 36 | 36 | {LUA_STRLIBNAME, luaopen_string}, |
| 37 | + {LUA_UTF8LIBNAME, luaopen_utf8}, | |
| 37 | 38 | {LUA_BITLIBNAME, luaopen_bit32}, |
| 38 | 39 | {LUA_MATHLIBNAME, luaopen_math}, |
| 39 | 40 | {LUA_DBLIBNAME, luaopen_debug}, |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: liolib.c,v 2.114 2013/06/07 19:01:35 roberto Exp $ | |
| 2 | +** $Id: liolib.c,v 2.120 2014/03/19 18:57:42 roberto Exp $ | |
| 3 | 3 | ** Standard I/O (and system) library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -29,14 +29,14 @@ · 23 unmodified lines | ||
| 29 | 29 | #include "lualib.h" |
| 30 | 30 | |
| 31 | 31 | |
| 32 | −#if !defined(lua_checkmode) | |
| 32 | +#if !defined(l_checkmode) | |
| 33 | 33 | |
| 34 | 34 | /* |
| 35 | 35 | ** Check whether 'mode' matches '[rwa]%+?b?'. |
| 36 | 36 | ** Change this macro to accept other modes for 'fopen' besides |
| 37 | 37 | ** the standard ones. |
| 38 | 38 | */ |
| 39 | −#define lua_checkmode(mode) \ | |
| 39 | +#define l_checkmode(mode) \ | |
| 40 | 40 | (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ |
| 41 | 41 | (*mode != '+' || ++mode) && /* skip if char is '+' */ \ |
| 42 | 42 | (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ |
| @@ -46,45 +46,61 @@ · 3 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | /* |
| 48 | 48 | ** {====================================================== |
| 49 | −** lua_popen spawns a new process connected to the current | |
| 49 | +** l_popen spawns a new process connected to the current | |
| 50 | 50 | ** one through the file streams. |
| 51 | 51 | ** ======================================================= |
| 52 | 52 | */ |
| 53 | 53 | |
| 54 | −#if !defined(lua_popen) /* { */ | |
| 54 | +#if !defined(l_popen) /* { */ | |
| 55 | 55 | |
| 56 | −#if defined(LUA_USE_POPEN) /* { */ | |
| 56 | +#if defined(LUA_USE_POSIX) /* { */ | |
| 57 | 57 | |
| 58 | −#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) | |
| 59 | −#define lua_pclose(L,file) ((void)L, pclose(file)) | |
| 58 | +#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) | |
| 59 | +#define l_pclose(L,file) (pclose(file)) | |
| 60 | 60 | |
| 61 | 61 | #elif defined(LUA_WIN) /* }{ */ |
| 62 | 62 | |
| 63 | −#define lua_popen(L,c,m) ((void)L, _popen(c,m)) | |
| 64 | −#define lua_pclose(L,file) ((void)L, _pclose(file)) | |
| 65 | − | |
| 63 | +#define l_popen(L,c,m) (_popen(c,m)) | |
| 64 | +#define l_pclose(L,file) (_pclose(file)) | |
| 66 | 65 | |
| 67 | 66 | #else /* }{ */ |
| 68 | 67 | |
| 69 | −#define lua_popen(L,c,m) ((void)((void)c, m), \ | |
| 70 | − luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) | |
| 71 | −#define lua_pclose(L,file) ((void)((void)L, file), -1) | |
| 72 | − | |
| 68 | +/* ANSI definitions */ | |
| 69 | +#define l_popen(L,c,m) \ | |
| 70 | + ((void)((void)c, m), \ | |
| 71 | + luaL_error(L, LUA_QL("popen") " not supported"), \ | |
| 72 | + (FILE*)0) | |
| 73 | +#define l_pclose(L,file) ((void)L, (void)file, -1) | |
| 73 | 74 | |
| 74 | 75 | #endif /* } */ |
| 75 | 76 | |
| 76 | −#endif /* } */ | |
| 77 | +#endif /* } */ | |
| 77 | 78 | |
| 78 | 79 | /* }====================================================== */ |
| 79 | 80 | |
| 80 | 81 | |
| 82 | +#if !defined(l_getc) /* { */ | |
| 83 | + | |
| 84 | +#if defined(LUA_USE_POSIX) | |
| 85 | +#define l_getc(f) getc_unlocked(f) | |
| 86 | +#define l_lockfile(f) flockfile(f) | |
| 87 | +#define l_unlockfile(f) funlockfile(f) | |
| 88 | +#else | |
| 89 | +#define l_getc(f) getc(f) | |
| 90 | +#define l_lockfile(f) ((void)0) | |
| 91 | +#define l_unlockfile(f) ((void)0) | |
| 92 | +#endif | |
| 93 | + | |
| 94 | +#endif /* } */ | |
| 95 | + | |
| 96 | + | |
| 81 | 97 | /* |
| 82 | 98 | ** {====================================================== |
| 83 | −** lua_fseek: configuration for longer offsets | |
| 99 | +** l_fseek: configuration for longer offsets | |
| 84 | 100 | ** ======================================================= |
| 85 | 101 | */ |
| 86 | 102 | |
| 87 | −#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ | |
| 103 | +#if !defined(l_fseek) /* { */ | |
| 88 | 104 | |
| 89 | 105 | #if defined(LUA_USE_POSIX) /* { */ |
| 90 | 106 | |
| @@ -94,22 +110,22 @@ · 3 unmodified lines | ||
| 94 | 110 | |
| 95 | 111 | #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ |
| 96 | 112 | && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ |
| 97 | −/* Windows (but not DDK) and Visual C++ 2005 or higher */ | |
| 98 | 113 | |
| 114 | +/* Windows (but not DDK) and Visual C++ 2005 or higher */ | |
| 99 | 115 | #define l_fseek(f,o,w) _fseeki64(f,o,w) |
| 100 | 116 | #define l_ftell(f) _ftelli64(f) |
| 101 | 117 | #define l_seeknum __int64 |
| 102 | 118 | |
| 103 | −#endif /* } */ | |
| 104 | − | |
| 105 | −#endif /* } */ | |
| 106 | − | |
| 119 | +#else /* }{ */ | |
| 107 | 120 | |
| 108 | −#if !defined(l_fseek) /* default definitions */ | |
| 121 | +/* ANSI definitions */ | |
| 109 | 122 | #define l_fseek(f,o,w) fseek(f,o,w) |
| 110 | 123 | #define l_ftell(f) ftell(f) |
| 111 | 124 | #define l_seeknum long |
| 112 | −#endif | |
| 125 | + | |
| 126 | +#endif /* } */ | |
| 127 | + | |
| 128 | +#endif /* } */ | |
| 113 | 129 | |
| 114 | 130 | /* }====================================================== */ |
| 115 | 131 | |
| @@ -228,7 +244,7 @@ static int io_open (lua_State *L) { · 112 unmodified lines | ||
| 228 | 244 | const char *mode = luaL_optstring(L, 2, "r"); |
| 229 | 245 | LStream *p = newfile(L); |
| 230 | 246 | const char *md = mode; /* to traverse/check mode */ |
| 231 | − luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); | |
| 247 | + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); | |
| 232 | 248 | p->f = fopen(filename, mode); |
| 233 | 249 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; |
| 234 | 250 | } |
| @@ -239,7 +255,7 @@ static int io_open (lua_State *L) { · 4 unmodified lines | ||
| 239 | 255 | */ |
| 240 | 256 | static int io_pclose (lua_State *L) { |
| 241 | 257 | LStream *p = tolstream(L); |
| 242 | − return luaL_execresult(L, lua_pclose(L, p->f)); | |
| 258 | + return luaL_execresult(L, l_pclose(L, p->f)); | |
| 243 | 259 | } |
| 244 | 260 | |
| 245 | 261 | |
| @@ -247,7 +263,7 @@ static int io_popen (lua_State *L) { · 1 unmodified line | ||
| 247 | 263 | const char *filename = luaL_checkstring(L, 1); |
| 248 | 264 | const char *mode = luaL_optstring(L, 2, "r"); |
| 249 | 265 | LStream *p = newprefile(L); |
| 250 | − p->f = lua_popen(L, filename, mode); | |
| 266 | + p->f = l_popen(L, filename, mode); | |
| 251 | 267 | p->closef = &io_pclose; |
| 252 | 268 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; |
| 253 | 269 | } |
| @@ -375,7 +391,7 @@ static int read_number (lua_State *L, FILE *f) { · 121 unmodified lines | ||
| 375 | 391 | |
| 376 | 392 | static int test_eof (lua_State *L, FILE *f) { |
| 377 | 393 | int c = getc(f); |
| 378 | − ungetc(c, f); | |
| 394 | + ungetc(c, f); /* no-op when c == EOF */ | |
| 379 | 395 | lua_pushlstring(L, NULL, 0); |
| 380 | 396 | return (c != EOF); |
| 381 | 397 | } |
| @@ -383,40 +399,27 @@ static int test_eof (lua_State *L, FILE *f) { · 1 unmodified line | ||
| 383 | 399 | |
| 384 | 400 | static int read_line (lua_State *L, FILE *f, int chop) { |
| 385 | 401 | luaL_Buffer b; |
| 402 | + int c; | |
| 386 | 403 | luaL_buffinit(L, &b); |
| 387 | − for (;;) { | |
| 388 | − size_t l; | |
| 389 | − char *p = luaL_prepbuffer(&b); | |
| 390 | − if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ | |
| 391 | − luaL_pushresult(&b); /* close buffer */ | |
| 392 | − return (lua_rawlen(L, -1) > 0); /* check whether read something */ | |
| 393 | − } | |
| 394 | − l = strlen(p); | |
| 395 | − if (l == 0 || p[l-1] != '\n') | |
| 396 | − luaL_addsize(&b, l); | |
| 397 | − else { | |
| 398 | − luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ | |
| 399 | − luaL_pushresult(&b); /* close buffer */ | |
| 400 | − return 1; /* read at least an `eol' */ | |
| 401 | − } | |
| 402 | − } | |
| 404 | + l_lockfile(f); | |
| 405 | + while ((c = l_getc(f)) != EOF && c != '\n') | |
| 406 | + luaL_addchar(&b, c); | |
| 407 | + l_unlockfile(f); | |
| 408 | + if (!chop && c == '\n') luaL_addchar(&b, c); | |
| 409 | + luaL_pushresult(&b); /* close buffer */ | |
| 410 | + return (c == '\n' || lua_rawlen(L, -1) > 0); | |
| 403 | 411 | } |
| 404 | 412 | |
| 405 | 413 | |
| 406 | −#define MAX_SIZE_T (~(size_t)0) | |
| 407 | − | |
| 408 | 414 | static void read_all (lua_State *L, FILE *f) { |
| 409 | − size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ | |
| 415 | + size_t nr; | |
| 410 | 416 | luaL_Buffer b; |
| 411 | 417 | luaL_buffinit(L, &b); |
| 412 | − for (;;) { | |
| 413 | − char *p = luaL_prepbuffsize(&b, rlen); | |
| 414 | − size_t nr = fread(p, sizeof(char), rlen, f); | |
| 418 | + do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ | |
| 419 | + char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE); | |
| 420 | + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); | |
| 415 | 421 | luaL_addsize(&b, nr); |
| 416 | − if (nr < rlen) break; /* eof? */ | |
| 417 | − else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ | |
| 418 | − rlen *= 2; /* double buffer size at each iteration */ | |
| 419 | − } | |
| 422 | + } while (nr == LUAL_BUFFERSIZE); | |
| 420 | 423 | luaL_pushresult(&b); /* close buffer */ |
| 421 | 424 | } |
| 422 | 425 | |
| @@ -566,15 +569,15 @@ static int f_seek (lua_State *L) { · 143 unmodified lines | ||
| 566 | 569 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
| 567 | 570 | FILE *f = tofile(L); |
| 568 | 571 | int op = luaL_checkoption(L, 2, "cur", modenames); |
| 569 | − lua_Number p3 = luaL_optnumber(L, 3, 0); | |
| 572 | + lua_Integer p3 = luaL_optinteger(L, 3, 0); | |
| 570 | 573 | l_seeknum offset = (l_seeknum)p3; |
| 571 | − luaL_argcheck(L, (lua_Number)offset == p3, 3, | |
| 574 | + luaL_argcheck(L, (lua_Integer)offset == p3, 3, | |
| 572 | 575 | "not an integer in proper range"); |
| 573 | 576 | op = l_fseek(f, offset, mode[op]); |
| 574 | 577 | if (op) |
| 575 | 578 | return luaL_fileresult(L, 0, NULL); /* error */ |
| 576 | 579 | else { |
| 577 | − lua_pushnumber(L, (lua_Number)l_ftell(f)); | |
| 580 | + lua_pushinteger(L, (lua_Integer)l_ftell(f)); | |
| 578 | 581 | return 1; |
| 579 | 582 | } |
| 580 | 583 | } |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: llex.c,v 2.67 2013/06/19 14:27:00 roberto Exp $ | |
| 2 | +** $Id: llex.c,v 2.74 2014/02/14 15:23:51 roberto Exp $ | |
| 3 | 3 | ** Lexical Analyzer |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -15,6 +15,7 @@ · 9 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include "lctype.h" |
| 17 | 17 | #include "ldo.h" |
| 18 | +#include "lgc.h" | |
| 18 | 19 | #include "llex.h" |
| 19 | 20 | #include "lobject.h" |
| 20 | 21 | #include "lparser.h" |
| @@ -38,7 +39,8 @@ static const char *const luaX_tokens [] = { · 17 unmodified lines | ||
| 38 | 39 | "end", "false", "for", "function", "goto", "if", |
| 39 | 40 | "in", "local", "nil", "not", "or", "repeat", |
| 40 | 41 | "return", "then", "true", "until", "while", |
| 41 | − "//", "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", | |
| 42 | + "//", "..", "...", "==", ">=", "<=", "~=", | |
| 43 | + "<<", ">>", "::", "<eof>", | |
| 42 | 44 | "<number>", "<number>", "<name>", "<string>" |
| 43 | 45 | }; |
| 44 | 46 | |
| @@ -64,9 +66,11 @@ static void save (LexState *ls, int c) { · 19 unmodified lines | ||
| 64 | 66 | |
| 65 | 67 | void luaX_init (lua_State *L) { |
| 66 | 68 | int i; |
| 69 | + TString *e = luaS_new(L, LUA_ENV); /* create env name */ | |
| 70 | + luaC_fix(L, obj2gco(e)); /* never collect this name */ | |
| 67 | 71 | for (i=0; i<NUM_RESERVED; i++) { |
| 68 | 72 | TString *ts = luaS_new(L, luaX_tokens[i]); |
| 69 | − luaS_fix(ts); /* reserved words are never collected */ | |
| 73 | + luaC_fix(L, obj2gco(ts)); /* reserved words are never collected */ | |
| 70 | 74 | ts->tsv.extra = cast_byte(i+1); /* reserved word */ |
| 71 | 75 | } |
| 72 | 76 | } |
| @@ -116,22 +120,25 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { · 43 unmodified lines | ||
| 116 | 120 | |
| 117 | 121 | |
| 118 | 122 | /* |
| 119 | −** creates a new string and anchors it in function's table so that | |
| 120 | −** it will not be collected until the end of the function's compilation | |
| 121 | −** (by that time it should be anchored in function's prototype) | |
| 123 | +** creates a new string and anchors it in scanner's table so that | |
| 124 | +** it will not be collected until the end of the compilation | |
| 125 | +** (by that time it should be anchored somewhere) | |
| 122 | 126 | */ |
| 123 | 127 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
| 124 | 128 | lua_State *L = ls->L; |
| 125 | 129 | TValue *o; /* entry for `str' */ |
| 126 | 130 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ |
| 127 | 131 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ |
| 128 | − o = luaH_set(L, ls->fs->h, L->top - 1); | |
| 129 | − if (ttisnil(o)) { /* not in use yet? (see 'addK') */ | |
| 132 | + o = luaH_set(L, ls->h, L->top - 1); | |
| 133 | + if (ttisnil(o)) { /* not in use yet? */ | |
| 130 | 134 | /* boolean value does not need GC barrier; |
| 131 | 135 | table has no metatable, so it does not need to invalidate cache */ |
| 132 | 136 | setbvalue(o, 1); /* t[string] = true */ |
| 133 | 137 | luaC_checkGC(L); |
| 134 | 138 | } |
| 139 | + else { /* string already present */ | |
| 140 | + ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ | |
| 141 | + } | |
| 135 | 142 | L->top--; /* remove string from stack */ |
| 136 | 143 | return ts; |
| 137 | 144 | } |
| @@ -163,8 +170,7 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, · 25 unmodified lines | ||
| 163 | 170 | ls->linenumber = 1; |
| 164 | 171 | ls->lastline = 1; |
| 165 | 172 | ls->source = source; |
| 166 | − ls->envn = luaS_new(L, LUA_ENV); /* create env name */ | |
| 167 | − luaS_fix(ls->envn); /* never collect this name */ | |
| 173 | + ls->envn = luaS_new(L, LUA_ENV); /* get env name */ | |
| 168 | 174 | luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ |
| 169 | 175 | } |
| 170 | 176 | |
| @@ -314,40 +320,65 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { · 143 unmodified lines | ||
| 314 | 320 | } |
| 315 | 321 | |
| 316 | 322 | |
| 317 | −static void escerror (LexState *ls, int *c, int n, const char *msg) { | |
| 318 | − int i; | |
| 319 | − luaZ_resetbuffer(ls->buff); /* prepare error message */ | |
| 320 | − save(ls, '\\'); | |
| 321 | − for (i = 0; i < n && c[i] != EOZ; i++) | |
| 322 | − save(ls, c[i]); | |
| 323 | − lexerror(ls, msg, TK_STRING); | |
| 323 | +static void esccheck (LexState *ls, int c, const char *msg) { | |
| 324 | + if (!c) { | |
| 325 | + if (ls->current != EOZ) | |
| 326 | + save_and_next(ls); /* add current to buffer for error message */ | |
| 327 | + lexerror(ls, msg, TK_STRING); | |
| 328 | + } | |
| 329 | +} | |
| 330 | + | |
| 331 | + | |
| 332 | +static int gethexa (LexState *ls) { | |
| 333 | + save_and_next(ls); | |
| 334 | + esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); | |
| 335 | + return luaO_hexavalue(ls->current); | |
| 324 | 336 | } |
| 325 | 337 | |
| 326 | 338 | |
| 327 | 339 | static int readhexaesc (LexState *ls) { |
| 328 | − int c[3], i; /* keep input for error message */ | |
| 329 | − int r = 0; /* result accumulator */ | |
| 330 | − c[0] = 'x'; /* for error message */ | |
| 331 | − for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ | |
| 332 | − c[i] = next(ls); | |
| 333 | − if (!lisxdigit(c[i])) | |
| 334 | − escerror(ls, c, i + 1, "hexadecimal digit expected"); | |
| 335 | − r = (r << 4) + luaO_hexavalue(c[i]); | |
| 340 | + int r = gethexa(ls); | |
| 341 | + r = (r << 4) + gethexa(ls); | |
| 342 | + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ | |
| 343 | + return r; | |
| 344 | +} | |
| 345 | + | |
| 346 | + | |
| 347 | +static unsigned int readutf8esc (LexState *ls) { | |
| 348 | + unsigned int r; | |
| 349 | + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ | |
| 350 | + save_and_next(ls); /* skip 'u' */ | |
| 351 | + esccheck(ls, ls->current == '{', "missing '{'"); | |
| 352 | + r = gethexa(ls); /* must have at least one digit */ | |
| 353 | + while ((save_and_next(ls), lisxdigit(ls->current))) { | |
| 354 | + i++; | |
| 355 | + r = (r << 4) + luaO_hexavalue(ls->current); | |
| 356 | + esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); | |
| 336 | 357 | } |
| 358 | + esccheck(ls, ls->current == '}', "missing '}'"); | |
| 359 | + next(ls); /* skip '}' */ | |
| 360 | + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ | |
| 337 | 361 | return r; |
| 338 | 362 | } |
| 339 | 363 | |
| 340 | 364 | |
| 365 | +static void utf8esc (LexState *ls) { | |
| 366 | + char buff[UTF8BUFFSZ]; | |
| 367 | + int n = luaO_utf8esc(buff, readutf8esc(ls)); | |
| 368 | + for (; n > 0; n--) /* add 'buff' to string */ | |
| 369 | + save(ls, buff[UTF8BUFFSZ - n]); | |
| 370 | +} | |
| 371 | + | |
| 372 | + | |
| 341 | 373 | static int readdecesc (LexState *ls) { |
| 342 | − int c[3], i; | |
| 374 | + int i; | |
| 343 | 375 | int r = 0; /* result accumulator */ |
| 344 | 376 | for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ |
| 345 | − c[i] = ls->current; | |
| 346 | − r = 10*r + c[i] - '0'; | |
| 347 | − next(ls); | |
| 377 | + r = 10*r + ls->current - '0'; | |
| 378 | + save_and_next(ls); | |
| 348 | 379 | } |
| 349 | − if (r > UCHAR_MAX) | |
| 350 | − escerror(ls, c, i, "decimal escape too large"); | |
| 380 | + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); | |
| 381 | + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ | |
| 351 | 382 | return r; |
| 352 | 383 | } |
| 353 | 384 | |
| @@ -365,7 +396,7 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { · 11 unmodified lines | ||
| 365 | 396 | break; /* to avoid warnings */ |
| 366 | 397 | case '\\': { /* escape sequences */ |
| 367 | 398 | int c; /* final character to be saved */ |
| 368 | − next(ls); /* do not save the `\' */ | |
| 399 | + save_and_next(ls); /* keep '\\' for error messages */ | |
| 369 | 400 | switch (ls->current) { |
| 370 | 401 | case 'a': c = '\a'; goto read_save; |
| 371 | 402 | case 'b': c = '\b'; goto read_save; |
| @@ -375,12 +406,14 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { · 3 unmodified lines | ||
| 375 | 406 | case 't': c = '\t'; goto read_save; |
| 376 | 407 | case 'v': c = '\v'; goto read_save; |
| 377 | 408 | case 'x': c = readhexaesc(ls); goto read_save; |
| 409 | + case 'u': utf8esc(ls); goto no_save; | |
| 378 | 410 | case '\n': case '\r': |
| 379 | 411 | inclinenumber(ls); c = '\n'; goto only_save; |
| 380 | 412 | case '\\': case '\"': case '\'': |
| 381 | 413 | c = ls->current; goto read_save; |
| 382 | 414 | case EOZ: goto no_save; /* will raise an error next loop */ |
| 383 | 415 | case 'z': { /* zap following span of spaces */ |
| 416 | + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ | |
| 384 | 417 | next(ls); /* skip the 'z' */ |
| 385 | 418 | while (lisspace(ls->current)) { |
| 386 | 419 | if (currIsNewline(ls)) inclinenumber(ls); |
| @@ -389,15 +422,18 @@ static void read_string (LexState *ls, int del, SemInfo *seminfo) { · 2 unmodified lines | ||
| 389 | 422 | goto no_save; |
| 390 | 423 | } |
| 391 | 424 | default: { |
| 392 | − if (!lisdigit(ls->current)) | |
| 393 | − escerror(ls, &ls->current, 1, "invalid escape sequence"); | |
| 394 | − /* digital escape \ddd */ | |
| 395 | − c = readdecesc(ls); | |
| 425 | + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); | |
| 426 | + c = readdecesc(ls); /* digital escape \ddd */ | |
| 396 | 427 | goto only_save; |
| 397 | 428 | } |
| 398 | 429 | } |
| 399 | − read_save: next(ls); /* read next character */ | |
| 400 | − only_save: save(ls, c); /* save 'c' */ | |
| 430 | + read_save: | |
| 431 | + next(ls); | |
| 432 | + /* go through */ | |
| 433 | + only_save: | |
| 434 | + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ | |
| 435 | + save(ls, c); | |
| 436 | + /* go through */ | |
| 401 | 437 | no_save: break; |
| 402 | 438 | } |
| 403 | 439 | default: |
| @@ -457,13 +493,15 @@ static int llex (LexState *ls, SemInfo *seminfo) { · 53 unmodified lines | ||
| 457 | 493 | } |
| 458 | 494 | case '<': { |
| 459 | 495 | next(ls); |
| 460 | − if (ls->current != '=') return '<'; | |
| 461 | − else { next(ls); return TK_LE; } | |
| 496 | + if (ls->current == '=') { next(ls); return TK_LE; } | |
| 497 | + if (ls->current == '<') { next(ls); return TK_SHL; } | |
| 498 | + return '<'; | |
| 462 | 499 | } |
| 463 | 500 | case '>': { |
| 464 | 501 | next(ls); |
| 465 | − if (ls->current != '=') return '>'; | |
| 466 | − else { next(ls); return TK_GE; } | |
| 502 | + if (ls->current == '=') { next(ls); return TK_GE; } | |
| 503 | + if (ls->current == '>') { next(ls); return TK_SHR; } | |
| 504 | + return '>'; | |
| 467 | 505 | } |
| 468 | 506 | case '/': { |
| 469 | 507 | next(ls); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: llex.h,v 1.74 2013/04/26 13:07:53 roberto Exp $ | |
| 2 | +** $Id: llex.h,v 1.76 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Lexical Analyzer |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -27,6 +27,7 @@ enum RESERVED { · 21 unmodified lines | ||
| 27 | 27 | TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, |
| 28 | 28 | /* other terminal symbols */ |
| 29 | 29 | TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, |
| 30 | + TK_SHL, TK_SHR, | |
| 30 | 31 | TK_DBCOLON, TK_EOS, |
| 31 | 32 | TK_FLT, TK_INT, TK_NAME, TK_STRING |
| 32 | 33 | }; |
| @@ -60,6 +61,7 @@ typedef struct LexState { · 27 unmodified lines | ||
| 60 | 61 | struct lua_State *L; |
| 61 | 62 | ZIO *z; /* input stream */ |
| 62 | 63 | Mbuffer *buff; /* buffer for tokens */ |
| 64 | + Table *h; /* to avoid collection/reuse strings */ | |
| 63 | 65 | struct Dyndata *dyd; /* dynamic structures used by the parser */ |
| 64 | 66 | TString *source; /* current source name */ |
| 65 | 67 | TString *envn; /* environment variable name */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: llimits.h,v 1.108 2013/06/19 14:27:00 roberto Exp $ | |
| 2 | +** $Id: llimits.h,v 1.111 2014/03/07 16:19:00 roberto Exp $ | |
| 3 | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -43,11 +43,13 @@ typedef unsigned char lu_byte; · 37 unmodified lines | ||
| 43 | 43 | #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ |
| 44 | 44 | |
| 45 | 45 | |
| 46 | +/* maximum value for a lua_Unsigned */ | |
| 47 | +#define MAX_UINTEGER (~(lua_Unsigned)0) | |
| 48 | + | |
| 46 | 49 | /* minimum and maximum values for lua_Integer */ |
| 47 | −#define MAX_INTEGER ((lua_Integer)(~(lua_Unsigned)0 >> 1)) | |
| 50 | +#define MAX_INTEGER ((lua_Integer)(MAX_UINTEGER >> 1)) | |
| 48 | 51 | #define MIN_INTEGER (~MAX_INTEGER) |
| 49 | 52 | |
| 50 | − | |
| 51 | 53 | /* |
| 52 | 54 | ** conversion of pointer to integer |
| 53 | 55 | ** this is for hashing only; there is no problem if the integer |
| @@ -104,6 +106,7 @@ typedef LUAI_UACNUMBER l_uacNumber; · 50 unmodified lines | ||
| 104 | 106 | |
| 105 | 107 | #define cast(t, exp) ((t)(exp)) |
| 106 | 108 | |
| 109 | +#define cast_void(i) cast(void, (i)) | |
| 107 | 110 | #define cast_byte(i) cast(lu_byte, (i)) |
| 108 | 111 | #define cast_num(i) cast(lua_Number, (i)) |
| 109 | 112 | #define cast_int(i) cast(int, (i)) |
| @@ -155,7 +158,7 @@ typedef lu_int32 Instruction; · 45 unmodified lines | ||
| 155 | 158 | |
| 156 | 159 | /* minimum size for the string table (must be power of 2) */ |
| 157 | 160 | #if !defined(MINSTRTABSIZE) |
| 158 | −#define MINSTRTABSIZE 32 | |
| 161 | +#define MINSTRTABSIZE 64 /* minimum size for "predefined" strings */ | |
| 159 | 162 | #endif |
| 160 | 163 | |
| 161 | 164 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lmathlib.c,v 1.90 2013/07/03 17:23:19 roberto Exp $ | |
| 2 | +** $Id: lmathlib.c,v 1.92 2013/07/22 16:05:53 roberto Exp $ | |
| 3 | 3 | ** Standard mathematical library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -251,9 +251,16 @@ static int math_randomseed (lua_State *L) { · 245 unmodified lines | ||
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | |
| 254 | −static int math_isfloat (lua_State *L) { | |
| 254 | +static int math_type (lua_State *L) { | |
| 255 | 255 | luaL_checkany(L, 1); |
| 256 | − lua_pushboolean(L, (lua_type(L, 1) == LUA_TNUMBER && !lua_isinteger(L, 1))); | |
| 256 | + if (lua_type(L, 1) == LUA_TNUMBER) { | |
| 257 | + if (lua_isinteger(L, 1)) | |
| 258 | + lua_pushliteral(L, "integer"); | |
| 259 | + else | |
| 260 | + lua_pushliteral(L, "float"); | |
| 261 | + } | |
| 262 | + else | |
| 263 | + lua_pushnil(L); | |
| 257 | 264 | return 1; |
| 258 | 265 | } |
| 259 | 266 | |
| @@ -273,7 +280,6 @@ static const luaL_Reg mathlib[] = { · 13 unmodified lines | ||
| 273 | 280 | {"ifloor", math_ifloor}, |
| 274 | 281 | {"fmod", math_fmod}, |
| 275 | 282 | {"frexp", math_frexp}, |
| 276 | − {"isfloat", math_isfloat}, | |
| 277 | 283 | {"ldexp", math_ldexp}, |
| 278 | 284 | #if defined(LUA_COMPAT_LOG10) |
| 279 | 285 | {"log10", math_log10}, |
| @@ -291,6 +297,7 @@ static const luaL_Reg mathlib[] = { · 11 unmodified lines | ||
| 291 | 297 | {"sqrt", math_sqrt}, |
| 292 | 298 | {"tanh", math_tanh}, |
| 293 | 299 | {"tan", math_tan}, |
| 300 | + {"type", math_type}, | |
| 294 | 301 | {NULL, NULL} |
| 295 | 302 | }; |
| 296 | 303 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $ | |
| 2 | +** $Id: loadlib.c,v 1.113 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Dynamic library loader for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | ** |
| @@ -31,21 +31,21 @@ · 25 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | |
| 33 | 33 | /* |
| 34 | −** LUA_PATH and LUA_CPATH are the names of the environment | |
| 34 | +** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment | |
| 35 | 35 | ** variables that Lua check to set its paths. |
| 36 | 36 | */ |
| 37 | −#if !defined(LUA_PATH) | |
| 38 | −#define LUA_PATH "LUA_PATH" | |
| 37 | +#if !defined(LUA_PATH_VAR) | |
| 38 | +#define LUA_PATH_VAR "LUA_PATH" | |
| 39 | 39 | #endif |
| 40 | 40 | |
| 41 | −#if !defined(LUA_CPATH) | |
| 42 | −#define LUA_CPATH "LUA_CPATH" | |
| 41 | +#if !defined(LUA_CPATH_VAR) | |
| 42 | +#define LUA_CPATH_VAR "LUA_CPATH" | |
| 43 | 43 | #endif |
| 44 | 44 | |
| 45 | 45 | #define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR |
| 46 | 46 | |
| 47 | −#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX | |
| 48 | −#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX | |
| 47 | +#define LUA_PATHVARVERSION LUA_PATH_VAR LUA_PATHSUFFIX | |
| 48 | +#define LUA_CPATHVARVERSION LUA_CPATH_VAR LUA_PATHSUFFIX | |
| 49 | 49 | |
| 50 | 50 | /* |
| 51 | 51 | ** LUA_PATH_SEP is the character that separates templates in a path. |
| @@ -468,8 +468,7 @@ static int searcher_Croot (lua_State *L) { · 416 unmodified lines | ||
| 468 | 468 | static int searcher_preload (lua_State *L) { |
| 469 | 469 | const char *name = luaL_checkstring(L, 1); |
| 470 | 470 | lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); |
| 471 | − lua_getfield(L, -1, name); | |
| 472 | − if (lua_isnil(L, -1)) /* not found? */ | |
| 471 | + if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ | |
| 473 | 472 | lua_pushfstring(L, "\n\tno field package.preload['%s']", name); |
| 474 | 473 | return 1; |
| 475 | 474 | } |
| @@ -484,8 +483,7 @@ static void findloader (lua_State *L, const char *name) { · 8 unmodified lines | ||
| 484 | 483 | luaL_error(L, LUA_QL("package.searchers") " must be a table"); |
| 485 | 484 | /* iterate over available searchers to find a loader */ |
| 486 | 485 | for (i = 1; ; i++) { |
| 487 | − lua_rawgeti(L, 3, i); /* get a searcher */ | |
| 488 | − if (lua_isnil(L, -1)) { /* no more searchers? */ | |
| 486 | + if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ | |
| 489 | 487 | lua_pop(L, 1); /* remove nil */ |
| 490 | 488 | luaL_pushresult(&msg); /* create error message */ |
| 491 | 489 | luaL_error(L, "module " LUA_QS " not found:%s", |
| @@ -520,8 +518,7 @@ static int ll_require (lua_State *L) { · 28 unmodified lines | ||
| 520 | 518 | lua_call(L, 2, 1); /* run loader to load module */ |
| 521 | 519 | if (!lua_isnil(L, -1)) /* non-nil return? */ |
| 522 | 520 | lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ |
| 523 | − lua_getfield(L, 2, name); | |
| 524 | − if (lua_isnil(L, -1)) { /* module did not set a value? */ | |
| 521 | + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ | |
| 525 | 522 | lua_pushboolean(L, 1); /* use true as result */ |
| 526 | 523 | lua_pushvalue(L, -1); /* extra copy to be returned */ |
| 527 | 524 | lua_setfield(L, 2, name); /* _LOADED[name] = true */ |
| @@ -587,9 +584,8 @@ static int ll_module (lua_State *L) { · 59 unmodified lines | ||
| 587 | 584 | int lastarg = lua_gettop(L); /* last parameter */ |
| 588 | 585 | luaL_pushmodule(L, modname, 1); /* get/create module table */ |
| 589 | 586 | /* check whether table already has a _NAME field */ |
| 590 | − lua_getfield(L, -1, "_NAME"); | |
| 591 | − if (!lua_isnil(L, -1)) /* is table an initialized module? */ | |
| 592 | − lua_pop(L, 1); | |
| 587 | + if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) | |
| 588 | + lua_pop(L, 1); /* table is an initialized module */ | |
| 593 | 589 | else { /* no; initialize it */ |
| 594 | 590 | lua_pop(L, 1); |
| 595 | 591 | modinit(L, modname); |
| @@ -703,9 +699,9 @@ LUAMOD_API int luaopen_package (lua_State *L) { · 107 unmodified lines | ||
| 703 | 699 | #endif |
| 704 | 700 | lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ |
| 705 | 701 | /* set field 'path' */ |
| 706 | − setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); | |
| 702 | + setpath(L, "path", LUA_PATHVARVERSION, LUA_PATH_VAR, LUA_PATH_DEFAULT); | |
| 707 | 703 | /* set field 'cpath' */ |
| 708 | − setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); | |
| 704 | + setpath(L, "cpath", LUA_CPATHVARVERSION, LUA_CPATH_VAR, LUA_CPATH_DEFAULT); | |
| 709 | 705 | /* store config information */ |
| 710 | 706 | lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" |
| 711 | 707 | LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp $ | |
| 2 | +** $Id: lobject.c,v 2.76 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Some generic functions over Lua objects |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -77,22 +77,30 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, · 71 unmodified lines | ||
| 77 | 77 | case LUA_OPSUB:return intop(-, v1, v2); |
| 78 | 78 | case LUA_OPMUL:return intop(*, v1, v2); |
| 79 | 79 | case LUA_OPMOD: return luaV_mod(L, v1, v2); |
| 80 | − case LUA_OPPOW: return luaV_pow(v1, v2); | |
| 81 | − case LUA_OPUNM: return -v1; | |
| 80 | + case LUA_OPPOW: return luaV_pow(L, v1, v2); | |
| 81 | + case LUA_OPIDIV: return luaV_div(L, v1, v2); | |
| 82 | + case LUA_OPBAND: return intop(&, v1, v2); | |
| 83 | + case LUA_OPBOR: return intop(|, v1, v2); | |
| 84 | + case LUA_OPBXOR: return intop(^, v1, v2); | |
| 85 | + case LUA_OPSHL: return luaV_shiftl(v1, v2); | |
| 86 | + case LUA_OPSHR: return luaV_shiftl(v1, -v2); | |
| 87 | + case LUA_OPUNM: return intop(-, 0, v1); | |
| 88 | + case LUA_OPBNOT: return intop(^, cast_integer(-1), v1); | |
| 82 | 89 | default: lua_assert(0); return 0; |
| 83 | 90 | } |
| 84 | 91 | } |
| 85 | 92 | |
| 86 | 93 | |
| 87 | −static lua_Number numarith (int op, lua_Number v1, lua_Number v2) { | |
| 94 | +static lua_Number numarith (lua_State *L, int op, lua_Number v1, | |
| 95 | + lua_Number v2) { | |
| 88 | 96 | switch (op) { |
| 89 | − case LUA_OPADD: return luai_numadd(NULL, v1, v2); | |
| 90 | − case LUA_OPSUB: return luai_numsub(NULL, v1, v2); | |
| 91 | − case LUA_OPMUL: return luai_nummul(NULL, v1, v2); | |
| 92 | − case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); | |
| 93 | − case LUA_OPMOD: return luai_nummod(NULL, v1, v2); | |
| 94 | − case LUA_OPPOW: return luai_numpow(NULL, v1, v2); | |
| 95 | − case LUA_OPUNM: return luai_numunm(NULL, v1); | |
| 97 | + case LUA_OPADD: return luai_numadd(L, v1, v2); | |
| 98 | + case LUA_OPSUB: return luai_numsub(L, v1, v2); | |
| 99 | + case LUA_OPMUL: return luai_nummul(L, v1, v2); | |
| 100 | + case LUA_OPDIV: return luai_numdiv(L, v1, v2); | |
| 101 | + case LUA_OPMOD: return luai_nummod(L, v1, v2); | |
| 102 | + case LUA_OPPOW: return luai_numpow(L, v1, v2); | |
| 103 | + case LUA_OPUNM: return luai_numunm(L, v1); | |
| 96 | 104 | default: lua_assert(0); return 0; |
| 97 | 105 | } |
| 98 | 106 | } |
| @@ -100,29 +108,40 @@ static lua_Number numarith (int op, lua_Number v1, lua_Number v2) { · 1 unmodified line | ||
| 100 | 108 | |
| 101 | 109 | void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, |
| 102 | 110 | TValue *res) { |
| 103 | − if (op == LUA_OPIDIV) { /* operates only on integers */ | |
| 104 | − lua_Integer i1; lua_Integer i2; | |
| 105 | − if (tointeger(p1, &i1) && tointeger(p2, &i2)) { | |
| 106 | − setivalue(res, luaV_div(L, i1, i2)); | |
| 107 | − return; | |
| 111 | + switch (op) { | |
| 112 | + case LUA_OPIDIV: case LUA_OPBAND: case LUA_OPBOR: | |
| 113 | + case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR: | |
| 114 | + case LUA_OPBNOT: { /* operates only on integers */ | |
| 115 | + lua_Integer i1; lua_Integer i2; | |
| 116 | + if (tointeger(p1, &i1) && tointeger(p2, &i2)) { | |
| 117 | + setivalue(res, intarith(L, op, i1, i2)); | |
| 118 | + return; | |
| 119 | + } | |
| 120 | + else break; /* go to the end */ | |
| 108 | 121 | } |
| 109 | − /* else go to the end */ | |
| 110 | − } | |
| 111 | − else { /* other operations */ | |
| 112 | − lua_Number n1; lua_Number n2; | |
| 113 | − if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV && | |
| 114 | − (op != LUA_OPPOW || ivalue(p2) >= 0)) { | |
| 115 | − setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); | |
| 116 | − return; | |
| 122 | + case LUA_OPDIV: { /* operates only on floats */ | |
| 123 | + lua_Number n1; lua_Number n2; | |
| 124 | + if (tonumber(p1, &n1) && tonumber(p2, &n2)) { | |
| 125 | + setnvalue(res, numarith(L, op, n1, n2)); | |
| 126 | + return; | |
| 127 | + } | |
| 128 | + else break; /* go to the end */ | |
| 117 | 129 | } |
| 118 | − else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { | |
| 119 | − setnvalue(res, numarith(op, n1, n2)); | |
| 120 | − return; | |
| 130 | + default: { /* other operations */ | |
| 131 | + lua_Number n1; lua_Number n2; | |
| 132 | + if (ttisinteger(p1) && ttisinteger(p2)) { | |
| 133 | + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); | |
| 134 | + return; | |
| 135 | + } | |
| 136 | + else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { | |
| 137 | + setnvalue(res, numarith(L, op, n1, n2)); | |
| 138 | + return; | |
| 139 | + } | |
| 140 | + else break; /* go to the end */ | |
| 121 | 141 | } |
| 122 | − /* else go to the end */ | |
| 123 | 142 | } |
| 124 | − /* could not perform raw operation; try metmethod */ | |
| 125 | − lua_assert(L != NULL); /* cannot fail when folding (compile time) */ | |
| 143 | + /* could not perform raw operation; try metamethod */ | |
| 144 | + lua_assert(L != NULL); /* should not fail when folding (compile time) */ | |
| 126 | 145 | luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); |
| 127 | 146 | } |
| 128 | 147 | |
| @@ -141,22 +160,26 @@ static int isneg (const char **s) { · 12 unmodified lines | ||
| 141 | 160 | |
| 142 | 161 | |
| 143 | 162 | /* |
| 163 | +** {====================================================== | |
| 144 | 164 | ** lua_strx2number converts an hexadecimal numeric string to a number. |
| 145 | 165 | ** In C99, 'strtod' does both conversions. C89, however, has no function |
| 146 | 166 | ** to convert floating hexadecimal strings to numbers. For these |
| 147 | 167 | ** systems, you can leave 'lua_strx2number' undefined and Lua will |
| 148 | 168 | ** provide its own implementation. |
| 169 | +** ======================================================= | |
| 149 | 170 | */ |
| 150 | −#if defined(LUA_USE_STRTODHEX) | |
| 171 | +#if !defined(lua_strx2number) /* { */ | |
| 172 | + | |
| 173 | +#if defined(LUA_USE_C99) /* { */ | |
| 174 | + | |
| 151 | 175 | #define lua_strx2number(s,p) lua_str2number(s,p) |
| 152 | −#endif | |
| 153 | 176 | |
| 177 | +#else /* }{ */ | |
| 154 | 178 | |
| 155 | −#if !defined(lua_strx2number) | |
| 179 | +/* Lua's implementation for 'lua_strx2number' */ | |
| 156 | 180 | |
| 157 | 181 | #include <math.h> |
| 158 | 182 | |
| 159 | − | |
| 160 | 183 | /* maximum number of significant digits to read (to avoid overflows |
| 161 | 184 | even with single floats) */ |
| 162 | 185 | #define MAXSIGDIG 30 |
| @@ -219,7 +242,11 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { · 56 unmodified lines | ||
| 219 | 242 | return l_mathop(ldexp)(r, e); |
| 220 | 243 | } |
| 221 | 244 | |
| 222 | −#endif | |
| 245 | +#endif /* } */ | |
| 246 | + | |
| 247 | +#endif /* } */ | |
| 248 | + | |
| 249 | +/* }====================================================== */ | |
| 223 | 250 | |
| 224 | 251 | |
| 225 | 252 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { |
| @@ -260,19 +287,36 @@ int luaO_str2int (const char *s, size_t len, lua_Integer *result) { · 34 unmodified lines | ||
| 260 | 287 | while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ |
| 261 | 288 | if (empty || s != ends) return 0; /* something wrong in the numeral */ |
| 262 | 289 | else { |
| 263 | − if (neg) *result = -cast(lua_Integer, a); | |
| 264 | − else *result = cast(lua_Integer, a); | |
| 290 | + *result = cast_integer((neg) ? 0u - a : a); | |
| 265 | 291 | return 1; |
| 266 | 292 | } |
| 267 | 293 | } |
| 268 | 294 | |
| 269 | 295 | |
| 296 | +int luaO_utf8esc (char *buff, unsigned int x) { | |
| 297 | + int n = 1; /* number of bytes put in buffer (backwards) */ | |
| 298 | + if (x < 0x80) /* ascii? */ | |
| 299 | + buff[UTF8BUFFSZ - 1] = x; | |
| 300 | + else { /* need continuation bytes */ | |
| 301 | + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ | |
| 302 | + do { | |
| 303 | + buff[UTF8BUFFSZ - (n++)] = 0x80 | (x & 0x3f); /* add continuation byte */ | |
| 304 | + x >>= 6; /* remove added bits */ | |
| 305 | + mfb >>= 1; /* now there is one less bit available in first byte */ | |
| 306 | + } while (x > mfb); /* still needs continuation byte? */ | |
| 307 | + buff[UTF8BUFFSZ - n] = (~mfb << 1) | x; /* add first byte */ | |
| 308 | + } | |
| 309 | + return n; | |
| 310 | +} | |
| 311 | + | |
| 312 | + | |
| 270 | 313 | static void pushstr (lua_State *L, const char *str, size_t l) { |
| 271 | 314 | setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); |
| 272 | 315 | } |
| 273 | 316 | |
| 274 | 317 | |
| 275 | −/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ | |
| 318 | +/* this function handles only '%d', '%c', '%f', '%p', and '%s' | |
| 319 | + conventional formats, plus Lua-specific '%L' and '%U' */ | |
| 276 | 320 | const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { |
| 277 | 321 | int n = 0; |
| 278 | 322 | for (;;) { |
| @@ -311,6 +355,12 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { · 32 unmodified lines | ||
| 311 | 355 | pushstr(L, buff, l); |
| 312 | 356 | break; |
| 313 | 357 | } |
| 358 | + case 'U': { | |
| 359 | + char buff[UTF8BUFFSZ]; | |
| 360 | + int l = luaO_utf8esc(buff, va_arg(argp, int)); | |
| 361 | + pushstr(L, buff + UTF8BUFFSZ - l, l); | |
| 362 | + break; | |
| 363 | + } | |
| 314 | 364 | case '%': { |
| 315 | 365 | pushstr(L, "%", 1); |
| 316 | 366 | break; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lobject.h,v 2.78 2013/05/14 15:59:04 roberto Exp $ | |
| 2 | +** $Id: lobject.h,v 2.86 2014/02/19 13:52:42 roberto Exp $ | |
| 3 | 3 | ** Type definitions for Lua objects |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -20,13 +20,12 @@ · 14 unmodified lines | ||
| 20 | 20 | ** Extra tags for non-values |
| 21 | 21 | */ |
| 22 | 22 | #define LUA_TPROTO LUA_NUMTAGS |
| 23 | −#define LUA_TUPVAL (LUA_NUMTAGS+1) | |
| 24 | −#define LUA_TDEADKEY (LUA_NUMTAGS+2) | |
| 23 | +#define LUA_TDEADKEY (LUA_NUMTAGS+1) | |
| 25 | 24 | |
| 26 | 25 | /* |
| 27 | 26 | ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) |
| 28 | 27 | */ |
| 29 | −#define LUA_TOTALTAGS (LUA_TUPVAL+2) | |
| 28 | +#define LUA_TOTALTAGS (LUA_TPROTO + 2) | |
| 30 | 29 | |
| 31 | 30 | |
| 32 | 31 | /* |
| @@ -147,7 +146,7 @@ typedef struct lua_TValue TValue; · 114 unmodified lines | ||
| 147 | 146 | #define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) |
| 148 | 147 | #define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) |
| 149 | 148 | #define ttislcf(o) checktag((o), LUA_TLCF) |
| 150 | −#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) | |
| 149 | +#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) | |
| 151 | 150 | #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) |
| 152 | 151 | #define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) |
| 153 | 152 | |
| @@ -159,7 +158,7 @@ typedef struct lua_TValue TValue; · 5 unmodified lines | ||
| 159 | 158 | #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) |
| 160 | 159 | #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) |
| 161 | 160 | #define tsvalue(o) (&rawtsvalue(o)->tsv) |
| 162 | −#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) | |
| 161 | +#define rawuvalue(o) check_exp(ttisfulluserdata(o), &val_(o).gc->u) | |
| 163 | 162 | #define uvalue(o) (&rawuvalue(o)->uv) |
| 164 | 163 | #define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) |
| 165 | 164 | #define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) |
| @@ -311,8 +310,9 @@ typedef union TString { · 145 unmodified lines | ||
| 311 | 310 | struct { |
| 312 | 311 | CommonHeader; |
| 313 | 312 | lu_byte extra; /* reserved words for short strings; "has hash" for longs */ |
| 314 | − unsigned int hash; | |
| 315 | 313 | size_t len; /* number of characters in string */ |
| 314 | + union TString *hnext; /* linked list for hash table */ | |
| 315 | + unsigned int hash; | |
| 316 | 316 | } tsv; |
| 317 | 317 | } TString; |
| 318 | 318 | |
| @@ -331,13 +331,25 @@ typedef union Udata { · 12 unmodified lines | ||
| 331 | 331 | L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ |
| 332 | 332 | struct { |
| 333 | 333 | CommonHeader; |
| 334 | + lu_byte ttuv_; /* user value's tag */ | |
| 334 | 335 | struct Table *metatable; |
| 335 | − struct Table *env; | |
| 336 | 336 | size_t len; /* number of bytes */ |
| 337 | + union Value user_; /* user value */ | |
| 337 | 338 | } uv; |
| 338 | 339 | } Udata; |
| 339 | 340 | |
| 340 | 341 | |
| 342 | +#define setuservalue(L,u,o) \ | |
| 343 | + { const TValue *io=(o); Udata *iu = (u); \ | |
| 344 | + iu->uv.user_ = io->value_; iu->uv.ttuv_ = io->tt_; \ | |
| 345 | + checkliveness(G(L),io); } | |
| 346 | + | |
| 347 | + | |
| 348 | +#define getuservalue(L,u,o) \ | |
| 349 | + { TValue *io=(o); const Udata *iu = (u); \ | |
| 350 | + io->value_ = iu->uv.user_; io->tt_ = iu->uv.ttuv_; \ | |
| 351 | + checkliveness(G(L),io); } | |
| 352 | + | |
| 341 | 353 | |
| 342 | 354 | /* |
| 343 | 355 | ** Description of an upvalue for function prototypes |
| @@ -392,17 +404,7 @@ typedef struct Proto { · 48 unmodified lines | ||
| 392 | 404 | /* |
| 393 | 405 | ** Lua Upvalues |
| 394 | 406 | */ |
| 395 | −typedef struct UpVal { | |
| 396 | − CommonHeader; | |
| 397 | − TValue *v; /* points to stack or to its own value */ | |
| 398 | − union { | |
| 399 | − TValue value; /* the value (when closed) */ | |
| 400 | − struct { /* double linked list (when open) */ | |
| 401 | − struct UpVal *prev; | |
| 402 | − struct UpVal *next; | |
| 403 | − } l; | |
| 404 | − } u; | |
| 405 | −} UpVal; | |
| 407 | +typedef struct UpVal UpVal; | |
| 406 | 408 | |
| 407 | 409 | |
| 408 | 410 | /* |
| @@ -444,7 +446,7 @@ typedef union Closure { · 35 unmodified lines | ||
| 444 | 446 | typedef union TKey { |
| 445 | 447 | struct { |
| 446 | 448 | TValuefields; |
| 447 | − struct Node *next; /* for chaining */ | |
| 449 | + int next; /* for chaining (offset for next node) */ | |
| 448 | 450 | } nk; |
| 449 | 451 | TValue tvk; |
| 450 | 452 | } TKey; |
| @@ -489,9 +491,12 @@ typedef struct Table { · 38 unmodified lines | ||
| 489 | 491 | |
| 490 | 492 | LUAI_DDEC const TValue luaO_nilobject_; |
| 491 | 493 | |
| 494 | +/* size of buffer for 'luaO_utf8esc' function */ | |
| 495 | +#define UTF8BUFFSZ 8 | |
| 492 | 496 | |
| 493 | 497 | LUAI_FUNC int luaO_int2fb (unsigned int x); |
| 494 | 498 | LUAI_FUNC int luaO_fb2int (int x); |
| 499 | +LUAI_FUNC int luaO_utf8esc (char *buff, unsigned int x); | |
| 495 | 500 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); |
| 496 | 501 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, |
| 497 | 502 | const TValue *p2, TValue *res); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lopcodes.c,v 1.50 2013/04/26 13:07:53 roberto Exp $ | |
| 2 | +** $Id: lopcodes.c,v 1.53 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Opcodes for Lua virtual machine |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -31,11 +31,17 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { · 25 unmodified lines | ||
| 31 | 31 | "ADD", |
| 32 | 32 | "SUB", |
| 33 | 33 | "MUL", |
| 34 | − "DIV", | |
| 35 | − "IDIV", | |
| 36 | 34 | "MOD", |
| 37 | 35 | "POW", |
| 36 | + "DIV", | |
| 37 | + "IDIV", | |
| 38 | + "BAND", | |
| 39 | + "BOR", | |
| 40 | + "BXOR", | |
| 41 | + "SHL", | |
| 42 | + "SHR", | |
| 38 | 43 | "UNM", |
| 44 | + "BNOT", | |
| 39 | 45 | "NOT", |
| 40 | 46 | "LEN", |
| 41 | 47 | "CONCAT", |
| @@ -80,11 +86,17 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { · 38 unmodified lines | ||
| 80 | 86 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ |
| 81 | 87 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ |
| 82 | 88 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ |
| 83 | − ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ | |
| 84 | − ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ | |
| 85 | 89 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ |
| 86 | 90 | ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ |
| 91 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ | |
| 92 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ | |
| 93 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ | |
| 94 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ | |
| 95 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ | |
| 96 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ | |
| 97 | + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ | |
| 87 | 98 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ |
| 99 | + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ | |
| 88 | 100 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ |
| 89 | 101 | ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ |
| 90 | 102 | ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lopcodes.h,v 1.143 2013/04/26 13:07:53 roberto Exp $ | |
| 2 | +** $Id: lopcodes.h,v 1.146 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Opcodes for Lua virtual machine |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -187,11 +187,17 @@ OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ · 181 unmodified lines | ||
| 187 | 187 | OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ |
| 188 | 188 | OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ |
| 189 | 189 | OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ |
| 190 | −OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ | |
| 191 | −OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */ | |
| 192 | 190 | OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ |
| 193 | 191 | OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ |
| 192 | +OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ | |
| 193 | +OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */ | |
| 194 | +OP_BAND,/* A B C R(A) := RK(B) & RK(C) */ | |
| 195 | +OP_BOR,/* A B C R(A) := RK(B) | RK(C) */ | |
| 196 | +OP_BXOR,/* A B C R(A) := RK(B) ~ RK(C) */ | |
| 197 | +OP_SHL,/* A B C R(A) := RK(B) << RK(C) */ | |
| 198 | +OP_SHR,/* A B C R(A) := RK(B) >> RK(C) */ | |
| 194 | 199 | OP_UNM,/* A B R(A) := -R(B) */ |
| 200 | +OP_BNOT,/* A B R(A) := ~R(B) */ | |
| 195 | 201 | OP_NOT,/* A B R(A) := not R(B) */ |
| 196 | 202 | OP_LEN,/* A B R(A) := length of R(B) */ |
| 197 | 203 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: loslib.c,v 1.41 2013/05/14 15:57:11 roberto Exp $ | |
| 2 | +** $Id: loslib.c,v 1.45 2014/03/20 19:18:54 roberto Exp $ | |
| 3 | 3 | ** Standard Operating System library |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -20,29 +20,44 @@ · 14 unmodified lines | ||
| 20 | 20 | #include "lualib.h" |
| 21 | 21 | |
| 22 | 22 | |
| 23 | +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ | |
| 23 | 24 | /* |
| 24 | 25 | ** list of valid conversion specifiers for the 'strftime' function |
| 25 | 26 | */ |
| 26 | −#if !defined(LUA_STRFTIMEOPTIONS) | |
| 27 | 27 | |
| 28 | 28 | #if !defined(LUA_USE_POSIX) |
| 29 | 29 | #define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } |
| 30 | 30 | #else |
| 31 | 31 | #define LUA_STRFTIMEOPTIONS \ |
| 32 | − { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ | |
| 33 | − "", "E", "cCxXyY", \ | |
| 32 | + { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \ | |
| 33 | + "E", "cCxXyY", \ | |
| 34 | 34 | "O", "deHImMSuUVwWy" } |
| 35 | 35 | #endif |
| 36 | 36 | |
| 37 | −#endif | |
| 37 | +#endif /* } */ | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | +#if !defined(l_time_t) /* { */ | |
| 42 | +/* | |
| 43 | +** type to represent time_t in Lua | |
| 44 | +*/ | |
| 45 | +#define l_timet lua_Integer | |
| 46 | +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) | |
| 47 | +#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a)) | |
| 38 | 48 | |
| 49 | +#endif /* } */ | |
| 39 | 50 | |
| 40 | 51 | |
| 52 | + | |
| 53 | +#if !defined(lua_tmpnam) /* { */ | |
| 41 | 54 | /* |
| 42 | 55 | ** By default, Lua uses tmpnam except when POSIX is available, where it |
| 43 | 56 | ** uses mkstemp. |
| 44 | 57 | */ |
| 45 | −#if defined(LUA_USE_MKSTEMP) | |
| 58 | + | |
| 59 | +#if defined(LUA_USE_POSIX) /* { */ | |
| 60 | + | |
| 46 | 61 | #include <unistd.h> |
| 47 | 62 | #define LUA_TMPNAMBUFSIZE 32 |
| 48 | 63 | #define lua_tmpnam(b,e) { \ |
| @@ -51,29 +66,38 @@ · 2 unmodified lines | ||
| 51 | 66 | if (e != -1) close(e); \ |
| 52 | 67 | e = (e == -1); } |
| 53 | 68 | |
| 54 | −#elif !defined(lua_tmpnam) | |
| 69 | +#else /* }{ */ | |
| 55 | 70 | |
| 71 | +/* ANSI definitions */ | |
| 56 | 72 | #define LUA_TMPNAMBUFSIZE L_tmpnam |
| 57 | 73 | #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } |
| 58 | 74 | |
| 59 | −#endif | |
| 75 | +#endif /* } */ | |
| 76 | + | |
| 77 | +#endif /* } */ | |
| 78 | + | |
| 60 | 79 | |
| 61 | 80 | |
| 81 | +#if !defined(l_gmtime) /* { */ | |
| 62 | 82 | /* |
| 63 | 83 | ** By default, Lua uses gmtime/localtime, except when POSIX is available, |
| 64 | 84 | ** where it uses gmtime_r/localtime_r |
| 65 | 85 | */ |
| 66 | −#if defined(LUA_USE_GMTIME_R) | |
| 86 | + | |
| 87 | +#if defined(LUA_USE_POSIX) /* { */ | |
| 67 | 88 | |
| 68 | 89 | #define l_gmtime(t,r) gmtime_r(t,r) |
| 69 | 90 | #define l_localtime(t,r) localtime_r(t,r) |
| 70 | 91 | |
| 71 | −#elif !defined(l_gmtime) | |
| 92 | +#else /* }{ */ | |
| 72 | 93 | |
| 94 | +/* ANSI definitions */ | |
| 73 | 95 | #define l_gmtime(t,r) ((void)r, gmtime(t)) |
| 74 | 96 | #define l_localtime(t,r) ((void)r, localtime(t)) |
| 75 | 97 | |
| 76 | −#endif | |
| 98 | +#endif /* } */ | |
| 99 | + | |
| 100 | +#endif /* } */ | |
| 77 | 101 | |
| 78 | 102 | |
| 79 | 103 | |
| @@ -147,8 +171,7 @@ static void setboolfield (lua_State *L, const char *key, int value) { · 67 unmodified lines | ||
| 147 | 171 | |
| 148 | 172 | static int getboolfield (lua_State *L, const char *key) { |
| 149 | 173 | int res; |
| 150 | − lua_getfield(L, -1, key); | |
| 151 | − res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); | |
| 174 | + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); | |
| 152 | 175 | lua_pop(L, 1); |
| 153 | 176 | return res; |
| 154 | 177 | } |
| @@ -194,7 +217,7 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) { · 39 unmodified lines | ||
| 194 | 217 | |
| 195 | 218 | static int os_date (lua_State *L) { |
| 196 | 219 | const char *s = luaL_optstring(L, 1, "%c"); |
| 197 | − time_t t = luaL_opt(L, (time_t)luaL_checkinteger, 2, time(NULL)); | |
| 220 | + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); | |
| 198 | 221 | struct tm tmr, *stm; |
| 199 | 222 | if (*s == '!') { /* UTC? */ |
| 200 | 223 | stm = l_gmtime(&t, &tmr); |
| @@ -255,17 +278,18 @@ static int os_time (lua_State *L) { · 54 unmodified lines | ||
| 255 | 278 | ts.tm_isdst = getboolfield(L, "isdst"); |
| 256 | 279 | t = mktime(&ts); |
| 257 | 280 | } |
| 258 | − if (t == (time_t)(-1)) | |
| 281 | + if (t != (time_t)(l_timet)t) | |
| 282 | + luaL_error(L, "time result cannot be represented in this Lua instalation"); | |
| 283 | + else if (t == (time_t)(-1)) | |
| 259 | 284 | lua_pushnil(L); |
| 260 | 285 | else |
| 261 | − lua_pushinteger(L, t); | |
| 286 | + l_pushtime(L, t); | |
| 262 | 287 | return 1; |
| 263 | 288 | } |
| 264 | 289 | |
| 265 | 290 | |
| 266 | 291 | static int os_difftime (lua_State *L) { |
| 267 | − lua_pushnumber(L, difftime((time_t)(luaL_checkinteger(L, 1)), | |
| 268 | − (time_t)(luaL_optinteger(L, 2, 0)))); | |
| 292 | + lua_pushnumber(L, difftime((l_checktime(L, 1)), (l_checktime(L, 2)))); | |
| 269 | 293 | return 1; |
| 270 | 294 | } |
| 271 | 295 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp $ | |
| 2 | +** $Id: lparser.c,v 2.138 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Lua Parser |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -35,6 +35,10 @@ · 29 unmodified lines | ||
| 35 | 35 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
| 36 | 36 | |
| 37 | 37 | |
| 38 | +/* because all strings are unified by the scanner, the parser | |
| 39 | + can use pointer equality for string equality */ | |
| 40 | +#define eqstr(a,b) ((a) == (b)) | |
| 41 | + | |
| 38 | 42 | |
| 39 | 43 | /* |
| 40 | 44 | ** nodes for block list (list of active blocks) |
| @@ -57,16 +61,6 @@ static void statement (LexState *ls); · 16 unmodified lines | ||
| 57 | 61 | static void expr (LexState *ls, expdesc *v); |
| 58 | 62 | |
| 59 | 63 | |
| 60 | −static void anchor_token (LexState *ls) { | |
| 61 | − /* last token from outer function must be EOS */ | |
| 62 | − lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); | |
| 63 | − if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { | |
| 64 | − TString *ts = ls->t.seminfo.ts; | |
| 65 | − luaX_newstring(ls, getstr(ts), ts->tsv.len); | |
| 66 | − } | |
| 67 | −} | |
| 68 | − | |
| 69 | − | |
| 70 | 64 | /* semantic error */ |
| 71 | 65 | static l_noret semerror (LexState *ls, const char *msg) { |
| 72 | 66 | ls->t.token = 0; /* remove 'near to' from final message */ |
| @@ -222,7 +216,7 @@ static int searchupvalue (FuncState *fs, TString *name) { · 149 unmodified lines | ||
| 222 | 216 | int i; |
| 223 | 217 | Upvaldesc *up = fs->f->upvalues; |
| 224 | 218 | for (i = 0; i < fs->nups; i++) { |
| 225 | − if (luaS_eqstr(up[i].name, name)) return i; | |
| 219 | + if (eqstr(up[i].name, name)) return i; | |
| 226 | 220 | } |
| 227 | 221 | return -1; /* not found */ |
| 228 | 222 | } |
| @@ -246,7 +240,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { · 17 unmodified lines | ||
| 246 | 240 | static int searchvar (FuncState *fs, TString *n) { |
| 247 | 241 | int i; |
| 248 | 242 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
| 249 | − if (luaS_eqstr(n, getlocvar(fs, i)->varname)) | |
| 243 | + if (eqstr(n, getlocvar(fs, i)->varname)) | |
| 250 | 244 | return i; |
| 251 | 245 | } |
| 252 | 246 | return -1; /* not found */ |
| @@ -342,7 +336,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { · 89 unmodified lines | ||
| 342 | 336 | FuncState *fs = ls->fs; |
| 343 | 337 | Labellist *gl = &ls->dyd->gt; |
| 344 | 338 | Labeldesc *gt = &gl->arr[g]; |
| 345 | − lua_assert(luaS_eqstr(gt->name, label->name)); | |
| 339 | + lua_assert(eqstr(gt->name, label->name)); | |
| 346 | 340 | if (gt->nactvar < label->nactvar) { |
| 347 | 341 | TString *vname = getlocvar(fs, gt->nactvar)->varname; |
| 348 | 342 | const char *msg = luaO_pushfstring(ls->L, |
| @@ -369,7 +363,7 @@ static int findlabel (LexState *ls, int g) { · 20 unmodified lines | ||
| 369 | 363 | /* check labels in current block for a match */ |
| 370 | 364 | for (i = bl->firstlabel; i < dyd->label.n; i++) { |
| 371 | 365 | Labeldesc *lb = &dyd->label.arr[i]; |
| 372 | − if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ | |
| 366 | + if (eqstr(lb->name, gt->name)) { /* correct label? */ | |
| 373 | 367 | if (gt->nactvar > lb->nactvar && |
| 374 | 368 | (bl->upval || dyd->label.n > bl->firstlabel)) |
| 375 | 369 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); |
| @@ -403,7 +397,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) { · 27 unmodified lines | ||
| 403 | 397 | Labellist *gl = &ls->dyd->gt; |
| 404 | 398 | int i = ls->fs->bl->firstgoto; |
| 405 | 399 | while (i < gl->n) { |
| 406 | − if (luaS_eqstr(gl->arr[i].name, lb->name)) | |
| 400 | + if (eqstr(gl->arr[i].name, lb->name)) | |
| 407 | 401 | closegoto(ls, i, lb); |
| 408 | 402 | else |
| 409 | 403 | i++; |
| @@ -525,7 +519,6 @@ static void codeclosure (LexState *ls, expdesc *v) { · 115 unmodified lines | ||
| 525 | 519 | |
| 526 | 520 | |
| 527 | 521 | static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { |
| 528 | − lua_State *L = ls->L; | |
| 529 | 522 | Proto *f; |
| 530 | 523 | fs->prev = ls->fs; /* linked list of funcstates */ |
| 531 | 524 | fs->ls = ls; |
| @@ -544,10 +537,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { · 12 unmodified lines | ||
| 544 | 537 | f = fs->f; |
| 545 | 538 | f->source = ls->source; |
| 546 | 539 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
| 547 | − fs->h = luaH_new(L); | |
| 548 | − /* anchor table of constants (to avoid being collected) */ | |
| 549 | − sethvalue2s(L, L->top, fs->h); | |
| 550 | − incr_top(L); | |
| 551 | 540 | enterblock(fs, bl, 0); |
| 552 | 541 | } |
| 553 | 542 | |
| @@ -572,9 +561,6 @@ static void close_func (LexState *ls) { · 18 unmodified lines | ||
| 572 | 561 | f->sizeupvalues = fs->nups; |
| 573 | 562 | lua_assert(fs->bl == NULL); |
| 574 | 563 | ls->fs = fs->prev; |
| 575 | − /* last token read was anchored in defunct function; must re-anchor it */ | |
| 576 | − anchor_token(ls); | |
| 577 | − L->top--; /* pop table of constants */ | |
| 578 | 564 | luaC_checkGC(L); |
| 579 | 565 | } |
| 580 | 566 | |
| @@ -993,6 +979,7 @@ static UnOpr getunopr (int op) { · 412 unmodified lines | ||
| 993 | 979 | switch (op) { |
| 994 | 980 | case TK_NOT: return OPR_NOT; |
| 995 | 981 | case '-': return OPR_MINUS; |
| 982 | + case '~': return OPR_BNOT; | |
| 996 | 983 | case '#': return OPR_LEN; |
| 997 | 984 | default: return OPR_NOUNOPR; |
| 998 | 985 | } |
| @@ -1004,10 +991,15 @@ static BinOpr getbinopr (int op) { · 5 unmodified lines | ||
| 1004 | 991 | case '+': return OPR_ADD; |
| 1005 | 992 | case '-': return OPR_SUB; |
| 1006 | 993 | case '*': return OPR_MUL; |
| 1007 | − case '/': return OPR_DIV; | |
| 1008 | − case TK_IDIV: return OPR_IDIV; | |
| 1009 | 994 | case '%': return OPR_MOD; |
| 1010 | 995 | case '^': return OPR_POW; |
| 996 | + case '/': return OPR_DIV; | |
| 997 | + case TK_IDIV: return OPR_IDIV; | |
| 998 | + case '&': return OPR_BAND; | |
| 999 | + case '|': return OPR_BOR; | |
| 1000 | + case '~': return OPR_BXOR; | |
| 1001 | + case TK_SHL: return OPR_SHL; | |
| 1002 | + case TK_SHR: return OPR_SHR; | |
| 1011 | 1003 | case TK_CONCAT: return OPR_CONCAT; |
| 1012 | 1004 | case TK_NE: return OPR_NE; |
| 1013 | 1005 | case TK_EQ: return OPR_EQ; |
| @@ -1026,15 +1018,19 @@ static const struct { · 12 unmodified lines | ||
| 1026 | 1018 | lu_byte left; /* left priority for each binary operator */ |
| 1027 | 1019 | lu_byte right; /* right priority */ |
| 1028 | 1020 | } priority[] = { /* ORDER OPR */ |
| 1029 | − {6, 6}, {6, 6}, /* '+' '-' */ | |
| 1030 | − {7, 7}, {7, 7}, {7, 7}, {7, 7}, /* '*' '/' '//' '%' */ | |
| 1031 | − {10, 9}, {5, 4}, /* ^, .. (right associative) */ | |
| 1032 | − {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ | |
| 1033 | − {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ | |
| 1034 | − {2, 2}, {1, 1} /* and, or */ | |
| 1021 | + {10, 10}, {10, 10}, /* '+' '-' */ | |
| 1022 | + {11, 11}, {11, 11}, /* '*' '%' */ | |
| 1023 | + {14, 13}, /* '^' (right associative) */ | |
| 1024 | + {11, 11}, {11, 11}, /* '/' '//' */ | |
| 1025 | + {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ | |
| 1026 | + {7, 7}, {7, 7}, /* '<<' '>>' */ | |
| 1027 | + {9, 8}, /* '..' (right associative) */ | |
| 1028 | + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ | |
| 1029 | + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ | |
| 1030 | + {2, 2}, {1, 1} /* and, or */ | |
| 1035 | 1031 | }; |
| 1036 | 1032 | |
| 1037 | −#define UNARY_PRIORITY 8 /* priority for unary operators */ | |
| 1033 | +#define UNARY_PRIORITY 12 /* priority for unary operators */ | |
| 1038 | 1034 | |
| 1039 | 1035 | |
| 1040 | 1036 | /* |
| @@ -1202,7 +1198,7 @@ static void gotostat (LexState *ls, int pc) { · 161 unmodified lines | ||
| 1202 | 1198 | static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { |
| 1203 | 1199 | int i; |
| 1204 | 1200 | for (i = fs->bl->firstlabel; i < ll->n; i++) { |
| 1205 | − if (luaS_eqstr(label, ll->arr[i].name)) { | |
| 1201 | + if (eqstr(label, ll->arr[i].name)) { | |
| 1206 | 1202 | const char *msg = luaO_pushfstring(fs->ls->L, |
| 1207 | 1203 | "label " LUA_QS " already defined on line %d", |
| 1208 | 1204 | getstr(label), ll->arr[i].line); |
| @@ -1627,11 +1623,14 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, · 418 unmodified lines | ||
| 1627 | 1623 | LexState lexstate; |
| 1628 | 1624 | FuncState funcstate; |
| 1629 | 1625 | Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ |
| 1630 | − /* anchor closure (to avoid being collected) */ | |
| 1631 | − setclLvalue(L, L->top, cl); | |
| 1626 | + setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ | |
| 1627 | + incr_top(L); | |
| 1628 | + lexstate.h = luaH_new(L); /* create table for scanner */ | |
| 1629 | + sethvalue(L, L->top, lexstate.h); /* anchor it */ | |
| 1632 | 1630 | incr_top(L); |
| 1633 | 1631 | funcstate.f = cl->l.p = luaF_newproto(L); |
| 1634 | 1632 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
| 1633 | + luaC_objbarrier(L, funcstate.f, funcstate.f->source); | |
| 1635 | 1634 | lexstate.buff = buff; |
| 1636 | 1635 | lexstate.dyd = dyd; |
| 1637 | 1636 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; |
| @@ -1640,6 +1639,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, · 2 unmodified lines | ||
| 1640 | 1639 | lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); |
| 1641 | 1640 | /* all scopes should be correctly finished */ |
| 1642 | 1641 | lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); |
| 1643 | − return cl; /* it's on the stack too */ | |
| 1642 | + L->top--; /* remove scanner's table */ | |
| 1643 | + return cl; /* closure is on the stack, too */ | |
| 1644 | 1644 | } |
| 1645 | 1645 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lparser.h,v 1.71 2013/04/16 18:46:28 roberto Exp $ | |
| 2 | +** $Id: lparser.h,v 1.72 2013/08/30 16:01:37 roberto Exp $ | |
| 3 | 3 | ** Lua Parser |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -97,7 +97,6 @@ struct BlockCnt; /* defined in lparser.c */ · 91 unmodified lines | ||
| 97 | 97 | /* state needed to generate code for a given function */ |
| 98 | 98 | typedef struct FuncState { |
| 99 | 99 | Proto *f; /* current function header */ |
| 100 | − Table *h; /* table to find (and reuse) elements in `k' */ | |
| 101 | 100 | struct FuncState *prev; /* enclosing function */ |
| 102 | 101 | struct LexState *ls; /* lexical state */ |
| 103 | 102 | struct BlockCnt *bl; /* chain of current blocks */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstate.c,v 2.99 2012/10/02 17:40:53 roberto Exp $ | |
| 2 | +** $Id: lstate.c,v 2.121 2014/02/18 13:46:26 roberto Exp $ | |
| 3 | 3 | ** Global State |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -30,10 +30,6 @@ · 24 unmodified lines | ||
| 30 | 30 | #define LUAI_GCPAUSE 200 /* 200% */ |
| 31 | 31 | #endif |
| 32 | 32 | |
| 33 | −#if !defined(LUAI_GCMAJOR) | |
| 34 | −#define LUAI_GCMAJOR 200 /* 200% */ | |
| 35 | −#endif | |
| 36 | − | |
| 37 | 33 | #if !defined(LUAI_GCMUL) |
| 38 | 34 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ |
| 39 | 35 | #endif |
| @@ -119,6 +115,9 @@ CallInfo *luaE_extendCI (lua_State *L) { · 79 unmodified lines | ||
| 119 | 115 | } |
| 120 | 116 | |
| 121 | 117 | |
| 118 | +/* | |
| 119 | +** free all CallInfo structures not in use by a thread | |
| 120 | +*/ | |
| 122 | 121 | void luaE_freeCI (lua_State *L) { |
| 123 | 122 | CallInfo *ci = L->ci; |
| 124 | 123 | CallInfo *next = ci->next; |
| @@ -130,6 +129,22 @@ void luaE_freeCI (lua_State *L) { · 5 unmodified lines | ||
| 130 | 129 | } |
| 131 | 130 | |
| 132 | 131 | |
| 132 | +/* | |
| 133 | +** free half of the CallInfo structures not in use by a thread | |
| 134 | +*/ | |
| 135 | +void luaE_shrinkCI (lua_State *L) { | |
| 136 | + CallInfo *ci = L->ci; | |
| 137 | + while (ci->next != NULL) { /* while there is 'next' */ | |
| 138 | + CallInfo *next2 = ci->next->next; /* next's next */ | |
| 139 | + if (next2 == NULL) break; | |
| 140 | + luaM_free(L, ci->next); /* remove next */ | |
| 141 | + ci->next = next2; /* remove 'next' from the list */ | |
| 142 | + next2->previous = ci; | |
| 143 | + ci = next2; | |
| 144 | + } | |
| 145 | +} | |
| 146 | + | |
| 147 | + | |
| 133 | 148 | static void stack_init (lua_State *L1, lua_State *L) { |
| 134 | 149 | int i; CallInfo *ci; |
| 135 | 150 | /* initialize stack array */ |
| @@ -163,22 +178,23 @@ static void freestack (lua_State *L) { · 27 unmodified lines | ||
| 163 | 178 | ** Create registry table and its predefined values |
| 164 | 179 | */ |
| 165 | 180 | static void init_registry (lua_State *L, global_State *g) { |
| 166 | − TValue mt; | |
| 181 | + TValue temp; | |
| 167 | 182 | /* create registry */ |
| 168 | 183 | Table *registry = luaH_new(L); |
| 169 | 184 | sethvalue(L, &g->l_registry, registry); |
| 170 | 185 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); |
| 171 | 186 | /* registry[LUA_RIDX_MAINTHREAD] = L */ |
| 172 | − setthvalue(L, &mt, L); | |
| 173 | − luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); | |
| 187 | + setthvalue(L, &temp, L); /* temp = L */ | |
| 188 | + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); | |
| 174 | 189 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ |
| 175 | − sethvalue(L, &mt, luaH_new(L)); | |
| 176 | − luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); | |
| 190 | + sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ | |
| 191 | + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); | |
| 177 | 192 | } |
| 178 | 193 | |
| 179 | 194 | |
| 180 | 195 | /* |
| 181 | −** open parts of the state that may cause memory-allocation errors | |
| 196 | +** open parts of the state that may cause memory-allocation errors. | |
| 197 | +** ('g->version' != NULL flags that the state was completely build) | |
| 182 | 198 | */ |
| 183 | 199 | static void f_luaopen (lua_State *L, void *ud) { |
| 184 | 200 | global_State *g = G(L); |
| @@ -190,20 +206,23 @@ static void f_luaopen (lua_State *L, void *ud) { · 5 unmodified lines | ||
| 190 | 206 | luaX_init(L); |
| 191 | 207 | /* pre-create memory-error message */ |
| 192 | 208 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); |
| 193 | − luaS_fix(g->memerrmsg); /* it should never be collected */ | |
| 209 | + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ | |
| 194 | 210 | g->gcrunning = 1; /* allow gc */ |
| 211 | + g->version = lua_version(NULL); | |
| 212 | + luai_userstateopen(L); | |
| 195 | 213 | } |
| 196 | 214 | |
| 197 | 215 | |
| 198 | 216 | /* |
| 199 | −** preinitialize a state with consistent values without allocating | |
| 217 | +** preinitialize a thread with consistent values without allocating | |
| 200 | 218 | ** any memory (to avoid errors) |
| 201 | 219 | */ |
| 202 | −static void preinit_state (lua_State *L, global_State *g) { | |
| 220 | +static void preinit_thread (lua_State *L, global_State *g) { | |
| 203 | 221 | G(L) = g; |
| 204 | 222 | L->stack = NULL; |
| 205 | 223 | L->ci = NULL; |
| 206 | 224 | L->stacksize = 0; |
| 225 | + L->twups = L; /* thread has no upvalues */ | |
| 207 | 226 | L->errorJmp = NULL; |
| 208 | 227 | L->nCcalls = 0; |
| 209 | 228 | L->hook = NULL; |
| @@ -222,6 +241,8 @@ static void close_state (lua_State *L) { · 12 unmodified lines | ||
| 222 | 241 | global_State *g = G(L); |
| 223 | 242 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
| 224 | 243 | luaC_freeallobjects(L); /* collect all objects */ |
| 244 | + if (g->version) /* closing a fully built state? */ | |
| 245 | + luai_userstateclose(L); | |
| 225 | 246 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); |
| 226 | 247 | luaZ_freebuffer(L, &g->buff); |
| 227 | 248 | freestack(L); |
| @@ -231,13 +252,20 @@ static void close_state (lua_State *L) { · 3 unmodified lines | ||
| 231 | 252 | |
| 232 | 253 | |
| 233 | 254 | LUA_API lua_State *lua_newthread (lua_State *L) { |
| 255 | + global_State *g = G(L); | |
| 234 | 256 | lua_State *L1; |
| 235 | 257 | lua_lock(L); |
| 236 | 258 | luaC_checkGC(L); |
| 237 | − L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; | |
| 259 | + /* create new thread */ | |
| 260 | + L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; | |
| 261 | + L1->marked = luaC_white(g); | |
| 262 | + L1->tt = LUA_TTHREAD; | |
| 263 | + /* link it on list 'allgc' */ | |
| 264 | + L1->next = g->allgc; | |
| 265 | + g->allgc = obj2gco(L1); | |
| 238 | 266 | setthvalue(L, L->top, L1); |
| 239 | 267 | api_incr_top(L); |
| 240 | − preinit_state(L1, G(L)); | |
| 268 | + preinit_thread(L1, g); | |
| 241 | 269 | L1->hookmask = L->hookmask; |
| 242 | 270 | L1->basehookcount = L->basehookcount; |
| 243 | 271 | L1->hook = L->hook; |
| @@ -269,36 +297,32 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { · 25 unmodified lines | ||
| 269 | 297 | g = &l->g; |
| 270 | 298 | L->next = NULL; |
| 271 | 299 | L->tt = LUA_TTHREAD; |
| 272 | − g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); | |
| 300 | + g->currentwhite = bitmask(WHITE0BIT); | |
| 273 | 301 | L->marked = luaC_white(g); |
| 274 | − g->gckind = KGC_NORMAL; | |
| 275 | − preinit_state(L, g); | |
| 302 | + preinit_thread(L, g); | |
| 276 | 303 | g->frealloc = f; |
| 277 | 304 | g->ud = ud; |
| 278 | 305 | g->mainthread = L; |
| 279 | 306 | g->seed = makeseed(L); |
| 280 | − g->uvhead.u.l.prev = &g->uvhead; | |
| 281 | − g->uvhead.u.l.next = &g->uvhead; | |
| 282 | 307 | g->gcrunning = 0; /* no GC while building state */ |
| 283 | 308 | g->GCestimate = 0; |
| 284 | − g->strt.size = 0; | |
| 285 | − g->strt.nuse = 0; | |
| 309 | + g->strt.size = g->strt.nuse = 0; | |
| 286 | 310 | g->strt.hash = NULL; |
| 287 | 311 | setnilvalue(&g->l_registry); |
| 288 | 312 | luaZ_initbuffer(L, &g->buff); |
| 289 | 313 | g->panic = NULL; |
| 290 | − g->version = lua_version(NULL); | |
| 314 | + g->version = NULL; | |
| 291 | 315 | g->gcstate = GCSpause; |
| 292 | − g->allgc = NULL; | |
| 293 | − g->finobj = NULL; | |
| 294 | − g->tobefnz = NULL; | |
| 295 | − g->sweepgc = g->sweepfin = NULL; | |
| 316 | + g->gckind = KGC_NORMAL; | |
| 317 | + g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; | |
| 318 | + g->sweepgc = NULL; | |
| 296 | 319 | g->gray = g->grayagain = NULL; |
| 297 | 320 | g->weak = g->ephemeron = g->allweak = NULL; |
| 321 | + g->twups = NULL; | |
| 298 | 322 | g->totalbytes = sizeof(LG); |
| 299 | 323 | g->GCdebt = 0; |
| 324 | + g->gcfinnum = 0; | |
| 300 | 325 | g->gcpause = LUAI_GCPAUSE; |
| 301 | − g->gcmajorinc = LUAI_GCMAJOR; | |
| 302 | 326 | g->gcstepmul = LUAI_GCMUL; |
| 303 | 327 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
| 304 | 328 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
| @@ -306,8 +330,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { · 1 unmodified line | ||
| 306 | 330 | close_state(L); |
| 307 | 331 | L = NULL; |
| 308 | 332 | } |
| 309 | − else | |
| 310 | − luai_userstateopen(L); | |
| 311 | 333 | return L; |
| 312 | 334 | } |
| 313 | 335 | |
| @@ -315,7 +337,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { · 1 unmodified line | ||
| 315 | 337 | LUA_API void lua_close (lua_State *L) { |
| 316 | 338 | L = G(L)->mainthread; /* only the main thread can be closed */ |
| 317 | 339 | lua_lock(L); |
| 318 | − luai_userstateclose(L); | |
| 319 | 340 | close_state(L); |
| 320 | 341 | } |
| 321 | 342 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstate.h,v 2.82 2012/07/02 13:37:04 roberto Exp $ | |
| 2 | +** $Id: lstate.h,v 2.102 2014/02/18 13:46:26 roberto Exp $ | |
| 3 | 3 | ** Global State |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -16,25 +16,16 @@ · 10 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | /* |
| 18 | 18 | |
| 19 | −** Some notes about garbage-collected objects: All objects in Lua must | |
| 20 | −** be kept somehow accessible until being freed. | |
| 19 | +** Some notes about garbage-collected objects: All objects in Lua must | |
| 20 | +** be kept somehow accessible until being freed, so all objects always | |
| 21 | +** belong to one (and only one) of these lists, using field 'next' of | |
| 22 | +** the 'CommonHeader' for the link: | |
| 21 | 23 | ** |
| 22 | −** Lua keeps most objects linked in list g->allgc. The link uses field | |
| 23 | −** 'next' of the CommonHeader. | |
| 24 | −** | |
| 25 | −** Strings are kept in several lists headed by the array g->strt.hash. | |
| 26 | −** | |
| 27 | −** Open upvalues are not subject to independent garbage collection. They | |
| 28 | −** are collected together with their respective threads. Lua keeps a | |
| 29 | −** double-linked list with all open upvalues (g->uvhead) so that it can | |
| 30 | −** mark objects referred by them. (They are always gray, so they must | |
| 31 | −** be remarked in the atomic step. Usually their contents would be marked | |
| 32 | −** when traversing the respective threads, but the thread may already be | |
| 33 | −** dead, while the upvalue is still accessible through closures.) | |
| 34 | −** | |
| 35 | −** Objects with finalizers are kept in the list g->finobj. | |
| 36 | −** | |
| 37 | −** The list g->tobefnz links all objects being finalized. | |
| 24 | +** allgc: all objects not marked for finalization; | |
| 25 | +** finobj: all objects marked for finalization; | |
| 26 | +** tobefnz: all objects ready to be finalized; | |
| 27 | +** fixedgc: all objects that are not to be collected (currently | |
| 28 | +** only small strings, such as reserved words). | |
| 38 | 29 | |
| 39 | 30 | */ |
| 40 | 31 | |
| @@ -53,12 +44,11 @@ struct lua_longjmp; /* defined in ldo.c */ · 12 unmodified lines | ||
| 53 | 44 | /* kinds of Garbage Collection */ |
| 54 | 45 | #define KGC_NORMAL 0 |
| 55 | 46 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ |
| 56 | −#define KGC_GEN 2 /* generational collection */ | |
| 57 | 47 | |
| 58 | 48 | |
| 59 | 49 | typedef struct stringtable { |
| 60 | − GCObject **hash; | |
| 61 | − lu_int32 nuse; /* number of elements */ | |
| 50 | + TString **hash; | |
| 51 | + int nuse; /* number of elements */ | |
| 62 | 52 | int size; |
| 63 | 53 | } stringtable; |
| 64 | 54 | |
| @@ -123,21 +113,20 @@ typedef struct global_State { · 58 unmodified lines | ||
| 123 | 113 | lu_byte gcstate; /* state of garbage collector */ |
| 124 | 114 | lu_byte gckind; /* kind of GC running */ |
| 125 | 115 | lu_byte gcrunning; /* true if GC is running */ |
| 126 | − int sweepstrgc; /* position of sweep in `strt' */ | |
| 127 | 116 | GCObject *allgc; /* list of all collectable objects */ |
| 117 | + GCObject **sweepgc; /* current position of sweep in list */ | |
| 128 | 118 | GCObject *finobj; /* list of collectable objects with finalizers */ |
| 129 | − GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | |
| 130 | − GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | |
| 131 | 119 | GCObject *gray; /* list of gray objects */ |
| 132 | 120 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
| 133 | 121 | GCObject *weak; /* list of tables with weak values */ |
| 134 | 122 | GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ |
| 135 | 123 | GCObject *allweak; /* list of all-weak tables */ |
| 136 | 124 | GCObject *tobefnz; /* list of userdata to be GC */ |
| 137 | − UpVal uvhead; /* head of double-linked list of all open upvalues */ | |
| 125 | + GCObject *fixedgc; /* list of objects not to be collected */ | |
| 126 | + struct lua_State *twups; /* list of threads with open upvalues */ | |
| 138 | 127 | Mbuffer buff; /* temporary buffer for string concatenation */ |
| 128 | + unsigned int gcfinnum; /* number of finalizers to call in each GC step */ | |
| 139 | 129 | int gcpause; /* size of pause between successive GCs */ |
| 140 | − int gcmajorinc; /* pause between major collections (only in gen. mode) */ | |
| 141 | 130 | int gcstepmul; /* GC `granularity' */ |
| 142 | 131 | lua_CFunction panic; /* to be called in unprotected errors */ |
| 143 | 132 | struct lua_State *mainthread; |
| @@ -168,8 +157,9 @@ struct lua_State { · 24 unmodified lines | ||
| 168 | 157 | int basehookcount; |
| 169 | 158 | int hookcount; |
| 170 | 159 | lua_Hook hook; |
| 171 | − GCObject *openupval; /* list of open upvalues in this stack */ | |
| 160 | + UpVal *openupval; /* list of open upvalues in this stack */ | |
| 172 | 161 | GCObject *gclist; |
| 162 | + struct lua_State *twups; /* list of threads with open upvalues */ | |
| 173 | 163 | struct lua_longjmp *errorJmp; /* current error recover point */ |
| 174 | 164 | ptrdiff_t errfunc; /* current error handling function (stack index) */ |
| 175 | 165 | CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ |
| @@ -189,7 +179,6 @@ union GCObject { · 13 unmodified lines | ||
| 189 | 179 | union Closure cl; |
| 190 | 180 | struct Table h; |
| 191 | 181 | struct Proto p; |
| 192 | − struct UpVal uv; | |
| 193 | 182 | struct lua_State th; /* thread */ |
| 194 | 183 | }; |
| 195 | 184 | |
| @@ -208,7 +197,6 @@ union GCObject { · 12 unmodified lines | ||
| 208 | 197 | check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) |
| 209 | 198 | #define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) |
| 210 | 199 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) |
| 211 | −#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) | |
| 212 | 200 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) |
| 213 | 201 | |
| 214 | 202 | /* macro to convert any Lua object into a GCObject */ |
| @@ -222,6 +210,7 @@ LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); · 7 unmodified lines | ||
| 222 | 210 | LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); |
| 223 | 211 | LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); |
| 224 | 212 | LUAI_FUNC void luaE_freeCI (lua_State *L); |
| 213 | +LUAI_FUNC void luaE_shrinkCI (lua_State *L); | |
| 225 | 214 | |
| 226 | 215 | |
| 227 | 216 | #endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstring.c,v 2.27 2013/06/19 14:27:00 roberto Exp $ | |
| 2 | +** $Id: lstring.c,v 2.38 2014/03/19 18:51:42 roberto Exp $ | |
| 3 | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -12,12 +12,15 @@ · 6 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include "lua.h" |
| 14 | 14 | |
| 15 | +#include "ldebug.h" | |
| 16 | +#include "ldo.h" | |
| 15 | 17 | #include "lmem.h" |
| 16 | 18 | #include "lobject.h" |
| 17 | 19 | #include "lstate.h" |
| 18 | 20 | #include "lstring.h" |
| 19 | 21 | |
| 20 | 22 | |
| 23 | + | |
| 21 | 24 | /* |
| 22 | 25 | ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to |
| 23 | 26 | ** compute its hash |
| @@ -39,15 +42,6 @@ int luaS_eqlngstr (TString *a, TString *b) { · 15 unmodified lines | ||
| 39 | 42 | } |
| 40 | 43 | |
| 41 | 44 | |
| 42 | −/* | |
| 43 | −** equality for strings | |
| 44 | −*/ | |
| 45 | −int luaS_eqstr (TString *a, TString *b) { | |
| 46 | − return (a->tsv.tt == b->tsv.tt) && | |
| 47 | − (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); | |
| 48 | −} | |
| 49 | − | |
| 50 | − | |
| 51 | 45 | unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { |
| 52 | 46 | unsigned int h = seed ^ cast(unsigned int, l); |
| 53 | 47 | size_t l1; |
| @@ -64,43 +58,41 @@ unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { · 10 unmodified lines | ||
| 64 | 58 | void luaS_resize (lua_State *L, int newsize) { |
| 65 | 59 | int i; |
| 66 | 60 | stringtable *tb = &G(L)->strt; |
| 67 | − /* cannot resize while GC is traversing strings */ | |
| 68 | − luaC_runtilstate(L, ~bitmask(GCSsweepstring)); | |
| 69 | − if (newsize > tb->size) { | |
| 70 | − luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | |
| 71 | − for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; | |
| 61 | + if (newsize > tb->size) { /* grow table if needed */ | |
| 62 | + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); | |
| 63 | + for (i = tb->size; i < newsize; i++) | |
| 64 | + tb->hash[i] = NULL; | |
| 72 | 65 | } |
| 73 | − /* rehash */ | |
| 74 | − for (i=0; i<tb->size; i++) { | |
| 75 | − GCObject *p = tb->hash[i]; | |
| 66 | + for (i = 0; i < tb->size; i++) { /* rehash */ | |
| 67 | + TString *p = tb->hash[i]; | |
| 76 | 68 | tb->hash[i] = NULL; |
| 77 | 69 | while (p) { /* for each node in the list */ |
| 78 | − GCObject *next = gch(p)->next; /* save next */ | |
| 79 | − unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ | |
| 80 | − gch(p)->next = tb->hash[h]; /* chain it */ | |
| 70 | + TString *hnext = p->tsv.hnext; /* save next */ | |
| 71 | + unsigned int h = lmod(p->tsv.hash, newsize); /* new position */ | |
| 72 | + p->tsv.hnext = tb->hash[h]; /* chain it */ | |
| 81 | 73 | tb->hash[h] = p; |
| 82 | − resetoldbit(p); /* see MOVE OLD rule */ | |
| 83 | − p = next; | |
| 74 | + p = hnext; | |
| 84 | 75 | } |
| 85 | 76 | } |
| 86 | − if (newsize < tb->size) { | |
| 87 | − /* shrinking slice must be empty */ | |
| 77 | + if (newsize < tb->size) { /* shrink table if needed */ | |
| 78 | + /* vanishing slice should be empty */ | |
| 88 | 79 | lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); |
| 89 | − luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); | |
| 80 | + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); | |
| 90 | 81 | } |
| 91 | 82 | tb->size = newsize; |
| 92 | 83 | } |
| 93 | 84 | |
| 94 | 85 | |
| 86 | + | |
| 95 | 87 | /* |
| 96 | 88 | ** creates a new string object |
| 97 | 89 | */ |
| 98 | 90 | static TString *createstrobj (lua_State *L, const char *str, size_t l, |
| 99 | − int tag, unsigned int h, GCObject **list) { | |
| 91 | + int tag, unsigned int h) { | |
| 100 | 92 | TString *ts; |
| 101 | 93 | size_t totalsize; /* total size of TString object */ |
| 102 | 94 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); |
| 103 | − ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; | |
| 95 | + ts = &luaC_newobj(L, tag, totalsize)->ts; | |
| 104 | 96 | ts->tsv.len = l; |
| 105 | 97 | ts->tsv.hash = h; |
| 106 | 98 | ts->tsv.extra = 0; |
| @@ -110,20 +102,13 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, · 3 unmodified lines | ||
| 110 | 102 | } |
| 111 | 103 | |
| 112 | 104 | |
| 113 | −/* | |
| 114 | −** creates a new short string, inserting it into string table | |
| 115 | −*/ | |
| 116 | −static TString *newshrstr (lua_State *L, const char *str, size_t l, | |
| 117 | − unsigned int h) { | |
| 118 | − GCObject **list; /* (pointer to) list where it will be inserted */ | |
| 105 | +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts) { | |
| 119 | 106 | stringtable *tb = &G(L)->strt; |
| 120 | − TString *s; | |
| 121 | − if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) | |
| 122 | − luaS_resize(L, tb->size*2); /* too crowded */ | |
| 123 | − list = &tb->hash[lmod(h, tb->size)]; | |
| 124 | − s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); | |
| 125 | − tb->nuse++; | |
| 126 | − return s; | |
| 107 | + TString **p = &tb->hash[lmod(ts->tsv.hash, tb->size)]; | |
| 108 | + while (*p != ts) /* find previous element */ | |
| 109 | + p = &(*p)->tsv.hnext; | |
| 110 | + *p = (*p)->tsv.hnext; /* remove element from its list */ | |
| 111 | + tb->nuse--; | |
| 127 | 112 | } |
| 128 | 113 | |
| 129 | 114 | |
| @@ -131,22 +116,28 @@ static TString *newshrstr (lua_State *L, const char *str, size_t l, · 1 unmodified line | ||
| 131 | 116 | ** checks whether short string exists and reuses it or creates a new one |
| 132 | 117 | */ |
| 133 | 118 | static TString *internshrstr (lua_State *L, const char *str, size_t l) { |
| 134 | − GCObject *o; | |
| 119 | + TString *ts; | |
| 135 | 120 | global_State *g = G(L); |
| 136 | 121 | unsigned int h = luaS_hash(str, l, g->seed); |
| 137 | − for (o = g->strt.hash[lmod(h, g->strt.size)]; | |
| 138 | − o != NULL; | |
| 139 | − o = gch(o)->next) { | |
| 140 | − TString *ts = rawgco2ts(o); | |
| 141 | − if (h == ts->tsv.hash && | |
| 142 | − l == ts->tsv.len && | |
| 122 | + TString **list = &g->strt.hash[lmod(h, g->strt.size)]; | |
| 123 | + for (ts = *list; ts != NULL; ts = ts->tsv.hnext) { | |
| 124 | + if (l == ts->tsv.len && | |
| 143 | 125 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { |
| 144 | − if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ | |
| 145 | − changewhite(o); /* resurrect it */ | |
| 126 | + /* found! */ | |
| 127 | + if (isdead(g, obj2gco(ts))) /* dead (but not collected yet)? */ | |
| 128 | + changewhite(obj2gco(ts)); /* resurrect it */ | |
| 146 | 129 | return ts; |
| 147 | 130 | } |
| 148 | 131 | } |
| 149 | − return newshrstr(L, str, l, h); /* not found; create a new string */ | |
| 132 | + if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { | |
| 133 | + luaS_resize(L, g->strt.size * 2); | |
| 134 | + list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ | |
| 135 | + } | |
| 136 | + ts = createstrobj(L, str, l, LUA_TSHRSTR, h); | |
| 137 | + ts->tsv.hnext = *list; | |
| 138 | + *list = ts; | |
| 139 | + g->strt.nuse++; | |
| 140 | + return ts; | |
| 150 | 141 | } |
| 151 | 142 | |
| 152 | 143 | |
| @@ -159,7 +150,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { · 6 unmodified lines | ||
| 159 | 150 | else { |
| 160 | 151 | if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) |
| 161 | 152 | luaM_toobig(L); |
| 162 | − return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); | |
| 153 | + return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); | |
| 163 | 154 | } |
| 164 | 155 | } |
| 165 | 156 | |
| @@ -172,14 +163,14 @@ TString *luaS_new (lua_State *L, const char *str) { · 6 unmodified lines | ||
| 172 | 163 | } |
| 173 | 164 | |
| 174 | 165 | |
| 175 | −Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { | |
| 166 | +Udata *luaS_newudata (lua_State *L, size_t s) { | |
| 176 | 167 | Udata *u; |
| 177 | 168 | if (s > MAX_SIZE - sizeof(Udata)) |
| 178 | 169 | luaM_toobig(L); |
| 179 | − u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; | |
| 170 | + u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s)->u; | |
| 180 | 171 | u->uv.len = s; |
| 181 | 172 | u->uv.metatable = NULL; |
| 182 | − u->uv.env = e; | |
| 173 | + setuservalue(L, u, luaO_nilobject); | |
| 183 | 174 | return u; |
| 184 | 175 | } |
| 185 | 176 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp $ | |
| 2 | +** $Id: lstring.h,v 1.54 2014/03/19 18:51:42 roberto Exp $ | |
| 3 | 3 | ** String table (keep all strings handled by Lua) |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -19,8 +19,6 @@ · 13 unmodified lines | ||
| 19 | 19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
| 20 | 20 | (sizeof(s)/sizeof(char))-1)) |
| 21 | 21 | |
| 22 | −#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) | |
| 23 | − | |
| 24 | 22 | |
| 25 | 23 | /* |
| 26 | 24 | ** test whether a string is a reserved word |
| @@ -36,9 +34,9 @@ · 9 unmodified lines | ||
| 36 | 34 | |
| 37 | 35 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); |
| 38 | 36 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); |
| 39 | −LUAI_FUNC int luaS_eqstr (TString *a, TString *b); | |
| 40 | 37 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); |
| 41 | −LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); | |
| 38 | +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); | |
| 39 | +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); | |
| 42 | 40 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); |
| 43 | 41 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); |
| 44 | 42 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lstrlib.c,v 1.182 2013/06/20 15:06:51 roberto Exp $ | |
| 2 | +** $Id: lstrlib.c,v 1.189 2014/03/21 14:26:44 roberto Exp $ | |
| 3 | 3 | ** Standard library for string operations and pattern-matching |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -116,7 +116,7 @@ static int str_rep (lua_State *L) { · 110 unmodified lines | ||
| 116 | 116 | lua_Integer n = luaL_checkinteger(L, 2); |
| 117 | 117 | const char *sep = luaL_optlstring(L, 3, "", &lsep); |
| 118 | 118 | if (n <= 0) lua_pushliteral(L, ""); |
| 119 | − else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ | |
| 119 | + else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ | |
| 120 | 120 | return luaL_error(L, "resulting string too large"); |
| 121 | 121 | else { |
| 122 | 122 | size_t totallen = n * l + (n - 1) * lsep; |
| @@ -124,8 +124,9 @@ static int str_rep (lua_State *L) { · 1 unmodified line | ||
| 124 | 124 | char *p = luaL_buffinitsize(L, &b, totallen); |
| 125 | 125 | while (n-- > 1) { /* first n-1 copies (followed by separator) */ |
| 126 | 126 | memcpy(p, s, l * sizeof(char)); p += l; |
| 127 | − if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ | |
| 128 | − memcpy(p, sep, lsep * sizeof(char)); p += lsep; | |
| 127 | + if (lsep > 0) { /* empty 'memcpy' is not that cheap */ | |
| 128 | + memcpy(p, sep, lsep * sizeof(char)); | |
| 129 | + p += lsep; | |
| 129 | 130 | } |
| 130 | 131 | } |
| 131 | 132 | memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ |
| @@ -178,10 +179,11 @@ static int writer (lua_State *L, const void *b, size_t size, void *B) { · 46 unmodified lines | ||
| 178 | 179 | |
| 179 | 180 | static int str_dump (lua_State *L) { |
| 180 | 181 | luaL_Buffer b; |
| 182 | + int strip = lua_toboolean(L, 2); | |
| 181 | 183 | luaL_checktype(L, 1, LUA_TFUNCTION); |
| 182 | 184 | lua_settop(L, 1); |
| 183 | 185 | luaL_buffinit(L,&b); |
| 184 | − if (lua_dump(L, writer, &b) != 0) | |
| 186 | + if (lua_dump(L, writer, &b, strip) != 0) | |
| 185 | 187 | return luaL_error(L, "unable to dump given function"); |
| 186 | 188 | luaL_pushresult(&b); |
| 187 | 189 | return 1; |
| @@ -938,6 +940,217 @@ static int str_format (lua_State *L) { · 750 unmodified lines | ||
| 938 | 940 | /* }====================================================== */ |
| 939 | 941 | |
| 940 | 942 | |
| 943 | +/* | |
| 944 | +** {====================================================== | |
| 945 | +** PACK/UNPACK | |
| 946 | +** ======================================================= | |
| 947 | +*/ | |
| 948 | + | |
| 949 | +/* maximum size for the binary representation of an integer */ | |
| 950 | +#define MAXINTSIZE 8 | |
| 951 | + | |
| 952 | + | |
| 953 | +/* number of bits in a character */ | |
| 954 | +#define NB CHAR_BIT | |
| 955 | + | |
| 956 | +/* mask for one character (NB ones) */ | |
| 957 | +#define MC (((lua_Integer)1 << NB) - 1) | |
| 958 | + | |
| 959 | +/* mask for one character without sign ((NB - 1) ones) */ | |
| 960 | +#define SM (((lua_Integer)1 << (NB - 1)) - 1) | |
| 961 | + | |
| 962 | + | |
| 963 | +#define SZINT ((int)sizeof(lua_Integer)) | |
| 964 | + | |
| 965 | + | |
| 966 | +static union { | |
| 967 | + int dummy; | |
| 968 | + char little; /* true iff machine is little endian */ | |
| 969 | +} const nativeendian = {1}; | |
| 970 | + | |
| 971 | + | |
| 972 | +static int getendian (lua_State *L, int arg) { | |
| 973 | + const char *endian = luaL_optstring(L, arg, | |
| 974 | + (nativeendian.little ? "l" : "b")); | |
| 975 | + if (*endian == 'n') /* native? */ | |
| 976 | + return nativeendian.little; | |
| 977 | + luaL_argcheck(L, *endian == 'l' || *endian == 'b', arg, | |
| 978 | + "endianess must be 'l'/'b'/'n'"); | |
| 979 | + return (*endian == 'l'); | |
| 980 | +} | |
| 981 | + | |
| 982 | + | |
| 983 | +static int getintsize (lua_State *L, int arg) { | |
| 984 | + int size = luaL_optint(L, arg, 0); | |
| 985 | + if (size == 0) size = SZINT; | |
| 986 | + luaL_argcheck(L, 1 <= size && size <= MAXINTSIZE, arg, | |
| 987 | + "integer size out of valid range"); | |
| 988 | + return size; | |
| 989 | +} | |
| 990 | + | |
| 991 | + | |
| 992 | +static int packint (char *buff, lua_Integer n, int littleendian, int size) { | |
| 993 | + int i; | |
| 994 | + if (littleendian) { | |
| 995 | + for (i = 0; i < size - 1; i++) { | |
| 996 | + buff[i] = (n & MC); | |
| 997 | + n >>= NB; | |
| 998 | + } | |
| 999 | + } | |
| 1000 | + else { | |
| 1001 | + for (i = size - 1; i > 0; i--) { | |
| 1002 | + buff[i] = (n & MC); | |
| 1003 | + n >>= NB; | |
| 1004 | + } | |
| 1005 | + } | |
| 1006 | + buff[i] = (n & MC); /* last byte */ | |
| 1007 | + /* test for overflow: OK if there are only zeros left in higher bytes, | |
| 1008 | + or if there are only ones left and packed number is negative (signal | |
| 1009 | + bit, the higher bit in last byte, is one) */ | |
| 1010 | + return ((n & ~MC) == 0 || (n | SM) == ~(lua_Integer)0); | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | + | |
| 1014 | +static int packint_l (lua_State *L) { | |
| 1015 | + char buff[MAXINTSIZE]; | |
| 1016 | + lua_Integer n = luaL_checkinteger(L, 1); | |
| 1017 | + int size = getintsize(L, 2); | |
| 1018 | + int endian = getendian(L, 3); | |
| 1019 | + if (packint(buff, n, endian, size)) | |
| 1020 | + lua_pushlstring(L, buff, size); | |
| 1021 | + else | |
| 1022 | + luaL_error(L, "integer does not fit into given size (%d)", size); | |
| 1023 | + return 1; | |
| 1024 | +} | |
| 1025 | + | |
| 1026 | + | |
| 1027 | +/* mask to check higher-order byte in a Lua integer */ | |
| 1028 | +#define HIGHERBYTE (MC << (NB * (SZINT - 1))) | |
| 1029 | + | |
| 1030 | +/* mask to check higher-order byte + signal bit of next (lower) byte */ | |
| 1031 | +#define HIGHERBYTE1 (HIGHERBYTE | (HIGHERBYTE >> 1)) | |
| 1032 | + | |
| 1033 | +static int unpackint (const char *buff, lua_Integer *res, | |
| 1034 | + int littleendian, int size) { | |
| 1035 | + lua_Integer n = 0; | |
| 1036 | + int i; | |
| 1037 | + for (i = 0; i < size; i++) { | |
| 1038 | + if (i >= SZINT) { /* will throw away a byte? */ | |
| 1039 | + /* check for overflow: it is OK to throw away leading zeros for a | |
| 1040 | + positive number, leading ones for a negative number, and a | |
| 1041 | + leading zero byte to allow unsigned integers with a 1 in | |
| 1042 | + its "signal bit" */ | |
| 1043 | + if (!((n & HIGHERBYTE1) == 0 || /* zeros for positive number */ | |
| 1044 | + (n & HIGHERBYTE1) == HIGHERBYTE1 || /* ones for negative number */ | |
| 1045 | + ((n & HIGHERBYTE) == 0 && i == size - 1))) /* leading zero */ | |
| 1046 | + return 0; /* overflow */ | |
| 1047 | + } | |
| 1048 | + n <<= NB; | |
| 1049 | + n |= (lua_Integer)(unsigned char)buff[littleendian ? size - 1 - i : i]; | |
| 1050 | + } | |
| 1051 | + if (size < SZINT) { /* need sign extension? */ | |
| 1052 | + lua_Integer mask = (~(lua_Integer)0) << (size*NB - 1); | |
| 1053 | + if (n & mask) /* negative value? */ | |
| 1054 | + n |= mask; /* signal extension */ | |
| 1055 | + } | |
| 1056 | + *res = n; | |
| 1057 | + return 1; | |
| 1058 | +} | |
| 1059 | + | |
| 1060 | + | |
| 1061 | +static int unpackint_l (lua_State *L) { | |
| 1062 | + lua_Integer res; | |
| 1063 | + size_t len; | |
| 1064 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 1065 | + lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); | |
| 1066 | + int size = getintsize(L, 3); | |
| 1067 | + int endian = getendian(L, 4); | |
| 1068 | + luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, | |
| 1069 | + "string too short"); | |
| 1070 | + if(unpackint(s + pos - 1, &res, endian, size)) | |
| 1071 | + lua_pushinteger(L, res); | |
| 1072 | + else | |
| 1073 | + luaL_error(L, "result does not fit into a Lua integer"); | |
| 1074 | + return 1; | |
| 1075 | +} | |
| 1076 | + | |
| 1077 | + | |
| 1078 | +static void correctendianess (lua_State *L, char *b, int size, int endianarg) { | |
| 1079 | + int endian = getendian(L, endianarg); | |
| 1080 | + if (endian != nativeendian.little) { /* not native endianess? */ | |
| 1081 | + int i = 0; | |
| 1082 | + while (i < --size) { | |
| 1083 | + char temp = b[i]; | |
| 1084 | + b[i++] = b[size]; | |
| 1085 | + b[size] = temp; | |
| 1086 | + } | |
| 1087 | + } | |
| 1088 | +} | |
| 1089 | + | |
| 1090 | + | |
| 1091 | +static int getfloatsize (lua_State *L, int arg) { | |
| 1092 | + const char *size = luaL_optstring(L, arg, "n"); | |
| 1093 | + if (*size == 'n') return sizeof(lua_Number); | |
| 1094 | + luaL_argcheck(L, *size == 'd' || *size == 'f', arg, | |
| 1095 | + "size must be 'f'/'d'/'n'"); | |
| 1096 | + return (*size == 'd' ? sizeof(double) : sizeof(float)); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | + | |
| 1100 | +static int packfloat_l (lua_State *L) { | |
| 1101 | + float f; double d; | |
| 1102 | + char *pn; /* pointer to number */ | |
| 1103 | + lua_Number n = luaL_checknumber(L, 1); | |
| 1104 | + int size = getfloatsize(L, 2); | |
| 1105 | + if (size == sizeof(lua_Number)) | |
| 1106 | + pn = (char*)&n; | |
| 1107 | + else if (size == sizeof(float)) { | |
| 1108 | + f = (float)n; | |
| 1109 | + pn = (char*)&f; | |
| 1110 | + } | |
| 1111 | + else { /* native lua_Number may be neither float nor double */ | |
| 1112 | + lua_assert(size == sizeof(double)); | |
| 1113 | + d = (double)n; | |
| 1114 | + pn = (char*)&d; | |
| 1115 | + } | |
| 1116 | + correctendianess(L, pn, size, 3); | |
| 1117 | + lua_pushlstring(L, pn, size); | |
| 1118 | + return 1; | |
| 1119 | +} | |
| 1120 | + | |
| 1121 | + | |
| 1122 | +static int unpackfloat_l (lua_State *L) { | |
| 1123 | + lua_Number res; | |
| 1124 | + size_t len; | |
| 1125 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 1126 | + lua_Integer pos = posrelat(luaL_optinteger(L, 2, 1), len); | |
| 1127 | + int size = getfloatsize(L, 3); | |
| 1128 | + luaL_argcheck(L, 1 <= pos && (size_t)pos + size - 1 <= len, 1, | |
| 1129 | + "string too short"); | |
| 1130 | + if (size == sizeof(lua_Number)) { | |
| 1131 | + memcpy(&res, s + pos - 1, size); | |
| 1132 | + correctendianess(L, (char*)&res, size, 4); | |
| 1133 | + } | |
| 1134 | + else if (size == sizeof(float)) { | |
| 1135 | + float f; | |
| 1136 | + memcpy(&f, s + pos - 1, size); | |
| 1137 | + correctendianess(L, (char*)&f, size, 4); | |
| 1138 | + res = (lua_Number)f; | |
| 1139 | + } | |
| 1140 | + else { /* native lua_Number may be neither float nor double */ | |
| 1141 | + double d; | |
| 1142 | + lua_assert(size == sizeof(double)); | |
| 1143 | + memcpy(&d, s + pos - 1, size); | |
| 1144 | + correctendianess(L, (char*)&d, size, 4); | |
| 1145 | + res = (lua_Number)d; | |
| 1146 | + } | |
| 1147 | + lua_pushnumber(L, res); | |
| 1148 | + return 1; | |
| 1149 | +} | |
| 1150 | + | |
| 1151 | +/* }====================================================== */ | |
| 1152 | + | |
| 1153 | + | |
| 941 | 1154 | static const luaL_Reg strlib[] = { |
| 942 | 1155 | {"byte", str_byte}, |
| 943 | 1156 | {"char", str_char}, |
| @@ -953,6 +1166,10 @@ static const luaL_Reg strlib[] = { · 9 unmodified lines | ||
| 953 | 1166 | {"reverse", str_reverse}, |
| 954 | 1167 | {"sub", str_sub}, |
| 955 | 1168 | {"upper", str_upper}, |
| 1169 | + {"packfloat", packfloat_l}, | |
| 1170 | + {"packint", packint_l}, | |
| 1171 | + {"unpackfloat", unpackfloat_l}, | |
| 1172 | + {"unpackint", unpackint_l}, | |
| 956 | 1173 | {NULL, NULL} |
| 957 | 1174 | }; |
| 958 | 1175 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ltable.c,v 2.78 2013/06/20 15:02:49 roberto Exp $ | |
| 2 | +** $Id: ltable.c,v 2.84 2014/01/27 13:34:32 roberto Exp $ | |
| 3 | 3 | ** Lua tables (hash) |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -79,7 +79,7 @@ · 73 unmodified lines | ||
| 79 | 79 | |
| 80 | 80 | static const Node dummynode_ = { |
| 81 | 81 | {NILCONSTANT}, /* value */ |
| 82 | − {{NILCONSTANT, NULL}} /* key */ | |
| 82 | + {{NILCONSTANT, 0}} /* key */ | |
| 83 | 83 | }; |
| 84 | 84 | |
| 85 | 85 | |
| @@ -158,6 +158,7 @@ static int findindex (lua_State *L, Table *t, StkId key) { · 72 unmodified lines | ||
| 158 | 158 | if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ |
| 159 | 159 | return i-1; /* yes; that's the index (corrected to C) */ |
| 160 | 160 | else { |
| 161 | + int nx; | |
| 161 | 162 | Node *n = mainposition(t, key); |
| 162 | 163 | for (;;) { /* check whether `key' is somewhere in the chain */ |
| 163 | 164 | /* key may be dead already, but it is ok to use it in `next' */ |
| @@ -168,9 +169,10 @@ static int findindex (lua_State *L, Table *t, StkId key) { · 4 unmodified lines | ||
| 168 | 169 | /* hash elements are numbered after array ones */ |
| 169 | 170 | return i + t->sizearray; |
| 170 | 171 | } |
| 171 | − else n = gnext(n); | |
| 172 | − if (n == NULL) | |
| 172 | + nx = gnext(n); | |
| 173 | + if (nx == 0) | |
| 173 | 174 | luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ |
| 175 | + else n += nx; | |
| 174 | 176 | } |
| 175 | 177 | } |
| 176 | 178 | } |
| @@ -301,7 +303,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { · 124 unmodified lines | ||
| 301 | 303 | t->node = luaM_newvector(L, size, Node); |
| 302 | 304 | for (i=0; i<size; i++) { |
| 303 | 305 | Node *n = gnode(t, i); |
| 304 | − gnext(n) = NULL; | |
| 306 | + gnext(n) = 0; | |
| 305 | 307 | setnilvalue(gkey(n)); |
| 306 | 308 | setnilvalue(gval(n)); |
| 307 | 309 | } |
| @@ -376,7 +378,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { · 68 unmodified lines | ||
| 376 | 378 | |
| 377 | 379 | |
| 378 | 380 | Table *luaH_new (lua_State *L) { |
| 379 | − Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; | |
| 381 | + Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table))->h; | |
| 380 | 382 | t->metatable = NULL; |
| 381 | 383 | t->flags = cast_byte(~0); |
| 382 | 384 | t->array = NULL; |
| @@ -419,7 +421,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { · 36 unmodified lines | ||
| 419 | 421 | else if (ttisfloat(key)) { |
| 420 | 422 | lua_Number n = fltvalue(key); |
| 421 | 423 | lua_Integer k; |
| 422 | − if (luai_numisnan(L, n)) | |
| 424 | + if (luai_numisnan(n)) | |
| 423 | 425 | luaG_runerror(L, "table index is NaN"); |
| 424 | 426 | if (numisinteger(n, &k)) { /* index is int? */ |
| 425 | 427 | setivalue(&aux, k); |
| @@ -429,31 +431,37 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { · 3 unmodified lines | ||
| 429 | 431 | mp = mainposition(t, key); |
| 430 | 432 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ |
| 431 | 433 | Node *othern; |
| 432 | − Node *n = getfreepos(t); /* get a free place */ | |
| 433 | − if (n == NULL) { /* cannot find a free place? */ | |
| 434 | + Node *f = getfreepos(t); /* get a free place */ | |
| 435 | + if (f == NULL) { /* cannot find a free place? */ | |
| 434 | 436 | rehash(L, t, key); /* grow table */ |
| 435 | 437 | /* whatever called 'newkey' take care of TM cache and GC barrier */ |
| 436 | 438 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 437 | 439 | } |
| 438 | − lua_assert(!isdummy(n)); | |
| 440 | + lua_assert(!isdummy(f)); | |
| 439 | 441 | othern = mainposition(t, gkey(mp)); |
| 440 | 442 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 441 | 443 | /* yes; move colliding node into free position */ |
| 442 | − while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ | |
| 443 | − gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ | |
| 444 | − *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ | |
| 445 | − gnext(mp) = NULL; /* now `mp' is free */ | |
| 444 | + while (othern + gnext(othern) != mp) /* find previous */ | |
| 445 | + othern += gnext(othern); | |
| 446 | + gnext(othern) = f - othern; /* re-chain with 'f' in place of 'mp' */ | |
| 447 | + *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ | |
| 448 | + if (gnext(mp) != 0) { | |
| 449 | + gnext(f) += mp - f; /* correct 'next' */ | |
| 450 | + gnext(mp) = 0; /* now 'mp' is free */ | |
| 451 | + } | |
| 446 | 452 | setnilvalue(gval(mp)); |
| 447 | 453 | } |
| 448 | 454 | else { /* colliding node is in its own main position */ |
| 449 | 455 | /* new node will go into free position */ |
| 450 | − gnext(n) = gnext(mp); /* chain new position */ | |
| 451 | − gnext(mp) = n; | |
| 452 | − mp = n; | |
| 456 | + if (gnext(mp) != 0) | |
| 457 | + gnext(f) = (mp + gnext(mp)) - f; /* chain new position */ | |
| 458 | + else lua_assert(gnext(f) == 0); | |
| 459 | + gnext(mp) = f - mp; | |
| 460 | + mp = f; | |
| 453 | 461 | } |
| 454 | 462 | } |
| 455 | 463 | setobj2t(L, gkey(mp), key); |
| 456 | − luaC_barrierback(L, obj2gco(t), key); | |
| 464 | + luaC_barrierback(L, t, key); | |
| 457 | 465 | lua_assert(ttisnil(gval(mp))); |
| 458 | 466 | return gval(mp); |
| 459 | 467 | } |
| @@ -468,11 +476,15 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { · 8 unmodified lines | ||
| 468 | 476 | return &t->array[key - 1]; |
| 469 | 477 | else { |
| 470 | 478 | Node *n = hashint(t, key); |
| 471 | − do { /* check whether `key' is somewhere in the chain */ | |
| 479 | + for (;;) { /* check whether `key' is somewhere in the chain */ | |
| 472 | 480 | if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) |
| 473 | 481 | return gval(n); /* that's it */ |
| 474 | − else n = gnext(n); | |
| 475 | − } while (n); | |
| 482 | + else { | |
| 483 | + int nx = gnext(n); | |
| 484 | + if (nx == 0) break; | |
| 485 | + n += nx; | |
| 486 | + } | |
| 487 | + }; | |
| 476 | 488 | return luaO_nilobject; |
| 477 | 489 | } |
| 478 | 490 | } |
| @@ -484,11 +496,15 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { · 5 unmodified lines | ||
| 484 | 496 | const TValue *luaH_getstr (Table *t, TString *key) { |
| 485 | 497 | Node *n = hashstr(t, key); |
| 486 | 498 | lua_assert(key->tsv.tt == LUA_TSHRSTR); |
| 487 | − do { /* check whether `key' is somewhere in the chain */ | |
| 499 | + for (;;) { /* check whether `key' is somewhere in the chain */ | |
| 488 | 500 | if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) |
| 489 | 501 | return gval(n); /* that's it */ |
| 490 | − else n = gnext(n); | |
| 491 | − } while (n); | |
| 502 | + else { | |
| 503 | + int nx = gnext(n); | |
| 504 | + if (nx == 0) break; | |
| 505 | + n += nx; | |
| 506 | + } | |
| 507 | + }; | |
| 492 | 508 | return luaO_nilobject; |
| 493 | 509 | } |
| 494 | 510 | |
| @@ -509,11 +525,15 @@ const TValue *luaH_get (Table *t, const TValue *key) { · 14 unmodified lines | ||
| 509 | 525 | } |
| 510 | 526 | default: { |
| 511 | 527 | Node *n = mainposition(t, key); |
| 512 | − do { /* check whether `key' is somewhere in the chain */ | |
| 528 | + for (;;) { /* check whether `key' is somewhere in the chain */ | |
| 513 | 529 | if (luaV_rawequalobj(gkey(n), key)) |
| 514 | 530 | return gval(n); /* that's it */ |
| 515 | − else n = gnext(n); | |
| 516 | − } while (n); | |
| 531 | + else { | |
| 532 | + int nx = gnext(n); | |
| 533 | + if (nx == 0) break; | |
| 534 | + n += nx; | |
| 535 | + } | |
| 536 | + }; | |
| 517 | 537 | return luaO_nilobject; |
| 518 | 538 | } |
| 519 | 539 | } |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ltable.h,v 2.17 2013/04/26 15:39:25 roberto Exp $ | |
| 2 | +** $Id: ltable.h,v 2.18 2013/08/30 16:01:37 roberto Exp $ | |
| 3 | 3 | ** Lua tables (hash) |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -18,6 +18,11 @@ · 12 unmodified lines | ||
| 18 | 18 | #define invalidateTMcache(t) ((t)->flags = 0) |
| 19 | 19 | |
| 20 | 20 | |
| 21 | +/* returns the key, given the value of a table entry */ | |
| 22 | +#define keyfromval(v) \ | |
| 23 | + (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) | |
| 24 | + | |
| 25 | + | |
| 21 | 26 | LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); |
| 22 | 27 | LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, |
| 23 | 28 | TValue *value); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ltablib.c,v 1.65 2013/03/07 18:17:24 roberto Exp $ | |
| 2 | +** $Id: ltablib.c,v 1.66 2014/03/21 13:52:33 roberto Exp $ | |
| 3 | 3 | ** Library for Table Manipulation |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -140,7 +140,7 @@ static int unpack (lua_State *L) { · 134 unmodified lines | ||
| 140 | 140 | e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); |
| 141 | 141 | if (i > e) return 0; /* empty range */ |
| 142 | 142 | n = e - i + 1; /* number of elements */ |
| 143 | − if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ | |
| 143 | + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arithmetic overflow */ | |
| 144 | 144 | return luaL_error(L, "too many results to unpack"); |
| 145 | 145 | lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ |
| 146 | 146 | while (i++ < e) /* push arg[i + 1...e] */ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp $ | |
| 2 | +** $Id: ltm.c,v 2.25 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Tag methods |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -28,7 +28,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { · 22 unmodified lines | ||
| 28 | 28 | "no value", |
| 29 | 29 | "nil", "boolean", udatatypename, "number", |
| 30 | 30 | "string", "table", "function", udatatypename, "thread", |
| 31 | − "proto", "upval" /* these last two cases are used for tests only */ | |
| 31 | + "proto" /* this last case is used for tests only */ | |
| 32 | 32 | }; |
| 33 | 33 | |
| 34 | 34 | |
| @@ -36,14 +36,16 @@ void luaT_init (lua_State *L) { · 1 unmodified line | ||
| 36 | 36 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
| 37 | 37 | "__index", "__newindex", |
| 38 | 38 | "__gc", "__mode", "__len", "__eq", |
| 39 | − "__add", "__sub", "__mul", "__div", "__idiv", "__mod", | |
| 40 | − "__pow", "__unm", "__lt", "__le", | |
| 39 | + "__add", "__sub", "__mul", "__mod", "__pow", | |
| 40 | + "__div", "__idiv", | |
| 41 | + "__band", "__bor", "__bxor", "__shl", "__shr", | |
| 42 | + "__unm", "__bnot", "__lt", "__le", | |
| 41 | 43 | "__concat", "__call" |
| 42 | 44 | }; |
| 43 | 45 | int i; |
| 44 | 46 | for (i=0; i<TM_N; i++) { |
| 45 | 47 | G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); |
| 46 | − luaS_fix(G(L)->tmname[i]); /* never collect these names */ | |
| 48 | + luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ | |
| 47 | 49 | } |
| 48 | 50 | } |
| 49 | 51 | |
| @@ -110,12 +112,17 @@ int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, · 60 unmodified lines | ||
| 110 | 112 | void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, |
| 111 | 113 | StkId res, TMS event) { |
| 112 | 114 | if (!luaT_callbinTM(L, p1, p2, res, event)) { |
| 113 | − if (event == TM_CONCAT) | |
| 114 | − luaG_concaterror(L, p1, p2); | |
| 115 | − else if (event == TM_IDIV && ttisnumber(p1) && ttisnumber(p2)) | |
| 116 | − luaG_tointerror(L, p1, p2); | |
| 117 | − else | |
| 118 | − luaG_aritherror(L, p1, p2); | |
| 115 | + switch (event) { | |
| 116 | + case TM_CONCAT: | |
| 117 | + luaG_concaterror(L, p1, p2); | |
| 118 | + case TM_IDIV: case TM_BAND: case TM_BOR: case TM_BXOR: | |
| 119 | + case TM_SHL: case TM_SHR: case TM_BNOT: | |
| 120 | + if (ttisnumber(p1) && ttisnumber(p2)) | |
| 121 | + luaG_tointerror(L, p1, p2); | |
| 122 | + /* else go through */ | |
| 123 | + default: | |
| 124 | + luaG_aritherror(L, p1, p2); | |
| 125 | + } | |
| 119 | 126 | } |
| 120 | 127 | } |
| 121 | 128 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: ltm.h,v 2.16 2013/04/29 16:56:50 roberto Exp $ | |
| 2 | +** $Id: ltm.h,v 2.19 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Tag methods |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -13,7 +13,7 @@ · 7 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | /* |
| 15 | 15 | * WARNING: if you change the order of this enumeration, |
| 16 | −* grep "ORDER TM" | |
| 16 | +* grep "ORDER TM" and "ORDER OP" | |
| 17 | 17 | */ |
| 18 | 18 | typedef enum { |
| 19 | 19 | TM_INDEX, |
| @@ -25,11 +25,17 @@ typedef enum { · 5 unmodified lines | ||
| 25 | 25 | TM_ADD, |
| 26 | 26 | TM_SUB, |
| 27 | 27 | TM_MUL, |
| 28 | − TM_DIV, | |
| 29 | − TM_IDIV, | |
| 30 | 28 | TM_MOD, |
| 31 | 29 | TM_POW, |
| 30 | + TM_DIV, | |
| 31 | + TM_IDIV, | |
| 32 | + TM_BAND, | |
| 33 | + TM_BOR, | |
| 34 | + TM_BXOR, | |
| 35 | + TM_SHL, | |
| 36 | + TM_SHR, | |
| 32 | 37 | TM_UNM, |
| 38 | + TM_BNOT, | |
| 33 | 39 | TM_LT, |
| 34 | 40 | TM_LE, |
| 35 | 41 | TM_CONCAT, |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lua.c,v 1.206 2012/09/29 20:07:06 roberto Exp $ | |
| 2 | +** $Id: lua.c,v 1.210 2014/02/26 15:27:56 roberto Exp $ | |
| 3 | 3 | ** Lua stand-alone interpreter |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -31,28 +31,38 @@ · 25 unmodified lines | ||
| 31 | 31 | #define LUA_MAXINPUT 512 |
| 32 | 32 | #endif |
| 33 | 33 | |
| 34 | −#if !defined(LUA_INIT) | |
| 35 | −#define LUA_INIT "LUA_INIT" | |
| 34 | +#if !defined(LUA_INIT_VAR) | |
| 35 | +#define LUA_INIT_VAR "LUA_INIT" | |
| 36 | 36 | #endif |
| 37 | 37 | |
| 38 | −#define LUA_INITVERSION \ | |
| 39 | − LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR | |
| 38 | +#define LUA_INITVARVERSION \ | |
| 39 | + LUA_INIT_VAR "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR | |
| 40 | 40 | |
| 41 | 41 | |
| 42 | 42 | /* |
| 43 | 43 | ** lua_stdin_is_tty detects whether the standard input is a 'tty' (that |
| 44 | 44 | ** is, whether we're running lua interactively). |
| 45 | 45 | */ |
| 46 | −#if defined(LUA_USE_ISATTY) | |
| 46 | +#if !defined(lua_stdin_is_tty) /* { */ | |
| 47 | + | |
| 48 | +#if defined(LUA_USE_POSIX) /* { */ | |
| 49 | + | |
| 47 | 50 | #include <unistd.h> |
| 48 | 51 | #define lua_stdin_is_tty() isatty(0) |
| 49 | −#elif defined(LUA_WIN) | |
| 52 | + | |
| 53 | +#elif defined(LUA_WIN) /* }{ */ | |
| 54 | + | |
| 50 | 55 | #include <io.h> |
| 51 | −#include <stdio.h> | |
| 52 | 56 | #define lua_stdin_is_tty() _isatty(_fileno(stdin)) |
| 53 | −#else | |
| 57 | + | |
| 58 | +#else /* }{ */ | |
| 59 | + | |
| 60 | +/* ANSI definition */ | |
| 54 | 61 | #define lua_stdin_is_tty() 1 /* assume stdin is a tty */ |
| 55 | −#endif | |
| 62 | + | |
| 63 | +#endif /* } */ | |
| 64 | + | |
| 65 | +#endif /* } */ | |
| 56 | 66 | |
| 57 | 67 | |
| 58 | 68 | /* |
| @@ -61,9 +71,10 @@ · 2 unmodified lines | ||
| 61 | 71 | ** lua_saveline defines how to "save" a read line in a "history". |
| 62 | 72 | ** lua_freeline defines how to free a line read by lua_readline. |
| 63 | 73 | */ |
| 64 | −#if defined(LUA_USE_READLINE) | |
| 74 | +#if !defined(lua_readline) /* { */ | |
| 75 | + | |
| 76 | +#if defined(LUA_USE_READLINE) /* { */ | |
| 65 | 77 | |
| 66 | −#include <stdio.h> | |
| 67 | 78 | #include <readline/readline.h> |
| 68 | 79 | #include <readline/history.h> |
| 69 | 80 | #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) |
| @@ -72,7 +83,7 @@ · 2 unmodified lines | ||
| 72 | 83 | add_history(lua_tostring(L, idx)); /* add it to history */ |
| 73 | 84 | #define lua_freeline(L,b) ((void)L, free(b)) |
| 74 | 85 | |
| 75 | −#elif !defined(lua_readline) | |
| 86 | +#else /* }{ */ | |
| 76 | 87 | |
| 77 | 88 | #define lua_readline(L,b,p) \ |
| 78 | 89 | ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ |
| @@ -80,7 +91,9 @@ · 1 unmodified line | ||
| 80 | 91 | #define lua_saveline(L,idx) { (void)L; (void)idx; } |
| 81 | 92 | #define lua_freeline(L,b) { (void)L; (void)b; } |
| 82 | 93 | |
| 83 | −#endif | |
| 94 | +#endif /* } */ | |
| 95 | + | |
| 96 | +#endif /* } */ | |
| 84 | 97 | |
| 85 | 98 | |
| 86 | 99 | |
| @@ -257,20 +270,21 @@ static int incomplete (lua_State *L, int status) { · 170 unmodified lines | ||
| 257 | 270 | } |
| 258 | 271 | |
| 259 | 272 | |
| 273 | +/* prompt the user, read a line, and push it into the Lua stack */ | |
| 260 | 274 | static int pushline (lua_State *L, int firstline) { |
| 261 | 275 | char buffer[LUA_MAXINPUT]; |
| 262 | 276 | char *b = buffer; |
| 263 | 277 | size_t l; |
| 264 | 278 | const char *prmt = get_prompt(L, firstline); |
| 265 | 279 | int readstatus = lua_readline(L, b, prmt); |
| 266 | − lua_pop(L, 1); /* remove result from 'get_prompt' */ | |
| 267 | 280 | if (readstatus == 0) |
| 268 | − return 0; /* no input */ | |
| 281 | + return 0; /* no input (prompt will be popped by caller) */ | |
| 282 | + lua_pop(L, 1); /* remove prompt */ | |
| 269 | 283 | l = strlen(b); |
| 270 | 284 | if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ |
| 271 | 285 | b[l-1] = '\0'; /* remove it */ |
| 272 | − if (firstline && b[0] == '=') /* first line starts with `=' ? */ | |
| 273 | − lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ | |
| 286 | + if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ | |
| 287 | + lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ | |
| 274 | 288 | else |
| 275 | 289 | lua_pushstring(L, b); |
| 276 | 290 | lua_freeline(L, b); |
| @@ -278,24 +292,48 @@ static int pushline (lua_State *L, int firstline) { · 1 unmodified line | ||
| 278 | 292 | } |
| 279 | 293 | |
| 280 | 294 | |
| 281 | −static int loadline (lua_State *L) { | |
| 295 | +/* try to compile line on the stack as 'return <line>'; on return, stack | |
| 296 | + has either compiled chunk or original line (if compilation failed) */ | |
| 297 | +static int addreturn (lua_State *L) { | |
| 282 | 298 | int status; |
| 283 | − lua_settop(L, 0); | |
| 284 | − if (!pushline(L, 1)) | |
| 285 | − return -1; /* no input */ | |
| 299 | + size_t len; const char *line; | |
| 300 | + lua_pushliteral(L, "return "); | |
| 301 | + lua_pushvalue(L, -2); /* duplicate line */ | |
| 302 | + lua_concat(L, 2); /* new line is "return ..." */ | |
| 303 | + line = lua_tolstring(L, -1, &len); | |
| 304 | + if ((status = luaL_loadbuffer(L, line, len, "=stdin")) == LUA_OK) | |
| 305 | + lua_remove(L, -3); /* remove original line */ | |
| 306 | + else | |
| 307 | + lua_pop(L, 2); /* remove result from 'luaL_loadbuffer' and new line */ | |
| 308 | + return status; | |
| 309 | +} | |
| 310 | + | |
| 311 | + | |
| 312 | +/* read multiple lines until a complete line */ | |
| 313 | +static int multiline (lua_State *L) { | |
| 286 | 314 | for (;;) { /* repeat until gets a complete line */ |
| 287 | − size_t l; | |
| 288 | − const char *line = lua_tolstring(L, 1, &l); | |
| 289 | − status = luaL_loadbuffer(L, line, l, "=stdin"); | |
| 290 | − if (!incomplete(L, status)) break; /* cannot try to add lines? */ | |
| 291 | − if (!pushline(L, 0)) /* no more input? */ | |
| 292 | − return -1; | |
| 293 | − lua_pushliteral(L, "\n"); /* add a new line... */ | |
| 315 | + size_t len; | |
| 316 | + const char *line = lua_tolstring(L, 1, &len); /* get what it has */ | |
| 317 | + int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ | |
| 318 | + if (!incomplete(L, status) || !pushline(L, 0)) | |
| 319 | + return status; /* cannot/should not try to add continuation line */ | |
| 320 | + lua_pushliteral(L, "\n"); /* add newline... */ | |
| 294 | 321 | lua_insert(L, -2); /* ...between the two lines */ |
| 295 | 322 | lua_concat(L, 3); /* join them */ |
| 296 | 323 | } |
| 324 | +} | |
| 325 | + | |
| 326 | + | |
| 327 | +static int loadline (lua_State *L) { | |
| 328 | + int status; | |
| 329 | + lua_settop(L, 0); | |
| 330 | + if (!pushline(L, 1)) | |
| 331 | + return -1; /* no input */ | |
| 332 | + if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ | |
| 333 | + status = multiline(L); /* try as command, maybe with continuation lines */ | |
| 297 | 334 | lua_saveline(L, 1); |
| 298 | 335 | lua_remove(L, 1); /* remove line */ |
| 336 | + lua_assert(lua_gettop(L) == 1); | |
| 299 | 337 | return status; |
| 300 | 338 | } |
| 301 | 339 | |
| @@ -421,10 +459,10 @@ static int runargs (lua_State *L, char **argv, int n) { · 119 unmodified lines | ||
| 421 | 459 | |
| 422 | 460 | |
| 423 | 461 | static int handle_luainit (lua_State *L) { |
| 424 | − const char *name = "=" LUA_INITVERSION; | |
| 462 | + const char *name = "=" LUA_INITVARVERSION; | |
| 425 | 463 | const char *init = getenv(name + 1); |
| 426 | 464 | if (init == NULL) { |
| 427 | − name = "=" LUA_INIT; | |
| 465 | + name = "=" LUA_INIT_VAR; | |
| 428 | 466 | init = getenv(name + 1); /* try alternative name */ |
| 429 | 467 | } |
| 430 | 468 | if (init == NULL) return LUA_OK; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lua.h,v 1.292 2013/07/05 14:29:51 roberto Exp $ | |
| 2 | +** $Id: lua.h,v 1.302 2014/03/20 19:42:35 roberto Exp $ | |
| 3 | 3 | ** Lua - A Scripting Language |
| 4 | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
| 5 | 5 | ** See Copyright Notice at the end of this file |
| @@ -19,11 +19,11 @@ · 13 unmodified lines | ||
| 19 | 19 | #define LUA_VERSION_MAJOR "5" |
| 20 | 20 | #define LUA_VERSION_MINOR "3" |
| 21 | 21 | #define LUA_VERSION_NUM 503 |
| 22 | −#define LUA_VERSION_RELEASE "0 (work1)" | |
| 22 | +#define LUA_VERSION_RELEASE "0 (work2)" | |
| 23 | 23 | |
| 24 | 24 | #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR |
| 25 | 25 | #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE |
| 26 | −#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" | |
| 26 | +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2014 Lua.org, PUC-Rio" | |
| 27 | 27 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" |
| 28 | 28 | |
| 29 | 29 | |
| @@ -182,14 +182,20 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); · 152 unmodified lines | ||
| 182 | 182 | ** Comparison and arithmetic functions |
| 183 | 183 | */ |
| 184 | 184 | |
| 185 | −#define LUA_OPADD 0 /* ORDER TM */ | |
| 185 | +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ | |
| 186 | 186 | #define LUA_OPSUB 1 |
| 187 | 187 | #define LUA_OPMUL 2 |
| 188 | −#define LUA_OPDIV 3 | |
| 189 | −#define LUA_OPIDIV 4 | |
| 190 | −#define LUA_OPMOD 5 | |
| 191 | −#define LUA_OPPOW 6 | |
| 192 | −#define LUA_OPUNM 7 | |
| 188 | +#define LUA_OPMOD 3 | |
| 189 | +#define LUA_OPPOW 4 | |
| 190 | +#define LUA_OPDIV 5 | |
| 191 | +#define LUA_OPIDIV 6 | |
| 192 | +#define LUA_OPBAND 7 | |
| 193 | +#define LUA_OPBOR 8 | |
| 194 | +#define LUA_OPBXOR 9 | |
| 195 | +#define LUA_OPSHL 10 | |
| 196 | +#define LUA_OPSHR 11 | |
| 197 | +#define LUA_OPUNM 12 | |
| 198 | +#define LUA_OPBNOT 13 | |
| 193 | 199 | |
| 194 | 200 | LUA_API void (lua_arith) (lua_State *L, int op); |
| 195 | 201 | |
| @@ -222,12 +228,13 @@ LUA_API int (lua_pushthread) (lua_State *L); · 26 unmodified lines | ||
| 222 | 228 | /* |
| 223 | 229 | ** get functions (Lua -> stack) |
| 224 | 230 | */ |
| 225 | −LUA_API void (lua_getglobal) (lua_State *L, const char *var); | |
| 226 | −LUA_API void (lua_gettable) (lua_State *L, int idx); | |
| 227 | −LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); | |
| 228 | −LUA_API void (lua_rawget) (lua_State *L, int idx); | |
| 229 | −LUA_API void (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); | |
| 230 | −LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); | |
| 231 | +LUA_API int (lua_getglobal) (lua_State *L, const char *var); | |
| 232 | +LUA_API int (lua_gettable) (lua_State *L, int idx); | |
| 233 | +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); | |
| 234 | +LUA_API int (lua_rawget) (lua_State *L, int idx); | |
| 235 | +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); | |
| 236 | +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); | |
| 237 | + | |
| 231 | 238 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); |
| 232 | 239 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); |
| 233 | 240 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); |
| @@ -264,7 +271,7 @@ LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, · 30 unmodified lines | ||
| 264 | 271 | const char *chunkname, |
| 265 | 272 | const char *mode); |
| 266 | 273 | |
| 267 | −LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); | |
| 274 | +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); | |
| 268 | 275 | |
| 269 | 276 | |
| 270 | 277 | /* |
| @@ -288,10 +295,7 @@ LUA_API int (lua_status) (lua_State *L); · 17 unmodified lines | ||
| 288 | 295 | #define LUA_GCSTEP 5 |
| 289 | 296 | #define LUA_GCSETPAUSE 6 |
| 290 | 297 | #define LUA_GCSETSTEPMUL 7 |
| 291 | −#define LUA_GCSETMAJORINC 8 | |
| 292 | 298 | #define LUA_GCISRUNNING 9 |
| 293 | −#define LUA_GCGEN 10 | |
| 294 | −#define LUA_GCINC 11 | |
| 295 | 299 | |
| 296 | 300 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
| 297 | 301 | |
| @@ -394,7 +398,7 @@ LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); · 96 unmodified lines | ||
| 394 | 398 | LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, |
| 395 | 399 | int fidx2, int n2); |
| 396 | 400 | |
| 397 | −LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); | |
| 401 | +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); | |
| 398 | 402 | LUA_API lua_Hook (lua_gethook) (lua_State *L); |
| 399 | 403 | LUA_API int (lua_gethookmask) (lua_State *L); |
| 400 | 404 | LUA_API int (lua_gethookcount) (lua_State *L); |
| @@ -422,7 +426,7 @@ struct lua_Debug { · 21 unmodified lines | ||
| 422 | 426 | |
| 423 | 427 | |
| 424 | 428 | /****************************************************************************** |
| 425 | −* Copyright (C) 1994-2013 Lua.org, PUC-Rio. | |
| 429 | +* Copyright (C) 1994-2014 Lua.org, PUC-Rio. | |
| 426 | 430 | * |
| 427 | 431 | * Permission is hereby granted, free of charge, to any person obtaining |
| 428 | 432 | * a copy of this software and associated documentation files (the |
| @@ -202,7 +202,7 @@ int main(int argc, char* argv[]) · 201 unmodified lines | ||
| 202 | 202 | return EXIT_SUCCESS; |
| 203 | 203 | } |
| 204 | 204 | |
| 205 | −#define nvalue(x) 0 | |
| 205 | +#define nvalue(x) ((lua_Number)0) | |
| 206 | 206 | #define ttypenv(x) ttnov(x) |
| 207 | 207 | /* |
| 208 | 208 | ** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: luaconf.h,v 1.185 2013/06/25 19:04:40 roberto Exp $ | |
| 2 | +** $Id: luaconf.h,v 1.193 2014/03/21 14:27:16 roberto Exp $ | |
| 3 | 3 | ** Configuration file for Lua |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -19,6 +19,24 @@ · 13 unmodified lines | ||
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | 21 | |
| 22 | +/* | |
| 23 | +** =================================================================== | |
| 24 | +@@ LUA_INT_INT / LUA_INT_LONG / LUA_INT_LONGLONG defines size for | |
| 25 | +@* Lua integers; | |
| 26 | +@@ LUA_REAL_FLOAT / LUA_REAL_DOUBLE / LUA_REAL_LONGDOUBLE defines size for | |
| 27 | +@* Lua floats. | |
| 28 | +** | |
| 29 | +** These definitions set the numeric types for Lua. Lua should work | |
| 30 | +** fine with 32-bit or 64-bit integers mixed with 32-bit or 64-bit | |
| 31 | +** floats. The usual configurations are 64-bit integers and floats (the | |
| 32 | +** default) and 32-bit integers and floats (Small Lua, for restricted | |
| 33 | +** hardware). | |
| 34 | +** ===================================================================== | |
| 35 | +*/ | |
| 36 | +#define LUA_INT_LONGLONG | |
| 37 | +#define LUA_REAL_DOUBLE | |
| 38 | + | |
| 39 | + | |
| 22 | 40 | /* |
| 23 | 41 | @@ LUA_ANSI controls the use of non-ansi features. |
| 24 | 42 | ** CHANGE it (define it) if you want Lua to avoid the use of any |
| @@ -41,24 +59,28 @@ · 16 unmodified lines | ||
| 41 | 59 | |
| 42 | 60 | |
| 43 | 61 | #if defined(LUA_USE_LINUX) |
| 62 | +#define LUA_USE_C99 | |
| 44 | 63 | #define LUA_USE_POSIX |
| 45 | 64 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ |
| 46 | 65 | #define LUA_USE_READLINE /* needs some extra libraries */ |
| 47 | −#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ | |
| 48 | −#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | |
| 49 | −#define LUA_USE_LONGLONG /* assume support for long long */ | |
| 50 | 66 | #endif |
| 51 | 67 | |
| 52 | 68 | #if defined(LUA_USE_MACOSX) |
| 69 | +#define LUA_USE_C99 | |
| 53 | 70 | #define LUA_USE_POSIX |
| 54 | 71 | #define LUA_USE_DLOPEN /* does not need -ldl */ |
| 55 | 72 | #define LUA_USE_READLINE /* needs an extra library: -lreadline */ |
| 56 | −#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ | |
| 57 | −#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | |
| 58 | −#define LUA_USE_LONGLONG /* assume support for long long */ | |
| 59 | 73 | #endif |
| 60 | 74 | |
| 61 | 75 | |
| 76 | +/* | |
| 77 | +@@ LUA_USE_C99 includes all functionality from C 99. | |
| 78 | +** CHANGE it (define it) if your system is compatible. | |
| 79 | +*/ | |
| 80 | +#if defined(LUA_USE_C99) | |
| 81 | +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | |
| 82 | +#endif | |
| 83 | + | |
| 62 | 84 | |
| 63 | 85 | /* |
| 64 | 86 | @@ LUA_USE_POSIX includes all functionality listed as X/Open System |
| @@ -66,11 +88,6 @@ · 1 unmodified line | ||
| 66 | 88 | ** CHANGE it (define it) if your system is XSI compatible. |
| 67 | 89 | */ |
| 68 | 90 | #if defined(LUA_USE_POSIX) |
| 69 | −#define LUA_USE_MKSTEMP | |
| 70 | −#define LUA_USE_ISATTY | |
| 71 | −#define LUA_USE_POPEN | |
| 72 | −#define LUA_USE_ULONGJMP | |
| 73 | −#define LUA_USE_GMTIME_R | |
| 74 | 91 | #endif |
| 75 | 92 | |
| 76 | 93 | |
| @@ -93,7 +110,8 @@ · 16 unmodified lines | ||
| 93 | 110 | #define LUA_CDIR "!\\" |
| 94 | 111 | #define LUA_PATH_DEFAULT \ |
| 95 | 112 | LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ |
| 96 | − LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" | |
| 113 | + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ | |
| 114 | + ".\\?.lua;" ".\\?\\init.lua" | |
| 97 | 115 | #define LUA_CPATH_DEFAULT \ |
| 98 | 116 | LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" |
| 99 | 117 | |
| @@ -105,7 +123,8 @@ · 5 unmodified lines | ||
| 105 | 123 | #define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR |
| 106 | 124 | #define LUA_PATH_DEFAULT \ |
| 107 | 125 | LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ |
| 108 | − LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" | |
| 126 | + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ | |
| 127 | + "./?.lua;" "./?/init.lua" | |
| 109 | 128 | #define LUA_CPATH_DEFAULT \ |
| 110 | 129 | LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" |
| 111 | 130 | #endif /* } */ |
| @@ -246,6 +265,11 @@ · 134 unmodified lines | ||
| 246 | 265 | */ |
| 247 | 266 | #if defined(LUA_COMPAT_ALL) /* { */ |
| 248 | 267 | |
| 268 | +/* | |
| 269 | +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. | |
| 270 | +*/ | |
| 271 | +#define LUA_COMPAT_BITLIB | |
| 272 | + | |
| 249 | 273 | /* |
| 250 | 274 | @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. |
| 251 | 275 | ** You can replace it with 'table.unpack'. |
| @@ -350,7 +374,7 @@ · 98 unmodified lines | ||
| 350 | 374 | /* |
| 351 | 375 | @@ LUAI_MAXSTACK limits the size of the Lua stack. |
| 352 | 376 | ** CHANGE it if you need a different limit. This limit is arbitrary; |
| 353 | −** its only purpose is to stop Lua to consume unlimited stack | |
| 377 | +** its only purpose is to stop Lua from consuming unlimited stack | |
| 354 | 378 | ** space (and to reserve some numbers for pseudo-indices). |
| 355 | 379 | */ |
| 356 | 380 | #if LUAI_BITSINT >= 32 |
| @@ -372,26 +396,14 @@ · 15 unmodified lines | ||
| 372 | 396 | #define LUAL_BUFFERSIZE BUFSIZ |
| 373 | 397 | |
| 374 | 398 | |
| 375 | − | |
| 376 | − | |
| 377 | 399 | /* |
| 378 | 400 | ** {================================================================== |
| 379 | −** The following definitions set the numeric types for Lua. | |
| 380 | −** Lua should work fine with 32-bit or 64-bit integers mixed with | |
| 381 | −** 32-bit or 64-bit floats. The usual configurations are 64-bit | |
| 382 | −** integers and floats (the default) and 32-bit integers and floats. | |
| 401 | +** Configuration for Numbers. | |
| 402 | +** Change these definitions if no predefined LUA_REAL_* / LUA_INT_* | |
| 403 | +** satisfy your needs. | |
| 383 | 404 | ** =================================================================== |
| 384 | 405 | */ |
| 385 | 406 | |
| 386 | −/* | |
| 387 | −@@ LUA_INTSIZE defines size for Lua integer: 1=int, 2=long, 3=long long | |
| 388 | −@@ LUA_FLOATSIZE defines size for Lua float: 1=float, 2=double, 3=long double | |
| 389 | −** Default is long long + double | |
| 390 | −*/ | |
| 391 | −#define LUA_INTSIZE 3 | |
| 392 | −#define LUA_FLOATSIZE 2 | |
| 393 | − | |
| 394 | − | |
| 395 | 407 | /* |
| 396 | 408 | @@ LUA_NUMBER is the floating-point type used by Lua. |
| 397 | 409 | ** |
| @@ -401,14 +413,14 @@ · 3 unmodified lines | ||
| 401 | 413 | @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. |
| 402 | 414 | @@ LUA_NUMBER_SCAN is the format for reading floats. |
| 403 | 415 | @@ LUA_NUMBER_FMT is the format for writing floats. |
| 404 | −@@ lua_number2str converts a floats to a string. | |
| 416 | +@@ lua_number2str converts a float to a string. | |
| 405 | 417 | ** |
| 406 | 418 | @@ l_mathop allows the addition of an 'l' or 'f' to all math operations |
| 407 | 419 | ** |
| 408 | 420 | @@ lua_str2number converts a decimal numeric string to a number. |
| 409 | 421 | */ |
| 410 | 422 | |
| 411 | −#if LUA_FLOATSIZE == 1 /* { single float */ | |
| 423 | +#if defined(LUA_REAL_FLOAT) /* { single float */ | |
| 412 | 424 | |
| 413 | 425 | #define LUA_NUMBER float |
| 414 | 426 | |
| @@ -423,7 +435,7 @@ · 8 unmodified lines | ||
| 423 | 435 | #define lua_str2number(s,p) strtof((s), (p)) |
| 424 | 436 | |
| 425 | 437 | |
| 426 | −#elif LUA_FLOATSIZE == 3 /* }{ long double */ | |
| 438 | +#elif defined(LUA_REAL_LONGDOUBLE) /* }{ long double */ | |
| 427 | 439 | |
| 428 | 440 | #define LUA_NUMBER long double |
| 429 | 441 | |
| @@ -437,7 +449,7 @@ · 7 unmodified lines | ||
| 437 | 449 | |
| 438 | 450 | #define lua_str2number(s,p) strtold((s), (p)) |
| 439 | 451 | |
| 440 | −#else /* }{ default: double */ | |
| 452 | +#elif defined(LUA_REAL_DOUBLE) /* }{ double */ | |
| 441 | 453 | |
| 442 | 454 | #define LUA_NUMBER double |
| 443 | 455 | |
| @@ -451,7 +463,11 @@ · 7 unmodified lines | ||
| 451 | 463 | |
| 452 | 464 | #define lua_str2number(s,p) strtod((s), (p)) |
| 453 | 465 | |
| 454 | −#endif /* } */ | |
| 466 | +#else /* }{ */ | |
| 467 | + | |
| 468 | +#error "numeric real type not defined" | |
| 469 | + | |
| 470 | +#endif /* } */ | |
| 455 | 471 | |
| 456 | 472 | |
| 457 | 473 | #if defined(LUA_ANSI) |
| @@ -481,8 +497,8 @@ · 23 unmodified lines | ||
| 481 | 497 | /* the following operations need the math library */ |
| 482 | 498 | #if defined(lobject_c) || defined(lvm_c) |
| 483 | 499 | #include <math.h> |
| 484 | −#define luai_nummod(L,a,b) ((a) - l_floor((a)/(b))*(b)) | |
| 485 | −#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) | |
| 500 | +#define luai_nummod(L,a,b) ((void)L, (a) - l_floor((a)/(b))*(b)) | |
| 501 | +#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) | |
| 486 | 502 | #endif |
| 487 | 503 | |
| 488 | 504 | /* these are quite standard operations */ |
| @@ -493,12 +509,19 @@ · 4 unmodified lines | ||
| 493 | 509 | #define luai_numdiv(L,a,b) ((a)/(b)) |
| 494 | 510 | #define luai_numunm(L,a) (-(a)) |
| 495 | 511 | #define luai_numeq(a,b) ((a)==(b)) |
| 496 | −#define luai_numlt(L,a,b) ((a)<(b)) | |
| 497 | −#define luai_numle(L,a,b) ((a)<=(b)) | |
| 498 | −#define luai_numisnan(L,a) (!luai_numeq((a), (a))) | |
| 512 | +#define luai_numlt(a,b) ((a)<(b)) | |
| 513 | +#define luai_numle(a,b) ((a)<=(b)) | |
| 514 | +#define luai_numisnan(a) (!luai_numeq((a), (a))) | |
| 499 | 515 | #endif |
| 500 | 516 | |
| 501 | 517 | |
| 518 | +/* | |
| 519 | +** The following macro checks whether an operation is not safe to be | |
| 520 | +** performed by the constant folder. It should result in zero only if | |
| 521 | +** the operation is safe. | |
| 522 | +*/ | |
| 523 | +#define luai_numinvalidop(op,a,b) 0 | |
| 524 | + | |
| 502 | 525 | |
| 503 | 526 | /* |
| 504 | 527 | @@ LUA_INTEGER is the integer type used by Lua. |
| @@ -511,22 +534,31 @@ · 6 unmodified lines | ||
| 511 | 534 | @@ lua_integer2str converts an integer to a string. |
| 512 | 535 | */ |
| 513 | 536 | |
| 514 | −#if LUA_INTSIZE == 1 /* { int */ | |
| 537 | +#if defined(LUA_INT_INT) /* { int */ | |
| 515 | 538 | |
| 516 | 539 | #define LUA_INTEGER int |
| 517 | 540 | #define LUA_INTEGER_FRMLEN "" |
| 518 | 541 | |
| 519 | −#elif LUA_INTSIZE == 2 /* }{ long */ | |
| 542 | +#elif defined(LUA_INT_LONG) /* }{ long */ | |
| 520 | 543 | |
| 521 | 544 | #define LUA_INTEGER long |
| 522 | 545 | #define LUA_INTEGER_FRMLEN "l" |
| 523 | 546 | |
| 524 | −#else /* }{ default: long long */ | |
| 547 | +#elif defined(LUA_INT_LONGLONG) /* }{ long long */ | |
| 525 | 548 | |
| 549 | +#if defined(_WIN32) | |
| 550 | +#define LUA_INTEGER __int64 | |
| 551 | +#define LUA_INTEGER_FRMLEN "I64" | |
| 552 | +#else | |
| 526 | 553 | #define LUA_INTEGER long long |
| 527 | 554 | #define LUA_INTEGER_FRMLEN "ll" |
| 555 | +#endif | |
| 528 | 556 | |
| 529 | −#endif /* } */ | |
| 557 | +#else /* }{ */ | |
| 558 | + | |
| 559 | +#error "numeric integer type not defined" | |
| 560 | + | |
| 561 | +#endif /* } */ | |
| 530 | 562 | |
| 531 | 563 | |
| 532 | 564 | #define LUA_INTEGER_SCAN "%" LUA_INTEGER_FRMLEN "d" |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ | |
| 2 | +** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ | |
| 3 | 3 | ** Lua standard libraries |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -29,6 +29,9 @@ LUAMOD_API int (luaopen_os) (lua_State *L); · 23 unmodified lines | ||
| 29 | 29 | #define LUA_STRLIBNAME "string" |
| 30 | 30 | LUAMOD_API int (luaopen_string) (lua_State *L); |
| 31 | 31 | |
| 32 | +#define LUA_UTF8LIBNAME "utf8" | |
| 33 | +LUAMOD_API int (luaopen_utf8) (lua_State *L); | |
| 34 | + | |
| 32 | 35 | #define LUA_BITLIBNAME "bit32" |
| 33 | 36 | LUAMOD_API int (luaopen_bit32) (lua_State *L); |
| 34 | 37 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp $ | |
| 2 | +** $Id: lundump.c,v 2.34 2014/03/11 18:56:27 roberto Exp $ | |
| 3 | 3 | ** load precompiled Lua chunks |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -20,249 +20,247 @@ · 14 unmodified lines | ||
| 20 | 20 | #include "lundump.h" |
| 21 | 21 | #include "lzio.h" |
| 22 | 22 | |
| 23 | + | |
| 24 | +#if !defined(luai_verifycode) | |
| 25 | +#define luai_verifycode(L,b,f) /* empty */ | |
| 26 | +#endif | |
| 27 | + | |
| 28 | + | |
| 23 | 29 | typedef struct { |
| 24 | − lua_State* L; | |
| 25 | − ZIO* Z; | |
| 26 | − Mbuffer* b; | |
| 27 | − const char* name; | |
| 30 | + lua_State *L; | |
| 31 | + ZIO *Z; | |
| 32 | + Mbuffer *b; | |
| 33 | + const char *name; | |
| 28 | 34 | } LoadState; |
| 29 | 35 | |
| 30 | −static l_noret error(LoadState* S, const char* why) | |
| 31 | −{ | |
| 32 | − luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); | |
| 33 | − luaD_throw(S->L,LUA_ERRSYNTAX); | |
| 36 | + | |
| 37 | +static l_noret error(LoadState *S, const char *why) { | |
| 38 | + luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); | |
| 39 | + luaD_throw(S->L, LUA_ERRSYNTAX); | |
| 34 | 40 | } |
| 35 | 41 | |
| 36 | −#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) | |
| 37 | −#define LoadByte(S) (lu_byte)LoadChar(S) | |
| 38 | −#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) | |
| 39 | −#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) | |
| 40 | 42 | |
| 41 | −#if !defined(luai_verifycode) | |
| 42 | −#define luai_verifycode(L,b,f) /* empty */ | |
| 43 | −#endif | |
| 43 | +/* | |
| 44 | +** All high-level loads go through LoadVector; you can change it to | |
| 45 | +** adapt to the endianess of the input | |
| 46 | +*/ | |
| 47 | +#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) | |
| 44 | 48 | |
| 45 | −static void LoadBlock(LoadState* S, void* b, size_t size) | |
| 46 | −{ | |
| 47 | − if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); | |
| 49 | +static void LoadBlock (LoadState *S, void *b, size_t size) { | |
| 50 | + if (luaZ_read(S->Z, b, size) != 0) | |
| 51 | + error(S, "truncated"); | |
| 48 | 52 | } |
| 49 | 53 | |
| 50 | −static int LoadChar(LoadState* S) | |
| 51 | −{ | |
| 52 | − char x; | |
| 53 | − LoadVar(S,x); | |
| 54 | − return x; | |
| 54 | + | |
| 55 | +#define LoadVar(S,x) LoadVector(S,&x,1) | |
| 56 | + | |
| 57 | + | |
| 58 | +static lu_byte LoadByte (LoadState *S) { | |
| 59 | + lu_byte x; | |
| 60 | + LoadVar(S, x); | |
| 61 | + return x; | |
| 55 | 62 | } |
| 56 | 63 | |
| 57 | −static int LoadInt(LoadState* S) | |
| 58 | −{ | |
| 59 | − int x; | |
| 60 | − LoadVar(S,x); | |
| 61 | − if (x<0) error(S,"corrupted"); | |
| 62 | − return x; | |
| 64 | + | |
| 65 | +static int LoadInt (LoadState *S) { | |
| 66 | + int x; | |
| 67 | + LoadVar(S, x); | |
| 68 | + return x; | |
| 63 | 69 | } |
| 64 | 70 | |
| 65 | −static lua_Number LoadNumber(LoadState* S) | |
| 66 | −{ | |
| 67 | − lua_Number x; | |
| 68 | − LoadVar(S,x); | |
| 69 | − return x; | |
| 71 | + | |
| 72 | +static lua_Number LoadNumber (LoadState *S) { | |
| 73 | + lua_Number x; | |
| 74 | + LoadVar(S, x); | |
| 75 | + return x; | |
| 70 | 76 | } |
| 71 | 77 | |
| 72 | −static lua_Integer LoadInteger(LoadState* S) | |
| 73 | −{ | |
| 74 | − lua_Integer x; | |
| 75 | − LoadVar(S,x); | |
| 76 | − return x; | |
| 78 | + | |
| 79 | +static lua_Integer LoadInteger (LoadState *S) { | |
| 80 | + lua_Integer x; | |
| 81 | + LoadVar(S, x); | |
| 82 | + return x; | |
| 77 | 83 | } |
| 78 | 84 | |
| 79 | −static TString* LoadString(LoadState* S) | |
| 80 | −{ | |
| 81 | − size_t size; | |
| 82 | − LoadVar(S,size); | |
| 83 | − if (size==0) | |
| 84 | − return NULL; | |
| 85 | − else | |
| 86 | − { | |
| 87 | − char* s=luaZ_openspace(S->L,S->b,size); | |
| 88 | − LoadBlock(S,s,size*sizeof(char)); | |
| 89 | − return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | |
| 90 | − } | |
| 85 | + | |
| 86 | +static TString *LoadString (LoadState *S) { | |
| 87 | + size_t size = LoadByte(S); | |
| 88 | + if (size == 0xFF) | |
| 89 | + LoadVar(S, size); | |
| 90 | + if (size == 0) | |
| 91 | + return NULL; | |
| 92 | + else { | |
| 93 | + char *s = luaZ_openspace(S->L, S->b, --size); | |
| 94 | + LoadVector(S, s, size); | |
| 95 | + return luaS_newlstr(S->L, s, size); | |
| 96 | + } | |
| 91 | 97 | } |
| 92 | 98 | |
| 93 | −static void LoadCode(LoadState* S, Proto* f) | |
| 94 | −{ | |
| 95 | − int n=LoadInt(S); | |
| 96 | − f->code=luaM_newvector(S->L,n,Instruction); | |
| 97 | − f->sizecode=n; | |
| 98 | − LoadVector(S,f->code,n,sizeof(Instruction)); | |
| 99 | + | |
| 100 | +static void LoadCode (LoadState *S, Proto *f) { | |
| 101 | + int n = LoadInt(S); | |
| 102 | + f->code = luaM_newvector(S->L, n, Instruction); | |
| 103 | + f->sizecode = n; | |
| 104 | + LoadVector(S, f->code, n); | |
| 99 | 105 | } |
| 100 | 106 | |
| 101 | −static void LoadFunction(LoadState* S, Proto* f); | |
| 102 | − | |
| 103 | −static void LoadConstants(LoadState* S, Proto* f) | |
| 104 | −{ | |
| 105 | − int i,n; | |
| 106 | − n=LoadInt(S); | |
| 107 | − f->k=luaM_newvector(S->L,n,TValue); | |
| 108 | − f->sizek=n; | |
| 109 | − for (i=0; i<n; i++) setnilvalue(&f->k[i]); | |
| 110 | − for (i=0; i<n; i++) | |
| 111 | − { | |
| 112 | − TValue* o=&f->k[i]; | |
| 113 | − int t=LoadChar(S); | |
| 114 | − switch (t) | |
| 115 | − { | |
| 116 | − case LUA_TNIL: | |
| 117 | − setnilvalue(o); | |
| 118 | − break; | |
| 119 | − case LUA_TBOOLEAN: | |
| 120 | − setbvalue(o,LoadChar(S)); | |
| 121 | − break; | |
| 122 | − case LUA_TNUMFLT: | |
| 123 | − setnvalue(o,LoadNumber(S)); | |
| 124 | − break; | |
| 125 | − case LUA_TNUMINT: | |
| 126 | − setivalue(o,LoadInteger(S)); | |
| 127 | − break; | |
| 128 | − case LUA_TSHRSTR: case LUA_TLNGSTR: | |
| 129 | − setsvalue2n(S->L,o,LoadString(S)); | |
| 130 | − break; | |
| 131 | − default: lua_assert(0); | |
| 107 | + | |
| 108 | +static void LoadFunction(LoadState *S, Proto *f); | |
| 109 | + | |
| 110 | + | |
| 111 | +static void LoadConstants (LoadState *S, Proto *f) { | |
| 112 | + int i, n; | |
| 113 | + n = LoadInt(S); | |
| 114 | + f->k = luaM_newvector(S->L, n, TValue); | |
| 115 | + f->sizek = n; | |
| 116 | + for (i = 0; i < n; i++) | |
| 117 | + setnilvalue(&f->k[i]); | |
| 118 | + for (i = 0; i < n; i++) { | |
| 119 | + TValue *o = &f->k[i]; | |
| 120 | + int t = LoadByte(S); | |
| 121 | + switch (t) { | |
| 122 | + case LUA_TNIL: | |
| 123 | + setnilvalue(o); | |
| 124 | + break; | |
| 125 | + case LUA_TBOOLEAN: | |
| 126 | + setbvalue(o, LoadByte(S)); | |
| 127 | + break; | |
| 128 | + case LUA_TNUMFLT: | |
| 129 | + setnvalue(o, LoadNumber(S)); | |
| 130 | + break; | |
| 131 | + case LUA_TNUMINT: | |
| 132 | + setivalue(o, LoadInteger(S)); | |
| 133 | + break; | |
| 134 | + case LUA_TSHRSTR: | |
| 135 | + case LUA_TLNGSTR: | |
| 136 | + setsvalue2n(S->L, o, LoadString(S)); | |
| 137 | + break; | |
| 138 | + default: | |
| 139 | + lua_assert(0); | |
| 140 | + } | |
| 141 | + } | |
| 142 | + n = LoadInt(S); | |
| 143 | + f->p = luaM_newvector(S->L, n, Proto *); | |
| 144 | + f->sizep = n; | |
| 145 | + for (i = 0; i < n; i++) | |
| 146 | + f->p[i] = NULL; | |
| 147 | + for (i = 0; i < n; i++) { | |
| 148 | + f->p[i] = luaF_newproto(S->L); | |
| 149 | + LoadFunction(S, f->p[i]); | |
| 132 | 150 | } |
| 133 | − } | |
| 134 | − n=LoadInt(S); | |
| 135 | − f->p=luaM_newvector(S->L,n,Proto*); | |
| 136 | − f->sizep=n; | |
| 137 | − for (i=0; i<n; i++) f->p[i]=NULL; | |
| 138 | − for (i=0; i<n; i++) | |
| 139 | − { | |
| 140 | − f->p[i]=luaF_newproto(S->L); | |
| 141 | − LoadFunction(S,f->p[i]); | |
| 142 | − } | |
| 143 | 151 | } |
| 144 | 152 | |
| 145 | −static void LoadUpvalues(LoadState* S, Proto* f) | |
| 146 | −{ | |
| 147 | − int i,n; | |
| 148 | − n=LoadInt(S); | |
| 149 | − f->upvalues=luaM_newvector(S->L,n,Upvaldesc); | |
| 150 | − f->sizeupvalues=n; | |
| 151 | − for (i=0; i<n; i++) f->upvalues[i].name=NULL; | |
| 152 | − for (i=0; i<n; i++) | |
| 153 | − { | |
| 154 | − f->upvalues[i].instack=LoadByte(S); | |
| 155 | − f->upvalues[i].idx=LoadByte(S); | |
| 156 | − } | |
| 153 | + | |
| 154 | +static void LoadUpvalues (LoadState *S, Proto *f) { | |
| 155 | + int i, n; | |
| 156 | + n = LoadInt(S); | |
| 157 | + f->upvalues = luaM_newvector(S->L, n, Upvaldesc); | |
| 158 | + f->sizeupvalues = n; | |
| 159 | + for (i = 0; i < n; i++) | |
| 160 | + f->upvalues[i].name = NULL; | |
| 161 | + for (i = 0; i < n; i++) { | |
| 162 | + f->upvalues[i].instack = LoadByte(S); | |
| 163 | + f->upvalues[i].idx = LoadByte(S); | |
| 164 | + } | |
| 157 | 165 | } |
| 158 | 166 | |
| 159 | −static void LoadDebug(LoadState* S, Proto* f) | |
| 160 | −{ | |
| 161 | − int i,n; | |
| 162 | − f->source=LoadString(S); | |
| 163 | − n=LoadInt(S); | |
| 164 | − f->lineinfo=luaM_newvector(S->L,n,int); | |
| 165 | − f->sizelineinfo=n; | |
| 166 | − LoadVector(S,f->lineinfo,n,sizeof(int)); | |
| 167 | − n=LoadInt(S); | |
| 168 | − f->locvars=luaM_newvector(S->L,n,LocVar); | |
| 169 | − f->sizelocvars=n; | |
| 170 | − for (i=0; i<n; i++) f->locvars[i].varname=NULL; | |
| 171 | − for (i=0; i<n; i++) | |
| 172 | − { | |
| 173 | − f->locvars[i].varname=LoadString(S); | |
| 174 | − f->locvars[i].startpc=LoadInt(S); | |
| 175 | − f->locvars[i].endpc=LoadInt(S); | |
| 176 | − } | |
| 177 | − n=LoadInt(S); | |
| 178 | − for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S); | |
| 167 | + | |
| 168 | +static void LoadDebug (LoadState *S, Proto *f) { | |
| 169 | + int i, n; | |
| 170 | + f->source = LoadString(S); | |
| 171 | + n = LoadInt(S); | |
| 172 | + f->lineinfo = luaM_newvector(S->L, n, int); | |
| 173 | + f->sizelineinfo = n; | |
| 174 | + LoadVector(S, f->lineinfo, n); | |
| 175 | + n = LoadInt(S); | |
| 176 | + f->locvars = luaM_newvector(S->L, n, LocVar); | |
| 177 | + f->sizelocvars = n; | |
| 178 | + for (i = 0; i < n; i++) | |
| 179 | + f->locvars[i].varname = NULL; | |
| 180 | + for (i = 0; i < n; i++) { | |
| 181 | + f->locvars[i].varname = LoadString(S); | |
| 182 | + f->locvars[i].startpc = LoadInt(S); | |
| 183 | + f->locvars[i].endpc = LoadInt(S); | |
| 184 | + } | |
| 185 | + n = LoadInt(S); | |
| 186 | + for (i = 0; i < n; i++) | |
| 187 | + f->upvalues[i].name = LoadString(S); | |
| 179 | 188 | } |
| 180 | 189 | |
| 181 | −static void LoadFunction(LoadState* S, Proto* f) | |
| 182 | −{ | |
| 183 | − f->linedefined=LoadInt(S); | |
| 184 | − f->lastlinedefined=LoadInt(S); | |
| 185 | − f->numparams=LoadByte(S); | |
| 186 | − f->is_vararg=LoadByte(S); | |
| 187 | − f->maxstacksize=LoadByte(S); | |
| 188 | − LoadCode(S,f); | |
| 189 | − LoadConstants(S,f); | |
| 190 | − LoadUpvalues(S,f); | |
| 191 | − LoadDebug(S,f); | |
| 190 | + | |
| 191 | +static void LoadFunction (LoadState *S, Proto *f) { | |
| 192 | + f->linedefined = LoadInt(S); | |
| 193 | + f->lastlinedefined = LoadInt(S); | |
| 194 | + f->numparams = LoadByte(S); | |
| 195 | + f->is_vararg = LoadByte(S); | |
| 196 | + f->maxstacksize = LoadByte(S); | |
| 197 | + LoadCode(S, f); | |
| 198 | + LoadConstants(S, f); | |
| 199 | + LoadUpvalues(S, f); | |
| 200 | + LoadDebug(S, f); | |
| 192 | 201 | } |
| 193 | 202 | |
| 194 | −/* the code below must be consistent with the code in luaU_header */ | |
| 195 | −#define N0 LUAC_HEADERSIZE | |
| 196 | −#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) | |
| 197 | −#define N2 N1+2 | |
| 198 | −#define N3 N2+6 | |
| 199 | − | |
| 200 | −static void LoadHeader(LoadState* S) | |
| 201 | −{ | |
| 202 | − lu_byte h[LUAC_HEADERSIZE]; | |
| 203 | − lu_byte s[LUAC_HEADERSIZE]; | |
| 204 | − luaU_header(h); | |
| 205 | − memcpy(s,h,sizeof(char)); /* first char already read */ | |
| 206 | − LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); | |
| 207 | − if (memcmp(h,s,N0)==0) return; | |
| 208 | − if (memcmp(h,s,N1)!=0) error(S,"not a"); | |
| 209 | − if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); | |
| 210 | − if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); | |
| 203 | + | |
| 204 | +static void checkliteral (LoadState *S, const char *s, const char *msg) { | |
| 205 | + char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ | |
| 206 | + int len = strlen(s); | |
| 207 | + LoadVector(S, buff, len); | |
| 208 | + if (memcmp(s, buff, len) != 0) | |
| 209 | + error(S, msg); | |
| 211 | 210 | } |
| 212 | 211 | |
| 213 | −/* | |
| 214 | −** load precompiled chunk | |
| 215 | −*/ | |
| 216 | −Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) | |
| 217 | −{ | |
| 218 | − LoadState S; | |
| 219 | − Closure* cl; | |
| 220 | − if (*name=='@' || *name=='=') | |
| 221 | − S.name=name+1; | |
| 222 | − else if (*name==LUA_SIGNATURE[0]) | |
| 223 | − S.name="binary string"; | |
| 224 | − else | |
| 225 | − S.name=name; | |
| 226 | − S.L=L; | |
| 227 | − S.Z=Z; | |
| 228 | − S.b=buff; | |
| 229 | − LoadHeader(&S); | |
| 230 | − cl=luaF_newLclosure(L,1); | |
| 231 | − setclLvalue(L,L->top,cl); incr_top(L); | |
| 232 | − cl->l.p=luaF_newproto(L); | |
| 233 | − LoadFunction(&S,cl->l.p); | |
| 234 | − if (cl->l.p->sizeupvalues != 1) | |
| 235 | − { | |
| 236 | − Proto* p=cl->l.p; | |
| 237 | − cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); | |
| 238 | − cl->l.p=p; | |
| 239 | − setclLvalue(L,L->top-1,cl); | |
| 240 | − } | |
| 241 | − luai_verifycode(L,buff,cl->l.p); | |
| 242 | − return cl; | |
| 212 | + | |
| 213 | +static void fchecksize (LoadState *S, size_t size, const char *tname) { | |
| 214 | + if (LoadByte(S) != size) | |
| 215 | + error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); | |
| 216 | +} | |
| 217 | + | |
| 218 | + | |
| 219 | +#define checksize(S,t) fchecksize(S,sizeof(t),#t) | |
| 220 | + | |
| 221 | +static void checkHeader (LoadState *S) { | |
| 222 | + checkliteral(S, LUA_SIGNATURE + 1, "not a"); /* 1st char already checked */ | |
| 223 | + if (LoadByte(S) != LUAC_VERSION) | |
| 224 | + error(S, "version mismatch in"); | |
| 225 | + if (LoadByte(S) != LUAC_FORMAT) | |
| 226 | + error(S, "format mismatch in"); | |
| 227 | + checkliteral(S, LUAC_DATA, "corrupted"); | |
| 228 | + checksize(S, int); | |
| 229 | + checksize(S, size_t); | |
| 230 | + checksize(S, Instruction); | |
| 231 | + checksize(S, lua_Integer); | |
| 232 | + checksize(S, lua_Number); | |
| 233 | + if (LoadInteger(S) != LUAC_INT) | |
| 234 | + error(S, "endianess mismatch in"); | |
| 235 | + if (LoadNumber(S) != LUAC_NUM) | |
| 236 | + error(S, "float format mismatch in"); | |
| 243 | 237 | } |
| 244 | 238 | |
| 245 | −#define MYINT(s) (s[0]-'0') | |
| 246 | −#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) | |
| 247 | −#define FORMAT 0 /* this is the official format */ | |
| 248 | 239 | |
| 249 | 240 | /* |
| 250 | −* make header for precompiled chunks | |
| 251 | −* if you change the code below be sure to update LoadHeader and FORMAT above | |
| 252 | −* and LUAC_HEADERSIZE in lundump.h | |
| 241 | +** load precompiled chunk | |
| 253 | 242 | */ |
| 254 | −void luaU_header (lu_byte* h) | |
| 255 | −{ | |
| 256 | − int x=1; | |
| 257 | − memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); | |
| 258 | − h+=sizeof(LUA_SIGNATURE)-sizeof(char); | |
| 259 | − *h++=cast_byte(VERSION); | |
| 260 | − *h++=cast_byte(FORMAT); | |
| 261 | − *h++=cast_byte(*(char*)&x); /* endianness */ | |
| 262 | − *h++=cast_byte(sizeof(int)); | |
| 263 | − *h++=cast_byte(sizeof(size_t)); | |
| 264 | − *h++=cast_byte(sizeof(Instruction)); | |
| 265 | − *h++=cast_byte(sizeof(lua_Number)); | |
| 266 | − *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ | |
| 267 | − memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); | |
| 243 | +Closure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, | |
| 244 | + const char *name) { | |
| 245 | + LoadState S; | |
| 246 | + Closure *cl; | |
| 247 | + if (*name == '@' || *name == '=') | |
| 248 | + S.name = name + 1; | |
| 249 | + else if (*name == LUA_SIGNATURE[0]) | |
| 250 | + S.name = "binary string"; | |
| 251 | + else | |
| 252 | + S.name = name; | |
| 253 | + S.L = L; | |
| 254 | + S.Z = Z; | |
| 255 | + S.b = buff; | |
| 256 | + checkHeader(&S); | |
| 257 | + cl = luaF_newLclosure(L, LoadByte(&S)); | |
| 258 | + setclLvalue(L, L->top, cl); | |
| 259 | + incr_top(L); | |
| 260 | + cl->l.p = luaF_newproto(L); | |
| 261 | + LoadFunction(&S, cl->l.p); | |
| 262 | + lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); | |
| 263 | + luai_verifycode(L, buff, cl->l.p); | |
| 264 | + return cl; | |
| 268 | 265 | } |
| 266 | + | |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $ | |
| 2 | +** $Id: lundump.h,v 1.42 2014/03/11 14:22:54 roberto Exp $ | |
| 3 | 3 | ** load precompiled Lua chunks |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -7,22 +7,27 @@ · 1 unmodified line | ||
| 7 | 7 | #ifndef lundump_h |
| 8 | 8 | #define lundump_h |
| 9 | 9 | |
| 10 | +#include "llimits.h" | |
| 10 | 11 | #include "lobject.h" |
| 11 | 12 | #include "lzio.h" |
| 12 | 13 | |
| 13 | −/* load one chunk; from lundump.c */ | |
| 14 | −LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); | |
| 15 | 14 | |
| 16 | −/* make header; from lundump.c */ | |
| 17 | −LUAI_FUNC void luaU_header (lu_byte* h); | |
| 15 | +/* data to catch conversion errors */ | |
| 16 | +#define LUAC_DATA "\x19\x93\r\n\x1a\n" | |
| 18 | 17 | |
| 19 | −/* dump one chunk; from ldump.c */ | |
| 20 | −LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); | |
| 18 | +#define LUAC_INT cast_integer(0xABCD) | |
| 19 | +#define LUAC_NUM cast_num(370.5) | |
| 21 | 20 | |
| 22 | −/* data to catch conversion errors */ | |
| 23 | −#define LUAC_TAIL "\x19\x93\r\n\x1a\n" | |
| 21 | +#define MYINT(s) (s[0]-'0') | |
| 22 | +#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) | |
| 23 | +#define LUAC_FORMAT 0 /* this is the official format */ | |
| 24 | 24 | |
| 25 | −/* size in bytes of header of binary files */ | |
| 26 | −#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) | |
| 25 | +/* load one chunk; from lundump.c */ | |
| 26 | +LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, | |
| 27 | + const char* name); | |
| 28 | + | |
| 29 | +/* dump one chunk; from ldump.c */ | |
| 30 | +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, | |
| 31 | + void* data, int strip); | |
| 27 | 32 | |
| 28 | 33 | #endif |
| @@ -0,0 +1,240 @@ | ||
| 1 | +/* | |
| 2 | +** $Id: lutf8lib.c,v 1.4 2014/03/20 19:36:02 roberto Exp $ | |
| 3 | +** Standard library for UTF-8 manipulation | |
| 4 | +** See Copyright Notice in lua.h | |
| 5 | +*/ | |
| 6 | + | |
| 7 | + | |
| 8 | +#include <assert.h> | |
| 9 | +#include <stdlib.h> | |
| 10 | +#include <string.h> | |
| 11 | + | |
| 12 | +#define lutf8lib_c | |
| 13 | +#define LUA_LIB | |
| 14 | + | |
| 15 | +#include "lua.h" | |
| 16 | + | |
| 17 | +#include "lauxlib.h" | |
| 18 | +#include "lualib.h" | |
| 19 | + | |
| 20 | +#define MAXUNICODE 0x10FFFF | |
| 21 | + | |
| 22 | +#define iscont(p) ((*(p) & 0xC0) == 0x80) | |
| 23 | + | |
| 24 | + | |
| 25 | +/* from strlib */ | |
| 26 | +/* translate a relative string position: negative means back from end */ | |
| 27 | +static lua_Integer u_posrelat (lua_Integer pos, size_t len) { | |
| 28 | + if (pos >= 0) return pos; | |
| 29 | + else if (0u - (size_t)pos > len) return 0; | |
| 30 | + else return (lua_Integer)len + pos + 1; | |
| 31 | +} | |
| 32 | + | |
| 33 | + | |
| 34 | +/* | |
| 35 | +** Decode an UTF-8 sequence, returning NULL if byte sequence is invalid. | |
| 36 | +*/ | |
| 37 | +static const char *utf8_decode (const char *o, int *val) { | |
| 38 | + static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; | |
| 39 | + const unsigned char *s = (const unsigned char *)o; | |
| 40 | + unsigned int c = s[0]; | |
| 41 | + unsigned int res = 0; /* final result */ | |
| 42 | + if (c < 0x80) /* ascii? */ | |
| 43 | + res = c; | |
| 44 | + else { | |
| 45 | + int count = 0; /* to count number of continuation bytes */ | |
| 46 | + while (c & 0x40) { /* still have continuation bytes? */ | |
| 47 | + int cc = s[++count]; /* read next byte */ | |
| 48 | + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ | |
| 49 | + return NULL; /* invalid byte sequence */ | |
| 50 | + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ | |
| 51 | + c <<= 1; /* to test next bit */ | |
| 52 | + } | |
| 53 | + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ | |
| 54 | + if (count > 3 || res > MAXUNICODE || res <= limits[count]) | |
| 55 | + return NULL; /* invalid byte sequence */ | |
| 56 | + s += count; /* skip continuation bytes read */ | |
| 57 | + } | |
| 58 | + if (val) *val = res; | |
| 59 | + return (const char *)s + 1; /* +1 to include first byte */ | |
| 60 | +} | |
| 61 | + | |
| 62 | + | |
| 63 | +/* | |
| 64 | +** utf8len(s, [i]) --> number of codepoints in 's' after 'i'; | |
| 65 | +** nil if 's' not well formed | |
| 66 | +*/ | |
| 67 | +static int utflen (lua_State *L) { | |
| 68 | + int n = 0; | |
| 69 | + const char *ends; | |
| 70 | + size_t len; | |
| 71 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 72 | + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), 1); | |
| 73 | + luaL_argcheck(L, 1 <= posi && posi <= (lua_Integer)len, 1, | |
| 74 | + "initial position out of string"); | |
| 75 | + ends = s + len; | |
| 76 | + s += posi - 1; | |
| 77 | + while (s < ends && (s = utf8_decode(s, NULL)) != NULL) | |
| 78 | + n++; | |
| 79 | + if (s == ends) | |
| 80 | + lua_pushinteger(L, n); | |
| 81 | + else | |
| 82 | + lua_pushnil(L); | |
| 83 | + return 1; | |
| 84 | +} | |
| 85 | + | |
| 86 | + | |
| 87 | +/* | |
| 88 | +** codepoint(s, [i, [j]]) -> returns codepoints for all characters | |
| 89 | +** between i and j | |
| 90 | +*/ | |
| 91 | +static int codepoint (lua_State *L) { | |
| 92 | + size_t len; | |
| 93 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 94 | + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); | |
| 95 | + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); | |
| 96 | + int n; | |
| 97 | + const char *se; | |
| 98 | + luaL_argcheck(L, posi >= 1, 2, "out of range"); | |
| 99 | + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); | |
| 100 | + if (posi > pose) return 0; /* empty interval; return no values */ | |
| 101 | + n = (int)(pose - posi + 1); | |
| 102 | + if (posi + n <= pose) /* (lua_Integer -> int) overflow? */ | |
| 103 | + return luaL_error(L, "string slice too long"); | |
| 104 | + luaL_checkstack(L, n, "string slice too long"); | |
| 105 | + n = 0; | |
| 106 | + se = s + pose; | |
| 107 | + for (s += posi - 1; s < se;) { | |
| 108 | + int code; | |
| 109 | + s = utf8_decode(s, &code); | |
| 110 | + if (s == NULL) | |
| 111 | + return luaL_error(L, "invalid UTF-8 code"); | |
| 112 | + lua_pushinteger(L, code); | |
| 113 | + n++; | |
| 114 | + } | |
| 115 | + return n; | |
| 116 | +} | |
| 117 | + | |
| 118 | + | |
| 119 | +static void pushutfchar (lua_State *L, int arg) { | |
| 120 | + int code = luaL_checkint(L, arg); | |
| 121 | + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); | |
| 122 | + lua_pushfstring(L, "%U", code); | |
| 123 | +} | |
| 124 | + | |
| 125 | + | |
| 126 | +/* | |
| 127 | +** utfchar(n1, n2, ...) -> char(n1)..char(n2)... | |
| 128 | +*/ | |
| 129 | +static int utfchar (lua_State *L) { | |
| 130 | + int n = lua_gettop(L); /* number of arguments */ | |
| 131 | + if (n == 1) /* optimize common case of single char */ | |
| 132 | + pushutfchar(L, 1); | |
| 133 | + else { | |
| 134 | + int i; | |
| 135 | + luaL_Buffer b; | |
| 136 | + luaL_buffinit(L, &b); | |
| 137 | + for (i = 1; i <= n; i++) { | |
| 138 | + pushutfchar(L, i); | |
| 139 | + luaL_addvalue(&b); | |
| 140 | + } | |
| 141 | + luaL_pushresult(&b); | |
| 142 | + } | |
| 143 | + return 1; | |
| 144 | +} | |
| 145 | + | |
| 146 | + | |
| 147 | +/* | |
| 148 | +** offset(s, n, [i]) -> index where n-th character *after* | |
| 149 | +** position 'i' starts; 0 means character at 'i'. | |
| 150 | +*/ | |
| 151 | +static int byteoffset (lua_State *L) { | |
| 152 | + size_t len; | |
| 153 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 154 | + int n = luaL_checkint(L, 2); | |
| 155 | + lua_Integer posi = u_posrelat(luaL_optinteger(L, 3, 1), len) - 1; | |
| 156 | + luaL_argcheck(L, 0 <= posi && posi <= (lua_Integer)len, 3, | |
| 157 | + "position out of range"); | |
| 158 | + if (n == 0) { | |
| 159 | + /* find beginning of current byte sequence */ | |
| 160 | + while (posi > 0 && iscont(s + posi)) posi--; | |
| 161 | + } | |
| 162 | + else if (n < 0) { | |
| 163 | + while (n < 0 && posi > 0) { /* move back */ | |
| 164 | + do { /* find beginning of previous character */ | |
| 165 | + posi--; | |
| 166 | + } while (posi > 0 && iscont(s + posi)); | |
| 167 | + n++; | |
| 168 | + } | |
| 169 | + } | |
| 170 | + else { | |
| 171 | + n--; /* do not move for 1st character */ | |
| 172 | + while (n > 0 && posi < (lua_Integer)len) { | |
| 173 | + do { /* find beginning of next character */ | |
| 174 | + posi++; | |
| 175 | + } while (iscont(s + posi)); /* ('\0' is not continuation) */ | |
| 176 | + n--; | |
| 177 | + } | |
| 178 | + } | |
| 179 | + if (n == 0) | |
| 180 | + lua_pushinteger(L, posi + 1); | |
| 181 | + else | |
| 182 | + lua_pushnil(L); /* no such position */ | |
| 183 | + return 1; | |
| 184 | +} | |
| 185 | + | |
| 186 | + | |
| 187 | +static int iter_aux (lua_State *L) { | |
| 188 | + size_t len; | |
| 189 | + const char *s = luaL_checklstring(L, 1, &len); | |
| 190 | + int n = lua_tointeger(L, 2) - 1; | |
| 191 | + if (n < 0) /* first iteration? */ | |
| 192 | + n = 0; /* start from here */ | |
| 193 | + else if (n < (lua_Integer)len) { | |
| 194 | + n++; /* skip current byte */ | |
| 195 | + while (iscont(s + n)) n++; /* and its continuations */ | |
| 196 | + } | |
| 197 | + if (n >= (lua_Integer)len) | |
| 198 | + return 0; /* no more codepoints */ | |
| 199 | + else { | |
| 200 | + int code; | |
| 201 | + const char *next = utf8_decode(s + n, &code); | |
| 202 | + if (next == NULL || iscont(next)) | |
| 203 | + return luaL_error(L, "invalid UTF-8 code"); | |
| 204 | + lua_pushinteger(L, n + 1); | |
| 205 | + lua_pushinteger(L, code); | |
| 206 | + return 2; | |
| 207 | + } | |
| 208 | +} | |
| 209 | + | |
| 210 | + | |
| 211 | +static int iter_codes (lua_State *L) { | |
| 212 | + luaL_checkstring(L, 1); | |
| 213 | + lua_pushcfunction(L, iter_aux); | |
| 214 | + lua_pushvalue(L, 1); | |
| 215 | + lua_pushinteger(L, 0); | |
| 216 | + return 3; | |
| 217 | +} | |
| 218 | + | |
| 219 | + | |
| 220 | +/* pattern to match a single UTF-8 character */ | |
| 221 | +#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" | |
| 222 | + | |
| 223 | + | |
| 224 | +static struct luaL_Reg funcs[] = { | |
| 225 | + {"offset", byteoffset}, | |
| 226 | + {"codepoint", codepoint}, | |
| 227 | + {"char", utfchar}, | |
| 228 | + {"len", utflen}, | |
| 229 | + {"codes", iter_codes}, | |
| 230 | + {NULL, NULL} | |
| 231 | +}; | |
| 232 | + | |
| 233 | + | |
| 234 | +int luaopen_utf8 (lua_State *L) { | |
| 235 | + luaL_newlib(L, funcs); | |
| 236 | + lua_pushliteral(L, UTF8PATT); | |
| 237 | + lua_setfield(L, -2, "charpatt"); | |
| 238 | + return 1; | |
| 239 | +} | |
| 240 | + | |
| @@ -1,10 +1,11 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp $ | |
| 2 | +** $Id: lvm.c,v 2.190 2014/03/15 12:29:48 roberto Exp $ | |
| 3 | 3 | ** Lua virtual machine |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | |
| 8 | +#include <limits.h> | |
| 8 | 9 | #include <stdio.h> |
| 9 | 10 | #include <stdlib.h> |
| 10 | 11 | #include <string.h> |
| @@ -29,7 +30,7 @@ · 18 unmodified lines | ||
| 29 | 30 | |
| 30 | 31 | |
| 31 | 32 | /* limit for table tag-method chains (to avoid loops) */ |
| 32 | −#define MAXTAGLOOP 100 | |
| 33 | +#define MAXTAGLOOP 2000 | |
| 33 | 34 | |
| 34 | 35 | |
| 35 | 36 | /* maximum length of the conversion of a number to a string */ |
| @@ -52,17 +53,9 @@ int luaV_tostring (lua_State *L, StkId obj) { · 16 unmodified lines | ||
| 52 | 53 | return 0; |
| 53 | 54 | else { |
| 54 | 55 | char buff[MAXNUMBER2STR]; |
| 55 | − size_t len; | |
| 56 | − if (ttisinteger(obj)) | |
| 57 | − len = lua_integer2str(buff, ivalue(obj)); | |
| 58 | − else { | |
| 59 | − len = lua_number2str(buff, fltvalue(obj)); | |
| 60 | − if (strspn(buff, "-0123456789") == len) { /* look like an integer? */ | |
| 61 | − buff[len++] = '.'; /* add a '.0' */ | |
| 62 | − buff[len++] = '0'; | |
| 63 | − buff[len] = '\0'; | |
| 64 | − } | |
| 65 | − } | |
| 56 | + size_t len = (ttisinteger(obj)) | |
| 57 | + ? lua_integer2str(buff, ivalue(obj)) | |
| 58 | + : lua_number2str(buff, fltvalue(obj)); | |
| 66 | 59 | setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); |
| 67 | 60 | return 1; |
| 68 | 61 | } |
| @@ -73,7 +66,7 @@ int luaV_tostring (lua_State *L, StkId obj) { · 4 unmodified lines | ||
| 73 | 66 | ** Check whether a float number is within the range of a lua_Integer. |
| 74 | 67 | ** (The comparisons are tricky because of rounding, which can or |
| 75 | 68 | ** not occur depending on the relative sizes of floats and integers.) |
| 76 | −** This function is called only when 'n' has an integer value. | |
| 69 | +** This function should be called only when 'n' has an integral value. | |
| 77 | 70 | */ |
| 78 | 71 | int luaV_numtointeger (lua_Number n, lua_Integer *p) { |
| 79 | 72 | if (cast_num(MIN_INTEGER) <= n && n < (MAX_INTEGER + cast_num(1))) { |
| @@ -121,7 +114,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { · 41 unmodified lines | ||
| 121 | 114 | } |
| 122 | 115 | t = tm; /* else repeat with 'tm' */ |
| 123 | 116 | } |
| 124 | − luaG_runerror(L, "loop in gettable"); | |
| 117 | + luaG_runerror(L, "gettable chain too long; possible loop"); | |
| 125 | 118 | } |
| 126 | 119 | |
| 127 | 120 | |
| @@ -145,7 +138,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { · 17 unmodified lines | ||
| 145 | 138 | /* no metamethod and (now) there is an entry with given key */ |
| 146 | 139 | setobj2t(L, oldval, val); /* assign new value to that entry */ |
| 147 | 140 | invalidateTMcache(h); |
| 148 | − luaC_barrierback(L, obj2gco(h), val); | |
| 141 | + luaC_barrierback(L, h, val); | |
| 149 | 142 | return; |
| 150 | 143 | } |
| 151 | 144 | /* else will try the metamethod */ |
| @@ -160,7 +153,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { · 8 unmodified lines | ||
| 160 | 153 | } |
| 161 | 154 | t = tm; /* else repeat with 'tm' */ |
| 162 | 155 | } |
| 163 | − luaG_runerror(L, "loop in settable"); | |
| 156 | + luaG_runerror(L, "settable chain too long; possible loop"); | |
| 164 | 157 | } |
| 165 | 158 | |
| 166 | 159 | |
| @@ -192,7 +185,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { · 25 unmodified lines | ||
| 192 | 185 | if (ttisinteger(l) && ttisinteger(r)) |
| 193 | 186 | return (ivalue(l) < ivalue(r)); |
| 194 | 187 | else if (tonumber(l, &nl) && tonumber(r, &nr)) |
| 195 | − return luai_numlt(L, nl, nr); | |
| 188 | + return luai_numlt(nl, nr); | |
| 196 | 189 | else if (ttisstring(l) && ttisstring(r)) |
| 197 | 190 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; |
| 198 | 191 | else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) |
| @@ -207,7 +200,7 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { · 8 unmodified lines | ||
| 207 | 200 | if (ttisinteger(l) && ttisinteger(r)) |
| 208 | 201 | return (ivalue(l) <= ivalue(r)); |
| 209 | 202 | else if (tonumber(l, &nl) && tonumber(r, &nr)) |
| 210 | − return luai_numle(L, nl, nr); | |
| 203 | + return luai_numle(nl, nr); | |
| 211 | 204 | else if (ttisstring(l) && ttisstring(r)) |
| 212 | 205 | return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; |
| 213 | 206 | else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ |
| @@ -229,7 +222,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { · 15 unmodified lines | ||
| 229 | 222 | else { /* two numbers with different variants */ |
| 230 | 223 | lua_Number n1, n2; |
| 231 | 224 | lua_assert(ttisnumber(t1) && ttisnumber(t2)); |
| 232 | − (void)tonumber(t1, &n1); (void)tonumber(t2, &n2); | |
| 225 | + cast_void(tonumber(t1, &n1)); cast_void(tonumber(t2, &n2)); | |
| 233 | 226 | return luai_numeq(n1, n2); |
| 234 | 227 | } |
| 235 | 228 | } |
| @@ -272,7 +265,7 @@ void luaV_concat (lua_State *L, int total) { · 36 unmodified lines | ||
| 272 | 265 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) |
| 273 | 266 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); |
| 274 | 267 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ |
| 275 | − (void)tostring(L, top - 2); /* result is first operand */ | |
| 268 | + cast_void(tostring(L, top - 2)); /* result is first operand */ | |
| 276 | 269 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { |
| 277 | 270 | setobjs2s(L, top - 2, top - 1); /* result is second op. */ |
| 278 | 271 | } |
| @@ -333,8 +326,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { · 54 unmodified lines | ||
| 333 | 326 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ |
| 334 | 327 | if (y == 0) |
| 335 | 328 | luaG_runerror(L, "attempt to divide by zero"); |
| 336 | − else /* -1 */ | |
| 337 | − return -x; /* avoid overflow with 0x80000... */ | |
| 329 | + return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ | |
| 338 | 330 | } |
| 339 | 331 | else { |
| 340 | 332 | lua_Integer d = x / y; /* perform division */ |
| @@ -350,8 +342,7 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { · 9 unmodified lines | ||
| 350 | 342 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ |
| 351 | 343 | if (y == 0) |
| 352 | 344 | luaG_runerror(L, "attempt to perform 'n%%0'"); |
| 353 | − else /* -1 */ | |
| 354 | − return 0; /* avoid overflow with 0x80000... */ | |
| 345 | + return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ | |
| 355 | 346 | } |
| 356 | 347 | else { |
| 357 | 348 | lua_Integer r = x % y; |
| @@ -363,16 +354,36 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { · 5 unmodified lines | ||
| 363 | 354 | } |
| 364 | 355 | |
| 365 | 356 | |
| 366 | −lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { | |
| 367 | − lua_Integer r = 1; | |
| 368 | − lua_assert(y >= 0); | |
| 369 | − if (y == 0) return r; | |
| 370 | − for (; y > 1; y >>= 1) { | |
| 371 | − if (y & 1) r = intop(*, r, x); | |
| 372 | − x = intop(*, x, x); | |
| 357 | +lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) { | |
| 358 | + if (y <= 0) { /* special cases: 0 or negative exponent */ | |
| 359 | + if (y < 0) | |
| 360 | + luaG_runerror(L, "integer exponentiation with negative exponent"); | |
| 361 | + return 1; /* x^0 == 1 */ | |
| 362 | + } | |
| 363 | + else { | |
| 364 | + lua_Integer r = 1; | |
| 365 | + for (; y > 1; y >>= 1) { | |
| 366 | + if (y & 1) r = intop(*, r, x); | |
| 367 | + x = intop(*, x, x); | |
| 368 | + } | |
| 369 | + r = intop(*, r, x); | |
| 370 | + return r; | |
| 371 | + } | |
| 372 | +} | |
| 373 | + | |
| 374 | + | |
| 375 | +/* number of bits in an integer */ | |
| 376 | +#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) | |
| 377 | + | |
| 378 | +LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { | |
| 379 | + if (y < 0) { /* shift right? */ | |
| 380 | + if (y <= -NBITS) return 0; | |
| 381 | + else return cast_integer(cast_unsigned(x) >> (-y)); | |
| 382 | + } | |
| 383 | + else { /* shift left */ | |
| 384 | + if (y >= NBITS) return 0; | |
| 385 | + else return x << y; | |
| 373 | 386 | } |
| 374 | − r = intop(*, r, x); | |
| 375 | − return r; | |
| 376 | 387 | } |
| 377 | 388 | |
| 378 | 389 | |
| @@ -399,9 +410,9 @@ static Closure *getcached (Proto *p, UpVal **encup, StkId base) { · 20 unmodified lines | ||
| 399 | 410 | |
| 400 | 411 | /* |
| 401 | 412 | ** create a new Lua closure, push it in the stack, and initialize |
| 402 | −** its upvalues. Note that the call to 'luaC_barrierproto' must come | |
| 403 | −** before the assignment to 'p->cache', as the function needs the | |
| 404 | −** original value of that field. | |
| 413 | +** its upvalues. Note that the closure is not cached if prototype is | |
| 414 | +** already black (which means that 'cache' was already cleared by the | |
| 415 | +** GC). | |
| 405 | 416 | */ |
| 406 | 417 | static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, |
| 407 | 418 | StkId ra) { |
| @@ -416,9 +427,11 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, · 8 unmodified lines | ||
| 416 | 427 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); |
| 417 | 428 | else /* get upvalue from enclosing function */ |
| 418 | 429 | ncl->l.upvals[i] = encup[uv[i].idx]; |
| 430 | + ncl->l.upvals[i]->refcount++; | |
| 431 | + /* new closure is white, so we do not need a barrier here */ | |
| 419 | 432 | } |
| 420 | − luaC_barrierproto(L, p, ncl); | |
| 421 | − p->cache = ncl; /* save it on cache for reuse */ | |
| 433 | + if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */ | |
| 434 | + p->cache = ncl; /* save it on cache for reuse */ | |
| 422 | 435 | } |
| 423 | 436 | |
| 424 | 437 | |
| @@ -432,7 +445,9 @@ void luaV_finishOp (lua_State *L) { · 7 unmodified lines | ||
| 432 | 445 | OpCode op = GET_OPCODE(inst); |
| 433 | 446 | switch (op) { /* finish its execution */ |
| 434 | 447 | case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: |
| 435 | − case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: | |
| 448 | + case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: | |
| 449 | + case OP_MOD: case OP_POW: | |
| 450 | + case OP_UNM: case OP_BNOT: case OP_LEN: | |
| 436 | 451 | case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { |
| 437 | 452 | setobjs2s(L, base + GETARG_A(inst), --L->top); |
| 438 | 453 | break; |
| @@ -590,7 +605,7 @@ void luaV_execute (lua_State *L) { · 151 unmodified lines | ||
| 590 | 605 | vmcase(OP_SETUPVAL, |
| 591 | 606 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
| 592 | 607 | setobj(L, uv->v, ra); |
| 593 | − luaC_barrier(L, uv, ra); | |
| 608 | + luaC_upvalbarrier(L, uv); | |
| 594 | 609 | ) |
| 595 | 610 | vmcase(OP_SETTABLE, |
| 596 | 611 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); |
| @@ -666,6 +681,51 @@ void luaV_execute (lua_State *L) { · 69 unmodified lines | ||
| 666 | 681 | } |
| 667 | 682 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } |
| 668 | 683 | ) |
| 684 | + vmcase(OP_BAND, | |
| 685 | + TValue *rb = RKB(i); | |
| 686 | + TValue *rc = RKC(i); | |
| 687 | + lua_Integer ib; lua_Integer ic; | |
| 688 | + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | |
| 689 | + setivalue(ra, intop(&, ib, ic)); | |
| 690 | + } | |
| 691 | + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } | |
| 692 | + ) | |
| 693 | + vmcase(OP_BOR, | |
| 694 | + TValue *rb = RKB(i); | |
| 695 | + TValue *rc = RKC(i); | |
| 696 | + lua_Integer ib; lua_Integer ic; | |
| 697 | + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | |
| 698 | + setivalue(ra, intop(|, ib, ic)); | |
| 699 | + } | |
| 700 | + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } | |
| 701 | + ) | |
| 702 | + vmcase(OP_BXOR, | |
| 703 | + TValue *rb = RKB(i); | |
| 704 | + TValue *rc = RKC(i); | |
| 705 | + lua_Integer ib; lua_Integer ic; | |
| 706 | + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | |
| 707 | + setivalue(ra, intop(^, ib, ic)); | |
| 708 | + } | |
| 709 | + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } | |
| 710 | + ) | |
| 711 | + vmcase(OP_SHL, | |
| 712 | + TValue *rb = RKB(i); | |
| 713 | + TValue *rc = RKC(i); | |
| 714 | + lua_Integer ib; lua_Integer ic; | |
| 715 | + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | |
| 716 | + setivalue(ra, luaV_shiftl(ib, ic)); | |
| 717 | + } | |
| 718 | + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } | |
| 719 | + ) | |
| 720 | + vmcase(OP_SHR, | |
| 721 | + TValue *rb = RKB(i); | |
| 722 | + TValue *rc = RKC(i); | |
| 723 | + lua_Integer ib; lua_Integer ic; | |
| 724 | + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | |
| 725 | + setivalue(ra, luaV_shiftl(ib, -ic)); | |
| 726 | + } | |
| 727 | + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } | |
| 728 | + ) | |
| 669 | 729 | vmcase(OP_MOD, |
| 670 | 730 | TValue *rb = RKB(i); |
| 671 | 731 | TValue *rc = RKC(i); |
| @@ -683,11 +743,9 @@ void luaV_execute (lua_State *L) { · 11 unmodified lines | ||
| 683 | 743 | TValue *rb = RKB(i); |
| 684 | 744 | TValue *rc = RKC(i); |
| 685 | 745 | lua_Number nb; lua_Number nc; |
| 686 | − lua_Integer ic; | |
| 687 | − if (ttisinteger(rb) && ttisinteger(rc) && | |
| 688 | − (ic = ivalue(rc)) >= 0) { | |
| 689 | − lua_Integer ib = ivalue(rb); | |
| 690 | − setivalue(ra, luaV_pow(ib, ic)); | |
| 746 | + if (ttisinteger(rb) && ttisinteger(rc)) { | |
| 747 | + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); | |
| 748 | + setivalue(ra, luaV_pow(L, ib, ic)); | |
| 691 | 749 | } |
| 692 | 750 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
| 693 | 751 | setnvalue(ra, luai_numpow(L, nb, nc)); |
| @@ -699,7 +757,7 @@ void luaV_execute (lua_State *L) { · 5 unmodified lines | ||
| 699 | 757 | lua_Number nb; |
| 700 | 758 | if (ttisinteger(rb)) { |
| 701 | 759 | lua_Integer ib = ivalue(rb); |
| 702 | − setivalue(ra, -ib); | |
| 760 | + setivalue(ra, intop(-, 0, ib)); | |
| 703 | 761 | } |
| 704 | 762 | else if (tonumber(rb, &nb)) { |
| 705 | 763 | setnvalue(ra, luai_numunm(L, nb)); |
| @@ -708,6 +766,16 @@ void luaV_execute (lua_State *L) { · 2 unmodified lines | ||
| 708 | 766 | Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); |
| 709 | 767 | } |
| 710 | 768 | ) |
| 769 | + vmcase(OP_BNOT, | |
| 770 | + TValue *rb = RB(i); | |
| 771 | + lua_Integer ib; | |
| 772 | + if (tointeger(rb, &ib)) { | |
| 773 | + setivalue(ra, intop(^, cast_integer(-1), ib)); | |
| 774 | + } | |
| 775 | + else { | |
| 776 | + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); | |
| 777 | + } | |
| 778 | + ) | |
| 711 | 779 | vmcase(OP_NOT, |
| 712 | 780 | TValue *rb = RB(i); |
| 713 | 781 | int res = l_isfalse(rb); /* next assignment may change this value */ |
| @@ -831,7 +899,7 @@ void luaV_execute (lua_State *L) { · 117 unmodified lines | ||
| 831 | 899 | } |
| 832 | 900 | ) |
| 833 | 901 | vmcase(OP_FORLOOP, |
| 834 | − if (ttisinteger(ra)) { /* integer count? */ | |
| 902 | + if (ttisinteger(ra)) { /* integer loop? */ | |
| 835 | 903 | lua_Integer step = ivalue(ra + 2); |
| 836 | 904 | lua_Integer idx = ivalue(ra) + step; /* increment index */ |
| 837 | 905 | lua_Integer limit = ivalue(ra + 1); |
| @@ -841,12 +909,12 @@ void luaV_execute (lua_State *L) { · 3 unmodified lines | ||
| 841 | 909 | setivalue(ra + 3, idx); /* ...and external index */ |
| 842 | 910 | } |
| 843 | 911 | } |
| 844 | − else { /* floating count */ | |
| 912 | + else { /* floating loop */ | |
| 845 | 913 | lua_Number step = fltvalue(ra + 2); |
| 846 | 914 | lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ |
| 847 | 915 | lua_Number limit = fltvalue(ra + 1); |
| 848 | − if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) | |
| 849 | − : luai_numle(L, limit, idx)) { | |
| 916 | + if (luai_numlt(0, step) ? luai_numle(idx, limit) | |
| 917 | + : luai_numle(limit, idx)) { | |
| 850 | 918 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ |
| 851 | 919 | setnvalue(ra, idx); /* update internal index... */ |
| 852 | 920 | setnvalue(ra + 3, idx); /* ...and external index */ |
| @@ -857,10 +925,11 @@ void luaV_execute (lua_State *L) { · 4 unmodified lines | ||
| 857 | 925 | TValue *init = ra; |
| 858 | 926 | TValue *plimit = ra + 1; |
| 859 | 927 | TValue *pstep = ra + 2; |
| 860 | − if (ttisinteger(ra) && ttisinteger(ra + 1) && ttisinteger(ra + 2)) { | |
| 861 | − setivalue(ra, ivalue(ra) - ivalue(pstep)); | |
| 928 | + if (ttisinteger(init) && ttisinteger(plimit) && ttisinteger(pstep)) { | |
| 929 | + /* all values are integer */ | |
| 930 | + setivalue(init, ivalue(init) - ivalue(pstep)); | |
| 862 | 931 | } |
| 863 | − else { /* try with floats */ | |
| 932 | + else { /* try making all values floats */ | |
| 864 | 933 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |
| 865 | 934 | if (!tonumber(plimit, &nlimit)) |
| 866 | 935 | luaG_runerror(L, LUA_QL("for") " limit must be a number"); |
| @@ -870,7 +939,7 @@ void luaV_execute (lua_State *L) { · 3 unmodified lines | ||
| 870 | 939 | setnvalue(pstep, nstep); |
| 871 | 940 | if (!tonumber(init, &ninit)) |
| 872 | 941 | luaG_runerror(L, LUA_QL("for") " initial value must be a number"); |
| 873 | − setnvalue(ra, luai_numsub(L, ninit, nstep)); | |
| 942 | + setnvalue(init, luai_numsub(L, ninit, nstep)); | |
| 874 | 943 | } |
| 875 | 944 | ci->u.l.savedpc += GETARG_sBx(i); |
| 876 | 945 | ) |
| @@ -912,7 +981,7 @@ void luaV_execute (lua_State *L) { · 35 unmodified lines | ||
| 912 | 981 | for (; n > 0; n--) { |
| 913 | 982 | TValue *val = ra+n; |
| 914 | 983 | luaH_setint(L, h, last--, val); |
| 915 | − luaC_barrierback(L, obj2gco(h), val); | |
| 984 | + luaC_barrierback(L, h, val); | |
| 916 | 985 | } |
| 917 | 986 | L->top = ci->top; /* correct top (in case of previous open call) */ |
| 918 | 987 | ) |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp $ | |
| 2 | +** $Id: lvm.h,v 2.25 2013/12/30 20:47:58 roberto Exp $ | |
| 3 | 3 | ** Lua virtual machine |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -43,7 +43,8 @@ LUAI_FUNC void luaV_execute (lua_State *L); · 37 unmodified lines | ||
| 43 | 43 | LUAI_FUNC void luaV_concat (lua_State *L, int total); |
| 44 | 44 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); |
| 45 | 45 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); |
| 46 | −LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); | |
| 46 | +LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y); | |
| 47 | +LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); | |
| 47 | 48 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); |
| 48 | 49 | |
| 49 | 50 | #endif |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lzio.h,v 1.27 2013/06/07 14:51:10 roberto Exp $ | |
| 2 | +** $Id: lzio.h,v 1.28 2014/01/31 15:14:22 roberto Exp $ | |
| 3 | 3 | ** Buffered streams |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -32,6 +32,7 @@ typedef struct Mbuffer { · 26 unmodified lines | ||
| 32 | 32 | #define luaZ_sizebuffer(buff) ((buff)->buffsize) |
| 33 | 33 | #define luaZ_bufflen(buff) ((buff)->n) |
| 34 | 34 | |
| 35 | +#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) | |
| 35 | 36 | #define luaZ_resetbuffer(buff) ((buff)->n = 0) |
| 36 | 37 | |
| 37 | 38 | |