1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 20:30:28 +02:00

Language-specific case-conversion doesn't honor locale

Libunistring uses a function uc_locale_language to extract the
current language from the locale information.  It does this by calling
setlocale.  This makes incompatible with Guile functions that use the
locale_t thread-specific locale API, because the values returned by the
call to setlocale ignore the locale set by uselocale.

As a workaround, this patch extracts the language from the locale_t
structure's __names field.

A more complete solution is needed.  Perhaps that solution would test
that the __names field exists in the configure step and revert to
!USE_GNU_LOCALE_API in that case.

* libguile/i18n.c (locale_language): new function that performs the
  same job as uc_locale_language but is compatible with uselocale
  (u32_locale_casecoll, u32_locale_tocase): replace uc_locale_language
  with locale_language
This commit is contained in:
Michael Gran 2009-09-24 08:07:38 -07:00
parent bcccf04158
commit aafb5062b8

View file

@ -775,6 +775,50 @@ compare_u32_strings (SCM s1, SCM s2, SCM locale, const char *func_name)
} }
#undef FUNC_NAME #undef FUNC_NAME
/* Return the current language of the locale. */
static const char *
locale_language ()
{
#ifdef USE_GNU_LOCALE_API
{
static char lang[10];
scm_t_locale loc;
const char *c_result;
char *p;
/* If we are here, the locale has been set with 'uselocale'. We
can't use libunistring's uc_locale_language because it calls
setlocale. */
loc = uselocale (0);
if (loc == (scm_t_locale) -1)
return "";
/* The internal structure of locale_t may be specific to the C
library, but, there doesn't seem to be any other way to extract
the locale name. */
c_result = loc->__names[LC_CTYPE];
p = (char *) c_result;
while (*p != '\0' && *p != '_' && *p != '.' && *p != '@')
p++;
/* Return a statically allocated pointer to the language portion,
so that the caller of this function does not need to free() the
result. */
if (p != c_result)
{
memcpy (lang, c_result, p - c_result);
lang[p - c_result] = '\0';
return lang;
}
else
return "";
}
#else
/* The locale has been set with setlocale. */
return uc_locale_language ();
#endif
}
static inline int static inline int
u32_locale_casecoll (const char *func_name, const scm_t_uint32 *c_s1, u32_locale_casecoll (const char *func_name, const scm_t_uint32 *c_s1,
const scm_t_uint32 *c_s2, const scm_t_uint32 *c_s2,
@ -784,7 +828,7 @@ u32_locale_casecoll (const char *func_name, const scm_t_uint32 *c_s1,
make any non-local exit. */ make any non-local exit. */
int ret; int ret;
const char *loc = uc_locale_language (); const char *loc = locale_language ();
ret = u32_casecoll (c_s1, u32_strlen (c_s1), ret = u32_casecoll (c_s1, u32_strlen (c_s1),
c_s2, u32_strlen (c_s2), c_s2, u32_strlen (c_s2),
@ -1081,7 +1125,7 @@ u32_locale_tocase (const scm_t_uint32 *c_s1, size_t len,
make any non-local exit. */ make any non-local exit. */
scm_t_uint32 *ret; scm_t_uint32 *ret;
const char *loc = uc_locale_language (); const char *loc = locale_language ();
/* The first NULL here indicates that no NFC or NFKC normalization /* The first NULL here indicates that no NFC or NFKC normalization
is done. The second NULL means the return buffer is is done. The second NULL means the return buffer is