diff options
Diffstat (limited to 'intl')
-rw-r--r-- | intl/bindtextdom.c | 268 | ||||
-rw-r--r-- | intl/dcigettext.c | 103 | ||||
-rw-r--r-- | intl/finddomain.c | 9 | ||||
-rw-r--r-- | intl/gettextP.h | 10 | ||||
-rw-r--r-- | intl/l10nflist.c | 7 | ||||
-rw-r--r-- | intl/libintl.h | 5 | ||||
-rw-r--r-- | intl/loadinfo.h | 10 | ||||
-rw-r--r-- | intl/loadmsgcat.c | 89 | ||||
-rw-r--r-- | intl/localealias.c | 23 |
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; } |