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

to strings
This commit is contained in:
Roberto Ierusalimschy 2014-07-30 11:00:14 -03:00
parent 1aa5262634
commit 34ac039fb8
6 changed files with 54 additions and 52 deletions

12
lapi.c
View File

@ -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;

View File

@ -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");
}

View File

@ -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': {

View File

@ -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, ...);

37
lvm.c
View File

@ -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 */

10
lvm.h
View File

@ -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,