summaryrefslogtreecommitdiff
path: root/intl/dcgettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-08-20 19:52:54 +0000
committerUlrich Drepper <drepper@redhat.com>1999-08-20 19:52:54 +0000
commit6570e194e60822d81d6df31e260985e6a13b0f2a (patch)
tree505bc4144874d98bb1a19417ac3e69fe95debae9 /intl/dcgettext.c
parentbe7d999a0931203c5541714a255635459ee6dde2 (diff)
downloadglibc-6570e194e60822d81d6df31e260985e6a13b0f2a.tar.gz
Update.
* intl/gettextP.h (struct loaded_domain): Add conv element. * intl/dcgettext.c (find_msg): Rename to _nl_find_msg and make public. Instead of returning found message directly convert it using iconv if a conversion was found when opening the file. * intl/loadinfo.h: Protect against multiple inclusion. Declare _nl_find_msg. * intl/loadmsgcat.c (_nl_load_domain): Try to determine charset used in the message file and if necessary find approrpiate conversion to match currently selected charset.
Diffstat (limited to 'intl/dcgettext.c')
-rw-r--r--intl/dcgettext.c103
1 files changed, 95 insertions, 8 deletions
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index cc5299e460..0429cc904e 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -83,6 +83,10 @@ void free ();
# include <locale.h>
#endif
+#if defined HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+
#include "gettext.h"
#include "gettextP.h"
#ifdef _LIBC
@@ -92,6 +96,11 @@ void free ();
#endif
#include "hash-string.h"
+/* Thread safetyness. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#endif
+
/* @@ end of prolog @@ */
#ifdef _LIBC
@@ -171,8 +180,6 @@ const char _nl_default_dirname[] = GNULOCALEDIR;
struct binding *_nl_domain_bindings;
/* Prototypes for local functions. */
-static char *find_msg PARAMS ((struct loaded_l10nfile *domain_file,
- const char *msgid)) internal_function;
static const char *category_to_name PARAMS ((int category)) internal_function;
static const char *guess_category_value PARAMS ((int category,
const char *categoryname))
@@ -396,7 +403,7 @@ DCGETTEXT (domainname, msgid, category)
if (domain != NULL)
{
- retval = find_msg (domain, msgid);
+ retval = _nl_find_msg (domain, msgid);
if (retval == NULL)
{
@@ -404,7 +411,7 @@ DCGETTEXT (domainname, msgid, category)
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
{
- retval = find_msg (domain->successor[cnt], msgid);
+ retval = _nl_find_msg (domain->successor[cnt], msgid);
if (retval != NULL)
break;
@@ -428,9 +435,9 @@ weak_alias (__dcgettext, dcgettext);
#endif
-static char *
+char *
internal_function
-find_msg (domain_file, msgid)
+_nl_find_msg (domain_file, msgid)
struct loaded_l10nfile *domain_file;
const char *msgid;
{
@@ -464,8 +471,88 @@ find_msg (domain_file, msgid)
&& strcmp (msgid,
domain->data + W (domain->must_swap,
domain->orig_tab[nstr - 1].offset)) == 0)
- return (char *) domain->data + W (domain->must_swap,
- domain->trans_tab[nstr - 1].offset);
+ {
+ /* We found an entry. If we have to convert the string to use
+ a different character set this is the time. */
+ char *result =
+ (char *) domain->data + W (domain->must_swap,
+ domain->trans_tab[nstr - 1].offset);
+
+ if (
+#if HAVE_ICONV || defined _LIBC
+ domain->conv != (iconv_t) -1
+#endif
+ )
+ {
+ /* We are supposed to do a conversion. First allocate an
+ appropriate table with the same structure as the hash
+ table in the file where we can put the pointers to the
+ converted strings in. */
+ if (domain->conv_tab == NULL
+ && ((domain->conv_tab = (char **) calloc (domain->hash_size,
+ sizeof (char *)))
+ == NULL))
+ /* Mark that we didn't succeed allocating a table. */
+ domain->conv_tab = (char **) -1;
+
+ if (domain->conv_tab == (char **) -1)
+ /* Nothing we can do, no more memory. */
+ return NULL;
+
+ if (domain->conv_tab[idx] == NULL)
+ {
+ /* We haven't used this string so far, so it is not
+ translated yet. Do this now. */
+#ifdef _LIBC
+ /* For glibc we use a bit more efficient memory handling.
+ We allocate always larger blocks which get used over
+ time. This is faster than many small allocations. */
+ __libc_lock_define_initialized (static, lock)
+ static char *freemem;
+ static size_t freemem_size;
+ /* Note that we include the NUL byte. */
+ size_t resultlen = strlen (result) + 1;
+ const char *inbuf = result;
+ size_t inbytesleft = resultlen;
+ char *outbuf = freemem;
+ size_t outbytesleft = freemem_size;
+
+ __libc_lock_lock (lock);
+
+ while (iconv (domain->conv, &inbuf, &inbytesleft, &outbuf,
+ &outbytesleft) == (size_t) -1L)
+ {
+ if (errno != E2BIG)
+ 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;
+ inbytesleft = resultlen;
+ outbuf = freemem;
+ outbytesleft = freemem_size;
+ }
+
+ /* We have now in our buffer a converted string. Put this
+ in the hash table */
+ domain->conv_tab[idx] = freemem;
+ freemem = outbuf;
+ freemem_size = outbytesleft;
+
+ out:
+ __libc_lock_unlock (lock);
+#endif
+ }
+
+ result = domain->conv_tab[idx];
+ }
+
+ return result;
+ }
while (1)
{