mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
Update
2001-01-04 H.J. Lu <hjl@gnu.org> * elf/dl-support.c (DL_FIND_AUXV): New. Defined if not defined. (_dl_clktck): Declared. (non_dynamic_init): Take 3 arguments. Set _dl_pagesize, _dl_platform and _dl_clktck from AUX. 2001-01-01 Bruno Haible <haible@clisp.cons.org> Finish implementation of plural form handling. * intl/dcigettext.c (known_translation_t): Rename 'domain' field to 'domainname'. Remove 'plindex' field. Add 'domain' and 'translation_length' fields. (transcmp): Don't compare 'plindex' fields. (plural_lookup): New function. (DCIGETTEXT): Change cache handing in the plural case. Don't call plural_eval before the translation and its catalog file have been found. Remove plindex from cache key. Add 'translation_length' and 'domain' to cache result. (_nl_find_msg): Remove index argument, return length of translation to the caller instead. Weaken comparison of string lengths, to account for plural entries. Call iconv() on the entire result string, not only on the portion needed so far. * intl/loadinfo.h (_nl_find_msg): Remove index argument, add lengthp argument. * intl/loadmsgcat.c (_nl_load_domain): Adapt to _nl_find_msg change.
This commit is contained in:
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
|||||||
|
2001-01-04 H.J. Lu <hjl@gnu.org>
|
||||||
|
|
||||||
|
* elf/dl-support.c (DL_FIND_AUXV): New. Defined if not defined.
|
||||||
|
(_dl_clktck): Declared.
|
||||||
|
(non_dynamic_init): Take 3 arguments.
|
||||||
|
Set _dl_pagesize, _dl_platform and _dl_clktck from AUX.
|
||||||
|
|
||||||
|
2001-01-01 Bruno Haible <haible@clisp.cons.org>
|
||||||
|
|
||||||
|
Finish implementation of plural form handling.
|
||||||
|
* intl/dcigettext.c (known_translation_t): Rename 'domain' field to
|
||||||
|
'domainname'. Remove 'plindex' field. Add 'domain' and
|
||||||
|
'translation_length' fields.
|
||||||
|
(transcmp): Don't compare 'plindex' fields.
|
||||||
|
(plural_lookup): New function.
|
||||||
|
(DCIGETTEXT): Change cache handing in the plural case. Don't call
|
||||||
|
plural_eval before the translation and its catalog file have been
|
||||||
|
found. Remove plindex from cache key. Add 'translation_length' and
|
||||||
|
'domain' to cache result.
|
||||||
|
(_nl_find_msg): Remove index argument, return length of translation
|
||||||
|
to the caller instead. Weaken comparison of string lengths, to account
|
||||||
|
for plural entries. Call iconv() on the entire result string, not
|
||||||
|
only on the portion needed so far.
|
||||||
|
* intl/loadinfo.h (_nl_find_msg): Remove index argument, add lengthp
|
||||||
|
argument.
|
||||||
|
* intl/loadmsgcat.c (_nl_load_domain): Adapt to _nl_find_msg change.
|
||||||
|
|
||||||
2001-01-04 Ulrich Drepper <drepper@redhat.com>
|
2001-01-04 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
* intl/plural.y (yylex): Minimal improvement in number scanner.
|
* intl/plural.y (yylex): Minimal improvement in number scanner.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Support for dynamic linking code in static libc.
|
/* Support for dynamic linking code in static libc.
|
||||||
Copyright (C) 1996,97,98,99,2000 Free Software Foundation, Inc.
|
Copyright (C) 1996, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -107,16 +107,47 @@ int _dl_starting_up = 1;
|
|||||||
At this time it is not anymore a problem to modify the tables. */
|
At this time it is not anymore a problem to modify the tables. */
|
||||||
__libc_lock_define_initialized_recursive (, _dl_load_lock)
|
__libc_lock_define_initialized_recursive (, _dl_load_lock)
|
||||||
|
|
||||||
|
#ifndef DL_FIND_AUXV
|
||||||
|
# define DL_FIND_AUXV(auxp, envp) \
|
||||||
|
do { \
|
||||||
|
void **_tmp; \
|
||||||
|
for (_tmp = (void **) (envp); *_tmp; ++_tmp) \
|
||||||
|
continue; \
|
||||||
|
(auxp) = (void *) ++_tmp; \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void non_dynamic_init (void) __attribute__ ((unused));
|
extern int _dl_clktck;
|
||||||
|
|
||||||
|
static void non_dynamic_init (int argc, char **argv, char **envp)
|
||||||
|
__attribute__ ((unused));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
non_dynamic_init (void)
|
non_dynamic_init (int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
|
ElfW(auxv_t) *av;
|
||||||
|
|
||||||
|
DL_FIND_AUXV (av, envp);
|
||||||
|
|
||||||
|
for (; av->a_type != AT_NULL; ++av)
|
||||||
|
switch (av->a_type)
|
||||||
|
{
|
||||||
|
case AT_PAGESZ:
|
||||||
|
_dl_pagesize = av->a_un.a_val;
|
||||||
|
break;
|
||||||
|
case AT_PLATFORM:
|
||||||
|
_dl_platform = av->a_un.a_ptr;
|
||||||
|
break;
|
||||||
|
case AT_CLKTCK:
|
||||||
|
_dl_clktck = av->a_un.a_val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_dl_pagesize)
|
||||||
_dl_pagesize = __getpagesize ();
|
_dl_pagesize = __getpagesize ();
|
||||||
|
|
||||||
|
_dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
|
||||||
|
|
||||||
/* Initialize the data structures for the search paths for shared
|
/* Initialize the data structures for the search paths for shared
|
||||||
objects. */
|
objects. */
|
||||||
_dl_init_paths (getenv ("LD_LIBRARY_PATH"));
|
_dl_init_paths (getenv ("LD_LIBRARY_PATH"));
|
||||||
|
@ -210,10 +210,7 @@ static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
|
|||||||
struct known_translation_t
|
struct known_translation_t
|
||||||
{
|
{
|
||||||
/* Domain in which to search. */
|
/* Domain in which to search. */
|
||||||
char *domain;
|
char *domainname;
|
||||||
|
|
||||||
/* Plural index. */
|
|
||||||
unsigned long int plindex;
|
|
||||||
|
|
||||||
/* The category. */
|
/* The category. */
|
||||||
int category;
|
int category;
|
||||||
@ -221,8 +218,12 @@ struct known_translation_t
|
|||||||
/* State of the catalog counter at the point the string was found. */
|
/* State of the catalog counter at the point the string was found. */
|
||||||
int counter;
|
int counter;
|
||||||
|
|
||||||
|
/* Catalog where the string was found. */
|
||||||
|
struct loaded_l10nfile *domain;
|
||||||
|
|
||||||
/* And finally the translation. */
|
/* And finally the translation. */
|
||||||
const char *translation;
|
const char *translation;
|
||||||
|
size_t translation_length;
|
||||||
|
|
||||||
/* Pointer to the string in question. */
|
/* Pointer to the string in question. */
|
||||||
char msgid[ZERO];
|
char msgid[ZERO];
|
||||||
@ -253,17 +254,13 @@ transcmp (const void *p1, const void *p2)
|
|||||||
result = strcmp (s1->msgid, s2->msgid);
|
result = strcmp (s1->msgid, s2->msgid);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
result = strcmp (s1->domain, s2->domain);
|
result = strcmp (s1->domainname, s2->domainname);
|
||||||
if (result == 0)
|
|
||||||
{
|
|
||||||
result = s1->plindex - s2->plindex;
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
/* We compare the category last (though this is the cheapest
|
/* We compare the category last (though this is the cheapest
|
||||||
operation) since it is hopefully always the same (namely
|
operation) since it is hopefully always the same (namely
|
||||||
LC_MESSAGES). */
|
LC_MESSAGES). */
|
||||||
result = s1->category - s2->category;
|
result = s1->category - s2->category;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -284,8 +281,14 @@ const char _nl_default_dirname[] = GNULOCALEDIR;
|
|||||||
struct binding *_nl_domain_bindings;
|
struct binding *_nl_domain_bindings;
|
||||||
|
|
||||||
/* Prototypes for local functions. */
|
/* Prototypes for local functions. */
|
||||||
static unsigned long int plural_eval (struct expression *pexp,
|
static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
|
||||||
unsigned long int n) internal_function;
|
unsigned long int n,
|
||||||
|
const char *translation,
|
||||||
|
size_t translation_len))
|
||||||
|
internal_function;
|
||||||
|
static unsigned long int plural_eval PARAMS ((struct expression *pexp,
|
||||||
|
unsigned long int n))
|
||||||
|
internal_function;
|
||||||
static const char *category_to_name PARAMS ((int category)) internal_function;
|
static const char *category_to_name PARAMS ((int category)) internal_function;
|
||||||
static const char *guess_category_value PARAMS ((int category,
|
static const char *guess_category_value PARAMS ((int category,
|
||||||
const char *categoryname))
|
const char *categoryname))
|
||||||
@ -328,12 +331,17 @@ struct block_list
|
|||||||
#endif /* have alloca */
|
#endif /* have alloca */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
/* List of blocks allocated for translations. */
|
/* List of blocks allocated for translations. */
|
||||||
static struct transmem_list
|
typedef struct transmem_list
|
||||||
{
|
{
|
||||||
struct transmem_list *next;
|
struct transmem_list *next;
|
||||||
char data[0];
|
char data[0];
|
||||||
} *transmem_list;
|
} transmem_block_t;
|
||||||
|
static struct transmem_list *transmem_list;
|
||||||
|
#else
|
||||||
|
typedef char transmem_block_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Names for the libintl functions are a problem. They must not clash
|
/* Names for the libintl functions are a problem. They must not clash
|
||||||
@ -389,6 +397,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
char *dirname, *xdomainname;
|
char *dirname, *xdomainname;
|
||||||
char *single_locale;
|
char *single_locale;
|
||||||
char *retval;
|
char *retval;
|
||||||
|
size_t retlen;
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
#if defined HAVE_TSEARCH || defined _LIBC
|
#if defined HAVE_TSEARCH || defined _LIBC
|
||||||
struct known_translation_t *search;
|
struct known_translation_t *search;
|
||||||
@ -412,23 +421,26 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
#if defined HAVE_TSEARCH || defined _LIBC
|
#if defined HAVE_TSEARCH || defined _LIBC
|
||||||
msgid_len = strlen (msgid1) + 1;
|
msgid_len = strlen (msgid1) + 1;
|
||||||
|
|
||||||
if (plural == 0)
|
|
||||||
{
|
|
||||||
/* Try to find the translation among those which we found at
|
/* Try to find the translation among those which we found at
|
||||||
some time. */
|
some time. */
|
||||||
search = (struct known_translation_t *) alloca (sizeof (*search)
|
search =
|
||||||
+ msgid_len);
|
(struct known_translation_t *) alloca (sizeof (*search) + msgid_len);
|
||||||
memcpy (search->msgid, msgid1, msgid_len);
|
memcpy (search->msgid, msgid1, msgid_len);
|
||||||
search->domain = (char *) domainname;
|
search->domainname = (char *) domainname;
|
||||||
search->plindex = 0;
|
|
||||||
search->category = category;
|
search->category = category;
|
||||||
|
|
||||||
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
|
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
|
||||||
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
|
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
|
||||||
{
|
{
|
||||||
|
/* Now deal with plural. */
|
||||||
|
if (plural)
|
||||||
|
retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
|
||||||
|
(*foundp)->translation_length);
|
||||||
|
else
|
||||||
|
retval = (char *) (*foundp)->translation;
|
||||||
|
|
||||||
__libc_rwlock_unlock (_nl_state_lock);
|
__libc_rwlock_unlock (_nl_state_lock);
|
||||||
return (char *) (*foundp)->translation;
|
return retval;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -563,39 +575,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
|
|
||||||
if (domain != NULL)
|
if (domain != NULL)
|
||||||
{
|
{
|
||||||
unsigned long int index = 0;
|
retval = _nl_find_msg (domain, msgid1, &retlen);
|
||||||
|
|
||||||
if (plural != 0)
|
|
||||||
{
|
|
||||||
const struct loaded_domain *domaindata =
|
|
||||||
(const struct loaded_domain *) domain->data;
|
|
||||||
index = plural_eval (domaindata->plural, n);
|
|
||||||
if (index >= domaindata->nplurals)
|
|
||||||
/* This should never happen. It means the plural expression
|
|
||||||
and the given maximum value do not match. */
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
#if defined HAVE_TSEARCH || defined _LIBC
|
|
||||||
/* Try to find the translation among those which we
|
|
||||||
found at some time. */
|
|
||||||
search = (struct known_translation_t *) alloca (sizeof (*search)
|
|
||||||
+ msgid_len);
|
|
||||||
memcpy (search->msgid, msgid1, msgid_len);
|
|
||||||
search->domain = (char *) domainname;
|
|
||||||
search->plindex = index;
|
|
||||||
search->category = category;
|
|
||||||
|
|
||||||
foundp = (struct known_translation_t **) tfind (search, &root,
|
|
||||||
transcmp);
|
|
||||||
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
|
|
||||||
{
|
|
||||||
__libc_rwlock_unlock (_nl_state_lock);
|
|
||||||
return (char *) (*foundp)->translation;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = _nl_find_msg (domain, msgid1, index);
|
|
||||||
|
|
||||||
if (retval == NULL)
|
if (retval == NULL)
|
||||||
{
|
{
|
||||||
@ -604,15 +584,20 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
|
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
|
||||||
{
|
{
|
||||||
retval = _nl_find_msg (domain->successor[cnt], msgid1,
|
retval = _nl_find_msg (domain->successor[cnt], msgid1,
|
||||||
index);
|
&retlen);
|
||||||
|
|
||||||
if (retval != NULL)
|
if (retval != NULL)
|
||||||
|
{
|
||||||
|
domain = domain->successor[cnt];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (retval != NULL)
|
if (retval != NULL)
|
||||||
{
|
{
|
||||||
|
/* Found the translation of MSGID1 in domain DOMAIN:
|
||||||
|
starting at RETVAL, RETLEN bytes. */
|
||||||
FREE_BLOCKS (block_list);
|
FREE_BLOCKS (block_list);
|
||||||
__set_errno (saved_errno);
|
__set_errno (saved_errno);
|
||||||
#if defined HAVE_TSEARCH || defined _LIBC
|
#if defined HAVE_TSEARCH || defined _LIBC
|
||||||
@ -626,12 +611,14 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
+ domainname_len + 1 - ZERO);
|
+ domainname_len + 1 - ZERO);
|
||||||
if (newp != NULL)
|
if (newp != NULL)
|
||||||
{
|
{
|
||||||
newp->domain = mempcpy (newp->msgid, msgid1, msgid_len);
|
newp->domainname =
|
||||||
memcpy (newp->domain, domainname, domainname_len + 1);
|
mempcpy (newp->msgid, msgid1, msgid_len);
|
||||||
newp->plindex = index;
|
memcpy (newp->domainname, domainname, domainname_len + 1);
|
||||||
newp->category = category;
|
newp->category = category;
|
||||||
newp->counter = _nl_msg_cat_cntr;
|
newp->counter = _nl_msg_cat_cntr;
|
||||||
|
newp->domain = domain;
|
||||||
newp->translation = retval;
|
newp->translation = retval;
|
||||||
|
newp->translation_length = retlen;
|
||||||
|
|
||||||
/* Insert the entry in the search tree. */
|
/* Insert the entry in the search tree. */
|
||||||
foundp = (struct known_translation_t **)
|
foundp = (struct known_translation_t **)
|
||||||
@ -646,9 +633,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
{
|
{
|
||||||
/* We can update the existing entry. */
|
/* We can update the existing entry. */
|
||||||
(*foundp)->counter = _nl_msg_cat_cntr;
|
(*foundp)->counter = _nl_msg_cat_cntr;
|
||||||
|
(*foundp)->domain = domain;
|
||||||
(*foundp)->translation = retval;
|
(*foundp)->translation = retval;
|
||||||
|
(*foundp)->translation_length = retlen;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* Now deal with plural. */
|
||||||
|
if (plural)
|
||||||
|
retval = plural_lookup (domain, n, retval, retlen);
|
||||||
|
|
||||||
__libc_rwlock_unlock (_nl_state_lock);
|
__libc_rwlock_unlock (_nl_state_lock);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -660,14 +653,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
|
|||||||
|
|
||||||
char *
|
char *
|
||||||
internal_function
|
internal_function
|
||||||
_nl_find_msg (domain_file, msgid, index)
|
_nl_find_msg (domain_file, msgid, lengthp)
|
||||||
struct loaded_l10nfile *domain_file;
|
struct loaded_l10nfile *domain_file;
|
||||||
const char *msgid;
|
const char *msgid;
|
||||||
unsigned long int index;
|
size_t *lengthp;
|
||||||
{
|
{
|
||||||
const struct loaded_domain *domain;
|
const struct loaded_domain *domain;
|
||||||
size_t act;
|
size_t act;
|
||||||
char *result;
|
char *result;
|
||||||
|
size_t resultlen;
|
||||||
|
|
||||||
if (domain_file->decided == 0)
|
if (domain_file->decided == 0)
|
||||||
_nl_load_domain (domain_file);
|
_nl_load_domain (domain_file);
|
||||||
@ -691,17 +685,21 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
/* Hash table entry is empty. */
|
/* Hash table entry is empty. */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
|
while (1)
|
||||||
&& strcmp (msgid,
|
{
|
||||||
|
/* Compare msgid with the original string at index nstr-1.
|
||||||
|
We compare the lengths with >=, not ==, because plural entries
|
||||||
|
are represented by strings with an embedded NUL. */
|
||||||
|
if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
|
||||||
|
&& (strcmp (msgid,
|
||||||
domain->data + W (domain->must_swap,
|
domain->data + W (domain->must_swap,
|
||||||
domain->orig_tab[nstr - 1].offset)) == 0)
|
domain->orig_tab[nstr - 1].offset))
|
||||||
|
== 0))
|
||||||
{
|
{
|
||||||
act = nstr - 1;
|
act = nstr - 1;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (idx >= domain->hash_size - incr)
|
if (idx >= domain->hash_size - incr)
|
||||||
idx -= domain->hash_size - incr;
|
idx -= domain->hash_size - incr;
|
||||||
else
|
else
|
||||||
@ -711,16 +709,6 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
if (nstr == 0)
|
if (nstr == 0)
|
||||||
/* Hash table entry is empty. */
|
/* Hash table entry is empty. */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
|
|
||||||
&& (strcmp (msgid,
|
|
||||||
domain->data + W (domain->must_swap,
|
|
||||||
domain->orig_tab[nstr - 1].offset))
|
|
||||||
== 0))
|
|
||||||
{
|
|
||||||
act = nstr - 1;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
@ -756,6 +744,7 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
string to use a different character set, this is the time. */
|
string to use a different character set, this is the time. */
|
||||||
result = ((char *) domain->data
|
result = ((char *) domain->data
|
||||||
+ W (domain->must_swap, domain->trans_tab[act].offset));
|
+ W (domain->must_swap, domain->trans_tab[act].offset));
|
||||||
|
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
|
||||||
|
|
||||||
#if defined _LIBC || HAVE_ICONV
|
#if defined _LIBC || HAVE_ICONV
|
||||||
if (
|
if (
|
||||||
@ -772,9 +761,10 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
appropriate table with the same structure as the table
|
appropriate table with the same structure as the table
|
||||||
of translations in the file, where we can put the pointers
|
of translations in the file, where we can put the pointers
|
||||||
to the converted strings in.
|
to the converted strings in.
|
||||||
There is a slight complication with the INDEX: We don't know
|
There is a slight complication with plural entries. They
|
||||||
a priori which entries are plural entries. Therefore at any
|
are represented by consecutive NUL terminated strings. We
|
||||||
moment we can only translate the variants 0 .. INDEX. */
|
handle this case by converting RESULTLEN bytes, including
|
||||||
|
NULs. */
|
||||||
|
|
||||||
if (domain->conv_tab == NULL
|
if (domain->conv_tab == NULL
|
||||||
&& ((domain->conv_tab = (char **) calloc (domain->nstrings,
|
&& ((domain->conv_tab = (char **) calloc (domain->nstrings,
|
||||||
@ -787,8 +777,7 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
/* Nothing we can do, no more memory. */
|
/* Nothing we can do, no more memory. */
|
||||||
goto converted;
|
goto converted;
|
||||||
|
|
||||||
if (domain->conv_tab[act] == NULL
|
if (domain->conv_tab[act] == NULL)
|
||||||
|| *(nls_uint32 *) domain->conv_tab[act] < index)
|
|
||||||
{
|
{
|
||||||
/* We haven't used this string so far, so it is not
|
/* We haven't used this string so far, so it is not
|
||||||
translated yet. Do this now. */
|
translated yet. Do this now. */
|
||||||
@ -800,42 +789,33 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
static unsigned char *freemem;
|
static unsigned char *freemem;
|
||||||
static size_t freemem_size;
|
static size_t freemem_size;
|
||||||
|
|
||||||
size_t resultlen;
|
|
||||||
const unsigned char *inbuf;
|
const unsigned char *inbuf;
|
||||||
unsigned char *outbuf;
|
unsigned char *outbuf;
|
||||||
int malloc_count;
|
int malloc_count;
|
||||||
|
# ifndef _LIBC
|
||||||
/* Note that we translate (index + 1) consecutive strings at
|
transmem_block_t *transmem_list = NULL;
|
||||||
once, including the final NUL byte. */
|
# endif
|
||||||
{
|
|
||||||
unsigned long int i = index;
|
|
||||||
char *p = result;
|
|
||||||
do
|
|
||||||
p += strlen (p) + 1;
|
|
||||||
while (i-- > 0);
|
|
||||||
resultlen = p - result;
|
|
||||||
}
|
|
||||||
|
|
||||||
__libc_lock_lock (lock);
|
__libc_lock_lock (lock);
|
||||||
|
|
||||||
inbuf = result;
|
inbuf = result;
|
||||||
outbuf = freemem + sizeof (nls_uint32);
|
outbuf = freemem + sizeof (size_t);
|
||||||
|
|
||||||
malloc_count = 0;
|
malloc_count = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
transmem_block_t *newmem;
|
||||||
# ifdef _LIBC
|
# ifdef _LIBC
|
||||||
struct transmem_list *newmem;
|
|
||||||
size_t non_reversible;
|
size_t non_reversible;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (freemem_size < 4)
|
if (freemem_size < sizeof (size_t))
|
||||||
goto resize_freemem;
|
goto resize_freemem;
|
||||||
|
|
||||||
res = __gconv (domain->conv,
|
res = __gconv (domain->conv,
|
||||||
&inbuf, inbuf + resultlen,
|
&inbuf, inbuf + resultlen,
|
||||||
&outbuf,
|
&outbuf,
|
||||||
outbuf + freemem_size - sizeof (nls_uint32),
|
outbuf + freemem_size - sizeof (size_t),
|
||||||
&non_reversible);
|
&non_reversible);
|
||||||
|
|
||||||
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
|
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
|
||||||
@ -850,16 +830,15 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
inbuf = result;
|
inbuf = result;
|
||||||
# else
|
# else
|
||||||
# if HAVE_ICONV
|
# if HAVE_ICONV
|
||||||
# define transmem freemem
|
|
||||||
const char *inptr = (const char *) inbuf;
|
const char *inptr = (const char *) inbuf;
|
||||||
size_t inleft = resultlen;
|
size_t inleft = resultlen;
|
||||||
char *outptr = (char *) outbuf;
|
char *outptr = (char *) outbuf;
|
||||||
size_t outleft;
|
size_t outleft;
|
||||||
|
|
||||||
if (freemem_size < 4)
|
if (freemem_size < sizeof (size_t))
|
||||||
goto resize_freemem;
|
goto resize_freemem;
|
||||||
|
|
||||||
outleft = freemem_size - 4;
|
outleft = freemem_size - sizeof (size_t);
|
||||||
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
|
if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)
|
||||||
!= (size_t) (-1))
|
!= (size_t) (-1))
|
||||||
{
|
{
|
||||||
@ -871,30 +850,34 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
__libc_lock_unlock (lock);
|
__libc_lock_unlock (lock);
|
||||||
goto converted;
|
goto converted;
|
||||||
}
|
}
|
||||||
# else
|
|
||||||
# define transmem freemem
|
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
resize_freemem:
|
resize_freemem:
|
||||||
/* We must allocate a new buffer of resize the old one. */
|
/* We must allocate a new buffer or resize the old one. */
|
||||||
if (malloc_count > 0)
|
if (malloc_count > 0)
|
||||||
{
|
{
|
||||||
struct transmem_list *next = transmem_list->next;
|
|
||||||
|
|
||||||
++malloc_count;
|
++malloc_count;
|
||||||
freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
|
freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
|
||||||
newmem = (struct transmem_list *) realloc (transmem_list,
|
newmem = (transmem_block_t *) realloc (transmem_list,
|
||||||
freemem_size);
|
freemem_size);
|
||||||
|
# ifdef _LIBC
|
||||||
if (newmem != NULL)
|
if (newmem != NULL)
|
||||||
transmem_list = next;
|
transmem_list = transmem_list->next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct transmem_list *old = transmem_list;
|
||||||
|
|
||||||
|
transmem_list = transmem_list->next;
|
||||||
|
free (old);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
malloc_count = 1;
|
malloc_count = 1;
|
||||||
freemem_size = INITIAL_BLOCK_SIZE;
|
freemem_size = INITIAL_BLOCK_SIZE;
|
||||||
newmem = (struct transmem_list *) malloc (freemem_size);
|
newmem = (transmem_block_t *) malloc (freemem_size);
|
||||||
}
|
}
|
||||||
if (__builtin_expect (newmem == NULL, 0))
|
if (__builtin_expect (newmem == NULL, 0))
|
||||||
{
|
{
|
||||||
@ -912,27 +895,31 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
|
|
||||||
freemem = newmem->data;
|
freemem = newmem->data;
|
||||||
freemem_size -= offsetof (struct transmem_list, data);
|
freemem_size -= offsetof (struct transmem_list, data);
|
||||||
|
# else
|
||||||
|
transmem_list = newmem;
|
||||||
|
freemem = newmem;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
outbuf = freemem + sizeof (nls_uint32);
|
outbuf = freemem + sizeof (size_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have now in our buffer a converted string. Put this
|
/* We have now in our buffer a converted string. Put this
|
||||||
into the table of conversions. */
|
into the table of conversions. */
|
||||||
*(nls_uint32 *) freemem = index;
|
*(size_t *) freemem = outbuf - freemem - sizeof (size_t);
|
||||||
domain->conv_tab[act] = freemem;
|
domain->conv_tab[act] = freemem;
|
||||||
/* Shrink freemem, but keep it aligned. */
|
/* Shrink freemem, but keep it aligned. */
|
||||||
freemem_size -= outbuf - freemem;
|
freemem_size -= outbuf - freemem;
|
||||||
freemem = outbuf;
|
freemem = outbuf;
|
||||||
freemem += freemem_size & (alignof (nls_uint32) - 1);
|
freemem += freemem_size & (alignof (size_t) - 1);
|
||||||
freemem_size = freemem_size & ~ (alignof (nls_uint32) - 1);
|
freemem_size = freemem_size & ~ (alignof (size_t) - 1);
|
||||||
|
|
||||||
__libc_lock_unlock (lock);
|
__libc_lock_unlock (lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now domain->conv_tab[act] contains the translation of at least
|
/* Now domain->conv_tab[act] contains the translation of all
|
||||||
the variants 0 .. INDEX. */
|
the plural variants. */
|
||||||
result = domain->conv_tab[act] + sizeof (nls_uint32);
|
result = domain->conv_tab[act] + sizeof (size_t);
|
||||||
|
resultlen = *(size_t *) domain->conv_tab[act];
|
||||||
}
|
}
|
||||||
|
|
||||||
converted:
|
converted:
|
||||||
@ -940,26 +927,58 @@ _nl_find_msg (domain_file, msgid, index)
|
|||||||
|
|
||||||
#endif /* _LIBC || HAVE_ICONV */
|
#endif /* _LIBC || HAVE_ICONV */
|
||||||
|
|
||||||
/* Now skip some strings. How much depends on the index passed in. */
|
*lengthp = resultlen;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Look up a plural variant. */
|
||||||
|
static char *
|
||||||
|
internal_function
|
||||||
|
plural_lookup (domain, n, translation, translation_len)
|
||||||
|
struct loaded_l10nfile *domain;
|
||||||
|
unsigned long int n;
|
||||||
|
const char *translation;
|
||||||
|
size_t translation_len;
|
||||||
|
{
|
||||||
|
struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
|
||||||
|
unsigned long int index;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
index = plural_eval (domaindata->plural, n);
|
||||||
|
if (index >= domaindata->nplurals)
|
||||||
|
/* This should never happen. It means the plural expression and the
|
||||||
|
given maximum value do not match. */
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
/* Skip INDEX strings at TRANSLATION. */
|
||||||
|
p = translation;
|
||||||
while (index-- > 0)
|
while (index-- > 0)
|
||||||
{
|
{
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
result = __rawmemchr (result, '\0');
|
p = __rawmemchr (p, '\0');
|
||||||
#else
|
#else
|
||||||
result = strchr (result, '\0');
|
p = strchr (p, '\0');
|
||||||
#endif
|
#endif
|
||||||
/* And skip over the NUL byte. */
|
/* And skip over the NUL byte. */
|
||||||
++result;
|
p++;
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
if (p >= translation + translation_len)
|
||||||
|
/* This should never happen. It means the plural expression
|
||||||
|
evaluated to a value larger than the number of variants
|
||||||
|
available for MSGID1. */
|
||||||
|
return (char *) translation;
|
||||||
|
}
|
||||||
|
return (char *) p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Function to evaluate the plural expression and return an index value. */
|
/* Function to evaluate the plural expression and return an index value. */
|
||||||
static unsigned long int
|
static unsigned long int
|
||||||
internal_function
|
internal_function
|
||||||
plural_eval (struct expression *pexp, unsigned long int n)
|
plural_eval (pexp, n)
|
||||||
|
struct expression *pexp;
|
||||||
|
unsigned long int n;
|
||||||
{
|
{
|
||||||
switch (pexp->operation)
|
switch (pexp->operation)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ extern char *_nl_find_language PARAMS ((const char *name));
|
|||||||
|
|
||||||
|
|
||||||
extern char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
|
extern char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
|
||||||
const char *msgid, unsigned long int index))
|
const char *msgid, size_t *lengthp))
|
||||||
internal_function;
|
internal_function;
|
||||||
|
|
||||||
#endif /* loadinfo.h */
|
#endif /* loadinfo.h */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Load needed message catalogs.
|
/* Load needed message catalogs.
|
||||||
Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public License as
|
modify it under the terms of the GNU Library General Public License as
|
||||||
@ -107,7 +107,8 @@ static struct expression germanic_plural =
|
|||||||
.operation = not_equal,
|
.operation = not_equal,
|
||||||
.val =
|
.val =
|
||||||
{
|
{
|
||||||
.args2 = {
|
.args2 =
|
||||||
|
{
|
||||||
.left = (struct expression *) &plvar,
|
.left = (struct expression *) &plvar,
|
||||||
.right = (struct expression *) &plone
|
.right = (struct expression *) &plone
|
||||||
}
|
}
|
||||||
@ -160,6 +161,7 @@ _nl_load_domain (domain_file)
|
|||||||
int use_mmap = 0;
|
int use_mmap = 0;
|
||||||
struct loaded_domain *domain;
|
struct loaded_domain *domain;
|
||||||
char *nullentry;
|
char *nullentry;
|
||||||
|
size_t nullentrylen;
|
||||||
|
|
||||||
domain_file->decided = 1;
|
domain_file->decided = 1;
|
||||||
domain_file->data = NULL;
|
domain_file->data = NULL;
|
||||||
@ -297,7 +299,7 @@ _nl_load_domain (domain_file)
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
domain->conv_tab = NULL;
|
domain->conv_tab = NULL;
|
||||||
nullentry = _nl_find_msg (domain_file, "", 0);
|
nullentry = _nl_find_msg (domain_file, "", &nullentrylen);
|
||||||
if (nullentry != NULL)
|
if (nullentry != NULL)
|
||||||
{
|
{
|
||||||
#if defined _LIBC || HAVE_ICONV
|
#if defined _LIBC || HAVE_ICONV
|
||||||
|
Reference in New Issue
Block a user