diff options
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r-- | intl/dcigettext.c | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c index afbb181f..f2f01524 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -64,6 +64,20 @@ extern int errno; #include <locale.h> +#ifdef _LIBC + /* Guess whether integer division by zero raises signal SIGFPE. + Set to 1 only if you know for sure. In case of doubt, set to 0. */ +# if defined __alpha__ || defined __arm__ || defined __i386__ \ + || defined __m68k__ || defined __s390__ +# define INTDIV0_RAISES_SIGFPE 1 +# else +# define INTDIV0_RAISES_SIGFPE 0 +# endif +#endif +#if !INTDIV0_RAISES_SIGFPE +# include <signal.h> +#endif + #if defined HAVE_SYS_PARAM_H || defined _LIBC # include <sys/param.h> #endif @@ -102,10 +116,10 @@ extern int errno; names than the internal variables in GNU libc, otherwise programs using libintl.a cannot be linked statically. */ #if !defined _LIBC -# define _nl_default_default_domain _nl_default_default_domain__ -# define _nl_current_default_domain _nl_current_default_domain__ -# define _nl_default_dirname _nl_default_dirname__ -# define _nl_domain_bindings _nl_domain_bindings__ +# define _nl_default_default_domain libintl_nl_default_default_domain +# define _nl_current_default_domain libintl_nl_current_default_domain +# define _nl_default_dirname libintl_nl_default_dirname +# define _nl_domain_bindings libintl_nl_domain_bindings #endif /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ @@ -292,6 +306,7 @@ static const char *guess_category_value PARAMS ((int category, some additional code emulating it. */ #ifdef HAVE_ALLOCA /* Nothing has to be done. */ +# define freea(p) /* nothing */ # define ADD_BLOCK(list, address) /* nothing */ # define FREE_BLOCKS(list) /* nothing */ #else @@ -316,11 +331,13 @@ struct block_list while (list != NULL) { \ struct block_list *old = list; \ list = list->next; \ + free (old->address); \ free (old); \ } \ } while (0) # undef alloca # define alloca(size) (malloc (size)) +# define freea(p) free (p) #endif /* have alloca */ @@ -344,7 +361,7 @@ typedef unsigned char transmem_block_t; #ifdef _LIBC # define DCIGETTEXT __dcigettext #else -# define DCIGETTEXT dcigettext__ +# define DCIGETTEXT libintl_dcigettext #endif /* Lock variable to protect the global data in the gettext implementation. */ @@ -446,6 +463,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) search->category = category; foundp = (struct known_translation_t **) tfind (search, &root, transcmp); + freea (search); if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) { /* Now deal with plural. */ @@ -679,6 +697,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) size_t *lengthp; { struct loaded_domain *domain; + nls_uint32 nstrings; size_t act; char *result; size_t resultlen; @@ -691,8 +710,10 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) domain = (struct loaded_domain *) domain_file->data; + nstrings = domain->nstrings; + /* Locate the MSGID and its translation. */ - if (domain->hash_size > 2 && domain->hash_tab != NULL) + if (domain->hash_tab != NULL) { /* Use the hashing table. */ nls_uint32 len = strlen (msgid); @@ -702,22 +723,30 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) while (1) { - nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); + nls_uint32 nstr = + W (domain->must_swap_hash_tab, domain->hash_tab[idx]); if (nstr == 0) /* Hash table entry is empty. */ return NULL; - /* Compare msgid with the original string at index nstr-1. + nstr--; + + /* Compare msgid with the original string at index nstr. 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->orig_tab[nstr - 1].offset)) - == 0)) + if (nstr < nstrings + ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len + && (strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr].offset)) + == 0) + : domain->orig_sysdep_tab[nstr - nstrings].length > len + && (strcmp (msgid, + domain->orig_sysdep_tab[nstr - nstrings].pointer) + == 0)) { - act = nstr - 1; + act = nstr; goto found; } @@ -735,7 +764,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) size_t top, bottom; bottom = 0; - top = domain->nstrings; + top = nstrings; while (bottom < top) { int cmp_val; @@ -758,9 +787,17 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) found: /* The translation was found at index ACT. If we have to convert the string to use a different character set, this is the time. */ - result = ((char *) domain->data - + W (domain->must_swap, domain->trans_tab[act].offset)); - resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; + if (act < nstrings) + { + result = (char *) + (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); + resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; + } + else + { + result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; + resultlen = domain->trans_sysdep_tab[act - nstrings].length; + } #if defined _LIBC || HAVE_ICONV if (domain->codeset_cntr @@ -793,8 +830,9 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp) NULs. */ if (domain->conv_tab == NULL - && ((domain->conv_tab = (char **) calloc (domain->nstrings, - sizeof (char *))) + && ((domain->conv_tab = + (char **) calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *))) == NULL)) /* Mark that we didn't succeed allocating a table. */ domain->conv_tab = (char **) -1; |