mirror of
https://sourceware.org/git/glibc.git
synced 2026-01-06 11:51:29 +03:00
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.
This commit is contained in:
103
intl/dcgettext.c
103
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user