commit 34ac039fb84e3c12fb8c96c9c99c34224c09872b
parent 1aa526263405fb4906eafab3011b13de4e5daf73
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 30 Jul 2014 10:59:49 -0300
new macro 'cvt2str' to better control whether numbers are convertible
to strings
Diffstat:
6 files changed, 54 insertions(+), 52 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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.
@@ -120,32 +116,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.
** (The following explanation assumes a non-negative step; it is valid
@@ -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
@@ -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,