* 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.
This commit is contained in:
Ulrich Drepper 2005-04-28 18:21:03 +00:00
parent 572028fa7e
commit 8406a53a25
11 changed files with 7296 additions and 12 deletions

View File

@ -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.

View File

@ -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
@ -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) $@ $^
@ -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
@ -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
@ -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)"'

View File

@ -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
@ -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;
@ -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;
@ -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;
@ -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. */
@ -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;

8
intl/tst-gettext4-de.po Normal file
View File

@ -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
intl/tst-gettext4-fr.po Normal file
View File

@ -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
intl/tst-gettext4.c Normal file
View File

@ -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;
}

48
intl/tst-gettext4.sh Executable file
View File

@ -0,0 +1,48 @@
#! /bin/sh
# Test that gettext() in multithreaded applications works correctly if
# different threads operate in different locales with the same encoding.
# Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
# 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.
common_objpfx=$1
objpfx=$2
LC_ALL=C
export LC_ALL
# Generate the test data.
test -d ${objpfx}domaindir || mkdir ${objpfx}domaindir
# Create the domain directories.
test -d ${objpfx}domaindir/de_DE || mkdir ${objpfx}domaindir/de_DE
test -d ${objpfx}domaindir/de_DE/LC_MESSAGES || mkdir ${objpfx}domaindir/de_DE/LC_MESSAGES
test -d ${objpfx}domaindir/fr_FR || mkdir ${objpfx}domaindir/fr_FR
test -d ${objpfx}domaindir/fr_FR/LC_MESSAGES || mkdir ${objpfx}domaindir/fr_FR/LC_MESSAGES
# Populate them.
msgfmt -o ${objpfx}domaindir/de_DE/LC_MESSAGES/multithread.mo tst-gettext4-de.po
msgfmt -o ${objpfx}domaindir/fr_FR/LC_MESSAGES/multithread.mo tst-gettext4-fr.po
GCONV_PATH=${common_objpfx}iconvdata
export GCONV_PATH
LOCPATH=${common_objpfx}localedata
export LOCPATH
${common_objpfx}elf/ld.so --library-path $common_objpfx \
${objpfx}tst-gettext4 > ${objpfx}tst-gettext4.out
exit $?

156
intl/tst-gettext5.c Normal file
View File

@ -0,0 +1,156 @@
/* Test that gettext() in multithreaded applications works correctly if
different threads operate in different locales referring to the same
catalog file but with different encodings.
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);
/* Here we expect output in ISO-8859-1. */
waitfor (1);
s = gettext ("cheese");
puts (s);
if (strcmp (s, "K\344se"))
{
fprintf (stderr, "thread 1 call 1 returned: %s\n", s);
result = 1;
}
setto (2);
waitfor (1);
s = gettext ("cheese");
puts (s);
if (strcmp (s, "K\344se"))
{
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, "de_DE.UTF-8", NULL));
setto (1);
/* Here we expect output in UTF-8. */
waitfor (2);
s = gettext ("cheese");
puts (s);
if (strcmp (s, "K\303\244se"))
{
fprintf (stderr, "thread 2 call 1 returned: %s\n", s);
result = 1;
}
setto (1);
waitfor (2);
s = gettext ("cheese");
puts (s);
if (strcmp (s, "K\303\244se"))
{
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 ("codeset");
bindtextdomain ("codeset", 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;
}

46
intl/tst-gettext5.sh Executable file
View File

@ -0,0 +1,46 @@
#! /bin/sh
# Test that gettext() in multithreaded applications works correctly if
# different threads operate in different locales referring to the same
# catalog file but with different encodings.
# Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
# 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.
common_objpfx=$1
objpfx=$2
LC_ALL=C
export LC_ALL
# Generate the test data.
test -d ${objpfx}domaindir || mkdir ${objpfx}domaindir
# Create the domain directories.
test -d ${objpfx}domaindir/de_DE || mkdir ${objpfx}domaindir/de_DE
test -d ${objpfx}domaindir/de_DE/LC_MESSAGES || mkdir ${objpfx}domaindir/de_DE/LC_MESSAGES
# Populate them.
msgfmt -o ${objpfx}domaindir/de_DE/LC_MESSAGES/codeset.mo tstcodeset.po
GCONV_PATH=${common_objpfx}iconvdata
export GCONV_PATH
LOCPATH=${common_objpfx}localedata
export LOCPATH
${common_objpfx}elf/ld.so --library-path $common_objpfx \
${objpfx}tst-gettext5 > ${objpfx}tst-gettext5.out
exit $?

6767
po/rw.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Compare two memory blocks for differences in the first COUNT bytes.
Copyright (C) 2004 Free Software Foundation, Inc.
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -350,6 +350,7 @@ L(set):
sbbl $-1, %eax
popl %esi
RETURN
END (BP_SYM (memcmp))
.section .rodata
ALIGN (2)
@ -387,7 +388,6 @@ L(table_32bytes) :
.long L(30bytes) - . + 0x78
.long L(31bytes) - . + 0x7c
END (BP_SYM (memcmp))
#undef bcmp
weak_alias (BP_SYM (memcmp), BP_SYM (bcmp))