-/* Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2014 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
#include <unicase.h>
#include <unistr.h>
-#if (defined HAVE_NEWLOCALE) && (defined HAVE_STRCOLL_L)
+#if defined HAVE_NEWLOCALE && defined HAVE_STRCOLL_L && defined HAVE_USELOCALE
/* The GNU thread-aware locale API is documented in ``Thread-Aware Locale
Model, a Proposal'', by Ulrich Drepper:
# define USE_GNU_LOCALE_API
#endif
-#if (defined USE_GNU_LOCALE_API) && (defined HAVE_XLOCALE_H)
-# include <xlocale.h>
-#endif
-
#include "libguile/posix.h" /* for `scm_i_locale_mutex' */
-#if (defined HAVE_LANGINFO_H) && (defined HAVE_NL_TYPES_H)
-# include <langinfo.h>
-# include <nl_types.h>
-#endif
+/* Use Gnulib's header, which also provides `nl_item' & co. */
+#include <langinfo.h>
#ifndef HAVE_SETLOCALE
static inline char *
/* Helper stringification macro. */
#define SCM_I18N_STRINGIFY(_name) # _name
+/* Acquiring and releasing the locale lock. */
+
+static inline void
+lock_locale_mutex (void)
+{
+#ifdef HAVE_POSIX
+ scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
+#else
+#endif
+}
+
+static inline void
+unlock_locale_mutex (void)
+{
+#ifdef HAVE_POSIX
+ scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+#else
+#endif
+}
\f
/* Locale objects, string and character collation, and other locale-dependent
int category_mask;
} *scm_t_locale;
-
-/* Free the resources used by LOCALE. */
-static inline void
-scm_i_locale_free (scm_t_locale locale)
-{
- free (locale->locale_name);
- locale->locale_name = NULL;
-}
-
#else /* USE_GNU_LOCALE_API */
/* Alias for glibc's locale type. */
typedef locale_t scm_t_locale;
-#define scm_i_locale_free freelocale
-
#endif /* USE_GNU_LOCALE_API */
#define SCM_VALIDATE_OPTIONAL_LOCALE_COPY(_pos, _arg, _c_locale) \
do \
{ \
- if ((_arg) != SCM_UNDEFINED) \
+ if (!SCM_UNBNDP (_arg)) \
SCM_VALIDATE_LOCALE_COPY (_pos, _arg, _c_locale); \
else \
(_c_locale) = NULL; \
SCM_SMOB (scm_tc16_locale_smob_type, "locale", 0);
+#ifdef USE_GNU_LOCALE_API
+
SCM_SMOB_FREE (scm_tc16_locale_smob_type, smob_locale_free, locale)
{
scm_t_locale c_locale;
c_locale = (scm_t_locale) SCM_SMOB_DATA (locale);
- scm_i_locale_free (c_locale);
+ if (c_locale)
+ freelocale (c_locale);
return 0;
}
+#endif /* USE_GNU_LOCALE_API */
+
static void inline scm_locale_error (const char *, int) SCM_NORETURN;
account. */
category_mask |= locale->category_mask;
- if (locale->base_locale != SCM_UNDEFINED)
+ if (!SCM_UNBNDP (locale->base_locale))
locale = (scm_t_locale) SCM_SMOB_DATA (locale->base_locale);
else
locale = NULL;
/* Restore the previous locale settings. */
(void)restore_locale_settings (settings);
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+ unlock_locale_mutex ();
}
/* Enter a locked locale section. */
{
int err;
- scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
+ lock_locale_mutex ();
err = get_current_locale_settings (prev_locale);
if (err)
{
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+ unlock_locale_mutex ();
return err;
}
c_locale = scm_gc_malloc (sizeof (* c_locale), "locale");
-
- scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
+ lock_locale_mutex ();
c_locale->category_mask = LC_ALL_MASK;
c_locale->base_locale = SCM_UNDEFINED;
current_locale = setlocale (LC_ALL, NULL);
if (current_locale != NULL)
- {
- c_locale->locale_name = strdup (current_locale);
- if (c_locale->locale_name == NULL)
- err = ENOMEM;
- }
+ c_locale->locale_name = scm_gc_strdup (current_locale, "locale");
else
err = EINVAL;
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+ unlock_locale_mutex ();
- if (err)
- scm_gc_free (c_locale, sizeof (* c_locale), "locale");
- else
+ if (err == 0)
SCM_NEWSMOB (*result, scm_tc16_locale_smob_type, c_locale);
+ else
+ *result = SCM_BOOL_F;
return err;
}
#ifdef USE_GNU_LOCALE_API
if (scm_is_eq (base_locale, SCM_VARIABLE_REF (scm_global_locale)))
- {
- /* Fetch the current locale and turn in into a `locale_t'. Don't
- duplicate the resulting `locale_t' because we want it to be consumed
- by `newlocale ()'. */
- char *current_locale;
-
- scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
-
- current_locale = setlocale (LC_ALL, NULL);
- c_base_locale = newlocale (LC_ALL_MASK, current_locale, NULL);
+ c_base_locale = LC_GLOBAL_LOCALE;
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
-
- if (c_base_locale == (locale_t) 0)
- scm_locale_error (FUNC_NAME, errno);
- }
- else if (c_base_locale != (locale_t) 0)
+ if (c_base_locale != (locale_t) 0)
{
/* C_BASE_LOCALE is to be consumed by `newlocale ()' so it needs to be
duplicated before. */
c_base_locale = duplocale (c_base_locale);
+
if (c_base_locale == (locale_t) 0)
{
err = errno;
c_locale = newlocale (c_category_mask, c_locale_name, c_base_locale);
free (c_locale_name);
+ c_locale_name = NULL;
if (c_locale == (locale_t) 0)
{
- if (scm_is_eq (base_locale, SCM_VARIABLE_REF (scm_global_locale)))
- /* The base locale object was created lazily and must be freed. */
+ if (c_base_locale != (locale_t) 0)
freelocale (c_base_locale);
-
scm_locale_error (FUNC_NAME, errno);
}
else
c_locale = scm_gc_malloc (sizeof (* c_locale), "locale");
c_locale->category_mask = c_category_mask;
- c_locale->locale_name = c_locale_name;
+ c_locale->locale_name = scm_gc_strdup (c_locale_name, "locale");
+ free (c_locale_name);
+ c_locale_name = NULL;
if (scm_is_eq (base_locale, SCM_VARIABLE_REF (scm_global_locale)))
{
}
}
+ /* silence gcc's unused variable warning */
+ (void) c_base_locale;
#endif
return locale;
const char *buf = scm_i_string_chars (s1); \
\
len = scm_i_string_length (s1); \
- c_s1 = (scm_t_wchar *) alloca (sizeof (scm_t_wchar) * (len + 1)); \
+ c_s1 = alloca (sizeof (scm_t_wchar) * (len + 1)); \
\
for (i = 0; i < len; i ++) \
c_s1[i] = (unsigned char ) buf[i]; \
static const char *
locale_language ()
{
- /* FIXME: If the locale has been set with 'uselocale',
- libunistring's uc_locale_language will return the incorrect
- language: it will return the language appropriate for the global
- (non-thread-specific) locale.
-
- There appears to be no portable way to extract the language from
- the thread-specific locale_t. There is no LANGUAGE capability in
- nl_langinfo or nl_langinfo_l.
-
- Thus, uc_locale_language needs to be fixed upstream. */
+ /* Note: If the locale has been set with 'uselocale', uc_locale_language
+ from libunistring versions 0.9.1 and older will return the incorrect
+ (non-thread-specific) locale. This is fixed in versions 0.9.2 and
+ newer. */
return uc_locale_language ();
}
}
-
-SCM_DEFINE (scm_char_locale_downcase, "char-locale-downcase", 1, 1, 0,
- (SCM chr, SCM locale),
- "Return the lowercase character that corresponds to @var{chr} "
- "according to either @var{locale} or the current locale.")
-#define FUNC_NAME s_scm_char_locale_downcase
+static SCM
+chr_to_case (SCM chr, scm_t_locale c_locale,
+ scm_t_uint32 *(*func) (const scm_t_uint32 *, size_t, const char *,
+ uninorm_t, scm_t_uint32 *, size_t *),
+ const char *func_name,
+ int *err)
+#define FUNC_NAME func_name
{
int ret;
- scm_t_locale c_locale;
- scm_t_wchar *buf;
- scm_t_uint32 *downbuf;
- size_t downlen;
- SCM str, downchar;
+ scm_t_uint32 c;
+ scm_t_uint32 *convbuf;
+ size_t convlen;
+ SCM convchar;
- SCM_VALIDATE_CHAR (1, chr);
- SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
-
- str = scm_i_make_wide_string (1, &buf);
- buf[0] = SCM_CHAR (chr);
+ c = SCM_CHAR (chr);
if (c_locale != NULL)
RUN_IN_LOCALE_SECTION (c_locale, ret =
- u32_locale_tocase ((scm_t_uint32 *) buf, 1,
- &downbuf,
- &downlen, u32_tolower));
+ u32_locale_tocase (&c, 1, &convbuf, &convlen, func));
else
ret =
- u32_locale_tocase ((scm_t_uint32 *) buf, 1, &downbuf,
- &downlen, u32_tolower);
+ u32_locale_tocase (&c, 1, &convbuf, &convlen, func);
if (SCM_UNLIKELY (ret != 0))
{
- errno = ret;
- scm_syserror (FUNC_NAME);
+ *err = ret;
+ return SCM_BOOL_F;
}
- if (downlen == 1)
- downchar = SCM_MAKE_CHAR ((scm_t_wchar) downbuf[0]);
+ if (convlen == 1)
+ convchar = SCM_MAKE_CHAR ((scm_t_wchar) convbuf[0]);
else
- downchar = chr;
- free (downbuf);
+ convchar = chr;
+ free (convbuf);
+
+ return convchar;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_char_locale_downcase, "char-locale-downcase", 1, 1, 0,
+ (SCM chr, SCM locale),
+ "Return the lowercase character that corresponds to @var{chr} "
+ "according to either @var{locale} or the current locale.")
+#define FUNC_NAME s_scm_char_locale_downcase
+{
+ scm_t_locale c_locale;
+ SCM ret;
+ int err = 0;
+
+ SCM_VALIDATE_CHAR (1, chr);
+ SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
+
+ ret = chr_to_case (chr, c_locale, u32_tolower, FUNC_NAME, &err);
- return downchar;
+ if (err != 0)
+ {
+ errno = err;
+ scm_syserror (FUNC_NAME);
+ }
+ return ret;
}
#undef FUNC_NAME
"according to either @var{locale} or the current locale.")
#define FUNC_NAME s_scm_char_locale_upcase
{
- int ret;
scm_t_locale c_locale;
- scm_t_wchar *buf;
- scm_t_uint32 *upbuf;
- size_t uplen;
- SCM str, upchar;
+ SCM ret;
+ int err = 0;
SCM_VALIDATE_CHAR (1, chr);
SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
- str = scm_i_make_wide_string (1, &buf);
- buf[0] = SCM_CHAR (chr);
+ ret = chr_to_case (chr, c_locale, u32_toupper, FUNC_NAME, &err);
- if (c_locale != NULL)
- RUN_IN_LOCALE_SECTION (c_locale, ret =
- u32_locale_tocase ((scm_t_uint32 *) buf, 1,
- &upbuf,
- &uplen, u32_toupper));
- else
- ret =
- u32_locale_tocase ((scm_t_uint32 *) buf, 1, &upbuf,
- &uplen, u32_toupper);
+ if (err != 0)
+ {
+ errno = err;
+ scm_syserror (FUNC_NAME);
+ }
+ return ret;
+}
+#undef FUNC_NAME
- if (SCM_UNLIKELY (ret != 0))
+SCM_DEFINE (scm_char_locale_titlecase, "char-locale-titlecase", 1, 1, 0,
+ (SCM chr, SCM locale),
+ "Return the titlecase character that corresponds to @var{chr} "
+ "according to either @var{locale} or the current locale.")
+#define FUNC_NAME s_scm_char_locale_titlecase
+{
+ scm_t_locale c_locale;
+ SCM ret;
+ int err = 0;
+
+ SCM_VALIDATE_CHAR (1, chr);
+ SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
+
+ ret = chr_to_case (chr, c_locale, u32_totitle, FUNC_NAME, &err);
+
+ if (err != 0)
{
- errno = ret;
+ errno = err;
scm_syserror (FUNC_NAME);
}
- if (uplen == 1)
- upchar = SCM_MAKE_CHAR ((scm_t_wchar) upbuf[0]);
- else
- upchar = chr;
- free (upbuf);
- return upchar;
+ return ret;
}
#undef FUNC_NAME
-SCM_DEFINE (scm_string_locale_upcase, "string-locale-upcase", 1, 1, 0,
- (SCM str, SCM locale),
- "Return a new string that is the uppercase version of "
- "@var{str} according to either @var{locale} or the current "
- "locale.")
-#define FUNC_NAME s_scm_string_locale_upcase
+static SCM
+str_to_case (SCM str, scm_t_locale c_locale,
+ scm_t_uint32 *(*func) (const scm_t_uint32 *, size_t, const char *,
+ uninorm_t, scm_t_uint32 *, size_t *),
+ const char *func_name,
+ int *err)
+#define FUNC_NAME func_name
{
scm_t_wchar *c_str, *c_buf;
- scm_t_uint32 *c_upstr;
- size_t len, uplen;
+ scm_t_uint32 *c_convstr;
+ size_t len, convlen;
int ret;
- scm_t_locale c_locale;
- SCM upstr;
+ SCM convstr;
- SCM_VALIDATE_STRING (1, str);
- SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
len = scm_i_string_length (str);
if (len == 0)
return scm_nullstr;
if (c_locale)
RUN_IN_LOCALE_SECTION (c_locale, ret =
u32_locale_tocase ((scm_t_uint32 *) c_str, len,
- &c_upstr,
- &uplen, u32_toupper));
+ &c_convstr,
+ &convlen, func));
else
ret =
u32_locale_tocase ((scm_t_uint32 *) c_str, len,
- &c_upstr, &uplen, u32_toupper);
+ &c_convstr, &convlen, func);
scm_remember_upto_here (str);
if (SCM_UNLIKELY (ret != 0))
{
- errno = ret;
- scm_syserror (FUNC_NAME);
+ *err = ret;
+ return SCM_BOOL_F;
}
- upstr = scm_i_make_wide_string (uplen, &c_buf);
- memcpy (c_buf, c_upstr, uplen * sizeof (scm_t_wchar));
- free (c_upstr);
+ convstr = scm_i_make_wide_string (convlen, &c_buf, 0);
+ memcpy (c_buf, c_convstr, convlen * sizeof (scm_t_wchar));
+ free (c_convstr);
+
+ scm_i_try_narrow_string (convstr);
+
+ return convstr;
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_string_locale_upcase, "string-locale-upcase", 1, 1, 0,
+ (SCM str, SCM locale),
+ "Return a new string that is the uppercase version of "
+ "@var{str} according to either @var{locale} or the current "
+ "locale.")
+#define FUNC_NAME s_scm_string_locale_upcase
+{
+ scm_t_locale c_locale;
+ SCM ret;
+ int err = 0;
- scm_i_try_narrow_string (upstr);
+ SCM_VALIDATE_STRING (1, str);
+ SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
- return upstr;
+ ret = str_to_case (str, c_locale, u32_toupper, FUNC_NAME, &err);
+
+ if (err != 0)
+ {
+ errno = err;
+ scm_syserror (FUNC_NAME);
+ }
+ return ret;
}
#undef FUNC_NAME
"locale.")
#define FUNC_NAME s_scm_string_locale_downcase
{
- scm_t_wchar *c_str, *c_buf;
- scm_t_uint32 *c_downstr;
- size_t len, downlen;
- int ret;
scm_t_locale c_locale;
- SCM downstr;
+ SCM ret;
+ int err = 0;
SCM_VALIDATE_STRING (1, str);
SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
- len = scm_i_string_length (str);
- if (len == 0)
- return scm_nullstr;
- SCM_STRING_TO_U32_BUF (str, c_str);
-
- if (c_locale)
- RUN_IN_LOCALE_SECTION (c_locale, ret =
- u32_locale_tocase ((scm_t_uint32 *) c_str, len,
- &c_downstr,
- &downlen, u32_tolower));
- else
- ret =
- u32_locale_tocase ((scm_t_uint32 *) c_str, len,
- &c_downstr, &downlen, u32_tolower);
- scm_remember_upto_here (str);
+ ret = str_to_case (str, c_locale, u32_tolower, FUNC_NAME, &err);
- if (SCM_UNLIKELY (ret != 0))
+ if (err != 0)
{
- errno = ret;
+ errno = err;
scm_syserror (FUNC_NAME);
}
+ return ret;
+}
+#undef FUNC_NAME
- downstr = scm_i_make_wide_string (downlen, &c_buf);
- memcpy (c_buf, c_downstr, downlen * sizeof (scm_t_wchar));
- free (c_downstr);
+SCM_DEFINE (scm_string_locale_titlecase, "string-locale-titlecase", 1, 1, 0,
+ (SCM str, SCM locale),
+ "Return a new string that is the title-case version of "
+ "@var{str} according to either @var{locale} or the current "
+ "locale.")
+#define FUNC_NAME s_scm_string_locale_titlecase
+{
+ scm_t_locale c_locale;
+ SCM ret;
+ int err = 0;
+
+ SCM_VALIDATE_STRING (1, str);
+ SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
- scm_i_try_narrow_string (downstr);
+ ret = str_to_case (str, c_locale, u32_totitle, FUNC_NAME, &err);
- return downstr;
+ if (err != 0)
+ {
+ errno = err;
+ scm_syserror (FUNC_NAME);
+ }
+ return ret;
}
#undef FUNC_NAME
SCM_VALIDATE_STRING (1, str);
c_str = scm_i_string_chars (str);
- if (base != SCM_UNDEFINED)
+ if (!scm_is_eq (base, SCM_UNDEFINED))
SCM_VALIDATE_INT_COPY (2, base, c_base);
else
c_base = 10;
setting of the current locale. If nl_langinfo supports CODESET,
we can convert the string properly using scm_from_stringn. If
CODESET is not supported, we won't be able to make much sense of
- the returned string. */
+ the returned string.
+ Note: We don't use Gnulib's `nl_langinfo' module because it's currently not
+ as complete as the compatibility hacks in `i18n.scm'. */
+
+static char *
+copy_string_or_null (const char *s)
+{
+ if (s == NULL)
+ return NULL;
+ else
+ return strdup (s);
+}
SCM_DEFINE (scm_nl_langinfo, "nl-langinfo", 1, 1, 0,
(SCM item, SCM locale),
"Reference Manual}).")
#define FUNC_NAME s_scm_nl_langinfo
{
-#ifdef HAVE_NL_LANGINFO
SCM result;
nl_item c_item;
char *c_result;
scm_t_locale c_locale;
-#ifdef HAVE_LANGINFO_CODESET
char *codeset;
-#endif
SCM_VALIDATE_INT_COPY (2, item, c_item);
SCM_VALIDATE_OPTIONAL_LOCALE_COPY (2, locale, c_locale);
http://opengroup.org/onlinepubs/007908799/xsh/nl_langinfo.html for
details. */
- scm_i_pthread_mutex_lock (&scm_i_locale_mutex);
+ lock_locale_mutex ();
if (c_locale != NULL)
{
#ifdef USE_GNU_LOCALE_API
- c_result = nl_langinfo_l (c_item, c_locale);
-#ifdef HAVE_LANGINFO_CODESET
- codeset = nl_langinfo_l (CODESET, c_locale);
-#endif /* HAVE_LANGINFO_CODESET */
+ c_result = copy_string_or_null (nl_langinfo_l (c_item, c_locale));
+ codeset = copy_string_or_null (nl_langinfo_l (CODESET, c_locale));
#else /* !USE_GNU_LOCALE_API */
/* We can't use `RUN_IN_LOCALE_SECTION ()' here because the locale
mutex is already taken. */
lsec_err = get_current_locale_settings (&lsec_prev_locale);
if (lsec_err)
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+ unlock_locale_mutex ();
else
{
lsec_err = install_locale (c_locale);
scm_locale_error (FUNC_NAME, lsec_err);
else
{
- c_result = nl_langinfo (c_item);
-#ifdef HAVE_LANGINFO_CODESET
- codeset = nl_langinfo (CODESET);
-#endif /* HAVE_LANGINFO_CODESET */
+ c_result = copy_string_or_null (nl_langinfo (c_item));
+ codeset = copy_string_or_null (nl_langinfo (CODESET));
restore_locale_settings (&lsec_prev_locale);
free_locale_settings (&lsec_prev_locale);
}
else
{
- c_result = nl_langinfo (c_item);
-#ifdef HAVE_LANGINFO_CODESET
- codeset = nl_langinfo (CODESET);
-#endif /* HAVE_LANGINFO_CODESET */
+ c_result = copy_string_or_null (nl_langinfo (c_item));
+ codeset = copy_string_or_null (nl_langinfo (CODESET));
}
- c_result = strdup (c_result);
- scm_i_pthread_mutex_unlock (&scm_i_locale_mutex);
+ unlock_locale_mutex ();
if (c_result == NULL)
result = SCM_BOOL_F;
{
char *p;
- /* In this cases, the result is to be interpreted as a list of
- numbers. If the last item is `CHARS_MAX', it has the special
- meaning "no more grouping". */
+ /* In this cases, the result is to be interpreted as a list
+ of numbers. If the last item is `CHAR_MAX' or a negative
+ number, it has the special meaning "no more grouping"
+ (negative numbers aren't specified in POSIX but can be
+ used by glibc; see
+ <http://lists.gnu.org/archive/html/bug-guile/2011-02/msg00159.html>). */
result = SCM_EOL;
- for (p = c_result; (*p != '\0') && (*p != CHAR_MAX); p++)
+ for (p = c_result; (*p > 0) && (*p != CHAR_MAX); p++)
result = scm_cons (SCM_I_MAKINUM ((int) *p), result);
{
result = scm_reverse_x (result, SCM_EOL);
- if (*p != CHAR_MAX)
+ if (*p == 0)
{
/* Cyclic grouping information. */
- if (last_pair != SCM_EOL)
+ if (!scm_is_null (last_pair))
SCM_SETCDR (last_pair, result);
}
}
}
#endif
-#if (defined FRAC_DIGITS) && (defined INT_FRAC_DIGITS)
+#if defined FRAC_DIGITS || defined INT_FRAC_DIGITS
+#ifdef FRAC_DIGITS
case FRAC_DIGITS:
+#endif
+#ifdef INT_FRAC_DIGITS
case INT_FRAC_DIGITS:
+#endif
/* This is to be interpreted as a single integer. */
if (*c_result == CHAR_MAX)
/* Unspecified. */
break;
#endif
-#if (defined P_CS_PRECEDES) && (defined INT_N_CS_PRECEDES)
+#if defined P_CS_PRECEDES || defined N_CS_PRECEDES || \
+ defined INT_P_CS_PRECEDES || defined INT_N_CS_PRECEDES || \
+ defined P_SEP_BY_SPACE || defined N_SEP_BY_SPACE
+#ifdef P_CS_PRECEDES
case P_CS_PRECEDES:
case N_CS_PRECEDES:
+#endif
+#ifdef INT_N_CS_PRECEDES
case INT_P_CS_PRECEDES:
case INT_N_CS_PRECEDES:
-#if (defined P_SEP_BY_SPACE) && (defined N_SEP_BY_SPACE)
+#endif
+#ifdef P_SEP_BY_SPACE
case P_SEP_BY_SPACE:
case N_SEP_BY_SPACE:
#endif
break;
#endif
-#if (defined P_SIGN_POSN) && (defined INT_N_SIGN_POSN)
+#if defined P_SIGN_POSN || defined N_SIGN_POSN || \
+ defined INT_P_SIGN_POSN || defined INT_N_SIGN_POSN
+#ifdef P_SIGN_POSN
case P_SIGN_POSN:
case N_SIGN_POSN:
+#endif
+#ifdef INT_P_SIGN_POSN
case INT_P_SIGN_POSN:
case INT_N_SIGN_POSN:
+#endif
/* See `(libc) Sign of Money Amount' for the interpretation of the
return value here. */
switch (*c_result)
{
case 0:
- result = scm_from_locale_symbol ("parenthesize");
+ result = scm_from_latin1_symbol ("parenthesize");
break;
case 1:
- result = scm_from_locale_symbol ("sign-before");
+ result = scm_from_latin1_symbol ("sign-before");
break;
case 2:
- result = scm_from_locale_symbol ("sign-after");
+ result = scm_from_latin1_symbol ("sign-after");
break;
case 3:
- result = scm_from_locale_symbol ("sign-before-currency-symbol");
+ result = scm_from_latin1_symbol ("sign-before-currency-symbol");
break;
case 4:
- result = scm_from_locale_symbol ("sign-after-currency-symbol");
+ result = scm_from_latin1_symbol ("sign-after-currency-symbol");
break;
default:
- result = scm_from_locale_symbol ("unspecified");
+ result = scm_from_latin1_symbol ("unspecified");
}
+ free (c_result);
break;
#endif
default:
-#ifdef HAVE_LANGINFO_CODESET
result = scm_from_stringn (c_result, strlen (c_result),
codeset,
SCM_FAILED_CONVERSION_QUESTION_MARK);
-#else /* !HAVE_LANGINFO_CODESET */
- /* This may be incorrectly encoded if the locale differs
- from the c_locale. */
- result = scm_from_locale_string (c_result);
-#endif /* !HAVE_LANGINFO_CODESET */
free (c_result);
}
}
- return result;
-#else
- scm_syserror_msg (FUNC_NAME, "`nl-langinfo' not supported on your system",
- SCM_EOL, ENOSYS);
+ if (codeset != NULL)
+ free (codeset);
- return SCM_BOOL_F;
-#endif
+ return result;
}
#undef FUNC_NAME
static inline void
define_langinfo_items (void)
{
-#if (defined HAVE_NL_TYPES_H) && (defined HAVE_LANGINFO_H)
-
#define DEFINE_NLITEM_CONSTANT(_item) \
scm_c_define (# _item, scm_from_int (_item))
DEFINE_NLITEM_CONSTANT (T_FMT); /* Time format for strftime. */
DEFINE_NLITEM_CONSTANT (T_FMT_AMPM);/* 12-hour time format for strftime. */
+#ifdef ERA
DEFINE_NLITEM_CONSTANT (ERA); /* Alternate era. */
+#endif
+#ifdef ERA_D_FMT
DEFINE_NLITEM_CONSTANT (ERA_D_FMT); /* Date in alternate era format. */
+#endif
+#ifdef ERA_D_T_FMT
DEFINE_NLITEM_CONSTANT (ERA_D_T_FMT); /* Date and time in alternate era
format. */
+#endif
+#ifdef ERA_T_FMT
DEFINE_NLITEM_CONSTANT (ERA_T_FMT); /* Time in alternate era format. */
+#endif
+#ifdef ALT_DIGITS
DEFINE_NLITEM_CONSTANT (ALT_DIGITS); /* Alternate symbols for digits. */
+#endif
DEFINE_NLITEM_CONSTANT (RADIXCHAR);
DEFINE_NLITEM_CONSTANT (THOUSEP);
#endif
#undef DEFINE_NLITEM_CONSTANT
-
-#endif /* HAVE_NL_TYPES_H */
}
\f
{
SCM global_locale_smob;
-#ifdef HAVE_NL_LANGINFO
scm_add_feature ("nl-langinfo");
define_langinfo_items ();
-#endif
#include "libguile/i18n.x"
/* Initialize the global locale object with a special `locale' SMOB. */
+ /* XXX: We don't define it as `LC_GLOBAL_LOCALE' because of bugs as of
+ glibc <= 2.11 not (yet) worked around by Gnulib. See
+ http://sourceware.org/bugzilla/show_bug.cgi?id=11009 for details. */
SCM_NEWSMOB (global_locale_smob, scm_tc16_locale_smob_type, NULL);
SCM_VARIABLE_SET (scm_global_locale, global_locale_smob);
}
void
scm_bootstrap_i18n ()
{
- scm_c_register_extension ("libguile", "scm_init_i18n",
+ scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
+ "scm_init_i18n",
(scm_t_extension_init_func) scm_init_i18n,
NULL);