Use strtod_l() to correctly parse decimal numbers in French & other locales

Test with, eg.:
$ LC_ALL=fr_FR.utf-8 ./hb-view NotoSansArabic-VF.ttf بهداد --variations wght=1.2
This commit is contained in:
Behdad Esfahbod 2017-09-14 20:50:35 -04:00
parent 9355218f58
commit 3ca69c8c32
2 changed files with 53 additions and 4 deletions

View File

@ -69,8 +69,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
])
# Functions and headers
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty)
AC_CHECK_HEADERS(unistd.h sys/mman.h)
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)
# Compiler flags
AC_CANONICAL_HOST

View File

@ -32,6 +32,9 @@
#include "hb-object-private.hh"
#include <locale.h>
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
/* hb_options_t */
@ -246,8 +249,8 @@ struct hb_language_item_t {
static hb_language_item_t *langs;
#ifdef HB_USE_ATEXIT
static
void free_langs (void)
static void
free_langs (void)
{
while (langs) {
hb_language_item_t *next = langs->next;
@ -694,6 +697,48 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv)
return true;
}
#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
#define USE_XLOCALE 1
#endif
#ifdef USE_XLOCALE
static locale_t C_locale;
#ifdef HB_USE_ATEXIT
static void
free_C_locale (void)
{
if (C_locale)
freelocale (C_locale);
}
#endif
static locale_t
get_C_locale (void)
{
retry:
locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale);
if (unlikely (!C))
{
C = newlocale (LC_ALL_MASK, "C", NULL);
if (!hb_atomic_ptr_cmpexch (&C_locale, NULL, C))
{
freelocale (C_locale);
goto retry;
}
#ifdef HB_USE_ATEXIT
atexit (free_C_locale); /* First person registers atexit() callback. */
#endif
}
return C;
}
#endif
static bool
parse_float (const char **pp, const char *end, float *pv)
{
@ -707,7 +752,11 @@ parse_float (const char **pp, const char *end, float *pv)
float v;
errno = 0;
#ifdef USE_XLOCALE
v = strtod_l (p, &pend, get_C_locale ());
#else
v = strtod (p, &pend);
#endif
if (errno || p == pend)
return false;