Mercurial > gnulib
changeset 39917:5f0e12c5ef27
localename: Add support for per-thread locales on Solaris 11.4.
* lib/locale.in.h (newlocale, freelocale): New declarations.
(duplocale): Declare also when the 'localename' module requests it.
* lib/localename.c (struniq_hash_node): Renamed from hash_node.
(STRUNIQ_HASH_TABLE_SIZE): Renamed from HASH_TABLE_SIZE.
(struniq): Update.
(struct locale_categories_names, struct locale_hash_node): New types.
(LOCALE_HASH_TABLE_SIZE): New constant.
(locale_hash_table, locale_lock): New variables.
(pointer_hash, get_locale_t_name): New functions.
(newlocale, duplocale, freelocale): New overridden functions.
(gl_locale_name_thread_unsafe): Use get_locale_t_name.
* m4/intlsolaris.m4: New file.
* m4/localename.m4 (gl_LOCALENAME): Require gl_LOCALE_H_DEFAULTS. Invoke
gt_INTL_SOLARIS. Set HAVE_NEWLOCALE, HAVE_DUPLOCALE, HAVE_FREELOCALE,
REPLACE_NEWLOCALE, REPLACE_DUPLOCALE, REPLACE_FREELOCALE.
* m4/locale_h.m4 (gl_LOCALE_H): Test whether newlocale, freelocale are
declared.
(gl_LOCALE_H_DEFAULTS): Initialize GNULIB_LOCALENAME, HAVE_NEWLOCALE,
HAVE_FREELOCALE, REPLACE_NEWLOCALE, REPLACE_FREELOCALE.
* modules/locale (Makefile.am): Substitute GNULIB_LOCALENAME,
HAVE_NEWLOCALE, HAVE_FREELOCALE, REPLACE_NEWLOCALE, REPLACE_FREELOCALE.
* modules/localename (Files): Add intlsolaris.m4.
(Depends-on): Add 'locale'.
(configure.ac): Invoke gl_LOCALE_MODULE_INDICATOR.
* tests/test-locale-c++.cc (newlocale, freelocale): Prepare for checking
the signatures.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 14 Oct 2018 17:03:01 +0200 |
parents | dbcdcd1db895 |
children | c17f5376064e |
files | ChangeLog lib/locale.in.h lib/localename.c m4/intlsolaris.m4 m4/locale_h.m4 m4/localename.m4 modules/locale modules/localename tests/test-locale-c++.cc |
diffstat | 9 files changed, 606 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Fri Oct 12 06:46:09 2018 +0200 +++ b/ChangeLog Sun Oct 14 17:03:01 2018 +0200 @@ -1,3 +1,33 @@ +2018-10-14 Bruno Haible <bruno@clisp.org> + + localename: Add support for per-thread locales on Solaris 11.4. + * lib/locale.in.h (newlocale, freelocale): New declarations. + (duplocale): Declare also when the 'localename' module requests it. + * lib/localename.c (struniq_hash_node): Renamed from hash_node. + (STRUNIQ_HASH_TABLE_SIZE): Renamed from HASH_TABLE_SIZE. + (struniq): Update. + (struct locale_categories_names, struct locale_hash_node): New types. + (LOCALE_HASH_TABLE_SIZE): New constant. + (locale_hash_table, locale_lock): New variables. + (pointer_hash, get_locale_t_name): New functions. + (newlocale, duplocale, freelocale): New overridden functions. + (gl_locale_name_thread_unsafe): Use get_locale_t_name. + * m4/intlsolaris.m4: New file. + * m4/localename.m4 (gl_LOCALENAME): Require gl_LOCALE_H_DEFAULTS. Invoke + gt_INTL_SOLARIS. Set HAVE_NEWLOCALE, HAVE_DUPLOCALE, HAVE_FREELOCALE, + REPLACE_NEWLOCALE, REPLACE_DUPLOCALE, REPLACE_FREELOCALE. + * m4/locale_h.m4 (gl_LOCALE_H): Test whether newlocale, freelocale are + declared. + (gl_LOCALE_H_DEFAULTS): Initialize GNULIB_LOCALENAME, HAVE_NEWLOCALE, + HAVE_FREELOCALE, REPLACE_NEWLOCALE, REPLACE_FREELOCALE. + * modules/locale (Makefile.am): Substitute GNULIB_LOCALENAME, + HAVE_NEWLOCALE, HAVE_FREELOCALE, REPLACE_NEWLOCALE, REPLACE_FREELOCALE. + * modules/localename (Files): Add intlsolaris.m4. + (Depends-on): Add 'locale'. + (configure.ac): Invoke gl_LOCALE_MODULE_INDICATOR. + * tests/test-locale-c++.cc (newlocale, freelocale): Prepare for checking + the signatures. + 2018-10-14 Akim Demaille <akim@lrde.epita.fr> timevar: use gethrxtime to get wall clock time @@ -15,7 +45,6 @@ (timevar_print): Instead of checking whether the timings themselves are large enough for the timevar to be printed, check the percentages. - 2018-10-14 Bruno Haible <bruno@clisp.org> wcsnrtombs: Work around Solaris 11.4 bug.
--- a/lib/locale.in.h Fri Oct 12 06:46:09 2018 +0200 +++ b/lib/locale.in.h Sun Oct 14 17:03:01 2018 +0200 @@ -190,7 +190,34 @@ # endif #endif -#if @GNULIB_DUPLOCALE@ +#if /*@GNULIB_NEWLOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_NEWLOCALE@) +# if @REPLACE_NEWLOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef newlocale +# define newlocale rpl_newlocale +# endif +_GL_FUNCDECL_RPL (newlocale, locale_t, + (int category_mask, const char *name, locale_t base) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (newlocale, locale_t, + (int category_mask, const char *name, locale_t base)); +# else +# if @HAVE_NEWLOCALE@ +_GL_CXXALIAS_SYS (newlocale, locale_t, + (int category_mask, const char *name, locale_t base)); +# endif +# endif +# if @HAVE_NEWLOCALE@ +_GL_CXXALIASWARN (newlocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef newlocale +# if HAVE_RAW_DECL_NEWLOCALE +_GL_WARN_ON_USE (newlocale, "newlocale is not portable"); +# endif +#endif + +#if @GNULIB_DUPLOCALE@ || (@GNULIB_LOCALENAME@ && @HAVE_DUPLOCALE@) # if @REPLACE_DUPLOCALE@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # undef duplocale @@ -214,6 +241,29 @@ # endif #endif +#if /*@GNULIB_FREELOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_FREELOCALE@) +# if @REPLACE_FREELOCALE@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef freelocale +# define freelocale rpl_freelocale +# endif +_GL_FUNCDECL_RPL (freelocale, void, (locale_t locale) _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (freelocale, void, (locale_t locale)); +# else +# if @HAVE_FREELOCALE@ +_GL_CXXALIAS_SYS (freelocale, void, (locale_t locale)); +# endif +# endif +# if @HAVE_FREELOCALE@ +_GL_CXXALIASWARN (freelocale); +# endif +#elif defined GNULIB_POSIXCHECK +# undef freelocale +# if HAVE_RAW_DECL_FREELOCALE +_GL_WARN_ON_USE (freelocale, "freelocale is not portable"); +# endif +#endif + #endif /* _@GUARD_PREFIX@_LOCALE_H */ #endif /* _@GUARD_PREFIX@_LOCALE_H */ #endif /* !(__need_locale_t || _GL_ALREADY_INCLUDING_LOCALE_H) */
--- a/lib/localename.c Fri Oct 12 06:46:09 2018 +0200 +++ b/lib/localename.c Sun Oct 14 17:03:01 2018 +0200 @@ -50,6 +50,10 @@ /* Solaris >= 12. */ extern char * getlocalename_l(int, locale_t); # endif +# if HAVE_NAMELESS_LOCALES +# include <errno.h> +# include <stdint.h> +# endif #endif #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE @@ -2615,7 +2619,7 @@ #endif -#if HAVE_USELOCALE /* glibc, Mac OS X, Solaris 11 OpenIndiana, or Solaris 12 */ +#if HAVE_USELOCALE /* glibc, Mac OS X, Solaris 11 OpenIndiana, or Solaris >= 11.4 */ /* Simple hash set of strings. We don't want to drag in lots of hash table code here. */ @@ -2641,14 +2645,14 @@ simultaneously, but only one thread can insert into it at the same time. */ /* A node in a hash bucket collision list. */ -struct hash_node +struct struniq_hash_node { - struct hash_node * volatile next; + struct struniq_hash_node * volatile next; char contents[FLEXIBLE_ARRAY_MEMBER]; }; -# define HASH_TABLE_SIZE 257 -static struct hash_node * volatile struniq_hash_table[HASH_TABLE_SIZE] +# define STRUNIQ_HASH_TABLE_SIZE 257 +static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE] /* = { NULL, ..., NULL } */; /* This lock protects the struniq_hash_table against multiple simultaneous @@ -2661,17 +2665,17 @@ struniq (const char *string) { size_t hashcode = string_hash (string); - size_t slot = hashcode % HASH_TABLE_SIZE; + size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE; size_t size; - struct hash_node *new_node; - struct hash_node *p; + struct struniq_hash_node *new_node; + struct struniq_hash_node *p; for (p = struniq_hash_table[slot]; p != NULL; p = p->next) if (strcmp (p->contents, string) == 0) return p->contents; size = strlen (string) + 1; new_node = - (struct hash_node *) - malloc (FLEXSIZEOF (struct hash_node, contents, size)); + (struct struniq_hash_node *) + malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size)); if (new_node == NULL) /* Out of memory. Return a statically allocated string. */ return "C"; @@ -2700,6 +2704,421 @@ #endif +#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */ + +/* The 'locale_t' object does not contain the names of the locale categories. + We have to associate them with the object through a hash table. */ + +struct locale_categories_names + { + /* Locale category -> name (allocated with indefinite extent). */ + const char *category_name[6]; + }; + +/* A hash function for pointers. */ +static size_t _GL_ATTRIBUTE_CONST +pointer_hash (const void *x) +{ + uintptr_t p = (uintptr_t) x; + size_t h = ((p % 4177) << 12) + ((p % 79) << 6) + (p % 61); + return h; +} + +/* A hash table of fixed size. Multiple threads can access it read-only + simultaneously, but only one thread can insert into it or remove from it + at the same time. */ + +/* A node in a hash bucket collision list. */ +struct locale_hash_node + { + struct locale_hash_node *next; + locale_t locale; + struct locale_categories_names names; + }; + +# define LOCALE_HASH_TABLE_SIZE 101 +static struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE] + /* = { NULL, ..., NULL } */; + +/* This lock protects the locale_hash_table against multiple simultaneous + accesses (except that multiple simultaneous read accesses are allowed). */ + +gl_rwlock_define_initialized(static, locale_lock) + +/* Returns the name of a given locale category in a given locale_t object, + allocated as a string with indefinite extent. */ +static const char * +get_locale_t_name (int category, locale_t locale) +{ + if (locale == LC_GLOBAL_LOCALE) + { + /* Query the global locale. */ + const char *name = setlocale (category, NULL); + if (name != NULL) + return struniq (name); + else + /* Should normally not happen. */ + return ""; + } + else + { + /* Look up the names in the hash table. */ + size_t hashcode = pointer_hash (locale); + size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; + /* If the locale was not found in the table, return "". This can + happen if the application uses the original newlocale()/duplocale() + functions instead of the overridden ones. */ + const char *name = ""; + struct locale_hash_node *p; + /* Lock while looking up the hash node. */ + gl_rwlock_rdlock (locale_lock); + for (p = locale_hash_table[slot]; p != NULL; p = p->next) + if (p->locale == locale) + { + name = p->names.category_name[category]; + break; + } + gl_rwlock_unlock (locale_lock); + return name; + } +} + +# if !(defined newlocale && defined duplocale && defined freelocale) +# error "newlocale, duplocale, freelocale not being replaced as expected!" +# endif + +/* newlocale() override. */ +locale_t +newlocale (int category_mask, const char *name, locale_t base) +#undef newlocale +{ + struct locale_categories_names names; + struct locale_hash_node *node; + locale_t result; + + /* Make sure name has indefinite extent. */ + if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK + | LC_MONETARY_MASK | LC_MESSAGES_MASK) + & category_mask) != 0) + name = struniq (name); + + /* Determine the category names of the result. */ + if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK + | LC_MONETARY_MASK | LC_MESSAGES_MASK) + & ~category_mask) == 0) + { + /* Use name, ignore base. */ + int category; + + name = struniq (name); + for (category = 0; category < 6; category++) + names.category_name[category] = name; + } + else + { + /* Use base, possibly also name. */ + if (base == NULL) + { + int category; + + for (category = 0; category < 6; category++) + { + int mask; + + switch (category) + { + case LC_CTYPE: + mask = LC_CTYPE_MASK; + break; + case LC_NUMERIC: + mask = LC_NUMERIC_MASK; + break; + case LC_TIME: + mask = LC_TIME_MASK; + break; + case LC_COLLATE: + mask = LC_COLLATE_MASK; + break; + case LC_MONETARY: + mask = LC_MONETARY_MASK; + break; + case LC_MESSAGES: + mask = LC_MESSAGES_MASK; + break; + default: + abort (); + } + names.category_name[category] = + ((mask & category_mask) != 0 ? name : "C"); + } + } + else if (base == LC_GLOBAL_LOCALE) + { + int category; + + for (category = 0; category < 6; category++) + { + int mask; + + switch (category) + { + case LC_CTYPE: + mask = LC_CTYPE_MASK; + break; + case LC_NUMERIC: + mask = LC_NUMERIC_MASK; + break; + case LC_TIME: + mask = LC_TIME_MASK; + break; + case LC_COLLATE: + mask = LC_COLLATE_MASK; + break; + case LC_MONETARY: + mask = LC_MONETARY_MASK; + break; + case LC_MESSAGES: + mask = LC_MESSAGES_MASK; + break; + default: + abort (); + } + names.category_name[category] = + ((mask & category_mask) != 0 + ? name + : get_locale_t_name (category, LC_GLOBAL_LOCALE)); + } + } + else + { + /* Look up the names of base in the hash table. Like multiple calls + of get_locale_t_name, but locking only once. */ + struct locale_hash_node *p; + int category; + + /* Lock while looking up the hash node. */ + gl_rwlock_rdlock (locale_lock); + for (p = locale_hash_table[pointer_hash (base) % LOCALE_HASH_TABLE_SIZE]; + p != NULL; + p = p->next) + if (p->locale == base) + break; + + for (category = 0; category < 6; category++) + { + int mask; + + switch (category) + { + case LC_CTYPE: + mask = LC_CTYPE_MASK; + break; + case LC_NUMERIC: + mask = LC_NUMERIC_MASK; + break; + case LC_TIME: + mask = LC_TIME_MASK; + break; + case LC_COLLATE: + mask = LC_COLLATE_MASK; + break; + case LC_MONETARY: + mask = LC_MONETARY_MASK; + break; + case LC_MESSAGES: + mask = LC_MESSAGES_MASK; + break; + default: + abort (); + } + names.category_name[category] = + ((mask & category_mask) != 0 + ? name + : (p != NULL ? p->names.category_name[category] : "")); + } + + gl_rwlock_unlock (locale_lock); + } + } + + node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node)); + if (node == NULL) + /* errno is set to ENOMEM. */ + return NULL; + + result = newlocale (category_mask, name, base); + if (result == NULL) + { + int saved_errno = errno; + free (node); + errno = saved_errno; + return NULL; + } + + /* Fill the hash node. */ + node->locale = result; + node->names = names; + + /* Insert it in the hash table. */ + { + size_t hashcode = pointer_hash (result); + size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; + struct locale_hash_node *p; + + /* Lock while inserting the new node. */ + gl_rwlock_wrlock (locale_lock); + for (p = locale_hash_table[slot]; p != NULL; p = p->next) + if (p->locale == result) + { + /* This can happen if the application uses the original freelocale() + function instead of the overridden one. */ + p->names = node->names; + break; + } + if (p == NULL) + { + node->next = locale_hash_table[slot]; + locale_hash_table[slot] = node; + } + + gl_rwlock_unlock (locale_lock); + + if (p != NULL) + free (node); + } + + return result; +} + +/* duplocale() override. */ +locale_t +duplocale (locale_t locale) +#undef duplocale +{ + struct locale_hash_node *node; + locale_t result; + + if (locale == NULL) + /* Invalid argument. */ + abort (); + + node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node)); + if (node == NULL) + /* errno is set to ENOMEM. */ + return NULL; + + result = duplocale (locale); + if (result == NULL) + { + int saved_errno = errno; + free (node); + errno = saved_errno; + return NULL; + } + + /* Fill the hash node. */ + node->locale = result; + if (locale == LC_GLOBAL_LOCALE) + { + int category; + + for (category = 0; category < 6; category++) + node->names.category_name[category] = + get_locale_t_name (category, LC_GLOBAL_LOCALE); + + /* Lock before inserting the new node. */ + gl_rwlock_wrlock (locale_lock); + } + else + { + struct locale_hash_node *p; + + /* Lock once, for the lookup and the insertion. */ + gl_rwlock_wrlock (locale_lock); + + for (p = locale_hash_table[pointer_hash (locale) % LOCALE_HASH_TABLE_SIZE]; + p != NULL; + p = p->next) + if (p->locale == locale) + break; + if (p != NULL) + node->names = p->names; + else + { + /* This can happen if the application uses the original + newlocale()/duplocale() functions instead of the overridden + ones. */ + int category; + + for (category = 0; category < 6; category++) + node->names.category_name[category] = ""; + } + } + + /* Insert it in the hash table. */ + { + size_t hashcode = pointer_hash (result); + size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; + struct locale_hash_node *p; + + for (p = locale_hash_table[slot]; p != NULL; p = p->next) + if (p->locale == result) + { + /* This can happen if the application uses the original freelocale() + function instead of the overridden one. */ + p->names = node->names; + break; + } + if (p == NULL) + { + node->next = locale_hash_table[slot]; + locale_hash_table[slot] = node; + } + + gl_rwlock_unlock (locale_lock); + + if (p != NULL) + free (node); + } + + return result; +} + +/* freelocale() override. */ +void +freelocale (locale_t locale) +#undef freelocale +{ + if (locale == NULL || locale == LC_GLOBAL_LOCALE) + /* Invalid argument. */ + abort (); + + { + size_t hashcode = pointer_hash (locale); + size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE; + struct locale_hash_node *found; + struct locale_hash_node **p; + + found = NULL; + /* Lock while removing the hash node. */ + gl_rwlock_wrlock (locale_lock); + for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next) + if ((*p)->locale == locale) + { + found = *p; + *p = (*p)->next; + break; + } + gl_rwlock_unlock (locale_lock); + free (found); + } + + freelocale (locale); +} + +#endif + + #if defined IN_LIBINTL || HAVE_USELOCALE /* Like gl_locale_name_thread, except that the result is not in storage of @@ -2761,6 +3180,8 @@ # if HAVE_GETLOCALENAME_L /* Solaris >= 12. */ return getlocalename_l (category, thread_locale); +# elif HAVE_NAMELESS_LOCALES + return get_locale_t_name (category, thread_locale); # else /* Solaris 11 OpenIndiana. For the internal structure of locale objects, see
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/intlsolaris.m4 Sun Oct 14 17:03:01 2018 +0200 @@ -0,0 +1,53 @@ +# intlsolaris.m4 serial 1 +dnl Copyright (C) 2015-2018 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special localename support needed on Solaris. +dnl Sets gt_nameless_locales. +AC_DEFUN([gt_INTL_SOLARIS], +[ + dnl Persuade Solaris <locale.h> to define 'locale_t'. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + AC_CHECK_FUNCS_ONCE([uselocale]) + + gt_nameless_locales=no + dnl Solaris 12 provides getlocalename_l, while Illumos doesn't have + dnl it nor the equivalent. + if test $ac_cv_func_uselocale = yes; then + AC_CHECK_FUNCS([getlocalename_l]) + if test $ac_cv_func_getlocalename_l != yes; then + AC_CACHE_CHECK([for Solaris 11.4 locale system], + [gt_cv_locale_solaris114], + [dnl Test whether <locale.h> defines locale_t as a typedef of + dnl 'struct _LC_locale_t **' (whereas Illumos defines it as a + dnl typedef of 'struct _locale *'). + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + #include <locale.h> + struct _LC_locale_t *x; + locale_t y; + ]], + [[*y = x;]])], + [gt_cv_locale_solaris114=yes], + [gt_cv_locale_solaris114=no]) + ]) + if test $gt_cv_locale_solaris114 = yes; then + gt_nameless_locales=yes + AC_DEFINE([HAVE_NAMELESS_LOCALES], [1], + [Define if the locale_t type does not contain the name of each locale category.]) + fi + fi + fi +])
--- a/m4/locale_h.m4 Fri Oct 12 06:46:09 2018 +0200 +++ b/m4/locale_h.m4 Sun Oct 14 17:03:01 2018 +0200 @@ -1,4 +1,4 @@ -# locale_h.m4 serial 20 +# locale_h.m4 serial 21 dnl Copyright (C) 2007, 2009-2018 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -96,7 +96,7 @@ # include <xlocale.h> #endif ]], - [setlocale duplocale]) + [setlocale newlocale duplocale freelocale]) ]) AC_DEFUN([gl_LOCALE_MODULE_INDICATOR], @@ -113,10 +113,15 @@ GNULIB_LOCALECONV=0; AC_SUBST([GNULIB_LOCALECONV]) GNULIB_SETLOCALE=0; AC_SUBST([GNULIB_SETLOCALE]) GNULIB_DUPLOCALE=0; AC_SUBST([GNULIB_DUPLOCALE]) + GNULIB_LOCALENAME=0; AC_SUBST([GNULIB_LOCALENAME]) dnl Assume proper GNU behavior unless another module says otherwise. + HAVE_NEWLOCALE=1; AC_SUBST([HAVE_NEWLOCALE]) HAVE_DUPLOCALE=1; AC_SUBST([HAVE_DUPLOCALE]) + HAVE_FREELOCALE=1; AC_SUBST([HAVE_FREELOCALE]) REPLACE_LOCALECONV=0; AC_SUBST([REPLACE_LOCALECONV]) REPLACE_SETLOCALE=0; AC_SUBST([REPLACE_SETLOCALE]) + REPLACE_NEWLOCALE=0; AC_SUBST([REPLACE_NEWLOCALE]) REPLACE_DUPLOCALE=0; AC_SUBST([REPLACE_DUPLOCALE]) + REPLACE_FREELOCALE=0; AC_SUBST([REPLACE_FREELOCALE]) REPLACE_STRUCT_LCONV=0; AC_SUBST([REPLACE_STRUCT_LCONV]) ])
--- a/m4/localename.m4 Fri Oct 12 06:46:09 2018 +0200 +++ b/m4/localename.m4 Sun Oct 14 17:03:01 2018 +0200 @@ -1,4 +1,4 @@ -# localename.m4 serial 3 +# localename.m4 serial 4 dnl Copyright (C) 2007, 2009-2018 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -6,13 +6,25 @@ AC_DEFUN([gl_LOCALENAME], [ + AC_REQUIRE([gl_LOCALE_H_DEFAULTS]) AC_REQUIRE([gt_LC_MESSAGES]) AC_REQUIRE([gt_INTL_MACOSX]) AC_CHECK_HEADERS_ONCE([langinfo.h]) - AC_CHECK_FUNCS([setlocale uselocale]) - dnl Solaris 12 provides getlocalename_l, while Illumos doesn't have - dnl it nor the equivalent. - if test $ac_cv_func_uselocale = yes; then - AC_CHECK_FUNCS([getlocalename_l]) + AC_CHECK_FUNCS([setlocale]) + AC_CHECK_FUNCS_ONCE([uselocale newlocale duplocale freelocale]) + if test $ac_cv_func_newlocale != yes; then + HAVE_NEWLOCALE=0 + fi + if test $ac_cv_func_duplocale != yes; then + HAVE_DUPLOCALE=0 + fi + if test $ac_cv_func_freelocale != yes; then + HAVE_FREELOCALE=0 + fi + gt_INTL_SOLARIS + if test $gt_nameless_locales = yes; then + REPLACE_NEWLOCALE=1 + REPLACE_DUPLOCALE=1 + REPLACE_FREELOCALE=1 fi ])
--- a/modules/locale Fri Oct 12 06:46:09 2018 +0200 +++ b/modules/locale Sun Oct 14 17:03:01 2018 +0200 @@ -32,11 +32,16 @@ -e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \ -e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \ -e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \ + -e 's/@''GNULIB_LOCALENAME''@/$(GNULIB_LOCALENAME)/g' \ + -e 's|@''HAVE_NEWLOCALE''@|$(HAVE_NEWLOCALE)|g' \ -e 's|@''HAVE_DUPLOCALE''@|$(HAVE_DUPLOCALE)|g' \ + -e 's|@''HAVE_FREELOCALE''@|$(HAVE_FREELOCALE)|g' \ -e 's|@''HAVE_XLOCALE_H''@|$(HAVE_XLOCALE_H)|g' \ -e 's|@''REPLACE_LOCALECONV''@|$(REPLACE_LOCALECONV)|g' \ -e 's|@''REPLACE_SETLOCALE''@|$(REPLACE_SETLOCALE)|g' \ + -e 's|@''REPLACE_NEWLOCALE''@|$(REPLACE_NEWLOCALE)|g' \ -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ + -e 's|@''REPLACE_FREELOCALE''@|$(REPLACE_FREELOCALE)|g' \ -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
--- a/modules/localename Fri Oct 12 06:46:09 2018 +0200 +++ b/modules/localename Sun Oct 14 17:03:01 2018 +0200 @@ -6,10 +6,12 @@ lib/localename.c m4/localename.m4 m4/intlmacosx.m4 +m4/intlsolaris.m4 m4/lcmessage.m4 Depends-on: extensions +locale flexmember strdup lock @@ -17,6 +19,7 @@ configure.ac: gl_LOCALENAME +gl_LOCALE_MODULE_INDICATOR([localename]) Makefile.am: lib_SOURCES += localename.c
--- a/tests/test-locale-c++.cc Fri Oct 12 06:46:09 2018 +0200 +++ b/tests/test-locale-c++.cc Sun Oct 14 17:03:01 2018 +0200 @@ -32,10 +32,18 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::setlocale, char *, (int, const char *)); #endif +#if 0 +SIGNATURE_CHECK (GNULIB_NAMESPACE::newlocale, locale_t, (int const char *, locale_t)); +#endif + #if GNULIB_TEST_DUPLOCALE && HAVE_DUPLOCALE SIGNATURE_CHECK (GNULIB_NAMESPACE::duplocale, locale_t, (locale_t)); #endif +#if 0 +SIGNATURE_CHECK (GNULIB_NAMESPACE::freelocale, void, (locale_t)); +#endif + int main ()