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