]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Make it possible for multiple threads to use gettext() in different locales.
authorBruno Haible <bruno@clisp.org>
Mon, 2 May 2005 10:20:19 +0000 (10:20 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:12:32 +0000 (12:12 +0200)
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/dcigettext.c
gettext-tools/ChangeLog
gettext-tools/configure.ac
gettext-tools/tests/ChangeLog
gettext-tools/tests/Makefile.am

index 9ee195e41a999ecbb864177b2a1322a1a21da156..0c6ef59a963edd0a3026c70f176f2d557e30144c 100644 (file)
@@ -1,3 +1,16 @@
+2005-03-20  Bruno Haible  <bruno@clisp.org>
+
+       Make it possible for multiple threads to use gettext() in different
+       locales.
+       * dcigettext.c (HAVE_PER_THREAD_LOCALE): New macro.
+       (struct known_translation_t): If HAVE_PER_THREAD_LOCALE, add localename
+       field.
+       (transcmp): If HAVE_PER_THREAD_LOCALE, compare localename fields.
+       (DCIGETTEXT): If HAVE_PER_THREAD_LOCALE, fill the localename field in
+       search and newp.
+       (guess_category_value): If HAVE_PER_THREAD_LOCALE, look at the thread's
+       locale.
+
 2005-03-19  Bruno Haible  <bruno@clisp.org>
 
        * gettextP.h (struct loaded_domain): Remove codeset_cntr field.
index 63534b86e82fe48aa1244fcbfc3152b3560c788c..f5a8915b1706423739e8bf307d545cfad517147d 100644 (file)
@@ -216,6 +216,11 @@ static void *mempcpy (void *dest, const void *src, size_t n);
 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
 #endif
 
+/* Whether to support different locales in different threads.  */
+#if defined _LIBC || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS)
+# define HAVE_PER_THREAD_LOCALE
+#endif
+
 /* This is the type used for the search tree where known translations
    are stored.  */
 struct known_translation_t
@@ -226,6 +231,11 @@ struct known_translation_t
   /* The category.  */
   int category;
 
+#ifdef HAVE_PER_THREAD_LOCALE
+  /* Name of the relevant locale category, or "" for the global locale.  */
+  const char *localename;
+#endif
+
   /* State of the catalog counter at the point the string was found.  */
   int counter;
 
@@ -267,10 +277,16 @@ transcmp (const void *p1, const void *p2)
     {
       result = strcmp (s1->domainname, s2->domainname);
       if (result == 0)
-       /* We compare the category last (though this is the cheapest
-          operation) since it is hopefully always the same (namely
-          LC_MESSAGES).  */
-       result = s1->category - s2->category;
+       {
+#ifdef HAVE_PER_THREAD_LOCALE
+         result = strcmp (s1->localename, s2->localename);
+         if (result == 0)
+#endif
+           /* We compare the category last (though this is the cheapest
+              operation) since it is hopefully always the same (namely
+              LC_MESSAGES).  */
+           result = s1->category - s2->category;
+       }
     }
 
   return result;
@@ -447,6 +463,9 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
   struct known_translation_t *search;
   struct known_translation_t **foundp = NULL;
   size_t msgid_len;
+# ifdef HAVE_PER_THREAD_LOCALE
+  const char *localename;
+# endif
 #endif
   size_t domainname_len;
 
@@ -487,6 +506,24 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
   memcpy (search->msgid, msgid1, msgid_len);
   search->domainname = domainname;
   search->category = category;
+# ifdef HAVE_PER_THREAD_LOCALE
+#  ifdef _LIBC
+  localename = __current_locale_name (category);
+#  else
+#   if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
+  /* The __names field is not public glibc API and must therefore not be used
+     in code that is installed in public locations.  */
+  {
+    locale_t thread_locale = uselocale (NULL);
+    if (thread_locale != LC_GLOBAL_LOCALE)
+      localename = thread_locale->__names[category];
+    else
+      localename = "";
+  }
+#   endif
+#  endif
+  search->localename = localename;
+# endif
 
   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
   freea (search);
@@ -649,19 +686,33 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
              if (foundp == NULL)
                {
                  /* Create a new entry and add it to the search tree.  */
+                 size_t size;
                  struct known_translation_t *newp;
 
-                 newp = (struct known_translation_t *)
-                   malloc (offsetof (struct known_translation_t, msgid)
-                           + msgid_len + domainname_len + 1);
+                 size = offsetof (struct known_translation_t, msgid)
+                        + msgid_len + domainname_len + 1;
+# ifdef HAVE_PER_THREAD_LOCALE
+                 size += strlen (localename) + 1;
+# endif
+                 newp = (struct known_translation_t *) malloc (size);
                  if (newp != NULL)
                    {
                      char *new_domainname;
+# ifdef HAVE_PER_THREAD_LOCALE
+                     char *new_localename;
+# endif
 
                      new_domainname = mempcpy (newp->msgid, msgid1, msgid_len);
                      memcpy (new_domainname, domainname, domainname_len + 1);
+# ifdef HAVE_PER_THREAD_LOCALE
+                     new_localename = new_domainname + domainname_len + 1;
+                     strcpy (new_localename, localename);
+# endif
                      newp->domainname = new_domainname;
                      newp->category = category;
+# ifdef HAVE_PER_THREAD_LOCALE
+                     newp->localename = new_localename;
+# endif
                      newp->counter = _nl_msg_cat_cntr;
                      newp->domain = domain;
                      newp->translation = retval;
@@ -1286,12 +1337,25 @@ guess_category_value (int category, const char *categoryname)
 #ifdef _LIBC
   locale = __current_locale_name (category);
 #else
-  locale = _nl_locale_name_posix (category, categoryname);
-  locale_defaulted = 0;
-  if (locale == NULL)
+# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
+  /* The __names field is not public glibc API and must therefore not be used
+     in code that is installed in public locations.  */
+  locale_t thread_locale = uselocale (NULL);
+  if (thread_locale != LC_GLOBAL_LOCALE)
     {
-      locale = _nl_locale_name_default ();
-      locale_defaulted = 1;
+      locale = thread_locale->__names[category];
+      locale_defaulted = 0;
+    }
+  else
+# endif
+    {
+      locale = _nl_locale_name_posix (category, categoryname);
+      locale_defaulted = 0;
+      if (locale == NULL)
+       {
+         locale = _nl_locale_name_default ();
+         locale_defaulted = 1;
+       }
     }
 #endif
 
index 766ef8e54dcd772fb9183ac94f5c6191ead439f1..d0b39d0583bda078cadae5d09e3c7434b652d230 100644 (file)
@@ -1,3 +1,8 @@
+2005-03-20  Bruno Haible  <bruno@clisp.org>
+
+       * configure.ac: Test for field __names in struct __locale_struct.
+       Also define USE_IN_GETTEXT_TESTS.
+
 2005-04-11  Bruno Haible  <bruno@clisp.org>
 
        * gettext-0.14.4 released.
index b44a95e92a4349f11aad1a294e4963794d6f9816..61af08b9037230059656066539d837f381c580ff 100644 (file)
@@ -115,6 +115,10 @@ gt_TYPE_SSIZE_T
 AC_TYPE_PID_T
 AC_TYPE_MODE_T
 gt_TYPE_SIG_ATOMIC_T
+gl_GLIBC21
+if test $GLIBC21 = yes; then
+  AC_CHECK_MEMBERS([struct __locale_struct.__names], , , [#include <xlocale.h>])
+fi
 
 dnl Checks for library functions.
 gl_ALLOCSA
@@ -168,6 +172,9 @@ AH_TOP([
 #define DEFAULT_OUTPUT_ALIGNMENT 1
 ])
 AH_BOTTOM([
+/* Indicator for intl/ that it is compiled for testing purposes only.  */
+#define USE_IN_GETTEXT_TESTS
+
 /* A file name cannot consist of any character possible.  INVALID_PATH_CHAR
    contains the characters not allowed.  */
 #if defined _MSC_VER || defined __MINGW32__
index 93e9706832b1dd3d9624fb71962f16dfbf4072be..7b45ca8e521d11f733c7dc3027df096113b016bb 100644 (file)
@@ -1,3 +1,20 @@
+2005-03-20  Bruno Haible  <bruno@clisp.org>
+
+       * gettext-6: New file.
+       * gettext-6-prg.c: New file.
+       * gettext-6-1.po: New file.
+       * gettext-6-2.po: New file.
+       * gettext-7: New file.
+       * gettext-7-prg.c: New file.
+       * gettext-7.po: New file.
+       * Makefile.am (TESTS): Add gettext-6, gettext-7.
+       (EXTRA_DIST): Add gettext-6-1.po, gettext-6-2.po, gettext-7.po.
+       (noinst_PROGRAMS): Add gettext-6-prg, gettext-7-prg.
+       (gettext_6_prg_SOURCES, gettext_6_prg_CFLAGS, gettext_6_prg_LDADD): New
+       variables.
+       (gettext_7_prg_SOURCES, gettext_7_prg_CFLAGS, gettext_7_prg_LDADD): New
+       variables.
+
 2005-03-19  Bruno Haible  <bruno@clisp.org>
 
        * gettext-3: New file.
index 41850c6d361d6bc4d4359817c013a8a0c2485e1e..542270175614f9f4bf26a33b8aa289726eca5eb1 100644 (file)
@@ -20,7 +20,7 @@
 AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
 EXTRA_DIST =
 
-TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 \
+TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \
        msgattrib-1 msgattrib-2 msgattrib-3 msgattrib-4 msgattrib-5 \
        msgattrib-6 msgattrib-7 msgattrib-8 msgattrib-9 msgattrib-10 \
        msgattrib-11 msgattrib-12 msgattrib-13 msgattrib-14 \
@@ -111,7 +111,8 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 \
 EXTRA_DIST += $(TESTS) \
        test.mo xg-c-1.ok.po mex-test2.ok msguniq-a.in msguniq-a.inp \
        msguniq-a.out qttest_pl.po qttest_pl.qm ChangeLog.0 gettext-3-1.po \
-       gettext-3-2.po gettext-4.po gettext-5.po
+       gettext-3-2.po gettext-4.po gettext-5.po gettext-6-1.po \
+       gettext-6-2.po gettext-7.po
 
 XGETTEXT = ../src/xgettext
 
@@ -172,7 +173,7 @@ DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
 LDADD = $(LDADD_@USE_INCLUDED_LIBINTL@) @INTL_MACOSX_LIBS@
 LDADD_yes = ../intl/libintl.la
 LDADD_no = ../intl/libgnuintl.la @LTLIBINTL@
-noinst_PROGRAMS = tstgettext tstngettext testlocale gettext-3-prg gettext-4-prg gettext-5-prg cake fc3 fc4 fc5
+noinst_PROGRAMS = tstgettext tstngettext testlocale gettext-3-prg gettext-4-prg gettext-5-prg gettext-6-prg gettext-7-prg cake fc3 fc4 fc5
 tstgettext_SOURCES = tstgettext.c setlocale.c
 tstgettext_CFLAGS = -DINSTALLDIR=\".\"
 tstgettext_LDADD = ../lib/libgettextlib.la $(LDADD)
@@ -186,6 +187,16 @@ gettext_4_prg_SOURCES = gettext-4-prg.c
 gettext_4_prg_LDADD = ../lib/libgettextlib.la $(LDADD)
 gettext_5_prg_SOURCES = gettext-5-prg.c
 gettext_5_prg_LDADD = ../lib/libgettextlib.la $(LDADD)
+gettext_6_prg_SOURCES = gettext-6-prg.c
+gettext_6_prg_CFLAGS = $(gettext_6_prg_CFLAGS_@GLIBC2@)
+gettext_6_prg_CFLAGS_yes = -DUSE_POSIX_THREADS
+gettext_6_prg_LDADD = $(gettext_6_prg_LDADD_@GLIBC2@)
+gettext_6_prg_LDADD_yes = ../lib/libgettextlib.la $(LDADD) -lpthread
+gettext_7_prg_SOURCES = gettext-7-prg.c
+gettext_7_prg_CFLAGS = $(gettext_7_prg_CFLAGS_@GLIBC2@)
+gettext_7_prg_CFLAGS_yes = -DUSE_POSIX_THREADS
+gettext_7_prg_LDADD = $(gettext_7_prg_LDADD_@GLIBC2@)
+gettext_7_prg_LDADD_yes = ../lib/libgettextlib.la $(LDADD) -lpthread
 cake_SOURCES = plural-1-prg.c setlocale.c
 cake_LDADD = ../lib/libgettextlib.la $(LDADD)
 fc3_SOURCES = format-c-3-prg.c setlocale.c