aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-05-19 13:29:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-05-19 13:29:40 -0300
commit01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913 (patch)
tree9517d358c0df8f97a0f336b4dcdfdeb84ef52faa /lstrlib.c
parent1bdc328c7542fac5101684a4ac31a25be3dff112 (diff)
downloadlua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.tar.gz
lua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.tar.bz2
lua-01c96ad12e1e45d6a36a07ae8ec97c09fd0ff913.zip
handling of inf, -inf, and NaN by string.format'%q'
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/lstrlib.c b/lstrlib.c
index 6ed2bdb8..89896fa6 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.255 2017/03/14 12:40:44 roberto Exp roberto $
3** Standard library for string operations and pattern-matching 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -14,6 +14,7 @@
14#include <float.h> 14#include <float.h>
15#include <limits.h> 15#include <limits.h>
16#include <locale.h> 16#include <locale.h>
17#include <math.h>
17#include <stddef.h> 18#include <stddef.h>
18#include <stdio.h> 19#include <stdio.h>
19#include <stdlib.h> 20#include <stdlib.h>
@@ -813,8 +814,6 @@ static int str_gsub (lua_State *L) {
813** Hexadecimal floating-point formatter 814** Hexadecimal floating-point formatter
814*/ 815*/
815 816
816#include <math.h>
817
818#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) 817#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
819 818
820 819
@@ -929,14 +928,32 @@ static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
929 928
930 929
931/* 930/*
932** Ensures the 'buff' string uses a dot as the radix character. 931** Serialize a floating-point number in such a way that it can be
932** scanned back by Lua. Use hexadecimal format for "common" numbers
933** (to preserve precision); inf, -inf, and NaN are handled separately.
934** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.)
933*/ 935*/
934static void checkdp (char *buff, int nb) { 936static int quotefloat (lua_State *L, char *buff, lua_Number n) {
935 if (memchr(buff, '.', nb) == NULL) { /* no dot? */ 937 const char *s; /* for the fixed representations */
936 char point = lua_getlocaledecpoint(); /* try locale point */ 938 if (n == (lua_Number)HUGE_VAL) /* inf? */
937 char *ppoint = (char *)memchr(buff, point, nb); 939 s = "1e9999";
938 if (ppoint) *ppoint = '.'; /* change it to a dot */ 940 else if (n == -(lua_Number)HUGE_VAL) /* -inf? */
941 s = "-1e9999";
942 else if (n != n) /* NaN? */
943 s = "(0/0)";
944 else { /* format number as hexadecimal */
945 int nb = lua_number2strx(L, buff, MAX_ITEM,
946 "%" LUA_NUMBER_FRMLEN "a", n);
947 /* ensures that 'buff' string uses a dot as the radix character */
948 if (memchr(buff, '.', nb) == NULL) { /* no dot? */
949 char point = lua_getlocaledecpoint(); /* try locale point */
950 char *ppoint = (char *)memchr(buff, point, nb);
951 if (ppoint) *ppoint = '.'; /* change it to a dot */
952 }
953 return nb;
939 } 954 }
955 /* for the fixed representations */
956 return l_sprintf(buff, MAX_ITEM, "%s", s);
940} 957}
941 958
942 959
@@ -951,11 +968,8 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
951 case LUA_TNUMBER: { 968 case LUA_TNUMBER: {
952 char *buff = luaL_prepbuffsize(b, MAX_ITEM); 969 char *buff = luaL_prepbuffsize(b, MAX_ITEM);
953 int nb; 970 int nb;
954 if (!lua_isinteger(L, arg)) { /* float? */ 971 if (!lua_isinteger(L, arg)) /* float? */
955 lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ 972 nb = quotefloat(L, buff, lua_tonumber(L, arg));
956 nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
957 checkdp(buff, nb); /* ensure it uses a dot */
958 }
959 else { /* integers */ 973 else { /* integers */
960 lua_Integer n = lua_tointeger(L, arg); 974 lua_Integer n = lua_tointeger(L, arg);
961 const char *format = (n == LUA_MININTEGER) /* corner case? */ 975 const char *format = (n == LUA_MININTEGER) /* corner case? */