Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* sysdeps/i386/i686/memcmp.S: Move misplaced END.
2005-03-27  Bruno Haible  <bruno@clisp.org>

	Make it possible for multiple threads to use gettext() in different
	locales.
	* intl/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.

	* intl/tst-gettext4.c: New file.
	* intl/tst-gettext4.sh: New file.
	* intl/tst-gettext4-de.po: New file.
	* intl/tst-gettext4-fr.po: New file.
	* intl/tst-gettext5.c: New file.
	* intl/tst-gettext5.sh: New file.
	* intl/Makefile (distribute): Add tst-gettext4.sh, tst-gettext4-de.po,
	tst-gettext4-fr.po, tst-gettext5.sh.
	(multithread-test-srcs): New variable.
	(test-srcs): Add its contents.
	(tests): Depend on tst-gettext4.out, tst-gettext5.out.
	(tst-gettext4.out, tst-gettext5.out): New rules.
	(CFLAGS-tst-gettext4.c, CFLAGS-tst-gettext5.c): New variables.
	Add rule for linking the multithread-test-srcs with the appropriate
	thread-library.

2005-04-28  Ulrich Drepper  <drepper@redhat.com>

	* po/rw.po: New file.  From translation team.
  • Loading branch information
Ulrich Drepper committed Apr 28, 2005
1 parent 572028f commit 8406a53
Show file tree
Hide file tree
Showing 11 changed files with 7,296 additions and 12 deletions.
33 changes: 33 additions & 0 deletions ChangeLog
@@ -1,5 +1,38 @@
2005-04-28 Ulrich Drepper <drepper@redhat.com>

* sysdeps/i386/i686/memcmp.S: Move misplaced END.

2005-03-27 Bruno Haible <bruno@clisp.org>

Make it possible for multiple threads to use gettext() in different
locales.
* intl/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.

* intl/tst-gettext4.c: New file.
* intl/tst-gettext4.sh: New file.
* intl/tst-gettext4-de.po: New file.
* intl/tst-gettext4-fr.po: New file.
* intl/tst-gettext5.c: New file.
* intl/tst-gettext5.sh: New file.
* intl/Makefile (distribute): Add tst-gettext4.sh, tst-gettext4-de.po,
tst-gettext4-fr.po, tst-gettext5.sh.
(multithread-test-srcs): New variable.
(test-srcs): Add its contents.
(tests): Depend on tst-gettext4.out, tst-gettext5.out.
(tst-gettext4.out, tst-gettext5.out): New rules.
(CFLAGS-tst-gettext4.c, CFLAGS-tst-gettext5.c): New variables.
Add rule for linking the multithread-test-srcs with the appropriate
thread-library.

2005-04-28 Ulrich Drepper <drepper@redhat.com>

* po/rw.po: New file. From translation team.

* scripts/config.guess: Update from upstream.
* scripts/config.sub: Likewise.

Expand Down
34 changes: 31 additions & 3 deletions intl/Makefile
Expand Up @@ -30,9 +30,17 @@ distribute = gmo.h gettextP.h hash-string.h loadinfo.h locale.alias \
tst-translit.sh translit.po \
tst-gettext2.sh tstlang1.po tstlang2.po \
tst-codeset.sh tstcodeset.po \
tst-gettext3.sh
tst-gettext3.sh \
tst-gettext4.sh tst-gettext4-de.po tst-gettext4-fr.po \
tst-gettext5.sh

include ../Makeconfig

multithread-test-srcs := tst-gettext4 tst-gettext5
test-srcs := tst-gettext tst-translit tst-gettext2 tst-codeset tst-gettext3
ifeq ($(have-thread-library),yes)
test-srcs += $(multithread-test-srcs)
endif
tests = tst-ngettext

before-compile = $(objpfx)msgs.h
Expand All @@ -42,8 +50,6 @@ install-others = $(inst_msgcatdir)/locale.alias
generated = msgs.h mtrace-tst-gettext tst-gettext.mtrace
generated-dirs := domaindir localedir

include ../Makeconfig

ifneq (no,$(BISON))
plural.c: plural.y
$(BISON) $(BISONFLAGS) $@ $^
Expand All @@ -60,6 +66,9 @@ ifeq (yes,$(build-shared))
ifneq ($(strip $(MSGFMT)),:)
tests: $(objpfx)tst-translit.out $(objpfx)tst-gettext2.out \
$(objpfx)tst-codeset.out $(objpfx)tst-gettext3.out
ifeq ($(have-thread-library),yes)
tests: $(objpfx)tst-gettext4.out $(objpfx)tst-gettext5.out
endif
ifneq (no,$(PERL))
tests: $(objpfx)mtrace-tst-gettext
endif
Expand All @@ -77,6 +86,10 @@ $(objpfx)tst-codeset.out: tst-codeset.sh $(objpfx)tst-codeset
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-gettext3.out: tst-gettext3.sh $(objpfx)tst-gettext3
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-gettext4.out: tst-gettext4.sh $(objpfx)tst-gettext4
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
$(objpfx)tst-gettext5.out: tst-gettext5.sh $(objpfx)tst-gettext5
$(SHELL) -e $< $(common-objpfx) $(common-objpfx)intl/
endif
endif

Expand All @@ -89,11 +102,26 @@ CFLAGS-tst-translit.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-gettext2.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-codeset.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-gettext3.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-gettext4.c = -DOBJPFX=\"$(objpfx)\"
CFLAGS-tst-gettext5.c = -DOBJPFX=\"$(objpfx)\"

ifeq ($(have-thread-library),yes)
ifeq (yes,$(build-shared))
$(addprefix $(objpfx),$(multithread-test-srcs)): $(shared-thread-library)
else
$(addprefix $(objpfx),$(multithread-test-srcs)): $(static-thread-library)
endif
ifeq (yes,$(build-bounded))
$(multithread-test-srcs:%=$(objpfx)%-bp): $(bounded-thread-library)
endif
endif

$(objpfx)tst-translit.out: $(objpfx)tst-gettext.out
$(objpfx)tst-gettext2.out: $(objpfx)tst-gettext.out
$(objpfx)tst-codeset.out: $(objpfx)tst-gettext.out
$(objpfx)tst-gettext3.out: $(objpfx)tst-gettext.out
$(objpfx)tst-gettext4.out: $(objpfx)tst-gettext.out
$(objpfx)tst-gettext5.out: $(objpfx)tst-gettext.out

CPPFLAGS += -D'LOCALEDIR="$(msgcatdir)"' \
-D'LOCALE_ALIAS_PATH="$(msgcatdir)"'
Expand Down
53 changes: 46 additions & 7 deletions intl/dcigettext.c
Expand Up @@ -172,6 +172,11 @@ static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
# define PATH_MAX _POSIX_PATH_MAX
#endif

/* Whether to support different locales in different threads. */
#if defined _LIBC || HAVE_NL_LOCALE_NAME
# define HAVE_PER_THREAD_LOCALE
#endif

/* This is the type used for the search tree where known translations
are stored. */
struct known_translation_t
Expand All @@ -182,6 +187,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;

Expand Down Expand Up @@ -226,10 +236,16 @@ transcmp (p1, 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;
Expand Down Expand Up @@ -408,6 +424,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
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;

Expand Down Expand Up @@ -442,6 +461,12 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
memcpy (search->msgid, msgid1, msgid_len);
search->domainname = domainname;
search->category = category;
# ifdef HAVE_PER_THREAD_LOCALE
# ifdef _LIBC
localename = __current_locale_name (category);
# endif
search->localename = localename;
# endif

/* Since tfind/tsearch manage a balanced tree, concurrent tfind and
tsearch calls can be fatal. */
Expand Down Expand Up @@ -629,19 +654,33 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
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;
Expand Down
8 changes: 8 additions & 0 deletions intl/tst-gettext4-de.po
@@ -0,0 +1,8 @@
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8-bit\n"

msgid "beauty"
msgstr "Schönheit"
8 changes: 8 additions & 0 deletions intl/tst-gettext4-fr.po
@@ -0,0 +1,8 @@
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8-bit\n"

msgid "beauty"
msgstr "beauté"
151 changes: 151 additions & 0 deletions intl/tst-gettext4.c
@@ -0,0 +1,151 @@
/* Test that gettext() in multithreaded applications works correctly if
different threads operate in different locales with the same encoding.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Bruno Haible <bruno@clisp.org>, 2005.
The GNU C Library 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.
The GNU C Library 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 the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */

#include <libintl.h>
#include <locale.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Set to 1 if the program is not behaving correctly. */
int result;

/* Denotes which thread should run next. */
int flipflop;
/* Lock and wait queue used to switch between the threads. */
pthread_mutex_t lock;
pthread_cond_t waitqueue;

/* Waits until the flipflop has a given value.
Before the call, the lock is unlocked. After the call, it is locked. */
static void
waitfor (int value)
{
if (pthread_mutex_lock (&lock))
exit (10);
while (flipflop != value)
if (pthread_cond_wait (&waitqueue, &lock))
exit (11);
}

/* Sets the flipflop to a given value.
Before the call, the lock is locked. After the call, it is unlocked. */
static void
setto (int value)
{
flipflop = value;
if (pthread_cond_signal (&waitqueue))
exit (20);
if (pthread_mutex_unlock (&lock))
exit (21);
}

void *
thread1_execution (void *arg)
{
char *s;

waitfor (1);
uselocale (newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL));
setto (2);

waitfor (1);
s = gettext ("beauty");
puts (s);
if (strcmp (s, "Sch\366nheit"))
{
fprintf (stderr, "thread 1 call 1 returned: %s\n", s);
result = 1;
}
setto (2);

waitfor (1);
s = gettext ("beauty");
puts (s);
if (strcmp (s, "Sch\366nheit"))
{
fprintf (stderr, "thread 1 call 2 returned: %s\n", s);
result = 1;
}
setto (2);

return NULL;
}

void *
thread2_execution (void *arg)
{
char *s;

waitfor (2);
uselocale (newlocale (LC_ALL_MASK, "fr_FR.ISO-8859-1", NULL));
setto (1);

waitfor (2);
s = gettext ("beauty");
puts (s);
if (strcmp (s, "beaut\351"))
{
fprintf (stderr, "thread 2 call 1 returned: %s\n", s);
result = 1;
}
setto (1);

waitfor (2);
s = gettext ("beauty");
puts (s);
if (strcmp (s, "beaut\351"))
{
fprintf (stderr, "thread 2 call 2 returned: %s\n", s);
result = 1;
}
setto (1);

return NULL;
}

int
main (void)
{
pthread_t thread1;
pthread_t thread2;

unsetenv ("LANGUAGE");
unsetenv ("OUTPUT_CHARSET");
textdomain ("multithread");
bindtextdomain ("multithread", OBJPFX "domaindir");
result = 0;

flipflop = 1;
if (pthread_mutex_init (&lock, NULL))
exit (2);
if (pthread_cond_init (&waitqueue, NULL))
exit (2);
if (pthread_create (&thread1, NULL, &thread1_execution, NULL))
exit (2);
if (pthread_create (&thread2, NULL, &thread2_execution, NULL))
exit (2);
if (pthread_join (thread2, NULL))
exit (3);

return result;
}

0 comments on commit 8406a53

Please sign in to comment.