summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--lib/localename-table.c48
-rw-r--r--lib/localename-table.h73
-rw-r--r--lib/localename.c53
-rw-r--r--m4/intlsolaris.m462
-rw-r--r--modules/gettext1
-rw-r--r--modules/localename4
7 files changed, 190 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 3548a53d13..d1fd026fa7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2018-10-21 Bruno Haible <bruno@clisp.org>
+ localename: Fine-tune support for per-thread locales on Solaris 11.4.
+ * lib/localename-table.h: New file, extracted from lib/localename.c.
+ * lib/localename-table.c: Likewise.
+ * lib/localename.c: Include localename-table.h.
+ (get_locale_t_name, newlocale, duplocale, freelocale): Invoke
+ locale_hash_function instead of pointer_hash.
+ * modules/localename (Files): Add lib/localename-table.h,
+ lib/localename-table.c.
+ (lib_SOURCES): Add localename-table.c.
+ * m4/intlsolaris.m4 (gt_INTL_SOLARIS): Require AC_CANONICAL_HOST. Test
+ for Solaris 11.4 locale system only on Solaris. Test for it
+ independently whether getlocalename_l exists.
+ * m4/intl.m4 (gt_INTL_SUBDIR_CORE): Don't test for 'uselocale' and
+ 'getlocalename_l'. Instead, invoke gt_INTL_SOLARIS. Set
+ HAVE_NAMELESS_LOCALES.
+ * modules/gettext (Files): Add m4/intlsolaris.m4.
+
+2018-10-21 Bruno Haible <bruno@clisp.org>
+
Small update from gettext.
* m4/intl.m4: Update from gettext:
- 2018-01-02: Fix 'ar' invocation when cross-compiling and in 64-bit
diff --git a/lib/localename-table.c b/lib/localename-table.c
new file mode 100644
index 0000000000..54fd67d083
--- /dev/null
+++ b/lib/localename-table.c
@@ -0,0 +1,48 @@
+/* Table that maps a locale object to the names of the locale categories.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2018. */
+
+#include <config.h>
+
+#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */
+
+/* Specification. */
+#include "localename-table.h"
+
+#include <stdint.h>
+
+/* A hash function for pointers. */
+size_t _GL_ATTRIBUTE_CONST
+locale_hash_function (locale_t x)
+{
+ uintptr_t p = (uintptr_t) x;
+ size_t h = ((p % 4177) << 12) + ((p % 79) << 6) + (p % 61);
+ return h;
+}
+
+struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE]
+ /* = { NULL, ..., NULL } */;
+
+gl_rwlock_define_initialized(, locale_lock)
+
+#else
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#endif
diff --git a/lib/localename-table.h b/lib/localename-table.h
new file mode 100644
index 0000000000..0d204d6d14
--- /dev/null
+++ b/lib/localename-table.h
@@ -0,0 +1,73 @@
+/* Table that maps a locale object to the names of the locale categories.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2018. */
+
+#if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES /* Solaris >= 11.4 */
+
+# include <stddef.h>
+# include <locale.h>
+
+# ifdef IN_LIBINTL
+# include "lock.h"
+# else
+# include "glthread/lock.h"
+# endif
+
+struct locale_categories_names
+ {
+ /* Locale category -> name (allocated with indefinite extent). */
+ const char *category_name[6];
+ };
+
+/* 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.
+ This hash table has global scope, so that when an application uses both
+ GNU libintl and gnulib, the application sees only one hash table. (When
+ linking statically with libintl, the fact that localename-table.c is a
+ separate compilation unit resolves the duplicate symbol conflict. When
+ linking with libintl as a shared library, we rely on ELF and the symbol
+ conflict resolution implemented in the ELF dynamic loader here.)
+ Both the libintl overrides and the gnulib overrides of the functions
+ newlocale, duplocale, freelocale see the same hash table (and the same lock).
+ For this reason, the internal layout of the hash table and the hash function
+ MUST NEVER CHANGE. If you need to change the internal layout or the hash
+ function, introduce versioning by appending a version suffix to the symbols
+ at the linker level. */
+# define locale_hash_function libintl_locale_hash_function
+# define locale_hash_table libintl_locale_hash_table
+# define locale_lock libintl_locale_lock
+
+extern size_t _GL_ATTRIBUTE_CONST locale_hash_function (locale_t x);
+
+/* 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
+extern struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE];
+
+/* This lock protects the locale_hash_table against multiple simultaneous
+ accesses (except that multiple simultaneous read accesses are allowed). */
+
+gl_rwlock_define(extern, locale_lock)
+
+#endif
diff --git a/lib/localename.c b/lib/localename.c
index 93fee9b920..04e6d42b34 100644
--- a/lib/localename.c
+++ b/lib/localename.c
@@ -52,7 +52,7 @@ extern char * getlocalename_l(int, locale_t);
# endif
# if HAVE_NAMELESS_LOCALES
# include <errno.h>
-# include <stdint.h>
+# include "localename-table.h"
# endif
#endif
@@ -2707,43 +2707,8 @@ struniq (const char *string)
#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)
+ We have to associate them with the object through a hash table.
+ The hash table is defined in localename-table.[hc]. */
/* Returns the name of a given locale category in a given locale_t object,
allocated as a string with indefinite extent. */
@@ -2763,7 +2728,7 @@ get_locale_t_name (int category, locale_t locale)
else
{
/* Look up the names in the hash table. */
- size_t hashcode = pointer_hash (locale);
+ size_t hashcode = locale_hash_function (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()
@@ -2898,7 +2863,7 @@ newlocale (int category_mask, const char *name, locale_t base)
/* Lock while looking up the hash node. */
gl_rwlock_rdlock (locale_lock);
- for (p = locale_hash_table[pointer_hash (base) % LOCALE_HASH_TABLE_SIZE];
+ for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
p != NULL;
p = p->next)
if (p->locale == base)
@@ -2961,7 +2926,7 @@ newlocale (int category_mask, const char *name, locale_t base)
/* Insert it in the hash table. */
{
- size_t hashcode = pointer_hash (result);
+ size_t hashcode = locale_hash_function (result);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *p;
@@ -3036,7 +3001,7 @@ duplocale (locale_t locale)
/* 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];
+ for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
p != NULL;
p = p->next)
if (p->locale == locale)
@@ -3057,7 +3022,7 @@ duplocale (locale_t locale)
/* Insert it in the hash table. */
{
- size_t hashcode = pointer_hash (result);
+ size_t hashcode = locale_hash_function (result);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *p;
@@ -3094,7 +3059,7 @@ freelocale (locale_t locale)
abort ();
{
- size_t hashcode = pointer_hash (locale);
+ size_t hashcode = locale_hash_function (locale);
size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
struct locale_hash_node *found;
struct locale_hash_node **p;
diff --git a/m4/intlsolaris.m4 b/m4/intlsolaris.m4
index 2e3db7fc5c..6d3ade465d 100644
--- a/m4/intlsolaris.m4
+++ b/m4/intlsolaris.m4
@@ -1,4 +1,4 @@
-# intlsolaris.m4 serial 1
+# intlsolaris.m4 serial 2
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,
@@ -17,37 +17,49 @@ dnl Checks for special localename support needed on Solaris.
dnl Sets gt_nameless_locales.
AC_DEFUN([gt_INTL_SOLARIS],
[
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
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_CACHE_CHECK([for Solaris 11.4 locale system],
+ [gt_cv_locale_solaris114],
+ [case "$host_os" in
+ solaris*)
+ 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])
+ ;;
+ *) gt_cv_locale_solaris114=no ;;
+ esac
+ ])
+ fi
+ 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
+
+ dnl Solaris 12 will maybe provide getlocalename_l. If it does, it will
+ dnl simplify the implementation of gl_locale_name_thread(). But the overrides
+ dnl of newlocale, duplocale, freelocale will still be necessary, in order to
+ dnl keep the libintl_locale_hash_table up-to-date, which may be used by
+ dnl libintl or gnulib code that was compiled on Solaris 11.4, before
+ dnl getlocalename_l was introduced.
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
])
diff --git a/modules/gettext b/modules/gettext
index 8c94e2d10c..15cf53b7a1 100644
--- a/modules/gettext
+++ b/modules/gettext
@@ -20,6 +20,7 @@ m4/intdiv0.m4
m4/intl.m4
m4/intldir.m4
m4/intlmacosx.m4
+m4/intlsolaris.m4
m4/intmax.m4
m4/inttypes_h.m4
m4/inttypes-pri.m4
diff --git a/modules/localename b/modules/localename
index 29c43213de..cb848b5dcb 100644
--- a/modules/localename
+++ b/modules/localename
@@ -4,6 +4,8 @@ Return current locale's name, according to glibc naming conventions.
Files:
lib/localename.h
lib/localename.c
+lib/localename-table.h
+lib/localename-table.c
m4/localename.m4
m4/intlmacosx.m4
m4/intlsolaris.m4
@@ -22,7 +24,7 @@ gl_LOCALENAME
gl_LOCALE_MODULE_INDICATOR([localename])
Makefile.am:
-lib_SOURCES += localename.c
+lib_SOURCES += localename.c localename-table.c
Include:
"localename.h"