diff options
Diffstat (limited to 'intl/bindtextdom.c')
-rw-r--r-- | intl/bindtextdom.c | 268 |
1 files changed, 209 insertions, 59 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 |