diff options
-rw-r--r-- | lib.c | 34 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | stream.c | 21 |
3 files changed, 54 insertions, 3 deletions
@@ -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(); @@ -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 @@ -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])) { |