/* Implementation of the bindtextdomain(3) function Copyright (C) 1995-2016 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <stddef.h> #include <stdlib.h> #include <string.h> #include "gettextP.h" #ifdef _LIBC # include <libintl.h> #else # include "libgnuintl.h" #endif /* Handle multi-threaded applications. */ #ifdef _LIBC # include <bits/libc-lock.h> # define gl_rwlock_define __libc_rwlock_define # define gl_rwlock_wrlock __libc_rwlock_wrlock # define gl_rwlock_unlock __libc_rwlock_unlock #else # include "lock.h" #endif /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ #ifndef offsetof # define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) #endif /* @@ end of prolog @@ */ /* Lock variable to protect the global data in the gettext implementation. */ gl_rwlock_define (extern, _nl_state_lock attribute_hidden) /* Names for the libintl functions are a problem. They must not clash with existing names and they should follow ANSI C. But this source code is also used in GNU C Library where the names have a __ 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 libintl_bindtextdomain # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset #endif /* 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 (const char *domainname, const char **dirnamep, const char **codesetp) { struct binding *binding; int modified; /* Some sanity checks. */ if (domainname == NULL || domainname[0] == '\0') { if (dirnamep) *dirnamep = NULL; if (codesetp) *codesetp = NULL; return; } gl_rwlock_wrlock (_nl_state_lock); modified = 0; for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) { int compare = strcmp (domainname, binding->domainname); if (compare == 0) /* We found it! */ break; if (compare < 0) { /* It is not in the list. */ binding = NULL; break; } } if (binding != NULL) { if (dirnamep) { 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); #else 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 (codeset == NULL) /* The current binding has be to returned. */ *codesetp = binding->codeset; 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->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 if (__builtin_expect (result != NULL, 1)) { 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. */ size_t len = strlen (domainname) + 1; struct binding *new_binding = (struct binding *) malloc (offsetof (struct binding, domainname) + len); if (__builtin_expect (new_binding == NULL, 0)) goto failed; memcpy (new_binding->domainname, domainname, len); if (dirnamep) { const char *dirname = *dirnamep; 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 = strdup (dirname); if (__builtin_expect (result == NULL, 0)) goto failed_dirname; #else 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 (codesetp) { const char *codeset = *codesetp; if (codeset != NULL) { char *result; #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; } } /* If we modified any binding, we flush the caches. */ if (modified) ++_nl_msg_cat_cntr; gl_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 (const char *domainname, const char *dirname) { #ifdef __EMX__ const char *saved_dirname = dirname; char dirname_with_drive[_MAX_PATH]; /* Resolve UNIXROOT into dirname if it is not resolved by os2compat.[ch]. */ if (dirname && (dirname[0] == '/' || dirname[0] == '\\' )) { const char *unixroot = getenv ("UNIXROOT"); size_t len = strlen (dirname) + 1; if (unixroot && unixroot[0] != '\0' && unixroot[1] == ':' && unixroot[2] == '\0' && 2 + len <= _MAX_PATH) { memcpy (dirname_with_drive, unixroot, 2); memcpy (dirname_with_drive + 2, dirname, len); dirname = dirname_with_drive; } } #endif set_binding_values (domainname, &dirname, NULL); #ifdef __EMX__ dirname = saved_dirname; #endif return (char *) dirname; } /* Specify the character encoding in which the messages from the DOMAINNAME message catalog will be returned. */ char * BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset) { set_binding_values (domainname, NULL, &codeset); return (char *) codeset; } #ifdef _LIBC /* Aliases for function names in GNU C Library. */ weak_alias (__bindtextdomain, bindtextdomain); weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); #endif
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
COPYING.LIB | File | 25.92 KB | 0644 |
|
Makefile.in | File | 24.53 KB | 0644 |
|
VERSION | File | 42 B | 0644 |
|
bindtextdom.c | File | 9.33 KB | 0644 |
|
config.charset | File | 22.5 KB | 0755 |
|
dcgettext.c | File | 1.71 KB | 0644 |
|
dcigettext.c | File | 46.49 KB | 0644 |
|
dcngettext.c | File | 1.74 KB | 0644 |
|
dgettext.c | File | 1.67 KB | 0644 |
|
dngettext.c | File | 1.78 KB | 0644 |
|
eval-plural.h | File | 2.67 KB | 0644 |
|
explodename.c | File | 3.26 KB | 0644 |
|
export.h | File | 157 B | 0644 |
|
finddomain.c | File | 5.86 KB | 0644 |
|
gettext.c | File | 1.78 KB | 0644 |
|
gettextP.h | File | 9.95 KB | 0644 |
|
gmo.h | File | 4.74 KB | 0644 |
|
hash-string.c | File | 1.51 KB | 0644 |
|
hash-string.h | File | 1.28 KB | 0644 |
|
intl-compat.c | File | 3.37 KB | 0644 |
|
intl-exports.c | File | 1.73 KB | 0644 |
|
l10nflist.c | File | 10.64 KB | 0644 |
|
langprefs.c | File | 12.42 KB | 0644 |
|
libgnuintl.in.h | File | 16.4 KB | 0644 |
|
libintl.rc | File | 1.58 KB | 0644 |
|
loadinfo.h | File | 4.99 KB | 0644 |
|
loadmsgcat.c | File | 33.73 KB | 0644 |
|
localcharset.c | File | 20.04 KB | 0644 |
|
localcharset.h | File | 1.31 KB | 0644 |
|
locale.alias | File | 3.01 KB | 0644 |
|
localealias.c | File | 10.39 KB | 0644 |
|
localename.c | File | 84.12 KB | 0644 |
|
lock.c | File | 26.16 KB | 0644 |
|
lock.h | File | 35.46 KB | 0644 |
|
log.c | File | 3.76 KB | 0644 |
|
ngettext.c | File | 1.86 KB | 0644 |
|
os2compat.c | File | 2.77 KB | 0644 |
|
os2compat.h | File | 1.47 KB | 0644 |
|
osdep.c | File | 988 B | 0644 |
|
plural-exp.c | File | 3.79 KB | 0644 |
|
plural-exp.h | File | 4.54 KB | 0644 |
|
plural.c | File | 52.03 KB | 0644 |
|
plural.y | File | 7.34 KB | 0644 |
|
printf-args.c | File | 6.43 KB | 0644 |
|
printf-args.h | File | 3.88 KB | 0644 |
|
printf-parse.c | File | 21.67 KB | 0644 |
|
printf-parse.h | File | 2.53 KB | 0644 |
|
printf.c | File | 10.09 KB | 0644 |
|
ref-add.sin | File | 1.02 KB | 0644 |
|
ref-del.sin | File | 996 B | 0644 |
|
relocatable.c | File | 17.09 KB | 0644 |
|
relocatable.h | File | 3.07 KB | 0644 |
|
setlocale.c | File | 32.34 KB | 0644 |
|
textdomain.c | File | 3.72 KB | 0644 |
|
threadlib.c | File | 1.89 KB | 0644 |
|
tsearch.c | File | 20.98 KB | 0644 |
|
tsearch.h | File | 2.75 KB | 0644 |
|
vasnprintf.c | File | 218.1 KB | 0644 |
|
vasnprintf.h | File | 2.74 KB | 0644 |
|
vasnwprintf.h | File | 1.64 KB | 0644 |
|
verify.h | File | 10.76 KB | 0644 |
|
version.c | File | 935 B | 0644 |
|
wprintf-parse.h | File | 2.58 KB | 0644 |
|
xsize.c | File | 78 B | 0644 |
|
xsize.h | File | 3.57 KB | 0644 |
|