commit 2435843ccd797d6bd70fa41872b92657cf6e98dc
Author: Fabian Greffrath <fabian@greffrath.com>
AuthorDate: Fri Mar 11 17:04:48 2022 +0100
Commit: GitHub <noreply@github.com>
CommitDate: Fri Mar 11 17:04:48 2022 +0100
convert first non-digit to locale's decimal in float value parsing (#1390)
* convert first non-digit to locale's decimal in float value parsing
Different locales use different characters as decimal separators.
Since the currently used locale isn't always under our own control
(c.f. https://github.com/fabiangreffrath/crispy-doom/issues/620) this
commit makes sure to translate the first non-digit character in a
string that is going to get parsed as a float value into the current
locale's decimal separator.
Fixes https://github.com/fabiangreffrath/crispy-doom/issues/758.
* let minus pass
* add elaborative comment to the hack
* skip sign indicators
* be more explicit about skipping sign indicators
---
src/m_config.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/m_config.c b/src/m_config.c
index adb11e45..1d043970 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -24,6 +24,7 @@
#include <ctype.h>
#include <errno.h>
#include <assert.h>
+#include <locale.h>
#include "SDL_filesystem.h"
@@ -1993,7 +1994,41 @@ static void SetVariable(default_t *def, const char *value)
break;
case DEFAULT_FLOAT:
- *def->location.f = (float) atof(value);
+ {
+ // Different locales use different decimal separators.
+ // However, the choice of the current locale isn't always
+ // under our own control. If the atof() function fails to
+ // parse the string representing the floating point number
+ // using the current locale's decimal separator, it will
+ // return 0, resulting in silent sound effects. To
+ // mitigate this, we replace the first non-digit,
+ // non-minus character in the string with the current
+ // locale's decimal separator before passing it to atof().
+ struct lconv *lc = localeconv();
+ char dec, *str;
+ int i = 0;
+
+ dec = lc->decimal_point[0];
+ str = M_StringDuplicate(value);
+
+ // Skip sign indicators.
+ if (str[i] == '-' || str[i] == '+')
+ {
+ i++;
+ }
+
+ for ( ; str[i] != '\0'; i++)
+ {
+ if (!isdigit(str[i]))
+ {
+ str[i] = dec;
+ break;
+ }
+ }
+
+ *def->location.f = (float) atof(str);
+ free(str);
+ }
break;
}
}