Bläddra i källkod

new macro 'cvt2str' to better control whether numbers are convertible
to strings

Roberto Ierusalimschy 11 år sedan
förälder
incheckning
34ac039fb8
6 ändrade filer med 54 tillägg och 52 borttagningar
  1. 6 6
      lapi.c
  2. 2 3
      ldebug.c
  3. 32 7
      lobject.c
  4. 2 1
      lobject.h
  5. 4 33
      lvm.c
  6. 8 2
      lvm.h

+ 6 - 6
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
 ** Lua API
 ** See Copyright Notice in lua.h
 ** 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) {
 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) {
 LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
   StkId o = index2addr(L, idx);
   StkId o = index2addr(L, idx);
   if (!ttisstring(o)) {
   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;
       if (len != NULL) *len = 0;
-      lua_unlock(L);
       return NULL;
       return NULL;
     }
     }
+    lua_lock(L);  /* `luaO_tostring' may create a new string */
     luaC_checkGC(L);
     luaC_checkGC(L);
     o = index2addr(L, idx);  /* previous call may reallocate the stack */
     o = index2addr(L, idx);  /* previous call may reallocate the stack */
+    luaO_tostring(L, o);
     lua_unlock(L);
     lua_unlock(L);
   }
   }
   if (len != NULL) *len = tsvalue(o)->len;
   if (len != NULL) *len = tsvalue(o)->len;

+ 2 - 3
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
 ** Debug Interface
 ** See Copyright Notice in lua.h
 ** 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) {
 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");
   luaG_typeerror(L, p1, "concatenate");
 }
 }
 
 

+ 32 - 7
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
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 ** 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) {
 static void pushstr (lua_State *L, const char *str, size_t l) {
   setsvalue2s(L, L->top++, luaS_newlstr(L, str, 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;
         break;
       }
       }
       case 'c': {
       case 'c': {
-        char buff;
-        buff = cast(char, va_arg(argp, int));
+        char buff = cast(char, va_arg(argp, int));
         pushstr(L, &buff, 1);
         pushstr(L, &buff, 1);
         break;
         break;
       }
       }
       case 'd': {
       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;
         break;
       }
       }
       case 'I': {
       case 'I': {
         setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
         setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt)));
-        luaV_tostring(L, L->top - 1);
+        luaO_tostring(L, L->top - 1);
         break;
         break;
       }
       }
       case 'f': {
       case 'f': {
         setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
         setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
-        luaV_tostring(L, L->top - 1);
+        luaO_tostring(L, L->top - 1);
         break;
         break;
       }
       }
       case 'p': {
       case 'p': {

+ 2 - 1
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
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 ** 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);
                            const TValue *p2, TValue *res);
 LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
 LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o);
 LUAI_FUNC int luaO_hexavalue (int c);
 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,
 LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
                                                        va_list argp);
                                                        va_list argp);
 LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
 LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);

+ 4 - 33
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
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -33,10 +33,6 @@
 #define MAXTAGLOOP	2000
 #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
 ** Similar to 'tonumber', but does not attempt to convert strings and
 ** ensure correct precision (no extra bits). Used in comparisons.
 ** 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
 ** Try to convert a 'for' limit to an integer, preserving the
 ** semantics of the loop.
 ** 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 */
 /* 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,
 ** Main operation for concatenation: concat 'total' values in the stack,
@@ -385,7 +356,7 @@ void luaV_concat (lua_State *L, int total) {
   do {
   do {
     StkId top = L->top;
     StkId top = L->top;
     int n = 2;  /* number of elements handled in this pass (at least 2) */
     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);
       luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT);
     else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
     else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
       cast_void(tostring(L, top - 2));  /* result is first operand */
       cast_void(tostring(L, top - 2));  /* result is first operand */

+ 8 - 2
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
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -24,12 +24,18 @@
 #define luaV_rawequalobj(t1,t2)		luaV_equalobj(NULL,t1,t2)
 #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_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_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_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_tonumber_ (const TValue *obj, lua_Number *n);
 LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p);
 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,
 LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,
                                             StkId val);
                                             StkId val);
 LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
 LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,