summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib.c34
-rw-r--r--lib.h2
-rw-r--r--stream.c21
3 files changed, 54 insertions, 3 deletions
diff --git a/lib.c b/lib.c
index f6c57552..338ff9fc 100644
--- a/lib.c
+++ b/lib.c
@@ -37,6 +37,7 @@
#include <math.h>
#include <signal.h>
#include <assert.h>
+#include <locale.h>
#include "config.h"
#include "alloca.h"
#if HAVE_GETENVIRONMENTSTRINGS
@@ -130,6 +131,10 @@ val list_f, less_f, greater_f;
val prog_string;
+#if CONFIG_LOCALE_TOLERANCE
+char dec_point = '.';
+#endif
+
static val recycled_conses;
const seq_kind_t seq_kind_tab[MAXTYPE+1] = {
@@ -5402,9 +5407,21 @@ val flo_str(val str)
{
const wchar_t *wcs = c_str(str);
wchar_t *ptr;
+ double value;
+
+#if CONFIG_LOCALE_TOLERANCE
+ if (dec_point != '.') {
+ size_t size = c_unum(length_str(str), lit("flot-str")) + 1;
+ wchar_t *wcopy = alloca(sizeof *wcopy * size), *dot = wcopy;
+ wmemcpy(wcopy, wcs, size);
+ wcs = wcopy;
+ while ((dot = wcschr(dot, '.')) != 0)
+ *dot++ = dec_point;
+ }
+#endif
+
+ value = wcstod(wcs, &ptr);
- /* TODO: detect if we have wcstod */
- double value = wcstod(wcs, &ptr);
if (value == 0 && ptr == wcs)
return nil;
if ((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE)
@@ -11888,6 +11905,16 @@ val in_range_star(val range, val num)
}
}
+#if CONFIG_LOCALE_TOLERANCE
+
+static void locale_init(void)
+{
+ struct lconv *lc = localeconv();
+ dec_point = *lc->decimal_point;
+}
+
+#endif
+
static void obj_init(void)
{
/*
@@ -12970,6 +12997,9 @@ void init(val *stack_bottom)
t = one;
gc_init(stack_bottom);
+#if CONFIG_LOCALE_TOLERANCE
+ locale_init();
+#endif
obj_init();
uw_init();
eval_init();
diff --git a/lib.h b/lib.h
index e9c1bd16..3a519905 100644
--- a/lib.h
+++ b/lib.h
@@ -538,6 +538,8 @@ extern val list_f, less_f, greater_f;
extern val prog_string;
+extern char dec_point;
+
#if HAVE_ULONGLONG_T
typedef ulonglong_t alloc_bytes_t;
#define SIZEOF_ALLOC_BYTES_T SIZEOF_LONGLONG_T
diff --git a/stream.c b/stream.c
index ef2c0a29..07a0060c 100644
--- a/stream.c
+++ b/stream.c
@@ -3494,7 +3494,11 @@ val formatv(val stream_in, val fmtstr, struct args *al)
if (ch == 'e') {
sprintf(num_buf, "%.*e", precision, n);
{
+#if CONFIG_LOCALE_TOLERANCE
+ char *dec = strchr(num_buf, dec_point);
+#else
char *dec = strchr(num_buf, '.');
+#endif
char *exp = strchr(dec ? dec : num_buf, 'e');
if (exp) {
@@ -3525,6 +3529,13 @@ val formatv(val stream_in, val fmtstr, struct args *al)
continue;
}
precision = (width ? width - 1 : 0);
+#if CONFIG_LOCALE_TOLERANCE
+ if (dec_point != '.') {
+ char *dot = num_buf;
+ while ((dot = strchr(dot, dec_point)) != 0)
+ *dot++ = '.';
+ }
+#endif
goto output_num;
}
case 'd':
@@ -3584,6 +3595,14 @@ val formatv(val stream_in, val fmtstr, struct args *al)
sprintf(num_buf, "%.*g", precision, obj->fl.n);
+#if CONFIG_LOCALE_TOLERANCE
+ if (dec_point != '.') {
+ char *dot = num_buf;
+ while ((dot = strchr(dot, dec_point)) != 0)
+ *dot++ = '.';
+ }
+#endif
+
{
char *dec = strchr(num_buf, '.');
char *exp = strchr(dec ? dec : num_buf, 'e');
@@ -3606,7 +3625,7 @@ val formatv(val stream_in, val fmtstr, struct args *al)
}
if (ch == 's' && (!precision_p || precision > 0) && !dec && !exp)
- strcat(num_buf, ".0");
+ strcat(num_buf, ".0");
}
if (!isdigit(num_buf[0]) && !isdigit(num_buf[1])) {