1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 04:10:18 +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,8 +775,52 @@ compare_u32_strings (SCM s1, SCM s2, SCM locale, const char *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
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,
int *result)
{
@ -784,9 +828,9 @@ u32_locale_casecoll (const char *func_name, const scm_t_uint32 *c_s1,
make any non-local exit. */
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),
loc, UNINORM_NFC, result);
@ -1081,7 +1125,7 @@ u32_locale_tocase (const scm_t_uint32 *c_s1, size_t len,
make any non-local exit. */
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
is done. The second NULL means the return buffer is
@ -1095,7 +1139,7 @@ u32_locale_tocase (const scm_t_uint32 *c_s1, size_t len,
return errno;
}
*p_c_s2 = ret;
return 0;
}