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:
parent
bcccf04158
commit
aafb5062b8
1 changed files with 49 additions and 5 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue