From 9a01ab5dd77830c425440bf497c04e7e88426034 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Thu, 25 Jun 2015 10:43:54 +0100 Subject: [PATCH] eolian: try replacing '.' with locale specific decimal point This fixes parsing of floating point number with locales that use a comma as decimal separator, as strtof/strtod follows locale specific conventions. @fix --- src/lib/eolian/eo_lexer.c | 44 ++++++++++++++++++++++++++++++++++++++- src/lib/eolian/eo_lexer.h | 9 +++++--- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/lib/eolian/eo_lexer.c b/src/lib/eolian/eo_lexer.c index 5ecdd8758f..d97c9c6676 100644 --- a/src/lib/eolian/eo_lexer.c +++ b/src/lib/eolian/eo_lexer.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -574,6 +575,38 @@ get_type(Eo_Lexer *ls, Eina_Bool is_float) return NUM_INT; } +static void +replace_decpoint(Eo_Lexer *ls, char prevdecp) +{ + if (ls->decpoint == prevdecp) return; + char *bufs = eina_strbuf_string_steal(ls->buff); + char *p = bufs; + while ((p = strchr(p, prevdecp))) *p = ls->decpoint; + eina_strbuf_append(ls->buff, bufs); + free(bufs); +} + +static void +write_val_with_decpoint(Eo_Lexer *ls, Eo_Token *tok, int type) +{ + struct lconv *lc = localeconv(); + char prev = ls->decpoint; + ls->decpoint = lc ? lc->decimal_point[0] : '.'; + if (ls->decpoint == prev) + { + eo_lexer_lex_error(ls, "malformed number", TOK_NUMBER); + return; + } + replace_decpoint(ls, prev); + char *end = NULL; + if (type == NUM_FLOAT) + tok->value.f = strtof(eina_strbuf_string_get(ls->buff), &end); + else if (type == NUM_DOUBLE) + tok->value.d = strtod(eina_strbuf_string_get(ls->buff), &end); + if (end && end[0]) + eo_lexer_lex_error(ls, "malformed number", TOK_NUMBER); +} + static void write_val(Eo_Lexer *ls, Eo_Token *tok, Eina_Bool is_float) { @@ -582,6 +615,7 @@ write_val(Eo_Lexer *ls, Eo_Token *tok, Eina_Bool is_float) char *end = NULL; if (is_float) { + replace_decpoint(ls, '.'); if (type == NUM_FLOAT) tok->value.f = strtof(str, &end); else if (type == NUM_DOUBLE) @@ -598,7 +632,14 @@ write_val(Eo_Lexer *ls, Eo_Token *tok, Eina_Bool is_float) tok->value.ull = strtoull(str, &end, 0); } if (end && end[0]) - eo_lexer_lex_error(ls, "malformed number", TOK_NUMBER); + { + if (is_float) + { + write_val_with_decpoint(ls, tok, type); + return; + } + eo_lexer_lex_error(ls, "malformed number", TOK_NUMBER); + } tok->kw = type; } @@ -875,6 +916,7 @@ eo_lexer_set_input(Eo_Lexer *ls, const char *source) ls->filename = get_filename(ls); ls->line_number = 1; ls->icolumn = ls->column = -1; + ls->decpoint = '.'; next_char(ls); if (ls->current != 0xEF) return; diff --git a/src/lib/eolian/eo_lexer.h b/src/lib/eolian/eo_lexer.h index 713599d1d9..c15b8e25f4 100644 --- a/src/lib/eolian/eo_lexer.h +++ b/src/lib/eolian/eo_lexer.h @@ -161,9 +161,6 @@ typedef struct _Eo_Lexer /* this is jumped to when an error happens */ jmp_buf err_jmp; - /* whether we allow lexing expression related tokens */ - Eina_Bool expr_mode; - /* saved context info */ Eina_List *saved_ctxs; @@ -172,6 +169,12 @@ typedef struct _Eo_Lexer * case of error - and it's nulled when it's written into a more permanent * position (e.g. as part of another struct, or into nodes */ Eo_Lexer_Temps tmp; + + /* whether we allow lexing expression related tokens */ + Eina_Bool expr_mode; + + /* decimal point, by default '.' */ + char decpoint; } Eo_Lexer; int eo_lexer_init (void);