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
This commit is contained in:
Daniel Kolesa 2015-06-25 10:43:54 +01:00
parent 6f846d89cd
commit 9a01ab5dd7
2 changed files with 49 additions and 4 deletions

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include <setjmp.h>
#include <assert.h>
@ -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;

View File

@ -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);