diff --git a/lapi.c b/lapi.c index 680630dd..eb901cb3 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.230 2014/07/21 16:02:57 roberto Exp roberto $ +** $Id: lapi.c,v 2.231 2014/07/22 18:07:47 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -279,8 +279,8 @@ LUA_API int lua_isnumber (lua_State *L, int idx) { LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); + const TValue *o = index2addr(L, idx); + return (ttisstring(o) || cvt2str(o)); } @@ -371,14 +371,14 @@ LUA_API int lua_toboolean (lua_State *L, int idx) { LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { StkId o = index2addr(L, idx); if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (!cvt2str(o)) { /* not convertible? */ if (len != NULL) *len = 0; - lua_unlock(L); return NULL; } + lua_lock(L); /* `luaO_tostring' may create a new string */ luaC_checkGC(L); o = index2addr(L, idx); /* previous call may reallocate the stack */ + luaO_tostring(L, o); lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; diff --git a/ldebug.c b/ldebug.c index f7b2866e..e31c0607 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.98 2014/07/15 21:26:50 roberto Exp roberto $ +** $Id: ldebug.c,v 2.99 2014/07/17 12:30:53 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -526,8 +526,7 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { 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(p1)); + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; luaG_typeerror(L, p1, "concatenate"); } diff --git a/lobject.c b/lobject.c index cd049075..d079e937 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.86 2014/05/12 21:44:17 roberto Exp roberto $ +** $Id: lobject.c,v 2.87 2014/06/30 19:48:08 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -327,6 +327,32 @@ int luaO_utf8esc (char *buff, unsigned int x) { } +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +/* +** Convert a number object to a string +*/ +void luaO_tostring (lua_State *L, StkId obj) { + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, ivalue(obj)); + else { + len = lua_number2str(buff, fltvalue(obj)); +#if !defined(LUA_COMPAT_FLOATSTRING) + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = '.'; + buff[len++] = '0'; /* adds '.0' to result */ + } +#endif + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); +} + + static void pushstr (lua_State *L, const char *str, size_t l) { setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); } @@ -349,24 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'c': { - char buff; - buff = cast(char, va_arg(argp, int)); + char buff = cast(char, va_arg(argp, int)); pushstr(L, &buff, 1); break; } case 'd': { - setivalue(L->top++, cast_int(va_arg(argp, int))); - luaV_tostring(L, L->top - 1); + setivalue(L->top++, va_arg(argp, int)); + luaO_tostring(L, L->top - 1); break; } case 'I': { setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt))); - luaV_tostring(L, L->top - 1); + luaO_tostring(L, L->top - 1); break; } case 'f': { setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); - luaV_tostring(L, L->top - 1); + luaO_tostring(L, L->top - 1); break; } case 'p': { diff --git a/lobject.h b/lobject.h index 93356dd2..8097853c 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.99 2014/07/18 14:46:47 roberto Exp roberto $ +** $Id: lobject.h,v 2.100 2014/07/29 16:22:24 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -527,6 +527,7 @@ LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res); LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); diff --git a/lvm.c b/lvm.c index ec5bf62b..89ef8997 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.219 2014/07/18 13:36:14 roberto Exp roberto $ +** $Id: lvm.c,v 2.220 2014/07/21 16:02:10 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -33,10 +33,6 @@ #define MAXTAGLOOP 2000 -/* maximum length of the conversion of a number to a string */ -#define MAXNUMBER2STR 50 - - /* ** Similar to 'tonumber', but does not attempt to convert strings and ** ensure correct precision (no extra bits). Used in comparisons. @@ -119,32 +115,6 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { } -/* -** Convert a number object to a string -*/ -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char buff[MAXNUMBER2STR]; - size_t len; - if (ttisinteger(obj)) - len = lua_integer2str(buff, ivalue(obj)); - else { - len = lua_number2str(buff, fltvalue(obj)); -#if !defined(LUA_COMPAT_FLOATSTRING) - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = '.'; - buff[len++] = '0'; /* adds '.0' to result */ - } -#endif - } - setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); - return 1; - } -} - - /* ** Try to convert a 'for' limit to an integer, preserving the ** semantics of the loop. @@ -374,7 +344,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { /* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ -#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) +#define tostring(L,o) \ + (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) /* ** Main operation for concatenation: concat 'total' values in the stack, @@ -385,7 +356,7 @@ 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 (!(ttisstring(top-2) || cvt2str(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? */ cast_void(tostring(L, top - 2)); /* result is first operand */ diff --git a/lvm.h b/lvm.h index 6dff8b1e..0a4984cb 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.30 2014/05/12 21:22:05 roberto Exp roberto $ +** $Id: lvm.h,v 2.31 2014/05/26 17:10:22 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -24,12 +24,18 @@ #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) +#if !defined(LUA_NOCVTN2S) +#define cvt2str(o) ttisnumber(o) +#else +#define cvt2str(o) 0 /* no convertion from numbers to strings */ +#endif + + 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 int luaV_tonumber_ (const TValue *obj, lua_Number *n); LUAI_FUNC int luaV_tointeger_ (const TValue *obj, 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); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,