shithub: choc

Download patch

ref: 2435843ccd797d6bd70fa41872b92657cf6e98dc
parent: 9546b2f0392a606bb6220671741525ba40480685
author: Fabian Greffrath <fabian@greffrath.com>
date: Fri Mar 11 12:04:48 EST 2022

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

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