diff options
author | Lua Team <team@lua.org> | 2013-07-06 12:00:00 +0000 |
---|---|---|
committer | repogen <> | 2013-07-06 12:00:00 +0000 |
commit | 87cc247b6b22184fba47184c218a642ea7a49e96 (patch) | |
tree | 299ba8b72b95aa32336b5c810b7133f8efc4fb29 /src | |
parent | dc27609467d2699ac9252e89d632432ac5f798f2 (diff) | |
download | lua-github-5.3.0-work1.tar.gz |
Lua 5.3.0-work15.3.0-work1
Diffstat (limited to 'src')
-rw-r--r-- | src/.fix | 2 | ||||
-rw-r--r-- | src/Makefile | 9 | ||||
-rw-r--r-- | src/lapi.c | 141 | ||||
-rw-r--r-- | src/lauxlib.c | 47 | ||||
-rw-r--r-- | src/lauxlib.h | 14 | ||||
-rw-r--r-- | src/lbaselib.c | 71 | ||||
-rw-r--r-- | src/lbitlib.c | 18 | ||||
-rw-r--r-- | src/lcode.c | 126 | ||||
-rw-r--r-- | src/lcode.h | 6 | ||||
-rw-r--r-- | src/ldblib.c | 15 | ||||
-rw-r--r-- | src/ldebug.c | 70 | ||||
-rw-r--r-- | src/ldebug.h | 9 | ||||
-rw-r--r-- | src/ldo.c | 15 | ||||
-rw-r--r-- | src/ldump.c | 20 | ||||
-rw-r--r-- | src/lgc.c | 13 | ||||
-rw-r--r-- | src/liolib.c | 45 | ||||
-rw-r--r-- | src/llex.c | 57 | ||||
-rw-r--r-- | src/llex.h | 8 | ||||
-rw-r--r-- | src/llimits.h | 113 | ||||
-rw-r--r-- | src/lmathlib.c | 56 | ||||
-rw-r--r-- | src/lobject.c | 161 | ||||
-rw-r--r-- | src/lobject.h | 143 | ||||
-rw-r--r-- | src/lopcodes.c | 4 | ||||
-rw-r--r-- | src/lopcodes.h | 3 | ||||
-rw-r--r-- | src/loslib.c | 10 | ||||
-rw-r--r-- | src/lparser.c | 19 | ||||
-rw-r--r-- | src/lparser.h | 8 | ||||
-rw-r--r-- | src/lstring.c | 6 | ||||
-rw-r--r-- | src/lstrlib.c | 109 | ||||
-rw-r--r-- | src/ltable.c | 83 | ||||
-rw-r--r-- | src/ltable.h | 7 | ||||
-rw-r--r-- | src/ltm.c | 74 | ||||
-rw-r--r-- | src/ltm.h | 17 | ||||
-rw-r--r-- | src/lua.h | 24 | ||||
-rw-r--r-- | src/luac.c | 6 | ||||
-rw-r--r-- | src/luaconf.h | 200 | ||||
-rw-r--r-- | src/lundump.c | 16 | ||||
-rw-r--r-- | src/lvm.c | 418 | ||||
-rw-r--r-- | src/lvm.h | 25 | ||||
-rw-r--r-- | src/lzio.h | 6 |
40 files changed, 1275 insertions, 919 deletions
diff --git a/src/.fix b/src/.fix new file mode 100644 index 00000000..b390c3ca --- /dev/null +++ b/src/.fix @@ -0,0 +1,2 @@ +#define nvalue(x) 0 +#define ttypenv(x) ttnov(x) diff --git a/src/Makefile b/src/Makefile index fea895bc..ca156758 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ PLAT= none CC= gcc -CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) +CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) LIBS= -lm $(SYSLIBS) $(MYLIBS) @@ -106,7 +106,7 @@ linux: $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" macosx: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc mingw: $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ @@ -173,8 +173,8 @@ lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h -ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ - lmem.h lstring.h lgc.h ltable.h +ltm.o: ltm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lstring.h lgc.h ltable.h lvm.h lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h @@ -185,3 +185,4 @@ lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ lzio.h +# (end of Makefile) @@ -1,10 +1,11 @@ /* -** $Id: lapi.c,v 2.171 2013/03/16 21:10:18 roberto Exp $ +** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ +#include <math.h> #include <stdarg.h> #include <string.h> @@ -248,7 +249,7 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { StkId o = index2addr(L, idx); - return (isvalid(o) ? ttypenv(o) : LUA_TNONE); + return (isvalid(o) ? ttnov(o) : LUA_TNONE); } @@ -264,8 +265,14 @@ LUA_API int lua_iscfunction (lua_State *L, int idx) { } +LUA_API int lua_isinteger (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return ttisinteger(o); +} + + LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; + lua_Number n; const TValue *o = index2addr(L, idx); return tonumber(o, &n); } @@ -291,8 +298,6 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { LUA_API void lua_arith (lua_State *L, int op) { - StkId o1; /* 1st operand */ - StkId o2; /* 2nd operand */ lua_lock(L); if (op != LUA_OPUNM) /* all other operations expect two operands */ api_checknelems(L, 2); @@ -301,14 +306,9 @@ LUA_API void lua_arith (lua_State *L, int op) { setobjs2s(L, L->top, L->top - 1); L->top++; } - o1 = L->top - 2; - o2 = L->top - 1; - if (ttisnumber(o1) && ttisnumber(o2)) { - setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); - } - else - luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); - L->top--; + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); + L->top--; /* remove second operand */ lua_unlock(L); } @@ -321,7 +321,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { o2 = index2addr(L, index2); if (isvalid(o1) && isvalid(o2)) { switch (op) { - case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; default: api_check(L, 0, "invalid option"); @@ -332,51 +332,74 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { } -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - if (isnum) *isnum = 1; - return nvalue(o); +LUA_API int lua_strtonum (lua_State *L, const char *s, size_t len) { + lua_Integer i; lua_Number n; + if (luaO_str2int(s, len, &i)) { /* try as an integer */ + setivalue(L->top, i); } - else { - if (isnum) *isnum = 0; - return 0; + else if (luaO_str2d(s, len, &n)) { /* else try as a float */ + setnvalue(L->top, n); } + else + return 0; /* conversion failed */ + api_incr_top(L); + return 1; } -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { - TValue n; +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { + lua_Number n; const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; - } + int isnum = tonumber(o, &n); + if (!isnum) + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return n; } -LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { - TValue n; +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { + lua_Integer res; const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Unsigned res; - lua_Number num = nvalue(o); - lua_number2unsigned(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; + int isnum = tointeger(o, &res); + if (!isnum) + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return res; +} + + +LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) { + lua_Unsigned res = 0; + const TValue *o = index2addr(L, idx); + int isnum = 0; + switch (ttype(o)) { + case LUA_TNUMINT: { + res = cast_unsigned(ivalue(o)); + isnum = 1; + break; + } + case LUA_TNUMFLT: { + const lua_Number twop = (~(lua_Unsigned)0) + cast_num(1); + lua_Number n = fltvalue(o); + int neg = 0; + n = l_floor(n); + if (n < 0) { + neg = 1; + n = -n; + } + n = l_mathop(fmod)(n, twop); + if (luai_numisnan(L,n)) /* not a number? */ + break; /* not an integer, too */ + res = cast_unsigned(n); + if (neg) res = 0u - res; + isnum = 1; + break; + } + default: break; } + if (pisnum) *pisnum = isnum; + return res; } @@ -406,7 +429,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { LUA_API size_t lua_rawlen (lua_State *L, int idx) { StkId o = index2addr(L, idx); - switch (ttypenv(o)) { + switch (ttnov(o)) { case LUA_TSTRING: return tsvalue(o)->len; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); @@ -426,7 +449,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { LUA_API void *lua_touserdata (lua_State *L, int idx) { StkId o = index2addr(L, idx); - switch (ttypenv(o)) { + switch (ttnov(o)) { case LUA_TUSERDATA: return (rawuvalue(o) + 1); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; @@ -482,17 +505,15 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); - setnvalue(L->top, cast_num(n)); + setivalue(L->top, n); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { - lua_Number n; lua_lock(L); - n = lua_unsigned2number(u); - setnvalue(L->top, n); + setivalue(L->top, cast_integer(u)); api_incr_top(L); lua_unlock(L); } @@ -646,7 +667,7 @@ LUA_API void lua_rawget (lua_State *L, int idx) { } -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { +LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); t = index2addr(L, idx); @@ -689,7 +710,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { int res; lua_lock(L); obj = index2addr(L, objindex); - switch (ttypenv(obj)) { + switch (ttnov(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; break; @@ -697,7 +718,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { mt = uvalue(obj)->metatable; break; default: - mt = G(L)->mt[ttypenv(obj)]; + mt = G(L)->mt[ttnov(obj)]; break; } if (mt == NULL) @@ -781,7 +802,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) { } -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { StkId t; lua_lock(L); api_checknelems(L, 1); @@ -821,7 +842,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } - switch (ttypenv(obj)) { + switch (ttnov(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) { @@ -839,7 +860,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { break; } default: { - G(L)->mt[ttypenv(obj)] = mt; + G(L)->mt[ttnov(obj)] = mt; break; } } diff --git a/src/lauxlib.c b/src/lauxlib.c index 2e989d66..68373b0a 100644 --- a/src/lauxlib.c +++ b/src/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $ +** $Id: lauxlib.c,v 1.255 2013/06/27 18:32:33 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -386,11 +386,20 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { } +static void interror (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNUMBER) + luaL_argerror(L, narg, "float value out of range"); + else + tag_error(L, narg, LUA_TNUMBER); +} + + LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { int isnum; lua_Integer d = lua_tointegerx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); + if (!isnum) { + interror(L, narg); + } return d; } @@ -399,7 +408,7 @@ LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { int isnum; lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); if (!isnum) - tag_error(L, narg, LUA_TNUMBER); + interror(L, narg); return d; } @@ -722,13 +731,13 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { } -LUALIB_API int luaL_len (lua_State *L, int idx) { - int l; +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { + lua_Integer l; int isnum; lua_len(L, idx); - l = (int)lua_tointegerx(L, -1, &isnum); + l = lua_tointegerx(L, -1, &isnum); if (!isnum) - luaL_error(L, "object length is not a number"); + luaL_error(L, "object length is not an integer"); lua_pop(L, 1); /* remove object */ return l; } @@ -737,7 +746,12 @@ LUALIB_API int luaL_len (lua_State *L, int idx) { LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ switch (lua_type(L, idx)) { - case LUA_TNUMBER: + case LUA_TNUMBER: { /* concatenate with empty string to convert */ + lua_pushvalue(L, idx); + lua_pushliteral(L, ""); + lua_concat(L, 2); + break; + } case LUA_TSTRING: lua_pushvalue(L, idx); break; @@ -846,7 +860,6 @@ LUALIB_API void luaL_openlib (lua_State *L, const char *libname, ** Returns with only the table at the stack. */ LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkversion(L); luaL_checkstack(L, nup, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; @@ -941,19 +954,15 @@ LUALIB_API lua_State *luaL_newstate (void) { } -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { +LUALIB_API void luaL_checkversion_ (lua_State *L, int ver, size_t sz) { const lua_Number *v = lua_version(L); if (v != lua_version(NULL)) luaL_error(L, "multiple Lua VMs detected"); else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + luaL_error(L, "version mismatch: app. needs %d, Lua core provides %f", ver, *v); - /* check conversions number -> integer types */ - lua_pushnumber(L, -(lua_Number)0x1234); - if (lua_tointeger(L, -1) != -0x1234 || - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) - luaL_error(L, "bad conversion number->int;" - " must recompile Lua with proper settings"); - lua_pop(L, 1); + /* check numeric types */ + if (sz != LUAL_NUMSIZES) + luaL_error(L, "core and library have incompatible numeric types"); } diff --git a/src/lauxlib.h b/src/lauxlib.h index ac4d15fb..6b345e28 100644 --- a/src/lauxlib.h +++ b/src/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ +** $Id: lauxlib.h,v 1.122 2013/06/27 18:32:33 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -26,8 +26,11 @@ typedef struct luaL_Reg { } luaL_Reg; -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, int ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); @@ -83,7 +86,7 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); -LUALIB_API int (luaL_len) (lua_State *L, int idx); +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); @@ -108,7 +111,8 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, #define luaL_newlibtable(L,l) \ lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) #define luaL_argcheck(L, cond,numarg,extramsg) \ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) diff --git a/src/lbaselib.c b/src/lbaselib.c index 540e9a5c..d074b92d 100644 --- a/src/lbaselib.c +++ b/src/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp $ +** $Id: lbaselib.c,v 1.279 2013/07/05 14:39:15 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -45,42 +45,57 @@ static int luaB_print (lua_State *L) { #define SPACECHARS " \f\n\r\t\v" +static int b_str2int (const char *s, const char *e, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return 0; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : toupper((unsigned char)*s) - 'A' + 10; + if (digit >= base) return 0; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + if (s != e) /* invalid trailing characters? */ + return 0; + *pn = (neg) ? -(lua_Integer)n : (lua_Integer)n; + return 1; +} + + static int luaB_tonumber (lua_State *L) { if (lua_isnoneornil(L, 2)) { /* standard conversion */ - int isnum; - lua_Number n = lua_tonumberx(L, 1, &isnum); - if (isnum) { - lua_pushnumber(L, n); - return 1; - } /* else not a number; must be something */ luaL_checkany(L, 1); + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ + return 1; + } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_strtonum(L, s, l)) /* can convert to a number? */ + return 1; + /* else not a number */ + } } else { size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *e = s + l; /* end point for 's' */ + const char *s; + lua_Integer n; int base = luaL_checkint(L, 2); - int neg = 0; + luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */ + s = luaL_checklstring(L, 1, &l); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (isalnum((unsigned char)*s)) { - lua_Number n = 0; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : toupper((unsigned char)*s) - 'A' + 10; - if (digit >= base) break; /* invalid numeral; force a fail */ - n = n * (lua_Number)base + (lua_Number)digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - if (s == e) { /* no invalid trailing characters? */ - lua_pushnumber(L, (neg) ? -n : n); - return 1; - } /* else not a number */ + if (b_str2int(s, s + l, base, &n)) { + lua_pushinteger(L, n); + return 1; } /* else not a number */ - } + } /* else not a number */ lua_pushnil(L); /* not a number */ return 1; } diff --git a/src/lbitlib.c b/src/lbitlib.c index 9637532e..d6d436bc 100644 --- a/src/lbitlib.c +++ b/src/lbitlib.c @@ -1,5 +1,5 @@ /* -** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $ +** $Id: lbitlib.c,v 1.20 2013/06/21 17:27:24 roberto Exp $ ** Standard library for bitwise operations ** See Copyright Notice in lua.h */ @@ -19,7 +19,12 @@ #endif -#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) +/* type with (at least) LUA_NBITS bits */ +typedef unsigned long b_uint; + + +#define ALLONES (~(((~(b_uint)0) << (LUA_NBITS - 1)) << 1)) + /* macro to trim extra bits */ #define trim(x) ((x) & ALLONES) @@ -29,9 +34,6 @@ #define mask(n) (~((ALLONES << 1) << ((n) - 1))) -typedef lua_Unsigned b_uint; - - static b_uint andaux (lua_State *L) { int i, n = lua_gettop(L); @@ -118,7 +120,7 @@ static int b_arshift (lua_State *L) { else { /* arithmetic shift for 'negative' number */ if (i >= LUA_NBITS) r = ALLONES; else - r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ + r = trim((r >> i) | ~(trim(~(b_uint)0) >> i)); /* add signal bit */ lua_pushunsigned(L, r); return 1; } @@ -165,7 +167,7 @@ static int fieldargs (lua_State *L, int farg, int *width) { static int b_extract (lua_State *L) { int w; - b_uint r = luaL_checkunsigned(L, 1); + b_uint r = trim(luaL_checkunsigned(L, 1)); int f = fieldargs(L, 2, &w); r = (r >> f) & mask(w); lua_pushunsigned(L, r); @@ -175,7 +177,7 @@ static int b_extract (lua_State *L) { static int b_replace (lua_State *L) { int w; - b_uint r = luaL_checkunsigned(L, 1); + b_uint r = trim(luaL_checkunsigned(L, 1)); b_uint v = luaL_checkunsigned(L, 2); int f = fieldargs(L, 3, &w); int m = mask(w); diff --git a/src/lcode.c b/src/lcode.c index 56c26ac8..261090e0 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1,10 +1,11 @@ /* -** $Id: lcode.c,v 2.62 2012/08/16 17:34:28 roberto Exp $ +** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ +#include <math.h> #include <stdlib.h> #define lcode_c @@ -26,11 +27,29 @@ #include "lvm.h" +/* test for x == -0 */ +#if defined(signbit) +#define isminuszero(x) ((x) == 0.0 && signbit(x)) +#else +#define isminuszero(x) ((x) == 0.0 && 1.0/(x) < 0.0) +#endif + + #define hasjumps(e) ((e)->t != (e)->f) -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +static int tonumeral(expdesc *e, TValue *v) { + if (e->t != NO_JUMP || e->f != NO_JUMP) + return 0; /* not a numeral */ + switch (e->k) { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setnvalue(v, e->u.nval); + return 1; + default: return 0; + } } @@ -293,9 +312,8 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { TValue *idx = luaH_set(L, fs->h, key); Proto *f = fs->f; int k, oldsize; - if (ttisnumber(idx)) { - lua_Number n = nvalue(idx); - lua_number2int(k, n); + if (ttisinteger(idx)) { + k = ivalue(idx); if (luaV_rawequalobj(&f->k[k], v)) return k; /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); @@ -306,7 +324,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { k = fs->nk; /* numerical value does not need GC barrier; table has no metatable, so it does not need to invalidate cache */ - setnvalue(idx, cast_num(k)); + setivalue(idx, k); luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[k], v); @@ -323,20 +341,28 @@ int luaK_stringK (FuncState *fs, TString *s) { } -int luaK_numberK (FuncState *fs, lua_Number r) { - int n; - lua_State *L = fs->ls->L; +/* +** use userdata as key to avoid collision with float with same value; +** conversion to 'void*' used only for hash, no "precision" problems +*/ +int luaK_intK (FuncState *fs, lua_Integer n) { + TValue k, o; + setpvalue(&k, cast(void*, cast(size_t, n))); + setivalue(&o, n); + return addk(fs, &k, &o); +} + + +/* +** Both NaN and -0.0 should not go to the constant table, as they have +** problems with the hashing. (NaN is not ** a valid key, +** -0.0 collides with +0.0.) +*/ +static int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; + lua_assert(!luai_numisnan(NULL, r) && !isminuszero(r)); setnvalue(&o, r); - if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ - /* use raw representation as key to avoid numeric problems */ - setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); - n = addk(fs, L->top - 1, &o); - L->top--; - } - else - n = addk(fs, &o, &o); /* regular case */ - return n; + return addk(fs, &o, &o); } @@ -433,10 +459,14 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_codek(fs, reg, e->u.info); break; } - case VKNUM: { + case VKFLT: { luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); break; } + case VKINT: { + luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); + break; + } case VRELOCABLE: { Instruction *pc = &getcode(fs, e); SETARG_A(*pc, reg); @@ -538,12 +568,18 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { } else break; } - case VKNUM: { + case VKINT: { + e->u.info = luaK_intK(fs, e->u.ival); + e->k = VK; + goto vk; + } + case VKFLT: { e->u.info = luaK_numberK(fs, e->u.nval); e->k = VK; /* go through */ } case VK: { + vk: if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ return RKASK(e->u.info); else break; @@ -627,7 +663,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { pc = e->u.info; break; } - case VK: case VKNUM: case VTRUE: { + case VK: case VKFLT: case VKINT: case VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } @@ -672,7 +708,7 @@ static void codenot (FuncState *fs, expdesc *e) { e->k = VTRUE; break; } - case VK: case VKNUM: case VTRUE: { + case VK: case VKFLT: case VKINT: case VTRUE: { e->k = VFALSE; break; } @@ -711,21 +747,34 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) - return 0; /* do not attempt to divide by 0 */ - r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); - e1->u.nval = r; + TValue v1, v2, res; + lua_Integer i; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) + return 0; + if (op == OP_IDIV && + (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) + return 0; /* avoid division by 0 and conversion errors */ + if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0) + return 0; /* avoid module by 0 at compile time */ + luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); + if (ttisinteger(&res)) { + e1->k = VKINT; + e1->u.ival = ivalue(&res); + } + else { + lua_Number n = fltvalue(&res); + if (luai_numisnan(NULL, n) || isminuszero(n)) + return 0; /* folds neither NaN nor -0 */ + e1->k = VKFLT; + e1->u.nval = n; + } return 1; } static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int line) { - if (constfolding(op, e1, e2)) - return; - else { + if (!constfolding(op, e1, e2)) { /* could not fold operation? */ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; int o1 = luaK_exp2RK(fs, e1); if (o1 > o2) { @@ -761,12 +810,10 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; switch (op) { case OPR_MINUS: { - if (isnumeral(e)) /* minus constant? */ - e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ - else { + if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */ luaK_exp2anyreg(fs, e); codearith(fs, OP_UNM, e, &e2, line); } @@ -797,9 +844,10 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ break; } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_ADD: case OPR_SUB: + case OPR_MUL: case OPR_DIV: case OPR_IDIV: case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); + if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v); break; } default: { @@ -842,7 +890,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, break; } case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { + case OPR_IDIV: case OPR_MOD: case OPR_POW: { codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); break; } diff --git a/src/lcode.h b/src/lcode.h index 5a1fa9fe..07d451b4 100644 --- a/src/lcode.h +++ b/src/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $ +** $Id: lcode.h,v 1.60 2013/04/26 13:07:53 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -24,7 +24,7 @@ ** grep "ORDER OPR" if you change these enums (ORDER OP) */ typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_IDIV, OPR_MOD, OPR_POW, OPR_CONCAT, OPR_EQ, OPR_LT, OPR_LE, OPR_NE, OPR_GT, OPR_GE, @@ -52,7 +52,7 @@ LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); diff --git a/src/ldblib.c b/src/ldblib.c index c0226945..30499a62 100644 --- a/src/ldblib.c +++ b/src/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $ +** $Id: ldblib.c,v 1.133 2013/06/25 19:37:00 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -22,6 +22,18 @@ +static int db_numbits (lua_State *L) { + const char *s = luaL_checkstring(L, 1); + if (*s == 'i') + lua_pushinteger(L, sizeof(lua_Integer) * CHAR_BIT); + else if (*s == 'f') + lua_pushinteger(L, sizeof(lua_Number) * CHAR_BIT); + else + luaL_argerror(L, 1, lua_pushfstring(L, "invalid option '%s'", s)); + return 1; +} + + static int db_getregistry (lua_State *L) { lua_pushvalue(L, LUA_REGISTRYINDEX); return 1; @@ -379,6 +391,7 @@ static const luaL_Reg dblib[] = { {"getregistry", db_getregistry}, {"getmetatable", db_getmetatable}, {"getupvalue", db_getupvalue}, + {"numbits", db_numbits}, {"upvaluejoin", db_upvaluejoin}, {"upvalueid", db_upvalueid}, {"setuservalue", db_setuservalue}, diff --git a/src/ldebug.c b/src/ldebug.c index 7e04f9d0..c9b88803 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.90 2012/08/16 17:34:28 roberto Exp $ +** $Id: ldebug.c,v 2.95 2013/05/06 17:21:59 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -453,6 +453,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { case OP_SUB: tm = TM_SUB; break; case OP_MUL: tm = TM_MUL; break; case OP_DIV: tm = TM_DIV; break; + case OP_IDIV: tm = TM_IDIV; break; case OP_MOD: tm = TM_MOD; break; case OP_POW: tm = TM_POW; break; case OP_UNM: tm = TM_UNM; break; @@ -497,10 +498,9 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, } -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { +static const char *varinfo (lua_State *L, const TValue *o) { + const char *name; CallInfo *ci = L->ci; - const char *name = NULL; - const char *t = objtypename(o); const char *kind = NULL; if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ @@ -508,29 +508,40 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { kind = getobjname(ci_func(ci)->p, currentpc(ci), cast_int(o - ci->u.l.base), &name); } - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); + return (kind) ? luaO_pushfstring(L, " (%s " LUA_QS ")", kind, name) : ""; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *t = objtypename(o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); } -l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { +l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p2)); + lua_assert(!ttisstring(p1) && !ttisnumber(p1)); luaG_typeerror(L, p1, "concatenate"); } l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) + lua_Number temp; + if (!tonumber(p1, &temp)) p2 = p1; /* first operand is wrong */ luaG_typeerror(L, p2, "perform arithmetic on"); } +l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { + lua_Integer temp; + if (!tointeger(p1, &temp)) + p2 = p1; + luaG_runerror(L, "attempt to convert an out of range float%s to an integer", + varinfo(L, p2)); +} + + l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { const char *t1 = objtypename(p1); const char *t2 = objtypename(p2); @@ -578,3 +589,36 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { luaG_errormsg(L); } + +void luaG_traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); + if (counthook) + resethookcount(L); /* reset count */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } +} + diff --git a/src/ldebug.h b/src/ldebug.h index fe39556b..c668e1e4 100644 --- a/src/ldebug.h +++ b/src/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $ +** $Id: ldebug.h,v 2.10 2013/05/06 17:19:11 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -23,12 +23,17 @@ LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *opname); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, + const TValue *p2); LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2); +LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, + const TValue *p2); LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2); LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); LUAI_FUNC l_noret luaG_errormsg (lua_State *L); +LUAI_FUNC void luaG_traceexec (lua_State *L); + #endif @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $ +** $Id: ldo.c,v 2.109 2013/04/19 21:05:04 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -260,6 +260,7 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { StkId base, fixed; lua_assert(actual >= nfixargs); /* move fixed parameters to final position */ + luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ fixed = L->top - actual; /* first fixed argument */ base = L->top; /* final position of first argument */ for (i=0; i<nfixargs; i++) { @@ -324,12 +325,18 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { case LUA_TLCL: { /* Lua function: prepare its call */ StkId base; Proto *p = clLvalue(func)->p; - luaD_checkstack(L, p->maxstacksize); - func = restorestack(L, funcr); n = cast_int(L->top - func) - 1; /* number of real arguments */ + luaD_checkstack(L, p->maxstacksize); for (; n < p->numparams; n++) setnilvalue(L->top++); /* complete missing arguments */ - base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n); + if (!p->is_vararg) { + func = restorestack(L, funcr); + base = func + 1; + } + else { + base = adjust_varargs(L, p, n); + func = restorestack(L, funcr); /* previous call can change stack */ + } ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; ci->func = func; diff --git a/src/ldump.c b/src/ldump.c index d5e6a47c..b3a25624 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $ +** $Id: ldump.c,v 2.19 2013/04/26 18:48:35 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, DumpState* D) DumpVar(x,D); } +static void DumpInteger(lua_Integer x, DumpState* D) +{ + DumpVar(x,D); +} + static void DumpVector(const void* b, int n, size_t size, DumpState* D) { DumpInt(n,D); @@ -84,18 +89,21 @@ static void DumpConstants(const Proto* f, DumpState* D) for (i=0; i<n; i++) { const TValue* o=&f->k[i]; - DumpChar(ttypenv(o),D); - switch (ttypenv(o)) + DumpChar(ttype(o),D); + switch (ttype(o)) { case LUA_TNIL: break; case LUA_TBOOLEAN: DumpChar(bvalue(o),D); break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); + case LUA_TNUMFLT: + DumpNumber(fltvalue(o),D); + break; + case LUA_TNUMINT: + DumpInteger(ivalue(o),D); break; - case LUA_TSTRING: + case LUA_TSHRSTR: case LUA_TLNGSTR: DumpString(rawtsvalue(o),D); break; default: lua_assert(0); @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.140 2013/03/16 21:10:18 roberto Exp $ +** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -493,17 +493,24 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) { static lu_mem traversestack (global_State *g, lua_State *th) { + int n = 0; StkId o = th->stack; if (o == NULL) return 1; /* stack not completely built yet */ - for (; o < th->top; o++) + for (; o < th->top; o++) /* mark live elements in the stack */ markvalue(g, o); if (g->gcstate == GCSatomic) { /* final traversal? */ StkId lim = th->stack + th->stacksize; /* real end of stack */ for (; o < lim; o++) /* clear not-marked stack slice */ setnilvalue(o); } - return sizeof(lua_State) + sizeof(TValue) * th->stacksize; + else { /* count call infos to compute size */ + CallInfo *ci; + for (ci = &th->base_ci; ci != th->ci; ci = ci->next) + n++; + } + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * n; } diff --git a/src/liolib.c b/src/liolib.c index 3f80db19..2c6202af 100644 --- a/src/liolib.c +++ b/src/liolib.c @@ -1,17 +1,17 @@ /* -** $Id: liolib.c,v 2.111 2013/03/21 13:57:27 roberto Exp $ +** $Id: liolib.c,v 2.114 2013/06/07 19:01:35 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ /* -** POSIX idiosyncrasy! ** This definition must come before the inclusion of 'stdio.h'; it ** should not affect non-POSIX systems */ #if !defined(_FILE_OFFSET_BITS) -#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 #endif @@ -80,36 +80,37 @@ /* ** {====================================================== -** lua_fseek/lua_ftell: configuration for longer offsets +** lua_fseek: configuration for longer offsets ** ======================================================= */ -#if !defined(lua_fseek) /* { */ +#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ -#if defined(LUA_USE_POSIX) +#if defined(LUA_USE_POSIX) /* { */ #define l_fseek(f,o,w) fseeko(f,o,w) #define l_ftell(f) ftello(f) #define l_seeknum off_t #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ - && defined(_MSC_VER) && (_MSC_VER >= 1400) + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ /* Windows (but not DDK) and Visual C++ 2005 or higher */ #define l_fseek(f,o,w) _fseeki64(f,o,w) #define l_ftell(f) _ftelli64(f) #define l_seeknum __int64 -#else +#endif /* } */ +#endif /* } */ + + +#if !defined(l_fseek) /* default definitions */ #define l_fseek(f,o,w) fseek(f,o,w) #define l_ftell(f) ftell(f) #define l_seeknum long - #endif -#endif /* } */ - /* }====================================================== */ @@ -346,6 +347,19 @@ static int io_lines (lua_State *L) { */ +static int read_integer (lua_State *L, FILE *f) { + lua_Integer d; + if (fscanf(f, LUA_INTEGER_SCAN, &d) == 1) { + lua_pushinteger(L, d); + return 1; + } + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + static int read_number (lua_State *L, FILE *f) { lua_Number d; if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { @@ -441,6 +455,9 @@ static int g_read (lua_State *L, FILE *f, int first) { const char *p = lua_tostring(L, n); luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); switch (p[1]) { + case 'i': /* integer */ + success = read_integer(L, f); + break; case 'n': /* number */ success = read_number(L, f); break; @@ -516,8 +533,10 @@ static int g_write (lua_State *L, FILE *f, int arg) { for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)); + status = status && (len > 0); } else { size_t l; @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.63 2013/03/16 21:10:18 roberto Exp $ +** $Id: llex.c,v 2.67 2013/06/19 14:27:00 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -38,8 +38,8 @@ static const char *const luaX_tokens [] = { "end", "false", "for", "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", - "<number>", "<name>", "<string>" + "//", "..", "...", "==", ">=", "<=", "~=", "::", "<eof>", + "<number>", "<number>", "<name>", "<string>" }; @@ -53,7 +53,7 @@ static void save (LexState *ls, int c) { Mbuffer *b = ls->buff; if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZET/2) + if (luaZ_sizebuffer(b) >= MAX_SIZE/2) lexerror(ls, "lexical element too long", 0); newsize = luaZ_sizebuffer(b) * 2; luaZ_resizebuffer(ls->L, b, newsize); @@ -90,9 +90,8 @@ const char *luaX_token2str (LexState *ls, int token) { static const char *txtToken (LexState *ls, int token) { switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: + case TK_NAME: case TK_STRING: + case TK_FLT: case TK_INT: save(ls, '\0'); return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); default: @@ -216,7 +215,7 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) { if (!buff2d(ls->buff, &seminfo->r)) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - lexerror(ls, "malformed number", TK_NUMBER); + lexerror(ls, "malformed number", TK_FLT); } } @@ -224,9 +223,10 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) { /* LUA_NUMBER */ /* ** this function is quite liberal in what it accepts, as 'luaO_str2d' -** will reject ill-formed numerals. +** will reject ill-formed numerals. 'isf' means the numeral is not +** an integer (it has a dot or an exponent). */ -static void read_numeral (LexState *ls, SemInfo *seminfo) { +static int read_numeral (LexState *ls, SemInfo *seminfo, int isf) { const char *expo = "Ee"; int first = ls->current; lua_assert(lisdigit(ls->current)); @@ -234,16 +234,31 @@ static void read_numeral (LexState *ls, SemInfo *seminfo) { if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ expo = "Pp"; for (;;) { - if (check_next(ls, expo)) /* exponent part? */ + if (check_next(ls, expo)) { /* exponent part? */ check_next(ls, "+-"); /* optional exponent sign */ - if (lisxdigit(ls->current) || ls->current == '.') + isf = 1; + } + if (lisxdigit(ls->current)) + save_and_next(ls); + else if (ls->current == '.') { save_and_next(ls); - else break; + isf = 1; + } + else break; } save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ + if (!isf) { + if (!luaO_str2int(luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff) - 1, + &seminfo->i)) + lexerror(ls, "malformed number", TK_INT); + return TK_INT; + } + else { + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ + return TK_FLT; + } } @@ -450,6 +465,11 @@ static int llex (LexState *ls, SemInfo *seminfo) { if (ls->current != '=') return '>'; else { next(ls); return TK_GE; } } + case '/': { + next(ls); + if (ls->current != '/') return '/'; + else { next(ls); return TK_IDIV; } + } case '~': { next(ls); if (ls->current != '=') return '~'; @@ -472,12 +492,11 @@ static int llex (LexState *ls, SemInfo *seminfo) { else return TK_CONCAT; /* '..' */ } else if (!lisdigit(ls->current)) return '.'; - /* else go through */ + else return read_numeral(ls, seminfo, 1); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { - read_numeral(ls, seminfo); - return TK_NUMBER; + return read_numeral(ls, seminfo, 0); } case EOZ: { return TK_EOS; @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $ +** $Id: llex.h,v 1.74 2013/04/26 13:07:53 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -26,8 +26,9 @@ enum RESERVED { TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, - TK_NUMBER, TK_NAME, TK_STRING + TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, + TK_DBCOLON, TK_EOS, + TK_FLT, TK_INT, TK_NAME, TK_STRING }; /* number of reserved words */ @@ -36,6 +37,7 @@ enum RESERVED { typedef union { lua_Number r; + lua_Integer i; TString *ts; } SemInfo; /* semantics information */ diff --git a/src/llimits.h b/src/llimits.h index 1b8c79bd..c4416f89 100644 --- a/src/llimits.h +++ b/src/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.103 2013/02/20 14:08:56 roberto Exp $ +** $Id: llimits.h,v 1.108 2013/06/19 14:27:00 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -27,8 +27,14 @@ typedef LUAI_MEM l_mem; typedef unsigned char lu_byte; +/* maximum value for size_t */ #define MAX_SIZET ((size_t)(~(size_t)0)-2) +/* maximum size visible for Lua (must be representable in a lua_Integer */ +#define MAX_SIZE (sizeof(size_t) <= sizeof(lua_Integer) ? MAX_SIZET \ + : (size_t)(~(lua_Unsigned)0)-2) + + #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) #define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) @@ -36,6 +42,12 @@ typedef unsigned char lu_byte; #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* minimum and maximum values for lua_Integer */ +#define MAX_INTEGER ((lua_Integer)(~(lua_Unsigned)0 >> 1)) +#define MIN_INTEGER (~MAX_INTEGER) + + /* ** conversion of pointer to integer ** this is for hashing only; there is no problem if the integer @@ -96,6 +108,8 @@ typedef LUAI_UACNUMBER l_uacNumber; #define cast_num(i) cast(lua_Number, (i)) #define cast_int(i) cast(int, (i)) #define cast_uchar(i) cast(unsigned char, (i)) +#define cast_integer(i) cast(lua_Integer, (i)) +#define cast_unsigned(i) cast(lua_Unsigned, (i)) /* @@ -190,103 +204,6 @@ typedef lu_int32 Instruction; #define luai_userstateyield(L,n) ((void)L) #endif -/* -** lua_number2int is a macro to convert lua_Number to int. -** lua_number2integer is a macro to convert lua_Number to lua_Integer. -** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. -** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. -** luai_hashnum is a macro to hash a lua_Number value into an integer. -** The hash must be deterministic and give reasonable values for -** both small and large values (outside the range of integers). -*/ - -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ -/* trick with Microsoft assembler for X86 */ - -#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} -#define lua_number2integer(i,n) lua_number2int(i, n) -#define lua_number2unsigned(i,n) \ - {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} - - -#elif defined(LUA_IEEE754TRICK) /* }{ */ -/* the next trick should work on any machine using IEEE754 with - a 32-bit int type */ - -union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; - -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ - static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) -#else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ - -#define lua_number2int32(i,n,t) \ - { LUAI_EXTRAIEEE \ - volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ - (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } - -#define luai_hashnum(i,n) \ - { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ - (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ - -#define lua_number2int(i,n) lua_number2int32(i, n, int) -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) - -/* the trick can be expanded to lua_Integer when it is a 32-bit value */ -#if defined(LUA_IEEELL) -#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) -#endif - -#endif /* } */ - - -/* the following definitions always work, but may be slow */ - -#if !defined(lua_number2int) -#define lua_number2int(i,n) ((i)=(int)(n)) -#endif - -#if !defined(lua_number2integer) -#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) -#endif - -#if !defined(lua_number2unsigned) /* { */ -/* the following definition assures proper modulo behavior */ -#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) -#include <math.h> -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) -#define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) -#else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) -#endif -#endif /* } */ - - -#if !defined(lua_unsigned2number) -/* on several machines, coercion from unsigned to double is slow, - so it may be worth to avoid */ -#define lua_unsigned2number(u) \ - (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) -#endif - - - -#if defined(ltable_c) && !defined(luai_hashnum) - -#include <float.h> -#include <math.h> - -#define luai_hashnum(i,n) { int e; \ - n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ - lua_number2int(i, n); i += e; } - -#endif - /* diff --git a/src/lmathlib.c b/src/lmathlib.c index a49f1fd2..f26b05ca 100644 --- a/src/lmathlib.c +++ b/src/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.83 2013/03/07 18:21:32 roberto Exp $ +** $Id: lmathlib.c,v 1.90 2013/07/03 17:23:19 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -22,7 +22,6 @@ #define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) - static int math_abs (lua_State *L) { lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); return 1; @@ -89,20 +88,40 @@ static int math_floor (lua_State *L) { return 1; } +static int math_ifloor (lua_State *L) { + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (valid) + lua_pushinteger(L, n); + else { + luaL_checktype(L, 1, LUA_TNUMBER); /* error if not a number */ + lua_pushnil(L); /* number with invalid integer value */ + } + return 1; +} + static int math_fmod (lua_State *L) { lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } +/* +** next function does not use 'modf', avoiding problems with 'double*' +** (which is not compatible with 'float*') when lua_Number is not +** 'double'. +*/ static int math_modf (lua_State *L) { - lua_Number ip; - lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? -l_mathop(floor)(-n) : l_mathop(floor)(n); lua_pushnumber(L, ip); - lua_pushnumber(L, fp); + /* fractionary part (test handles inf/-inf) */ + lua_pushnumber(L, (n == ip) ? 0.0 : (n - ip)); return 2; } + static int math_sqrt (lua_State *L) { lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); return 1; @@ -199,26 +218,28 @@ static int math_random (lua_State *L) { /* the `%' avoids the (rare) case of r==1, and is needed also because on some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + lua_Integer low, up; switch (lua_gettop(L)) { /* check number of arguments */ case 0: { /* no arguments */ lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; + return 1; } case 1: { /* only upper limit */ - lua_Number u = luaL_checknumber(L, 1); - luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ + low = 1; + up = luaL_checkinteger(L, 1); break; } case 2: { /* lower and upper limits */ - lua_Number l = luaL_checknumber(L, 1); - lua_Number u = luaL_checknumber(L, 2); - luaL_argcheck(L, l <= u, 2, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); break; } default: return luaL_error(L, "wrong number of arguments"); } + /* random integer in the interval [low, up] */ + up++; /* change interval to [low, up) */ + luaL_argcheck(L, up - low > 0, 1, "interval is empty"); + lua_pushinteger(L, (lua_Integer)(r * (lua_Number)(up - low)) + low); return 1; } @@ -230,6 +251,13 @@ static int math_randomseed (lua_State *L) { } +static int math_isfloat (lua_State *L) { + luaL_checkany(L, 1); + lua_pushboolean(L, (lua_type(L, 1) == LUA_TNUMBER && !lua_isinteger(L, 1))); + return 1; +} + + static const luaL_Reg mathlib[] = { {"abs", math_abs}, {"acos", math_acos}, @@ -242,8 +270,10 @@ static const luaL_Reg mathlib[] = { {"deg", math_deg}, {"exp", math_exp}, {"floor", math_floor}, + {"ifloor", math_ifloor}, {"fmod", math_fmod}, {"frexp", math_frexp}, + {"isfloat", math_isfloat}, {"ldexp", math_ldexp}, #if defined(LUA_COMPAT_LOG10) {"log10", math_log10}, diff --git a/src/lobject.c b/src/lobject.c index c152785a..edb0efeb 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $ +** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -70,7 +70,21 @@ int luaO_ceillog2 (unsigned int x) { } -lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { +static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, + lua_Integer v2) { + switch (op) { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB:return intop(-, v1, v2); + case LUA_OPMUL:return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPPOW: return luaV_pow(v1, v2); + case LUA_OPUNM: return -v1; + default: lua_assert(0); return 0; + } +} + + +static lua_Number numarith (int op, lua_Number v1, lua_Number v2) { switch (op) { case LUA_OPADD: return luai_numadd(NULL, v1, v2); case LUA_OPSUB: return luai_numsub(NULL, v1, v2); @@ -84,17 +98,41 @@ lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { } +void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, + TValue *res) { + if (op == LUA_OPIDIV) { /* operates only on integers */ + lua_Integer i1; lua_Integer i2; + if (tointeger(p1, &i1) && tointeger(p2, &i2)) { + setivalue(res, luaV_div(L, i1, i2)); + return; + } + /* else go to the end */ + } + else { /* other operations */ + lua_Number n1; lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV && + (op != LUA_OPPOW || ivalue(p2) >= 0)) { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return; + } + else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { + setnvalue(res, numarith(op, n1, n2)); + return; + } + /* else go to the end */ + } + /* could not perform raw operation; try metmethod */ + lua_assert(L != NULL); /* cannot fail when folding (compile time) */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); +} + + int luaO_hexavalue (int c) { if (lisdigit(c)) return c - '0'; else return ltolower(c) - 'a' + 10; } -#if !defined(lua_strx2number) - -#include <math.h> - - static int isneg (const char **s) { if (**s == '-') { (*s)++; return 1; } else if (**s == '+') (*s)++; @@ -102,52 +140,81 @@ static int isneg (const char **s) { } -static lua_Number readhexa (const char **s, lua_Number r, int *count) { - for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ - r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); - (*count)++; - } - return r; -} +/* +** lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does both conversions. C89, however, has no function +** to convert floating hexadecimal strings to numbers. For these +** systems, you can leave 'lua_strx2number' undefined and Lua will +** provide its own implementation. +*/ +#if defined(LUA_USE_STRTODHEX) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +#if !defined(lua_strx2number) + +#include <math.h> +/* maximum number of significant digits to read (to avoid overflows + even with single floats) */ +#define MAXSIGDIG 30 + /* ** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */ static lua_Number lua_strx2number (const char *s, char **endptr) { - lua_Number r = 0.0; - int e = 0, i = 0; + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ int neg = 0; /* 1 if number is negative */ + int dot = 0; /* true after seen a dot */ *endptr = cast(char *, s); /* nothing is valid yet */ while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ neg = isneg(&s); /* check signal */ if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ return 0.0; /* invalid format (no '0x') */ - s += 2; /* skip '0x' */ - r = readhexa(&s, r, &i); /* read integer part */ - if (*s == '.') { - s++; /* skip dot */ - r = readhexa(&s, r, &e); /* read fractional part */ + for (s += 2; ; s++) { /* skip '0x' and read numeral */ + if (*s == '.') { + if (dot) break; /* second dot? stop loop */ + else dot = 1; + } + else if (lisxdigit(cast_uchar(*s))) { + if (sigdig == 0 && *s == '0') { /* non-significant zero? */ + nosigdig++; + if (dot) e--; /* zero after dot? correct exponent */ + } + else { + if (++sigdig <= MAXSIGDIG) { /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(cast_uchar(*s)); + if (dot) e--; /* decimal digit */ + } + else /* too many digits; ignore */ + if (!dot) e++; /* still count it for exponent */ + } + } + else break; /* neither a dot nor a digit */ } - if (i == 0 && e == 0) - return 0.0; /* invalid format (no digit) */ - e *= -4; /* each fractional digit divides value by 2^-4 */ + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ *endptr = cast(char *, s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; - int neg1; + int exp1 = 0; /* exponent value */ + int neg1; /* exponent signal */ s++; /* skip 'p' */ neg1 = isneg(&s); /* signal */ if (!lisdigit(cast_uchar(*s))) - goto ret; /* must have at least one digit */ + return 0.0; /* invalid; must have at least one digit */ while (lisdigit(cast_uchar(*s))) /* read exponent */ exp1 = exp1 * 10 + *(s++) - '0'; if (neg1) exp1 = -exp1; e += exp1; + *endptr = cast(char *, s); /* valid up to here */ } - *endptr = cast(char *, s); /* valid up to here */ - ret: if (neg) r = -r; return l_mathop(ldexp)(r, e); } @@ -169,6 +236,36 @@ int luaO_str2d (const char *s, size_t len, lua_Number *result) { } +int luaO_str2int (const char *s, size_t len, lua_Integer *result) { + const char *ends = s + len; + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { /* hexa? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) { + a = a * 16 + luaO_hexavalue(cast_uchar(*s)); + empty = 0; + } + } + else { /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) { + a = a * 10 + luaO_hexavalue(cast_uchar(*s)); + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || s != ends) return 0; /* something wrong in the numeral */ + else { + if (neg) *result = -cast(lua_Integer, a); + else *result = cast(lua_Integer, a); + return 1; + } +} + static void pushstr (lua_State *L, const char *str, size_t l) { setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); @@ -197,7 +294,11 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'd': { - setnvalue(L->top++, cast_num(va_arg(argp, int))); + setivalue(L->top++, cast_int(va_arg(argp, int))); + break; + } + case 'I': { + setivalue(L->top++, cast_integer(va_arg(argp, lua_Integer))); break; } case 'f': { diff --git a/src/lobject.h b/src/lobject.h index dd23b914..55b4e240 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.71 2012/09/11 18:21:44 roberto Exp $ +** $Id: lobject.h,v 2.78 2013/05/14 15:59:04 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -57,6 +57,11 @@ #define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ +/* Variant tags for numbers */ +#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ +#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ + + /* Bit mark for collectable types */ #define BIT_ISCOLLECTABLE (1 << 6) @@ -92,8 +97,6 @@ typedef struct GCheader { typedef union Value Value; -#define numfield lua_Number n; /* numbers */ - /* @@ -111,7 +114,6 @@ typedef struct lua_TValue TValue; #define val_(o) ((o)->value_) -#define num_(o) (val_(o).n) /* raw type tag of a TValue */ @@ -124,13 +126,15 @@ typedef struct lua_TValue TValue; #define ttype(o) (rttype(o) & 0x3F) /* type tag of a TValue with no variants (bits 0-3) */ -#define ttypenv(o) (novariant(rttype(o))) +#define ttnov(o) (novariant(rttype(o))) /* Macros to test type */ #define checktag(o,t) (rttype(o) == (t)) -#define checktype(o,t) (ttypenv(o) == (t)) -#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define checktype(o,t) (ttnov(o) == (t)) +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_TNUMFLT) +#define ttisinteger(o) checktag((o), LUA_TNUMINT) #define ttisnil(o) checktag((o), LUA_TNIL) #define ttisboolean(o) checktag((o), LUA_TBOOLEAN) #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) @@ -147,10 +151,10 @@ typedef struct lua_TValue TValue; #define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) #define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) -#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) /* Macros to access values */ -#define nvalue(o) check_exp(ttisnumber(o), num_(o)) +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) #define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) #define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) @@ -185,7 +189,10 @@ typedef struct lua_TValue TValue; #define settt_(o,t) ((o)->tt_=(t)) #define setnvalue(obj,x) \ - { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } + { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } + +#define setivalue(obj,x) \ + { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } #define setnilvalue(obj) settt_(obj, LUA_TNIL) @@ -267,115 +274,6 @@ typedef struct lua_TValue TValue; #define luai_checknum(L,o,c) { /* empty */ } -/* -** {====================================================== -** NaN Trick -** ======================================================= -*/ -#if defined(LUA_NANTRICK) - -/* -** numbers are represented in the 'd_' field. All other values have the -** value (NNMARK | tag) in 'tt__'. A number with such pattern would be -** a "signaled NaN", which is never generated by regular operations by -** the CPU (nor by 'strtod') -*/ - -/* allows for external implementation for part of the trick */ -#if !defined(NNMARK) /* { */ - - -#if !defined(LUA_IEEEENDIAN) -#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' -#endif - - -#define NNMARK 0x7FF7A500 -#define NNMASK 0x7FFFFF00 - -#undef TValuefields -#undef NILCONSTANT - -#if (LUA_IEEEENDIAN == 0) /* { */ - -/* little endian */ -#define TValuefields \ - union { struct { Value v__; int tt__; } i; double d__; } u -#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#else /* }{ */ - -/* big endian */ -#define TValuefields \ - union { struct { int tt__; Value v__; } i; double d__; } u -#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#endif /* } */ - -#endif /* } */ - - -/* correspondence with standard representation */ -#undef val_ -#define val_(o) v_(o) -#undef num_ -#define num_(o) d_(o) - - -#undef numfield -#define numfield /* no such field; numbers are the entire struct */ - -/* basic check to distinguish numbers from non-numbers */ -#undef ttisnumber -#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) - -#define tag2tt(t) (NNMARK | (t)) - -#undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) - -#undef settt_ -#define settt_(o,t) (tt_(o) = tag2tt(t)) - -#undef setnvalue -#define setnvalue(obj,x) \ - { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } - -#undef setobj -#define setobj(L,obj1,obj2) \ - { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ - o1_->u = o2_->u; \ - checkliveness(G(L),o1_); } - - -/* -** these redefinitions are not mandatory, but these forms are more efficient -*/ - -#undef checktag -#undef checktype -#define checktag(o,t) (tt_(o) == tag2tt(t)) -#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) - -#undef ttisequal -#define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) - - -#undef luai_checknum -#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } - -#endif -/* }====================================================== */ - /* @@ -390,7 +288,8 @@ union Value { void *p; /* light userdata */ int b; /* booleans */ lua_CFunction f; /* light C functions */ - numfield /* numbers */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ }; @@ -594,8 +493,10 @@ LUAI_DDEC const TValue luaO_nilobject_; LUAI_FUNC int luaO_int2fb (unsigned int x); LUAI_FUNC int luaO_fb2int (int x); LUAI_FUNC int luaO_ceillog2 (unsigned int x); -LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); +LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, + const TValue *p2, TValue *res); LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); +LUAI_FUNC int luaO_str2int (const char *s, size_t len, lua_Integer *result); LUAI_FUNC int luaO_hexavalue (int c); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); diff --git a/src/lopcodes.c b/src/lopcodes.c index ef736927..0bd7a3e8 100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $ +** $Id: lopcodes.c,v 1.50 2013/04/26 13:07:53 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -32,6 +32,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "SUB", "MUL", "DIV", + "IDIV", "MOD", "POW", "UNM", @@ -80,6 +81,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ diff --git a/src/lopcodes.h b/src/lopcodes.h index 07d2b3f3..6c27b27a 100644 --- a/src/lopcodes.h +++ b/src/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $ +** $Id: lopcodes.h,v 1.143 2013/04/26 13:07:53 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -188,6 +188,7 @@ OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ +OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */ OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ OP_UNM,/* A B R(A) := -R(B) */ diff --git a/src/loslib.c b/src/loslib.c index 5170fd0d..6d59bc39 100644 --- a/src/loslib.c +++ b/src/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.40 2012/10/19 15:54:02 roberto Exp $ +** $Id: loslib.c,v 1.41 2013/05/14 15:57:11 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -194,7 +194,7 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) { static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + time_t t = luaL_opt(L, (time_t)luaL_checkinteger, 2, time(NULL)); struct tm tmr, *stm; if (*s == '!') { /* UTC? */ stm = l_gmtime(&t, &tmr); @@ -258,14 +258,14 @@ static int os_time (lua_State *L) { if (t == (time_t)(-1)) lua_pushnil(L); else - lua_pushnumber(L, (lua_Number)t); + lua_pushinteger(L, t); return 1; } static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); + lua_pushnumber(L, difftime((time_t)(luaL_checkinteger(L, 1)), + (time_t)(luaL_optinteger(L, 2, 0)))); return 1; } diff --git a/src/lparser.c b/src/lparser.c index d8f5b4ff..e8a6b8ef 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.130 2013/02/06 13:37:39 roberto Exp $ +** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -935,14 +935,19 @@ static void suffixedexp (LexState *ls, expdesc *v) { static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | constructor | FUNCTION body | suffixedexp */ switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); + case TK_FLT: { + init_exp(v, VKFLT, 0); v->u.nval = ls->t.seminfo.r; break; } + case TK_INT: { + init_exp(v, VKINT, 0); + v->u.ival = ls->t.seminfo.i; + break; + } case TK_STRING: { codestring(ls, v, ls->t.seminfo.ts); break; @@ -1000,6 +1005,7 @@ static BinOpr getbinopr (int op) { case '-': return OPR_SUB; case '*': return OPR_MUL; case '/': return OPR_DIV; + case TK_IDIV: return OPR_IDIV; case '%': return OPR_MOD; case '^': return OPR_POW; case TK_CONCAT: return OPR_CONCAT; @@ -1020,7 +1026,8 @@ static const struct { lu_byte left; /* left priority for each binary operator */ lu_byte right; /* right priority */ } priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ + {6, 6}, {6, 6}, /* '+' '-' */ + {7, 7}, {7, 7}, {7, 7}, {7, 7}, /* '*' '/' '//' '%' */ {10, 9}, {5, 4}, /* ^, .. (right associative) */ {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ @@ -1321,7 +1328,7 @@ static void fornum (LexState *ls, TString *varname, int line) { if (testnext(ls, ',')) exp1(ls); /* optional step */ else { /* default step = 1 */ - luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); + luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); luaK_reserveregs(fs, 1); } forbody(ls, base, line, 1, 1); diff --git a/src/lparser.h b/src/lparser.h index 301167d4..147d3367 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $ +** $Id: lparser.h,v 1.71 2013/04/16 18:46:28 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -22,7 +22,8 @@ typedef enum { VTRUE, VFALSE, VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ + VKFLT, /* nval = numerical float value */ + VKINT, /* nval = numerical integer value */ VNONRELOC, /* info = result register */ VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in 'upvalues' */ @@ -46,7 +47,8 @@ typedef struct expdesc { lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ } ind; int info; /* for generic use */ - lua_Number nval; /* for VKNUM */ + lua_Number nval; /* for VKFLT */ + lua_Integer ival; /* for VKINT */ } u; int t; /* patch list of `exit when true' */ int f; /* patch list of `exit when false' */ diff --git a/src/lstring.c b/src/lstring.c index 8b5af0b2..d9781365 100644 --- a/src/lstring.c +++ b/src/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.26 2013/01/08 13:50:10 roberto Exp $ +** $Id: lstring.c,v 2.27 2013/06/19 14:27:00 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -157,7 +157,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { if (l <= LUAI_MAXSHORTLEN) /* short string? */ return internshrstr(L, str, l); else { - if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) luaM_toobig(L); return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); } @@ -174,7 +174,7 @@ TString *luaS_new (lua_State *L, const char *str) { Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) + if (s > MAX_SIZE - sizeof(Udata)) luaM_toobig(L); u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; u->uv.len = s; diff --git a/src/lstrlib.c b/src/lstrlib.c index fcc61c9a..28acab83 100644 --- a/src/lstrlib.c +++ b/src/lstrlib.c @@ -1,11 +1,12 @@ /* -** $Id: lstrlib.c,v 1.178 2012/08/14 18:12:34 roberto Exp $ +** $Id: lstrlib.c,v 1.182 2013/06/20 15:06:51 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ #include <ctype.h> +#include <limits.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> @@ -43,20 +44,20 @@ static int str_len (lua_State *L) { /* translate a relative string position: negative means back from end */ -static size_t posrelat (ptrdiff_t pos, size_t len) { - if (pos >= 0) return (size_t)pos; +static lua_Integer posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; else if (0u - (size_t)pos > len) return 0; - else return len - ((size_t)-pos) + 1; + else return (lua_Integer)len + pos + 1; } static int str_sub (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - size_t start = posrelat(luaL_checkinteger(L, 2), l); - size_t end = posrelat(luaL_optinteger(L, 3, -1), l); + lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); + lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; - if (end > l) end = l; + if (end > (lua_Integer)l) end = l; if (start <= end) lua_pushlstring(L, s + start - 1, end - start + 1); else lua_pushliteral(L, ""); @@ -102,13 +103,17 @@ static int str_upper (lua_State *L) { } -/* reasonable limit to avoid arithmetic overflow */ -#define MAXSIZE ((~(size_t)0) >> 1) +/* reasonable limit to avoid arithmetic overflow and strings too big */ +#if INT_MAX / 2 <= 0x10000000 +#define MAXSIZE ((size_t)(INT_MAX / 2)) +#else +#define MAXSIZE ((size_t)0x10000000) +#endif static int str_rep (lua_State *L) { size_t l, lsep; const char *s = luaL_checklstring(L, 1, &l); - int n = luaL_checkint(L, 2); + lua_Integer n = luaL_checkinteger(L, 2); const char *sep = luaL_optlstring(L, 3, "", &lsep); if (n <= 0) lua_pushliteral(L, ""); else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ @@ -133,14 +138,14 @@ static int str_rep (lua_State *L) { static int str_byte (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); + lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; if (posi < 1) posi = 1; - if (pose > l) pose = l; + if (pose > (lua_Integer)l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); - if (posi + n <= pose) /* (size_t -> int) overflow? */ + if (posi + n <= pose) /* arithmetic overflow? */ return luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i<n; i++) @@ -155,7 +160,7 @@ static int str_char (lua_State *L) { luaL_Buffer b; char *p = luaL_buffinitsize(L, &b, n); for (i=1; i<=n; i++) { - int c = luaL_checkint(L, i); + lua_Integer c = luaL_checkinteger(L, i); luaL_argcheck(L, uchar(c) == c, i, "value out of range"); p[i - 1] = uchar(c); } @@ -164,9 +169,9 @@ static int str_char (lua_State *L) { } -static int writer (lua_State *L, const void* b, size_t size, void* B) { +static int writer (lua_State *L, const void *b, size_t size, void *B) { (void)L; - luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + luaL_addlstring((luaL_Buffer *) B, (const char *)b, size); return 0; } @@ -578,9 +583,9 @@ static int str_find_aux (lua_State *L, int find) { size_t ls, lp; const char *s = luaL_checklstring(L, 1, &ls); const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); + lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); if (init < 1) init = 1; - else if (init > ls + 1) { /* start after string's end? */ + else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ lua_pushnil(L); /* cannot find anything */ return 1; } @@ -786,48 +791,17 @@ static int str_gsub (lua_State *L) { ** ======================================================= */ -/* -** LUA_INTFRMLEN is the length modifier for integer conversions in -** 'string.format'; LUA_INTFRM_T is the integer type corresponding to -** the previous length -*/ -#if !defined(LUA_INTFRMLEN) /* { */ -#if defined(LUA_USE_LONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif -#endif /* } */ - - -/* -** LUA_FLTFRMLEN is the length modifier for float conversions in -** 'string.format'; LUA_FLTFRM_T is the float type corresponding to -** the previous length -*/ -#if !defined(LUA_FLTFRMLEN) - -#define LUA_FLTFRMLEN "" -#define LUA_FLTFRM_T double - -#endif - - /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ #define MAX_ITEM 512 + /* valid flags in a format specification */ #define FLAGS "-+ #0" + /* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) +** maximum size of each format specification (such as "%-099.99d") +** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error) */ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) +#define MAX_FORMAT (sizeof(FLAGS) + 2 + 10) static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { @@ -914,24 +888,11 @@ static int str_format (lua_State *L) { nb = sprintf(buff, form, luaL_checkint(L, arg)); break; } - case 'd': case 'i': { - lua_Number n = luaL_checknumber(L, arg); - LUA_INTFRM_T ni = (LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); - break; - } + case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { - lua_Number n = luaL_checknumber(L, arg); - unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a non-negative number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = sprintf(buff, form, n); break; } case 'e': case 'E': case 'f': @@ -939,8 +900,8 @@ static int str_format (lua_State *L) { case 'a': case 'A': #endif case 'g': case 'G': { - addlenmod(form, LUA_FLTFRMLEN); - nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = sprintf(buff, form, luaL_checknumber(L, arg)); break; } case 'q': { diff --git a/src/ltable.c b/src/ltable.c index 420391fc..4b39a8de 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $ +** $Id: ltable.c,v 2.78 2013/06/20 15:02:49 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,6 +18,8 @@ ** Hence even when the load factor reaches 100%, performance remains good. */ +#include <float.h> +#include <math.h> #include <string.h> #define ltable_c @@ -52,6 +54,7 @@ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) #define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) /* @@ -64,6 +67,12 @@ #define hashpointer(t,p) hashmod(t, IntPoint(p)) +/* checks whether a float has a value representable as a lua_Integer + (and does the conversion if so) */ +#define numisinteger(x,i) \ + (((x) == l_floor(x)) && luaV_numtointeger(x, i)) + + #define dummynode (&dummynode_) #define isdummy(n) ((n) == dummynode) @@ -75,11 +84,12 @@ static const Node dummynode_ = { /* -** hash for lua_Numbers +** hash for floating-point numbers */ -static Node *hashnum (const Table *t, lua_Number n) { +static Node *hashfloat (const Table *t, lua_Number n) { int i; - luai_hashnum(i, n); + n = l_mathop(frexp)(n, &i) * cast_num(INT_MAX - DBL_MAX_EXP); + i += cast_int(n); if (i < 0) { if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ i = 0; /* handle INT_MIN */ @@ -96,8 +106,12 @@ static Node *hashnum (const Table *t, lua_Number n) { */ static Node *mainposition (const Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashfloat(t, fltvalue(key)); + case LUA_TSHRSTR: + return hashstr(t, rawtsvalue(key)); case LUA_TLNGSTR: { TString *s = rawtsvalue(key); if (s->tsv.extra == 0) { /* no hash? */ @@ -106,8 +120,6 @@ static Node *mainposition (const Table *t, const TValue *key) { } return hashstr(t, rawtsvalue(key)); } - case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: @@ -125,12 +137,10 @@ static Node *mainposition (const Table *t, const TValue *key) { ** the array part of the table, -1 otherwise. */ static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; + if (ttisinteger(key)) { + lua_Integer k = ivalue(key); + if (0 < k && k <= MAXASIZE) /* is `key' an appropriate array index? */ + return cast_int(k); } return -1; /* `key' did not match some condition */ } @@ -170,7 +180,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { int i = findindex(L, t, key); /* find original element */ for (i++; i < t->sizearray; i++) { /* try first array part */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); + setivalue(key, i + 1); setobj2s(L, key+1, &t->array[i]); return 1; } @@ -217,7 +227,7 @@ static int computesizes (int nums[], int *narray) { static int countint (const TValue *key, int *nums) { int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + if (k > 0) { /* is `key' an appropriate array index? */ nums[luaO_ceillog2(k)]++; /* count as such */ return 1; } @@ -404,9 +414,18 @@ static Node *getfreepos (Table *t) { */ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { Node *mp; + TValue aux; if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); + else if (ttisfloat(key)) { + lua_Number n = fltvalue(key); + lua_Integer k; + if (luai_numisnan(L, n)) + luaG_runerror(L, "table index is NaN"); + if (numisinteger(n, &k)) { /* index is int? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + } mp = mainposition(t, key); if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; @@ -443,15 +462,14 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { /* ** search function for integers */ -const TValue *luaH_getint (Table *t, int key) { +const TValue *luaH_getint (Table *t, lua_Integer key) { /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; + if (cast_unsigned(key - 1) < cast_unsigned(t->sizearray)) + return &t->array[key - 1]; else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); + Node *n = hashint(t, key); do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -481,12 +499,11 @@ const TValue *luaH_getstr (Table *t, TString *key) { const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) /* index is int? */ + case LUA_TNUMFLT: { + lua_Integer k; + if (numisinteger(fltvalue(key), &k)) /* index is int? */ return luaH_getint(t, k); /* use specialized version */ /* else go through */ } @@ -515,14 +532,14 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { } -void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { const TValue *p = luaH_getint(t, key); TValue *cell; if (p != luaO_nilobject) cell = cast(TValue *, p); else { TValue k; - setnvalue(&k, cast_num(key)); + setivalue(&k, key); cell = luaH_newkey(L, t, &k); } setobj2t(L, cell, value); @@ -535,13 +552,13 @@ static int unbound_search (Table *t, unsigned int j) { /* find `i' and `j' such that i is present and j is not */ while (!ttisnil(luaH_getint(t, j))) { i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + if (j > cast(unsigned int, MAX_INT)/2) { /* overflow? */ /* table was built with bad purposes: resort to linear search */ i = 1; while (!ttisnil(luaH_getint(t, i))) i++; return i - 1; } + j *= 2; } /* now do a binary search between them */ while (j - i > 1) { diff --git a/src/ltable.h b/src/ltable.h index 2f6f5c2d..5a65b52e 100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $ +** $Id: ltable.h,v 2.17 2013/04/26 15:39:25 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,8 +18,9 @@ #define invalidateTMcache(t) ((t)->flags = 0) -LUAI_FUNC const TValue *luaH_getint (Table *t, int key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, + TValue *value); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.14 2011/06/02 19:31:40 roberto Exp $ +** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -12,11 +12,14 @@ #include "lua.h" +#include "ldebug.h" +#include "ldo.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" +#include "lvm.h" static const char udatatypename[] = "userdata"; @@ -33,7 +36,7 @@ void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", + "__add", "__sub", "__mul", "__div", "__idiv", "__mod", "__pow", "__unm", "__lt", "__le", "__concat", "__call" }; @@ -62,7 +65,7 @@ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { Table *mt; - switch (ttypenv(o)) { + switch (ttnov(o)) { case LUA_TTABLE: mt = hvalue(o)->metatable; break; @@ -70,8 +73,71 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { mt = uvalue(o)->metatable; break; default: - mt = G(L)->mt[ttypenv(o)]; + mt = G(L)->mt[ttnov(o)]; } return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); } + +void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + setobj2s(L, L->top++, f); /* push function */ + setobj2s(L, L->top++, p1); /* 1st argument */ + setobj2s(L, L->top++, p2); /* 2nd argument */ + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } +} + + +int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + luaT_callTM(L, tm, p1, p2, res, 1); + return 1; +} + + +void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + if (!luaT_callbinTM(L, p1, p2, res, event)) { + if (event == TM_CONCAT) + luaG_concaterror(L, p1, p2); + else if (event == TM_IDIV && ttisnumber(p1) && ttisnumber(p2)) + luaG_tointerror(L, p1, p2); + else + luaG_aritherror(L, p1, p2); + } +} + + +const TValue *luaT_getequalTM (lua_State *L, Table *mt1, Table *mt2) { + const TValue *tm1 = fasttm(L, mt1, TM_EQ); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, TM_EQ); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (!luaT_callbinTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); +} + @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $ +** $Id: ltm.h,v 2.16 2013/04/29 16:56:50 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -26,6 +26,7 @@ typedef enum { TM_SUB, TM_MUL, TM_DIV, + TM_IDIV, TM_MOD, TM_POW, TM_UNM, @@ -44,7 +45,7 @@ typedef enum { #define fasttm(l,et,e) gfasttm(G(l), et, e) #define ttypename(x) luaT_typenames_[(x) + 1] -#define objtypename(x) ttypename(ttypenv(x)) +#define objtypename(x) ttypename(ttnov(x)) LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; @@ -54,4 +55,16 @@ LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event); LUAI_FUNC void luaT_init (lua_State *L); +LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres); +LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC const TValue *luaT_getequalTM (lua_State *L, Table *mt1, Table *mt2); +LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, + const TValue *p2, TMS event); + + + #endif @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.285 2013/03/15 13:04:22 roberto Exp $ +** $Id: lua.h,v 1.292 2013/07/05 14:29:51 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -17,9 +17,9 @@ #define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "2" -#define LUA_VERSION_NUM 502 -#define LUA_VERSION_RELEASE "2" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "0 (work1)" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE @@ -61,7 +61,7 @@ typedef int (*lua_CFunction) (lua_State *L); */ typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); /* @@ -161,6 +161,7 @@ LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); LUA_API int (lua_isnumber) (lua_State *L, int idx); LUA_API int (lua_isstring) (lua_State *L, int idx); LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); LUA_API int (lua_isuserdata) (lua_State *L, int idx); LUA_API int (lua_type) (lua_State *L, int idx); LUA_API const char *(lua_typename) (lua_State *L, int tp); @@ -185,9 +186,10 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); #define LUA_OPSUB 1 #define LUA_OPMUL 2 #define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 +#define LUA_OPIDIV 4 +#define LUA_OPMOD 5 +#define LUA_OPPOW 6 +#define LUA_OPUNM 7 LUA_API void (lua_arith) (lua_State *L, int op); @@ -224,7 +226,7 @@ LUA_API void (lua_getglobal) (lua_State *L, const char *var); LUA_API void (lua_gettable) (lua_State *L, int idx); LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); @@ -239,7 +241,7 @@ LUA_API void (lua_setglobal) (lua_State *L, const char *var); LUA_API void (lua_settable) (lua_State *L, int idx); LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); LUA_API int (lua_setmetatable) (lua_State *L, int objindex); LUA_API void (lua_setuservalue) (lua_State *L, int idx); @@ -305,6 +307,8 @@ LUA_API int (lua_next) (lua_State *L, int idx); LUA_API void (lua_concat) (lua_State *L, int n); LUA_API void (lua_len) (lua_State *L, int idx); +LUA_API int (lua_strtonum) (lua_State *L, const char *s, size_t len); + LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); @@ -202,8 +202,10 @@ int main(int argc, char* argv[]) return EXIT_SUCCESS; } +#define nvalue(x) 0 +#define ttypenv(x) ttnov(x) /* -** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $ +** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ @@ -251,7 +253,7 @@ static void PrintString(const TString* ts) static void PrintConstant(const Proto* f, int i) { const TValue* o=&f->k[i]; - switch (ttype(o)) + switch (ttypenv(o)) { case LUA_TNIL: printf("nil"); diff --git a/src/luaconf.h b/src/luaconf.h index df802c95..71d02561 100644 --- a/src/luaconf.h +++ b/src/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.176 2013/03/16 21:10:18 roberto Exp $ +** $Id: luaconf.h,v 1.185 2013/06/25 19:04:40 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -376,64 +376,112 @@ /* ** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. +** The following definitions set the numeric types for Lua. +** Lua should work fine with 32-bit or 64-bit integers mixed with +** 32-bit or 64-bit floats. The usual configurations are 64-bit +** integers and floats (the default) and 32-bit integers and floats. ** =================================================================== */ -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double +/* +@@ LUA_INTSIZE defines size for Lua integer: 1=int, 2=long, 3=long long +@@ LUA_FLOATSIZE defines size for Lua float: 1=float, 2=double, 3=long double +** Default is long long + double +*/ +#define LUA_INTSIZE 3 +#define LUA_FLOATSIZE 2 + /* +@@ LUA_NUMBER is the floating-point type used by Lua. +** @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. +@* over a floating number. +** +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_SCAN is the format for reading floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a floats to a string. +** +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations +** +@@ lua_str2number converts a decimal numeric string to a number. */ + +#if LUA_FLOATSIZE == 1 /* { single float */ + +#define LUA_NUMBER float + #define LUAI_UACNUMBER double +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_SCAN "%f" +#define LUA_NUMBER_FMT "%.7g" -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -*/ +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOATSIZE == 3 /* }{ long double */ + +#define LUA_NUMBER long double + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_SCAN "%Lf" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#else /* }{ default: double */ + +#define LUA_NUMBER double + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" #define LUA_NUMBER_SCAN "%lf" #define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define l_mathop(op) op -/* -@@ l_mathop allows the addition of an 'l' or 'f' to all math operations -*/ -#define l_mathop(x) (x) +#define lua_str2number(s,p) strtod((s), (p)) +#endif /* } */ -/* -@@ lua_str2number converts a decimal numeric string to a number. -@@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does both conversions. C89, however, has no function -** to convert floating hexadecimal strings to numbers. For these -** systems, you can leave 'lua_strx2number' undefined and Lua will -** provide its own implementation. -*/ -#define lua_str2number(s,p) strtod((s), (p)) -#if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) +#if defined(LUA_ANSI) +/* C89 does not support 'opf' variants for math functions */ +#undef l_mathop +#define l_mathop(op) (lua_Number)op +#endif + + +#if defined(LUA_ANSI) || defined(_WIN32) +/* C89 and Windows do not support 'strtof'... */ +#undef lua_str2number +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) #endif +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) + + /* @@ The luai_num* macros define the primitive operations over numbers. +@* They should work for any size of floating numbers. */ /* the following operations need the math library */ #if defined(lobject_c) || defined(lvm_c) #include <math.h> -#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) +#define luai_nummod(L,a,b) ((a) - l_floor((a)/(b))*(b)) #define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) #endif @@ -453,85 +501,39 @@ /* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - -/* -@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. -** It must have at least 32 bits. -*/ -#define LUA_UNSIGNED unsigned LUA_INT32 - - - -/* -** Some tricks with doubles -*/ - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ -/* -** The next definitions activate some tricks to speed up the -** conversion from doubles to integer types, mainly to LUA_UNSIGNED. +@@ LUA_INTEGER is the integer type used by Lua. ** -@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a -** DirectX idiosyncrasy. +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. ** -@@ LUA_IEEE754TRICK uses a trick that should work on any machine -** using IEEE754 with a 32-bit integer type. -** -@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be -** defined when LUA_INTEGER is a 32-bit integer. -** -@@ LUA_IEEEENDIAN is the endianness of doubles in your machine -** (0 for little endian, 1 for big endian); if not defined, Lua will -** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). -** -@@ LUA_NANTRICK controls the use of a trick to pack all types into -** a single double value, using NaN values to represent non-number -** values. The trick only works on 32-bit machines (ints and pointers -** are 32-bit values) with numbers represented as IEEE 754-2008 doubles -** with conventional endianess (12345678 or 87654321), in CPUs that do -** not produce signaling NaN values (all NaNs are quiet). +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_SCAN is the format for reading integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ lua_integer2str converts an integer to a string. */ -/* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ - -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK +#if LUA_INTSIZE == 1 /* { int */ +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" -/* pentium 32 bits? */ -#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ +#elif LUA_INTSIZE == 2 /* }{ long */ -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" -/* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ +#else /* }{ default: long long */ -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ +#endif /* } */ -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 -#else /* }{ */ +#define LUA_INTEGER_SCAN "%" LUA_INTEGER_FRMLEN "d" +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" +#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n)) -/* assume IEEE754 and a 32-bit integer type */ -#define LUA_IEEE754TRICK - -#endif /* } */ - -#endif /* } */ +#define LUA_UNSIGNED unsigned LUA_INTEGER /* }================================================================== */ @@ -547,5 +549,7 @@ + + #endif diff --git a/src/lundump.c b/src/lundump.c index 54de011a..38b04e42 100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $ +** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -69,6 +69,13 @@ static lua_Number LoadNumber(LoadState* S) return x; } +static lua_Integer LoadInteger(LoadState* S) +{ + lua_Integer x; + LoadVar(S,x); + return x; +} + static TString* LoadString(LoadState* S) { size_t size; @@ -112,10 +119,13 @@ static void LoadConstants(LoadState* S, Proto* f) case LUA_TBOOLEAN: setbvalue(o,LoadChar(S)); break; - case LUA_TNUMBER: + case LUA_TNUMFLT: setnvalue(o,LoadNumber(S)); break; - case LUA_TSTRING: + case LUA_TNUMINT: + setivalue(o,LoadInteger(S)); + break; + case LUA_TSHRSTR: case LUA_TLNGSTR: setsvalue2n(S->L,o,LoadString(S)); break; default: lua_assert(0); @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.155 2013/03/16 21:10:18 roberto Exp $ +** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -32,15 +32,18 @@ #define MAXTAGLOOP 100 -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { - setnvalue(n, num); - return n; +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +int luaV_tonumber_ (const TValue *obj, lua_Number *n) { + lua_assert(!ttisfloat(obj)); + if (ttisinteger(obj)) { + *n = cast_num(ivalue(obj)); + return 1; } else - return NULL; + return (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, n)); } @@ -48,62 +51,51 @@ int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - int l = lua_number2str(s, n); - setsvalue2s(L, obj, luaS_newlstr(L, s, l)); + char buff[MAXNUMBER2STR]; + size_t len; + if (ttisinteger(obj)) + len = lua_integer2str(buff, ivalue(obj)); + else { + len = lua_number2str(buff, fltvalue(obj)); + if (strspn(buff, "-0123456789") == len) { /* look like an integer? */ + buff[len++] = '.'; /* add a '.0' */ + buff[len++] = '0'; + buff[len] = '\0'; + } + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); return 1; } } -static void traceexec (lua_State *L) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); - if (counthook) - resethookcount(L); /* reset count */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return; /* do not call hook again (VM yielded, so it did not move) */ - } - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(ci)->p; - int npc = pcRel(ci->u.l.savedpc, p); - int newline = getfuncline(p, npc); - if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ - luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ - } - L->oldpc = ci->u.l.savedpc; - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - ci->func = L->top - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); +/* +** Check whether a float number is within the range of a lua_Integer. +** (The comparisons are tricky because of rounding, which can or +** not occur depending on the relative sizes of floats and integers.) +** This function is called only when 'n' has an integer value. +*/ +int luaV_numtointeger (lua_Number n, lua_Integer *p) { + if (cast_num(MIN_INTEGER) <= n && n < (MAX_INTEGER + cast_num(1))) { + *p = cast_integer(n); + lua_assert(cast_num(*p) == n); + return 1; } + return 0; /* number is outside integer limits */ } -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres) { - ptrdiff_t result = savestack(L, p3); - setobj2s(L, L->top++, f); /* push function */ - setobj2s(L, L->top++, p1); /* 1st argument */ - setobj2s(L, L->top++, p2); /* 2nd argument */ - if (!hasres) /* no result? 'p3' is third argument */ - setobj2s(L, L->top++, p3); /* 3rd argument */ - /* metamethod may yield only when called from Lua code */ - luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); - if (hasres) { /* if has result, move it to its place */ - p3 = restorestack(L, result); - setobjs2s(L, p3, --L->top); +/* +** try to convert a non-integer value to an integer +*/ +int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { + lua_Number n; + lua_assert(!ttisinteger(obj)); + if (tonumber(obj, &n)) { + n = l_floor(n); + return luaV_numtointeger(n, p); } + else return 0; } @@ -124,7 +116,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 1); + luaT_callTM(L, tm, t, key, val, 1); return; } t = tm; /* else repeat with 'tm' */ @@ -163,7 +155,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { luaG_typeerror(L, t, "index"); /* there is a metamethod */ if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 0); + luaT_callTM(L, tm, t, key, val, 0); return; } t = tm; /* else repeat with 'tm' */ @@ -172,40 +164,6 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { } -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTM(L, tm, p1, p2, res, 1); - return 1; -} - - -static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; -} - - -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - if (!call_binTM(L, p1, p2, L->top, event)) - return -1; /* no metamethod */ - else - return !l_isfalse(L->top); -} - - static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); size_t ll = ls->tsv.len; @@ -230,11 +188,14 @@ static int l_strcmp (const TString *ls, const TString *rs) { int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numlt(L, nvalue(l), nvalue(r)); + lua_Number nl, nr; + if (ttisinteger(l) && ttisinteger(r)) + return (ivalue(l) < ivalue(r)); + else if (tonumber(l, &nl) && tonumber(r, &nr)) + return luai_numlt(L, nl, nr); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) + else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) luaG_ordererror(L, l, r); return res; } @@ -242,13 +203,16 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numle(L, nvalue(l), nvalue(r)); + lua_Number nl, nr; + if (ttisinteger(l) && ttisinteger(r)) + return (ivalue(l) <= ivalue(r)); + else if (tonumber(l, &nl) && tonumber(r, &nr)) + return luai_numle(L, nl, nr); else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ + else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ + else if ((res = luaT_callorderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ luaG_ordererror(L, l, r); return !res; } @@ -257,12 +221,23 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { /* ** equality of Lua values. L == NULL means raw equality (no metamethods) */ -int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { +int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; - lua_assert(ttisequal(t1, t2)); + if (ttype(t1) != ttype(t2)) { + if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else { /* two numbers with different variants */ + lua_Number n1, n2; + lua_assert(ttisnumber(t1) && ttisnumber(t2)); + (void)tonumber(t1, &n1); (void)tonumber(t2, &n2); + return luai_numeq(n1, n2); + } + } + /* values have same type and same variant */ switch (ttype(t1)) { case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TLCF: return fvalue(t1) == fvalue(t2); @@ -271,21 +246,20 @@ int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1; else if (L == NULL) return 0; - tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); + tm = luaT_getequalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable); break; /* will try TM */ } case LUA_TTABLE: { if (hvalue(t1) == hvalue(t2)) return 1; else if (L == NULL) return 0; - tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + tm = luaT_getequalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable); break; /* will try TM */ } default: - lua_assert(iscollectable(t1)); return gcvalue(t1) == gcvalue(t2); } if (tm == NULL) return 0; /* no TM? */ - callTM(L, tm, t1, t2, L->top, 1); /* call TM */ + luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ return !l_isfalse(L->top); } @@ -295,10 +269,8 @@ void luaV_concat (lua_State *L, int total) { do { StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) + luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ (void)tostring(L, top - 2); /* result is first operand */ else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { @@ -312,7 +284,7 @@ void luaV_concat (lua_State *L, int total) { /* collect total length */ for (i = 1; i < total && tostring(L, top-i-1); i++) { size_t l = tsvalue(top-i-1)->len; - if (l >= (MAX_SIZET/sizeof(char)) - tl) + if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; } @@ -334,16 +306,16 @@ void luaV_concat (lua_State *L, int total) { void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { const TValue *tm; - switch (ttypenv(rb)) { + switch (ttnov(rb)) { case LUA_TTABLE: { Table *h = hvalue(rb); tm = fasttm(L, h->metatable, TM_LEN); if (tm) break; /* metamethod? break switch to call it */ - setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ + setivalue(ra, luaH_getn(h)); /* else primitive len */ return; } case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); + setivalue(ra, tsvalue(rb)->len); return; } default: { /* try metamethod */ @@ -353,21 +325,54 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { break; } } - callTM(L, tm, rb, rb, ra, 1); + luaT_callTM(L, tm, rb, rb, ra, 1); +} + + +lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { + if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ + if (y == 0) + luaG_runerror(L, "attempt to divide by zero"); + else /* -1 */ + return -x; /* avoid overflow with 0x80000... */ + } + else { + lua_Integer d = x / y; /* perform division */ + if ((x ^ y) >= 0 || x % y == 0) /* same signal or no rest? */ + return d; + else + return d - 1; /* correct 'div' for negative case */ + } +} + + +lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { + if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ + if (y == 0) + luaG_runerror(L, "attempt to perform 'n%%0'"); + else /* -1 */ + return 0; /* avoid overflow with 0x80000... */ + } + else { + lua_Integer r = x % y; + if (r == 0 || (x ^ y) >= 0) + return r; + else + return r + y; /* correct 'mod' for negative case */ + } } -void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); - setnvalue(ra, res); +lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { + lua_Integer r = 1; + lua_assert(y >= 0); + if (y == 0) return r; + for (; y > 1; y >>= 1) { + if (y & 1) r = intop(*, r, x); + x = intop(*, x, x); } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); + r = intop(*, r, x); + return r; } @@ -426,7 +431,7 @@ void luaV_finishOp (lua_State *L) { Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { setobjs2s(L, base + GETARG_A(inst), --L->top); @@ -446,7 +451,7 @@ void luaV_finishOp (lua_State *L) { break; } case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'call_binTM' was called */ + StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ int b = GETARG_B(inst); /* first element to concatenate */ int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ setobj2s(L, top - 2, top); /* put TM result in proper position */ @@ -517,16 +522,6 @@ void luaV_finishOp (lua_State *L) { luai_threadyield(L); ) -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(L, nb, nc)); \ - } \ - else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } - - #define vmdispatch(o) switch(o) #define vmcase(l,b) case l: {b} break; #define vmcasenb(l,b) case l: {b} /* nb = no break */ @@ -547,7 +542,7 @@ void luaV_execute (lua_State *L) { StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - Protect(traceexec(L)); + Protect(luaG_traceexec(L)); } /* WARNING: several calls may realloc the stack and invalidate `ra' */ ra = RA(i); @@ -614,32 +609,103 @@ void luaV_execute (lua_State *L) { setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); ) - vmcase(OP_ADD, - arith_op(luai_numadd, TM_ADD); + vmcase(OP_ADD, + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(+, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_numadd(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } ) vmcase(OP_SUB, - arith_op(luai_numsub, TM_SUB); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(-, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_numsub(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } ) vmcase(OP_MUL, - arith_op(luai_nummul, TM_MUL); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(*, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_nummul(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } ) - vmcase(OP_DIV, - arith_op(luai_numdiv, TM_DIV); + vmcase(OP_DIV, /* float division (always with floats) */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_numdiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } + ) + vmcase(OP_IDIV, /* integer division */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, luaV_div(L, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } ) vmcase(OP_MOD, - arith_op(luai_nummod, TM_MOD); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_mod(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_nummod(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } ) vmcase(OP_POW, - arith_op(luai_numpow, TM_POW); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + lua_Integer ic; + if (ttisinteger(rb) && ttisinteger(rc) && + (ic = ivalue(rc)) >= 0) { + lua_Integer ib = ivalue(rb); + setivalue(ra, luaV_pow(ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setnvalue(ra, luai_numpow(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } ) vmcase(OP_UNM, TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); + lua_Number nb; + if (ttisinteger(rb)) { + lua_Integer ib = ivalue(rb); + setivalue(ra, -ib); + } + else if (tonumber(rb, &nb)) { setnvalue(ra, luai_numunm(L, nb)); } else { - Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); + Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); } ) vmcase(OP_NOT, @@ -669,7 +735,7 @@ void luaV_execute (lua_State *L) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( - if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) + if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i)) ci->u.l.savedpc++; else donextjump(ci); @@ -765,27 +831,47 @@ void luaV_execute (lua_State *L) { } ) vmcase(OP_FORLOOP, - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) - : luai_numle(L, limit, idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ + if (ttisinteger(ra)) { /* integer count? */ + lua_Integer step = ivalue(ra + 2); + lua_Integer idx = ivalue(ra) + step; /* increment index */ + lua_Integer limit = ivalue(ra + 1); + if ((0 < step) ? (idx <= limit) : (limit <= idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + setivalue(ra, idx); /* update internal index... */ + setivalue(ra + 3, idx); /* ...and external index */ + } + } + else { /* floating count */ + lua_Number step = fltvalue(ra + 2); + lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ + lua_Number limit = fltvalue(ra + 1); + if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) + : luai_numle(L, limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra + 3, idx); /* ...and external index */ + } } ) vmcase(OP_FORPREP, - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); + TValue *init = ra; + TValue *plimit = ra + 1; + TValue *pstep = ra + 2; + if (ttisinteger(ra) && ttisinteger(ra + 1) && ttisinteger(ra + 2)) { + setivalue(ra, ivalue(ra) - ivalue(pstep)); + } + else { /* try with floats */ + lua_Number ninit; lua_Number nlimit; lua_Number nstep; + if (!tonumber(plimit, &nlimit)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + setnvalue(plimit, nlimit); + if (!tonumber(pstep, &nstep)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(pstep, nstep); + if (!tonumber(init, &ninit)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + setnvalue(ra, luai_numsub(L, ninit, nstep)); + } ci->u.l.savedpc += GETARG_sBx(i); ) vmcasenb(OP_TFORCALL, @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.18 2013/01/08 14:06:55 roberto Exp $ +** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -15,20 +15,24 @@ #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) -#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) +#define tonumber(o,n) \ + (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) -#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) +#define tointeger(o,i) \ + (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger_(o,i)) -#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) +#define intop(op,v1,v2) \ + cast_integer(cast_unsigned(v1) op cast_unsigned(v2)) - -/* not to called directly */ -LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); +#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) +LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); +LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p); +LUAI_FUNC int luaV_numtointeger (lua_Number n, lua_Integer *p); LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); @@ -37,8 +41,9 @@ LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op); +LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); #endif @@ -1,5 +1,5 @@ /* -** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $ +** $Id: lzio.h,v 1.27 2013/06/07 14:51:10 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -45,7 +45,7 @@ typedef struct Mbuffer { LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ @@ -55,7 +55,7 @@ struct Zio { size_t n; /* bytes still unread */ const char *p; /* current position in buffer */ lua_Reader reader; /* reader function */ - void* data; /* additional data */ + void *data; /* additional data */ lua_State *L; /* Lua state (for reader) */ }; |