diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-07-30 11:00:14 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-07-30 11:00:14 -0300 |
| commit | 34ac039fb84e3c12fb8c96c9c99c34224c09872b (patch) | |
| tree | a859f6338c6c851088a67b129765de662ed6f223 | |
| parent | 1aa526263405fb4906eafab3011b13de4e5daf73 (diff) | |
| download | lua-34ac039fb84e3c12fb8c96c9c99c34224c09872b.tar.gz lua-34ac039fb84e3c12fb8c96c9c99c34224c09872b.tar.bz2 lua-34ac039fb84e3c12fb8c96c9c99c34224c09872b.zip | |
new macro 'cvt2str' to better control whether numbers are convertible
to strings
| -rw-r--r-- | lapi.c | 12 | ||||
| -rw-r--r-- | ldebug.c | 5 | ||||
| -rw-r--r-- | lobject.c | 39 | ||||
| -rw-r--r-- | lobject.h | 3 | ||||
| -rw-r--r-- | lvm.c | 37 | ||||
| -rw-r--r-- | lvm.h | 10 |
6 files changed, 54 insertions, 52 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.230 2014/07/21 16:02:57 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.231 2014/07/22 18:07:47 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -279,8 +279,8 @@ LUA_API int lua_isnumber (lua_State *L, int idx) { | |||
| 279 | 279 | ||
| 280 | 280 | ||
| 281 | LUA_API int lua_isstring (lua_State *L, int idx) { | 281 | LUA_API int lua_isstring (lua_State *L, int idx) { |
| 282 | int t = lua_type(L, idx); | 282 | const TValue *o = index2addr(L, idx); |
| 283 | return (t == LUA_TSTRING || t == LUA_TNUMBER); | 283 | return (ttisstring(o) || cvt2str(o)); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | 286 | ||
| @@ -371,14 +371,14 @@ LUA_API int lua_toboolean (lua_State *L, int idx) { | |||
| 371 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | 371 | LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { |
| 372 | StkId o = index2addr(L, idx); | 372 | StkId o = index2addr(L, idx); |
| 373 | if (!ttisstring(o)) { | 373 | if (!ttisstring(o)) { |
| 374 | lua_lock(L); /* `luaV_tostring' may create a new string */ | 374 | if (!cvt2str(o)) { /* not convertible? */ |
| 375 | if (!luaV_tostring(L, o)) { /* conversion failed? */ | ||
| 376 | if (len != NULL) *len = 0; | 375 | if (len != NULL) *len = 0; |
| 377 | lua_unlock(L); | ||
| 378 | return NULL; | 376 | return NULL; |
| 379 | } | 377 | } |
| 378 | lua_lock(L); /* `luaO_tostring' may create a new string */ | ||
| 380 | luaC_checkGC(L); | 379 | luaC_checkGC(L); |
| 381 | o = index2addr(L, idx); /* previous call may reallocate the stack */ | 380 | o = index2addr(L, idx); /* previous call may reallocate the stack */ |
| 381 | luaO_tostring(L, o); | ||
| 382 | lua_unlock(L); | 382 | lua_unlock(L); |
| 383 | } | 383 | } |
| 384 | if (len != NULL) *len = tsvalue(o)->len; | 384 | if (len != NULL) *len = tsvalue(o)->len; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 2.98 2014/07/15 21:26:50 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.99 2014/07/17 12:30:53 roberto Exp roberto $ |
| 3 | ** Debug Interface | 3 | ** Debug Interface |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -526,8 +526,7 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
| 526 | 526 | ||
| 527 | 527 | ||
| 528 | l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { | 528 | l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { |
| 529 | if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; | 529 | if (ttisstring(p1) || cvt2str(p1)) p1 = p2; |
| 530 | lua_assert(!ttisstring(p1) && !ttisnumber(p1)); | ||
| 531 | luaG_typeerror(L, p1, "concatenate"); | 530 | luaG_typeerror(L, p1, "concatenate"); |
| 532 | } | 531 | } |
| 533 | 532 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.c,v 2.86 2014/05/12 21:44:17 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.87 2014/06/30 19:48:08 roberto Exp roberto $ |
| 3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -327,6 +327,32 @@ int luaO_utf8esc (char *buff, unsigned int x) { | |||
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | 329 | ||
| 330 | /* maximum length of the conversion of a number to a string */ | ||
| 331 | #define MAXNUMBER2STR 50 | ||
| 332 | |||
| 333 | |||
| 334 | /* | ||
| 335 | ** Convert a number object to a string | ||
| 336 | */ | ||
| 337 | void luaO_tostring (lua_State *L, StkId obj) { | ||
| 338 | char buff[MAXNUMBER2STR]; | ||
| 339 | size_t len; | ||
| 340 | lua_assert(ttisnumber(obj)); | ||
| 341 | if (ttisinteger(obj)) | ||
| 342 | len = lua_integer2str(buff, ivalue(obj)); | ||
| 343 | else { | ||
| 344 | len = lua_number2str(buff, fltvalue(obj)); | ||
| 345 | #if !defined(LUA_COMPAT_FLOATSTRING) | ||
| 346 | if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ | ||
| 347 | buff[len++] = '.'; | ||
| 348 | buff[len++] = '0'; /* adds '.0' to result */ | ||
| 349 | } | ||
| 350 | #endif | ||
| 351 | } | ||
| 352 | setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); | ||
| 353 | } | ||
| 354 | |||
| 355 | |||
| 330 | static void pushstr (lua_State *L, const char *str, size_t l) { | 356 | static void pushstr (lua_State *L, const char *str, size_t l) { |
| 331 | setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); | 357 | setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); |
| 332 | } | 358 | } |
| @@ -349,24 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { | |||
| 349 | break; | 375 | break; |
| 350 | } | 376 | } |
| 351 | case 'c': { | 377 | case 'c': { |
| 352 | char buff; | 378 | char buff = cast(char, va_arg(argp, int)); |
| 353 | buff = cast(char, va_arg(argp, int)); | ||
| 354 | pushstr(L, &buff, 1); | 379 | pushstr(L, &buff, 1); |
| 355 | break; | 380 | break; |
| 356 | } | 381 | } |
| 357 | case 'd': { | 382 | case 'd': { |
| 358 | setivalue(L->top++, cast_int(va_arg(argp, int))); | 383 | setivalue(L->top++, va_arg(argp, int)); |
| 359 | luaV_tostring(L, L->top - 1); | 384 | luaO_tostring(L, L->top - 1); |
| 360 | break; | 385 | break; |
| 361 | } | 386 | } |
| 362 | case 'I': { | 387 | case 'I': { |
| 363 | setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt))); | 388 | setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt))); |
| 364 | luaV_tostring(L, L->top - 1); | 389 | luaO_tostring(L, L->top - 1); |
| 365 | break; | 390 | break; |
| 366 | } | 391 | } |
| 367 | case 'f': { | 392 | case 'f': { |
| 368 | setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); | 393 | setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); |
| 369 | luaV_tostring(L, L->top - 1); | 394 | luaO_tostring(L, L->top - 1); |
| 370 | break; | 395 | break; |
| 371 | } | 396 | } |
| 372 | case 'p': { | 397 | case 'p': { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.99 2014/07/18 14:46:47 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.100 2014/07/29 16:22:24 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -527,6 +527,7 @@ LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, | |||
| 527 | const TValue *p2, TValue *res); | 527 | const TValue *p2, TValue *res); |
| 528 | LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); | 528 | LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); |
| 529 | LUAI_FUNC int luaO_hexavalue (int c); | 529 | LUAI_FUNC int luaO_hexavalue (int c); |
| 530 | LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); | ||
| 530 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, | 531 | LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, |
| 531 | va_list argp); | 532 | va_list argp); |
| 532 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); | 533 | LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.219 2014/07/18 13:36:14 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.220 2014/07/21 16:02:10 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -33,10 +33,6 @@ | |||
| 33 | #define MAXTAGLOOP 2000 | 33 | #define MAXTAGLOOP 2000 |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /* maximum length of the conversion of a number to a string */ | ||
| 37 | #define MAXNUMBER2STR 50 | ||
| 38 | |||
| 39 | |||
| 40 | /* | 36 | /* |
| 41 | ** Similar to 'tonumber', but does not attempt to convert strings and | 37 | ** Similar to 'tonumber', but does not attempt to convert strings and |
| 42 | ** ensure correct precision (no extra bits). Used in comparisons. | 38 | ** ensure correct precision (no extra bits). Used in comparisons. |
| @@ -120,32 +116,6 @@ int luaV_tointeger_ (const TValue *obj, lua_Integer *p) { | |||
| 120 | 116 | ||
| 121 | 117 | ||
| 122 | /* | 118 | /* |
| 123 | ** Convert a number object to a string | ||
| 124 | */ | ||
| 125 | int luaV_tostring (lua_State *L, StkId obj) { | ||
| 126 | if (!ttisnumber(obj)) | ||
| 127 | return 0; | ||
| 128 | else { | ||
| 129 | char buff[MAXNUMBER2STR]; | ||
| 130 | size_t len; | ||
| 131 | if (ttisinteger(obj)) | ||
| 132 | len = lua_integer2str(buff, ivalue(obj)); | ||
| 133 | else { | ||
| 134 | len = lua_number2str(buff, fltvalue(obj)); | ||
| 135 | #if !defined(LUA_COMPAT_FLOATSTRING) | ||
| 136 | if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ | ||
| 137 | buff[len++] = '.'; | ||
| 138 | buff[len++] = '0'; /* adds '.0' to result */ | ||
| 139 | } | ||
| 140 | #endif | ||
| 141 | } | ||
| 142 | setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); | ||
| 143 | return 1; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | |||
| 148 | /* | ||
| 149 | ** Try to convert a 'for' limit to an integer, preserving the | 119 | ** Try to convert a 'for' limit to an integer, preserving the |
| 150 | ** semantics of the loop. | 120 | ** semantics of the loop. |
| 151 | ** (The following explanation assumes a non-negative step; it is valid | 121 | ** (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) { | |||
| 374 | 344 | ||
| 375 | 345 | ||
| 376 | /* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ | 346 | /* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ |
| 377 | #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) | 347 | #define tostring(L,o) \ |
| 348 | (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) | ||
| 378 | 349 | ||
| 379 | /* | 350 | /* |
| 380 | ** Main operation for concatenation: concat 'total' values in the stack, | 351 | ** Main operation for concatenation: concat 'total' values in the stack, |
| @@ -385,7 +356,7 @@ void luaV_concat (lua_State *L, int total) { | |||
| 385 | do { | 356 | do { |
| 386 | StkId top = L->top; | 357 | StkId top = L->top; |
| 387 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 358 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 388 | if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) | 359 | if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) |
| 389 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); | 360 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); |
| 390 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ | 361 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ |
| 391 | cast_void(tostring(L, top - 2)); /* result is first operand */ | 362 | cast_void(tostring(L, top - 2)); /* result is first operand */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 2.30 2014/05/12 21:22:05 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.31 2014/05/26 17:10:22 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -24,12 +24,18 @@ | |||
| 24 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) | 24 | #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) |
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | #if !defined(LUA_NOCVTN2S) | ||
| 28 | #define cvt2str(o) ttisnumber(o) | ||
| 29 | #else | ||
| 30 | #define cvt2str(o) 0 /* no convertion from numbers to strings */ | ||
| 31 | #endif | ||
| 32 | |||
| 33 | |||
| 27 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); | 34 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); |
| 28 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); | 35 | LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); |
| 29 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); | 36 | LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); |
| 30 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); | 37 | LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); |
| 31 | LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p); | 38 | LUAI_FUNC int luaV_tointeger_ (const TValue *obj, lua_Integer *p); |
| 32 | LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); | ||
| 33 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, | 39 | LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, |
| 34 | StkId val); | 40 | StkId val); |
| 35 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, | 41 | LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, |
