Skip to content

Commit 2964f0e

Browse files
committed
Fix locale-dependent float parsing and leading-dot literals (#2082)
- Replace commas with dots before parsing in iron.h, iron_ui.c, iron_ui_ext.c, and iron_json.c for locale-independent float input. - Fix minic lexer to recognize leading-dot float literals like .3 and .5f. - Add test13 in minic_tests.c for leading-dot float literal parsing. - Fixes issue #2082 where UI Scale and other float inputs rejected comma decimal separators in certain locales.
1 parent 31d0a37 commit 2964f0e

6 files changed

Lines changed: 61 additions & 10 deletions

File tree

base/sources/iron.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,10 @@ i32 parse_int_hex(const char *s) {
530530
#endif
531531

532532
f32 parse_float(const char *s) {
533-
return strtof(s, NULL);
533+
// Replace comma with dot for locale-independent parsing
534+
char *s_copy = string_replace_all(s, ",", ".");
535+
f32 result = strtof(s_copy, NULL);
536+
return result;
534537
}
535538

536539
i32 color_from_floats(f32 r, f32 g, f32 b, f32 a) {

base/sources/iron_json.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,16 @@ static void token_write() {
162162
store_ptr_abs(NULL);
163163
}
164164
else {
165-
has_dot(source + t.start, t.end - t.start) ? store_f32(strtof(source + t.start, NULL)) :
165+
// Replace comma with dot for locale-independent parsing
166+
char *num_str = string_copy(source + t.start);
167+
for (int i = 0; i < (t.end - t.start); i++) {
168+
if (num_str[i] == ',') num_str[i] = '.';
169+
}
170+
has_dot(source + t.start, t.end - t.start) ? store_f32(strtof(num_str, NULL)) :
166171
#ifdef _WIN32
167-
store_i32(_strtoi64(source + t.start, NULL, 10));
172+
store_i32(_strtoi64(num_str, NULL, 10));
168173
#else
169-
store_i32(strtol(source + t.start, NULL, 10));
174+
store_i32(strtol(num_str, NULL, 10));
170175
#endif
171176
}
172177
}
@@ -567,7 +572,12 @@ static void jenc_array(int count) {
567572
armpack_write_u8(0xca);
568573
for (int i = 0; i < count; i++) {
569574
jsmntok_t t = jenc_tokens[jenc_ti++];
570-
armpack_write_f32(strtof(jenc_src + t.start, NULL));
575+
// Replace comma with dot for locale-independent parsing
576+
char *num_str = string_copy(jenc_src + t.start);
577+
for (int j = 0; j < (t.end - t.start); j++) {
578+
if (num_str[j] == ',') num_str[j] = '.';
579+
}
580+
armpack_write_f32(strtof(num_str, NULL));
571581
}
572582
}
573583
else if (elem_type == 0xd2) { // typed i32
@@ -637,7 +647,12 @@ static void jenc_value() {
637647
}
638648
else if (jenc_has_dot(t.start, t.end)) {
639649
armpack_write_u8(0xca);
640-
armpack_write_f32(strtof(jenc_src + t.start, NULL));
650+
// Replace comma with dot for locale-independent parsing
651+
char *num_str = string_copy(jenc_src + t.start);
652+
for (int j = 0; j < (t.end - t.start); j++) {
653+
if (num_str[j] == ',') num_str[j] = '.';
654+
}
655+
armpack_write_f32(strtof(num_str, NULL));
641656
}
642657
else {
643658
armpack_write_u8(0xd2);

base/sources/iron_ui.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,11 +2292,15 @@ float ui_slider(ui_handle_t *handle, char *text, float from, float to, bool fill
22922292
if (current->submit_text_handle == handle) {
22932293
ui_submit_text_edit();
22942294
#ifdef WITH_EVAL
2295-
minic_ctx_t *_ctx = minic_eval(string("float main() { return %s; }", handle->text));
2295+
// Replace comma with dot for locale-independent parsing
2296+
char *text_copy = string_replace_all(handle->text, ",", ".");
2297+
minic_ctx_t *_ctx = minic_eval(string("float main() { return %s; }", text_copy));
22962298
handle->f = minic_ctx_result(_ctx);
22972299
minic_ctx_free(_ctx);
22982300
#else
2299-
handle->f = atof(handle->text);
2301+
// Replace comma with dot for locale-independent parsing
2302+
char *text_copy = string_replace_all(handle->text, ",", ".");
2303+
handle->f = atof(text_copy);
23002304
#endif
23012305
handle->changed = current->changed = true;
23022306
}

base/sources/iron_ui_ext.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ float ui_float_input(ui_handle_t *handle, char *label, int align, float precisio
8181
handle->text = tmp;
8282
sprintf(handle->text, "%f", round(handle->f * precision) / precision);
8383
char *text = ui_text_input(handle, label, align, true, false);
84-
handle->f = atof(text);
84+
// Replace comma with dot for locale-independent parsing
85+
char *text_copy = string_replace_all(text, ",", ".");
86+
handle->f = atof(text_copy);
8587
return handle->f;
8688
}
8789

base/sources/libs/minic.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,21 @@ static void minic_lex_next(minic_lexer_t *l) {
370370
l->cur.type = TOK_COMMA;
371371
return;
372372
case '.':
373-
l->cur.type = TOK_DOT;
373+
if (isdigit((unsigned char)l->src[l->pos])) {
374+
double n = 0;
375+
double frac = 0.1;
376+
while (isdigit((unsigned char)l->src[l->pos])) {
377+
n += (l->src[l->pos++] - '0') * frac;
378+
frac *= 0.1;
379+
}
380+
if (l->src[l->pos] == 'f' || l->src[l->pos] == 'F') {
381+
l->pos++;
382+
}
383+
l->cur.val = minic_val_float((float)n);
384+
l->cur.type = TOK_NUMBER;
385+
} else {
386+
l->cur.type = TOK_DOT;
387+
}
374388
return;
375389
case '*':
376390
if (l->src[l->pos] == '=') {

base/sources/libs/minic_tests.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,18 @@ const char *test12 = " \n\
189189
} \n\
190190
";
191191

192+
// Test for leading-dot float literals (.3, .5f)
193+
const char *test13 = " \n\
194+
float main() { \n\
195+
float a = .3; \n\
196+
float b = .5f; \n\
197+
float c = 0.0; \n\
198+
c = .7; \n\
199+
if (a == 0.3 && b == 0.5 && c == 0.7) { return 0.0; } \n\
200+
return 1.0; \n\
201+
} \n\
202+
";
203+
192204
#define MINIC_TEST(n, src) \
193205
do { \
194206
minic_ctx_t *_c = minic_eval(src); \
@@ -216,6 +228,7 @@ void minic_tests() {
216228
MINIC_TEST(10, test10);
217229
MINIC_TEST(11, test11);
218230
MINIC_TEST(12, test12);
231+
MINIC_TEST(13, test13);
219232
}
220233

221234
#endif

0 commit comments

Comments
 (0)