summaryrefslogtreecommitdiff
path: root/intl
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-05-04 02:46:54 +0000
committerUlrich Drepper <drepper@redhat.com>2000-05-04 02:46:54 +0000
commit17c389fc2b8bdc74ae136c933988ad5d89f6350e (patch)
treed9f06e66be27ed5a2b1b021684de02745b3e594b /intl
parent160016c945d49cfe43f6d34aa077ea04309c983b (diff)
downloadglibc-17c389fc2b8bdc74ae136c933988ad5d89f6350e.tar.gz
Update.
* libio/stdio.h: Make fseeko and ftello prototypes available is __USE_LARGEFILE. Patch by Paul Eggert <eggert@twinsun.com>. * sysdeps/generic/dl-environ.c (unsetenv): Follow change to the real unsetenv implementation from 1999-07-29 [PR libc/1714]. 2000-05-03 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (dcigettext): Do the defaulting of 'domainname' before calling tfind. 2000-03-05 Jakub Jelinek <jakub@redhat.com> * resolv/resolv.h (res_querydomain): Remove redefinition to __res_querydomain (reported by Owen Taylor <otaylor@redhat.com>). 2000-05-03 Ulrich Drepper <drepper@redhat.com> * po/gl.po: Update from translation team. * manual/intro.texi (Program Basics): Change section title. * manual/process.texi: Fix reference. (Executing a File): Add reference exec in other section. * manual/signal.texi: Fix reference. * manual/startup.texi: Document syscall function. Patches by Bryan Henderson <bryanh@giraffe-data.com>. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/libintl.h (bind_textdomain_codeset): New declaration. * intl/bindtextdom.c (set_binding_values): New function. (bindtextdomain): Call it. (bind_textdomain_codeset): New function. * intl/dcigettext.c (dcigettext): Pass binding to _nl_find_domain. (free_mem): Free each binding's codeset. * intl/gettextP.h (struct binding): Add codeset field. (_nl_find_domain): Add domainbinding argument. * intl/finddomain.c (_nl_find_domain): Add domainbinding argument. Pass it to _nl_make_l10nflist. * intl/loadinfo.h (struct loaded_l10nfile): Add domainbinding field. (_nl_make_l10nflist): Add domainbinding argument. * intl/l10nflist.c (_nl_make_l10nflist): Add domainbinding argument. * intl/loadmsgcat.c (_nl_load_domain): Look at the domainbinding's codeset when determining outcharset. If !_LIBC && HAVE_ICONV, call locale_charset(). * manual/message.texi: New node "Charset conversion in gettext". 2000-04-30 Bruno Haible <haible@clisp.cons.org> * catgets/open_catalog.c (__open_catalog): Use __builtin_expect where appropriate. Handle possible __read error. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/gettextP.h (__builtin_expect): Define as empty if not a compiler builtin. * intl/loadinfo.h (__builtin_expect): Likewise. * intl/dcigettext.c (dcigettext, _nl_find_msg): Use __builtin_expect where appropriate. * intl/loadmsgcat.c (_nl_load_domain): Likewise. * intl/localealias.c (extend_alias_table): Return an error indicator. (read_alias_file): Bail out if extend_alias_table fails. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c: Define _GNU_SOURCE as early as possible. * intl/localealias.c: Likewise. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * intl/loadmsgcat.c (_nl_load_domain): Initialize domain->conv_tab. Initialize domain->plural and domain->nplurals even if there is no nullentry. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (_nl_find_msg): Terminate __gconv loop if return value is == __GCONV_OK or == __GCONV_EMPTY_INPUT, not != __GCONV_OK. In case of failure, goto converted. 2000-05-01 Bruno Haible <haible@clisp.cons.org> * wcsmbs/wcsmbsload.c (norm_add_slashes): Move away. * iconv/gconv_int.h (norm_add_slashes): Move to here. * intl/loadmsgcat.c (_nl_load_domain): Normalize strings passed to __gconv_open. 2000-04-29 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (transcmp): Compare the domains as well. (dcigettext): Call strlen (msgid1) after testing msgid1 against NULL, not before. * intl/loadmsgcat.c (_nl_load_domain): Deal with EINTR. Include <errno.h>. 2000-05-03 Ulrich Drepper <drepper@redhat.com>
Diffstat (limited to 'intl')
-rw-r--r--intl/bindtextdom.c268
-rw-r--r--intl/dcigettext.c103
-rw-r--r--intl/finddomain.c9
-rw-r--r--intl/gettextP.h10
-rw-r--r--intl/l10nflist.c7
-rw-r--r--intl/libintl.h5
-rw-r--r--intl/loadinfo.h10
-rw-r--r--intl/loadmsgcat.c89
-rw-r--r--intl/localealias.c23
9 files changed, 377 insertions, 147 deletions
diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c
index c5d4901a85..3d49344aaf 100644
--- a/intl/bindtextdom.c
+++ b/intl/bindtextdom.c
@@ -75,29 +75,44 @@ __libc_rwlock_define (extern, _nl_state_lock)
prefix. So we have to make a difference here. */
#ifdef _LIBC
# define BINDTEXTDOMAIN __bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
# ifndef strdup
# define strdup(str) __strdup (str)
# endif
#else
# define BINDTEXTDOMAIN bindtextdomain__
+# define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
#endif
-/* Specify that the DOMAINNAME message catalog will be found
- in DIRNAME rather than in the system locale data base. */
-char *
-BINDTEXTDOMAIN (domainname, dirname)
+/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
+ to be used for the DOMAINNAME message catalog.
+ If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
+ modified, only the current value is returned.
+ If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
+ modified nor returned. */
+static void
+set_binding_values (domainname, dirnamep, codesetp)
const char *domainname;
- const char *dirname;
+ const char **dirnamep;
+ const char **codesetp;
{
struct binding *binding;
- char *result;
+ int modified;
/* Some sanity checks. */
if (domainname == NULL || domainname[0] == '\0')
- return NULL;
+ {
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
+ return;
+ }
__libc_rwlock_wrlock (_nl_state_lock);
+ modified = 0;
+
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
{
int compare = strcmp (domainname, binding->domainname);
@@ -112,40 +127,96 @@ BINDTEXTDOMAIN (domainname, dirname)
}
}
- if (dirname == NULL)
- /* The current binding has be to returned. */
- result = binding == NULL ? (char *) _nl_default_dirname : binding->dirname;
- else if (binding != NULL)
+ if (binding != NULL)
{
- /* The domain is already bound. If the new value and the old
- one are equal we simply do nothing. Otherwise replace the
- old binding. */
- result = binding->dirname;
- if (strcmp (dirname, result) != 0)
+ if (dirnamep)
{
- if (strcmp (dirname, _nl_default_dirname) == 0)
- result = (char *) _nl_default_dirname;
+ const char *dirname = *dirnamep;
+
+ if (dirname == NULL)
+ /* The current binding has be to returned. */
+ *dirnamep = binding->dirname;
else
{
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->dirname;
+ if (strcmp (dirname, result) != 0)
+ {
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ result = (char *) _nl_default_dirname;
+ else
+ {
#if defined _LIBC || defined HAVE_STRDUP
- result = strdup (dirname);
+ result = strdup (dirname);
#else
- size_t len = strlen (dirname) + 1;
- result = (char *) malloc (len);
- if (result != NULL)
- memcpy (result, dirname, len);
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, dirname, len);
#endif
+ }
+
+ if (__builtin_expect (result != NULL, 1))
+ {
+ if (binding->dirname != _nl_default_dirname)
+ free (binding->dirname);
+
+ binding->dirname = result;
+ modified = 1;
+ }
+ }
+ *dirnamep = result;
}
+ }
+
+ if (codesetp)
+ {
+ const char *codeset = *codesetp;
- if (result != NULL)
+ if (codeset == NULL)
+ /* The current binding has be to returned. */
+ *codesetp = binding->codeset;
+ else
{
- if (binding->dirname != _nl_default_dirname)
- free (binding->dirname);
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->codeset;
+ if (result == NULL || strcmp (codeset, result) != 0)
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, codeset, len);
+#endif
- binding->dirname = result;
+ if (__builtin_expect (result != NULL, 1))
+ {
+ if (binding->codeset != NULL)
+ free (binding->codeset);
+
+ binding->codeset = result;
+ modified = 1;
+ }
+ }
+ *codesetp = result;
}
}
}
+ else if ((dirnamep == NULL || *dirnamep == NULL)
+ && (codesetp == NULL || *codesetp == NULL))
+ {
+ /* Simply return the default values. */
+ if (dirnamep)
+ *dirnamep = _nl_default_dirname;
+ if (codesetp)
+ *codesetp = NULL;
+ }
else
{
/* We have to create a new binding. */
@@ -153,61 +224,140 @@ BINDTEXTDOMAIN (domainname, dirname)
struct binding *new_binding =
(struct binding *) malloc (sizeof (*new_binding) + len);
- if (new_binding == NULL)
- result = NULL;
- else
+ if (__builtin_expect (new_binding == NULL, 0))
+ goto failed;
+
+ memcpy (new_binding->domainname, domainname, len);
+
+ if (dirnamep)
{
- memcpy (new_binding->domainname, domainname, len);
+ const char *dirname = *dirnamep;
- if (strcmp (dirname, _nl_default_dirname) == 0)
- result = new_binding->dirname = (char *) _nl_default_dirname;
+ if (dirname == NULL)
+ /* The default value. */
+ dirname = _nl_default_dirname;
else
{
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ dirname = _nl_default_dirname;
+ else
+ {
+ char *result;
#if defined _LIBC || defined HAVE_STRDUP
- result = new_binding->dirname = strdup (dirname);
+ result = strdup (dirname);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
#else
- len = strlen (dirname) + 1;
- result = new_binding->dirname = (char *) malloc (len);
- if (result != NULL)
- memcpy (new_binding->dirname, dirname, len);
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
+ memcpy (result, dirname, len);
#endif
+ dirname = result;
+ }
}
+ *dirnamep = dirname;
+ new_binding->dirname = (char *) dirname;
}
+ else
+ /* The default value. */
+ new_binding->dirname = (char *) _nl_default_dirname;
- if (result != NULL)
+ if (codesetp)
{
- /* Now enqueue it. */
- if (_nl_domain_bindings == NULL
- || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
- {
- new_binding->next = _nl_domain_bindings;
- _nl_domain_bindings = new_binding;
- }
- else
+ const char *codeset = *codesetp;
+
+ if (codeset != NULL)
{
- binding = _nl_domain_bindings;
- while (binding->next != NULL
- && strcmp (domainname, binding->next->domainname) > 0)
- binding = binding->next;
+ char *result;
- new_binding->next = binding->next;
- binding->next = new_binding;
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+ memcpy (result, codeset, len);
+#endif
+ codeset = result;
}
+ *codesetp = codeset;
+ new_binding->codeset = (char *) codeset;
+ }
+ else
+ new_binding->codeset = NULL;
+
+ /* Now enqueue it. */
+ if (_nl_domain_bindings == NULL
+ || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
+ {
+ new_binding->next = _nl_domain_bindings;
+ _nl_domain_bindings = new_binding;
+ }
+ else
+ {
+ binding = _nl_domain_bindings;
+ while (binding->next != NULL
+ && strcmp (domainname, binding->next->domainname) > 0)
+ binding = binding->next;
+
+ new_binding->next = binding->next;
+ binding->next = new_binding;
+ }
+
+ modified = 1;
+
+ /* Here we deal with memory allocation failures. */
+ if (0)
+ {
+ failed_codeset:
+ if (new_binding->dirname != _nl_default_dirname)
+ free (new_binding->dirname);
+ failed_dirname:
+ free (new_binding);
+ failed:
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
}
- else if (new_binding != NULL)
- free (new_binding);
}
- /* For a succesful call we flush the caches. */
- if (result != NULL)
+ /* If we modified any binding, we flush the caches. */
+ if (modified)
++_nl_msg_cat_cntr;
__libc_rwlock_unlock (_nl_state_lock);
+}
+
+/* Specify that the DOMAINNAME message catalog will be found
+ in DIRNAME rather than in the system locale data base. */
+char *
+BINDTEXTDOMAIN (domainname, dirname)
+ const char *domainname;
+ const char *dirname;
+{
+ set_binding_values (domainname, &dirname, NULL);
+ return (char *) dirname;
+}
- return result;
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+char *
+BIND_TEXTDOMAIN_CODESET (domainname, codeset)
+ const char *domainname;
+ const char *codeset;
+{
+ set_binding_values (domainname, NULL, &codeset);
+ return (char *) codeset;
}
#ifdef _LIBC
-/* Alias for function name in GNU C Library. */
+/* Aliases for function names in GNU C Library. */
weak_alias (__bindtextdomain, bindtextdomain);
+weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
#endif
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 4f27cbb3d8..92732582f9 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -230,7 +230,7 @@ transcmp (const void *p1, const void *p2)
result = strcmp (s1->msgid, s2->msgid);
if (result == 0)
{
- result = strcmp (s1->msgid, s2->msgid);
+ result = strcmp (s1->domain, s2->domain);
if (result == 0)
{
result = s1->plindex - s2->plindex;
@@ -362,7 +362,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
#if defined HAVE_TSEARCH || defined _LIBC
struct known_translation_t *search;
struct known_translation_t **foundp = NULL;
- size_t msgid_len = strlen (msgid1) + 1;
+ size_t msgid_len;
#endif
size_t domainname_len;
@@ -372,7 +372,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
__libc_rwlock_rdlock (_nl_state_lock);
+ /* If DOMAINNAME is NULL, we are interested in the default domain. If
+ CATEGORY is not LC_MESSAGES this might not make much sense but the
+ definition left this undefined. */
+ if (domainname == NULL)
+ domainname = _nl_current_default_domain;
+
#if defined HAVE_TSEARCH || defined _LIBC
+ msgid_len = strlen (msgid1) + 1;
+
if (plural == 0)
{
/* Try to find the translation among those which we found at
@@ -399,12 +407,6 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
/* See whether this is a SUID binary or not. */
DETERMINE_SECURE;
- /* If DOMAINNAME is NULL, we are interested in the default domain. If
- CATEGORY is not LC_MESSAGES this might not make much sense but the
- definition left this undefined. */
- if (domainname == NULL)
- domainname = _nl_current_default_domain;
-
/* First find matching binding. */
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
{
@@ -529,7 +531,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
/* Find structure describing the message catalog matching the
DOMAINNAME and CATEGORY. */
- domain = _nl_find_domain (dirname, single_locale, xdomainname);
+ domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
if (domain != NULL)
{
@@ -605,7 +607,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
/* Insert the entry in the search tree. */
foundp = (struct known_translation_t **)
tsearch (newp, &root, transcmp);
- if (&newp != foundp)
+ if (__builtin_expect (&newp != foundp, 0))
/* The insert failed. */
free (newp);
}
@@ -751,7 +753,7 @@ _nl_find_msg (domain_file, msgid, index)
/* Mark that we didn't succeed allocating a table. */
domain->conv_tab = (char **) -1;
- if (domain->conv_tab == (char **) -1)
+ if (__builtin_expect (domain->conv_tab == (char **) -1, 0))
/* Nothing we can do, no more memory. */
goto converted;
@@ -787,59 +789,61 @@ _nl_find_msg (domain_file, msgid, index)
__libc_lock_lock (lock);
+ while (1)
+ {
# ifdef _LIBC
- {
- size_t written;
- int res;
-
- while ((res = __gconv (domain->conv,
- &inbuf, inbuf + resultlen,
- &outbuf, outbuf + freemem_size,
- &written)) == __GCONV_OK)
- {
- if (res != __GCONV_FULL_OUTPUT)
- goto out;
-
- /* We must resize the buffer. */
- freemem_size = MAX (2 * freemem_size, 4064);
- freemem = (char *) malloc (freemem_size);
- if (freemem == NULL)
- goto out;
-
- inbuf = result;
- outbuf = freemem + 4;
- }
- }
+ size_t non_reversible;
+ int res;
+
+ res = __gconv (domain->conv,
+ &inbuf, inbuf + resultlen,
+ &outbuf, outbuf + freemem_size,
+ &non_reversible);
+
+ if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
+ break;
+
+ if (res != __GCONV_FULL_OUTPUT)
+ {
+ __libc_lock_unlock (lock);
+ goto converted;
+ }
+
+ inbuf = result;
# else
# if HAVE_ICONV
- for (;;)
- {
const char *inptr = (const char *) inbuf;
size_t inleft = resultlen;
char *outptr = (char *) outbuf;
size_t outleft = freemem_size;
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
- != (size_t)(-1))
+ != (size_t) (-1))
{
outbuf = (unsigned char *) outptr;
break;
}
if (errno != E2BIG)
- goto out;
+ {
+ __libc_lock_unlock (lock);
+ goto converted;
+ }
+# endif
+# endif
/* We must resize the buffer. */
freemem_size = 2 * freemem_size;
if (freemem_size < 4064)
freemem_size = 4064;
freemem = (char *) malloc (freemem_size);
- if (freemem == NULL)
- goto out;
+ if (__builtin_expect (freemem == NULL, 0))
+ {
+ __libc_lock_unlock (lock);
+ goto converted;
+ }
outbuf = freemem + 4;
}
-# endif
-# endif
/* We have now in our buffer a converted string. Put this
into the table of conversions. */
@@ -848,10 +852,9 @@ _nl_find_msg (domain_file, msgid, index)
/* Shrink freemem, but keep it aligned. */
freemem_size -= outbuf - freemem;
freemem = outbuf;
- freemem += freemem_size & 3;
- freemem_size = freemem_size & ~3;
+ freemem += freemem_size & (__alignof__ (nls_uint32) - 1);
+ freemem_size = freemem_size & ~ (__alignof__ (nls_uint32) - 1);
- out:
__libc_lock_unlock (lock);
}
@@ -1070,15 +1073,19 @@ free_mem (void)
struct binding *runp;
for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next)
- if (runp->dirname != _nl_default_dirname)
- /* Yes, this is a pointer comparison. */
- free (runp->dirname);
+ {
+ if (runp->dirname != _nl_default_dirname)
+ /* Yes, this is a pointer comparison. */
+ free (runp->dirname);
+ if (runp->codeset != NULL)
+ free (runp->codeset);
+ }
if (_nl_current_default_domain != _nl_default_default_domain)
/* Yes, again a pointer comparison. */
free ((char *) _nl_current_default_domain);
- /* Remove the search tree with the know translations. */
+ /* Remove the search tree with the known translations. */
__tdestroy (root, free);
}
diff --git a/intl/finddomain.c b/intl/finddomain.c
index 09f6a91fc2..dc215ad126 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -67,10 +67,11 @@ static struct loaded_l10nfile *_nl_loaded_domains;
established bindings. */
struct loaded_l10nfile *
internal_function
-_nl_find_domain (dirname, locale, domainname)
+_nl_find_domain (dirname, locale, domainname, domainbinding)
const char *dirname;
char *locale;
const char *domainname;
+ struct binding *domainbinding;
{
struct loaded_l10nfile *retval;
const char *language;
@@ -109,7 +110,8 @@ _nl_find_domain (dirname, locale, domainname)
be one data set in the list of loaded domains. */
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, 0, locale, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, domainname, 0);
+ NULL, NULL, NULL, NULL, NULL, domainname,
+ domainbinding, 0);
if (retval != NULL)
{
/* We know something about this locale. */
@@ -165,7 +167,8 @@ _nl_find_domain (dirname, locale, domainname)
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, mask, language, territory,
codeset, normalized_codeset, modifier, special,
- sponsor, revision, domainname, 1);
+ sponsor, revision, domainname, domainbinding,
+ 1);
if (retval == NULL)
/* This means we are out of core. */
return NULL;
diff --git a/intl/gettextP.h b/intl/gettextP.h
index 26d9de0e77..8dcbaf2859 100644
--- a/intl/gettextP.h
+++ b/intl/gettextP.h
@@ -44,6 +44,12 @@
# define internal_function
#endif
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
#ifndef W
# define W(flag, data) ((flag) ? SWAP (data) : (data))
#endif
@@ -137,6 +143,7 @@ struct binding
{
struct binding *next;
char *dirname;
+ char *codeset;
#ifdef __GNUC__
char domainname[0];
#else
@@ -148,7 +155,8 @@ extern int _nl_msg_cat_cntr;
struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
char *__locale,
- const char *__domainname))
+ const char *__domainname,
+ struct binding *__domainbinding))
internal_function;
void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
internal_function;
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
index 01e7e74956..4cd6615bac 100644
--- a/intl/l10nflist.c
+++ b/intl/l10nflist.c
@@ -175,7 +175,7 @@ pop (x)
struct loaded_l10nfile *
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
territory, codeset, normalized_codeset, modifier, special,
- sponsor, revision, filename, do_allocate)
+ sponsor, revision, filename, domainbinding, do_allocate)
struct loaded_l10nfile **l10nfile_list;
const char *dirlist;
size_t dirlist_len;
@@ -189,6 +189,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
const char *sponsor;
const char *revision;
const char *filename;
+ struct binding *domainbinding;
int do_allocate;
{
char *abs_filename;
@@ -309,6 +310,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
return NULL;
retval->filename = abs_filename;
+ retval->domainbinding = domainbinding;
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|| ((mask & XPG_CODESET) != 0
&& (mask & XPG_NORM_CODESET) != 0));
@@ -344,7 +346,8 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
language, territory, codeset,
normalized_codeset, modifier, special,
- sponsor, revision, filename, 1);
+ sponsor, revision, filename, domainbinding,
+ 1);
}
retval->successor[entries] = NULL;
diff --git a/intl/libintl.h b/intl/libintl.h
index 0f147228df..967a8cafcd 100644
--- a/intl/libintl.h
+++ b/intl/libintl.h
@@ -78,6 +78,11 @@ extern char *textdomain (__const char *__domainname) __THROW;
extern char *bindtextdomain (__const char *__domainname,
__const char *__dirname) __THROW;
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+extern char *bind_textdomain_codeset (__const char *__domainname,
+ __const char *__codeset) __THROW;
+
/* Optimized version of the function above. */
#if defined __OPTIMIZE__
diff --git a/intl/loadinfo.h b/intl/loadinfo.h
index 585ed11c5e..1013470f43 100644
--- a/intl/loadinfo.h
+++ b/intl/loadinfo.h
@@ -32,6 +32,12 @@
# define internal_function
#endif
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
/* Encoding of locale name parts. */
#define CEN_REVISION 1
#define CEN_SPONSOR 2
@@ -49,6 +55,7 @@
struct loaded_l10nfile
{
const char *filename;
+ struct binding *domainbinding;
int decided;
const void *data;
@@ -73,7 +80,8 @@ _nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
const char *normalized_codeset,
const char *modifier, const char *special,
const char *sponsor, const char *revision,
- const char *filename, int do_allocate));
+ const char *filename,
+ struct binding *domainbinding, int do_allocate));
extern const char *_nl_expand_alias PARAMS ((const char *name));
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 75265c84a8..4009525fe8 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -16,11 +16,19 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
+#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -30,9 +38,6 @@
#endif
#if defined HAVE_STRING_H || defined _LIBC
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-# endif
# include <string.h>
#else
# include <strings.h>
@@ -138,9 +143,9 @@ _nl_load_domain (domain_file)
return;
/* We must know about the size of the file. */
- if (fstat (fd, &st) != 0
- || (size = (size_t) st.st_size) != st.st_size
- || size < sizeof (struct mo_file_header))
+ if (__builtin_expect (fstat (fd, &st) != 0, 0)
+ || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
+ || __builtin_expect (size < sizeof (struct mo_file_header), 0))
{
/* Something went wrong. */
close (fd);
@@ -153,7 +158,7 @@ _nl_load_domain (domain_file)
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
MAP_PRIVATE, fd, 0);
- if (data != (struct mo_file_header *) -1)
+ if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
{
/* mmap() call was successful. */
close (fd);
@@ -177,12 +182,15 @@ _nl_load_domain (domain_file)
do
{
long int nb = (long int) read (fd, read_ptr, to_read);
- if (nb == -1)
+ if (nb <= 0)
{
+#ifdef EINTR
+ if (nb == -1 && errno == EINTR)
+ continue;
+#endif
close (fd);
return;
}
-
read_ptr += nb;
to_read -= nb;
}
@@ -193,7 +201,8 @@ _nl_load_domain (domain_file)
/* Using the magic number we can test whether it really is a message
catalog file. */
- if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
+ if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
+ 0))
{
/* The magic number is wrong: not a message catalog file. */
#ifdef HAVE_MMAP
@@ -254,14 +263,13 @@ _nl_load_domain (domain_file)
domain->conv = (iconv_t) -1;
# endif
#endif
+ domain->conv_tab = NULL;
nullentry = _nl_find_msg (domain_file, "", 0);
if (nullentry != NULL)
{
+#if defined _LIBC || HAVE_ICONV
const char *charsetstr;
- const char *plural;
- const char *nplurals;
-#if defined _LIBC || HAVE_ICONV
charsetstr = strstr (nullentry, "charset=");
if (charsetstr != NULL)
{
@@ -282,12 +290,33 @@ _nl_load_domain (domain_file)
/* The output charset should normally be determined by the
locale. But sometimes the locale is not used or not correctly
- set up so we provide a possibility to override this. */
- outcharset = getenv ("OUTPUT_CHARSET");
- if (outcharset == NULL || outcharset[0] == '\0')
- outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
+ set up, so we provide a possibility for the user to override
+ this. Moreover, the value specified through
+ bind_textdomain_codeset overrides both. */
+ if (domain_file->domainbinding != NULL
+ && domain_file->domainbinding->codeset != NULL)
+ outcharset = domain_file->domainbinding->codeset;
+ else
+ {
+ outcharset = getenv ("OUTPUT_CHARSET");
+ if (outcharset == NULL || outcharset[0] == '\0')
+ {
+# ifdef _LIBC
+ outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
+# else
+# if HAVE_ICONV
+ extern const char *locale_charset (void);
+ outcharset = locale_charset ();
+ if (outcharset == NULL)
+ outcharset = "";
+# endif
+# endif
+ }
+ }
# ifdef _LIBC
+ outcharset = norm_add_slashes (outcharset);
+ charset = norm_add_slashes (charset);
if (__gconv_open (outcharset, charset, &domain->conv,
GCONV_AVOID_NOCONV)
!= __GCONV_OK)
@@ -299,19 +328,18 @@ _nl_load_domain (domain_file)
# endif
}
#endif /* _LIBC || HAVE_ICONV */
+ }
+
+ /* Also look for a plural specification. */
+ if (nullentry != NULL)
+ {
+ const char *plural;
+ const char *nplurals;
- /* Also look for a plural specification. */
plural = strstr (nullentry, "plural=");
nplurals = strstr (nullentry, "nplurals=");
if (plural == NULL || nplurals == NULL)
- {
- /* By default we are using the Germanic form: singular form only
- for `one', the plural form otherwise. Yes, this is also what
- English is using since English is a Germanic language. */
- no_plural:
- domain->plural = &germanic_plural;
- domain->nplurals = 2;
- }
+ goto no_plural;
else
{
/* First get the number. */
@@ -336,6 +364,15 @@ _nl_load_domain (domain_file)
domain->plural = args.res;
}
}
+ else
+ {
+ /* By default we are using the Germanic form: singular form only
+ for `one', the plural form otherwise. Yes, this is also what
+ English is using since English is a Germanic language. */
+ no_plural:
+ domain->plural = &germanic_plural;
+ domain->nplurals = 2;
+ }
}
diff --git a/intl/localealias.c b/intl/localealias.c
index d2b5ae8895..57c693dcde 100644
--- a/intl/localealias.c
+++ b/intl/localealias.c
@@ -16,6 +16,13 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -53,9 +60,6 @@ void free ();
#endif
#if defined HAVE_STRING_H || defined _LIBC
-# ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-# endif
# include <string.h>
#else
# include <strings.h>
@@ -158,7 +162,7 @@ static size_t maxmap;
/* Prototypes for local functions. */
static size_t read_alias_file PARAMS ((const char *fname, int fname_len))
internal_function;
-static void extend_alias_table PARAMS ((void));
+static int extend_alias_table PARAMS ((void));
static int alias_compare PARAMS ((const struct alias_map *map1,
const struct alias_map *map2));
@@ -326,7 +330,11 @@ read_alias_file (fname, fname_len)
*cp++ = '\0';
if (nmap >= maxmap)
- extend_alias_table ();
+ if (__builtin_expect (extend_alias_table (), 0))
+ {
+ FREE_BLOCKS (block_list);
+ return added;
+ }
alias_len = strlen (alias) + 1;
value_len = strlen (value) + 1;
@@ -374,7 +382,7 @@ read_alias_file (fname, fname_len)
}
-static void
+static int
extend_alias_table ()
{
size_t new_size;
@@ -385,10 +393,11 @@ extend_alias_table ()
* sizeof (struct alias_map)));
if (new_map == NULL)
/* Simply don't extend: we don't have any more core. */
- return;
+ return -1;
map = new_map;
maxmap = new_size;
+ return 0;
}