1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008 Free Software
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published
7 by the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
32 # include "libgnuintl.h"
35 /* Handle multi-threaded applications. */
37 # include <bits/libc-lock.h>
38 # define gl_rwlock_define __libc_rwlock_define
39 # define gl_rwlock_wrlock __libc_rwlock_wrlock
40 # define gl_rwlock_unlock __libc_rwlock_unlock
45 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
47 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
50 /* @@ end of prolog @@ */
52 /* Lock variable to protect the global data in the gettext implementation. */
53 gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
56 /* Names for the libintl functions are a problem. They must not clash
57 with existing names and they should follow ANSI C. But this source
58 code is also used in GNU C Library where the names have a __
59 prefix. So we have to make a difference here. */
61 # define BINDTEXTDOMAIN __bindtextdomain
62 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
64 # define strdup(str) __strdup (str)
67 # define BINDTEXTDOMAIN libintl_bindtextdomain
68 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
71 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
72 to be used for the DOMAINNAME message catalog.
73 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
74 modified, only the current value is returned.
75 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
76 modified nor returned. */
78 set_binding_values (const char *domainname,
79 const char **dirnamep, const char **codesetp)
81 struct binding *binding;
84 /* Some sanity checks. */
85 if (domainname == NULL || domainname[0] == '\0')
94 gl_rwlock_wrlock (_nl_state_lock);
98 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
100 int compare = strcmp (domainname, binding->domainname);
106 /* It is not in the list. */
116 const char *dirname = *dirnamep;
119 /* The current binding has be to returned. */
120 *dirnamep = binding->dirname;
123 /* The domain is already bound. If the new value and the old
124 one are equal we simply do nothing. Otherwise replace the
126 char *result = binding->dirname;
127 if (strcmp (dirname, result) != 0)
129 if (strcmp (dirname, _nl_default_dirname) == 0)
130 result = (char *) _nl_default_dirname;
133 #if defined _LIBC || defined HAVE_STRDUP
134 result = strdup (dirname);
136 size_t len = strlen (dirname) + 1;
137 result = (char *) malloc (len);
138 if (__builtin_expect (result != NULL, 1))
139 memcpy (result, dirname, len);
143 if (__builtin_expect (result != NULL, 1))
145 if (binding->dirname != _nl_default_dirname)
146 free (binding->dirname);
148 binding->dirname = result;
158 const char *codeset = *codesetp;
161 /* The current binding has be to returned. */
162 *codesetp = binding->codeset;
165 /* The domain is already bound. If the new value and the old
166 one are equal we simply do nothing. Otherwise replace the
168 char *result = binding->codeset;
169 if (result == NULL || strcmp (codeset, result) != 0)
171 #if defined _LIBC || defined HAVE_STRDUP
172 result = strdup (codeset);
174 size_t len = strlen (codeset) + 1;
175 result = (char *) malloc (len);
176 if (__builtin_expect (result != NULL, 1))
177 memcpy (result, codeset, len);
180 if (__builtin_expect (result != NULL, 1))
182 free (binding->codeset);
184 binding->codeset = result;
192 else if ((dirnamep == NULL || *dirnamep == NULL)
193 && (codesetp == NULL || *codesetp == NULL))
195 /* Simply return the default values. */
197 *dirnamep = _nl_default_dirname;
203 /* We have to create a new binding. */
204 size_t len = strlen (domainname) + 1;
205 struct binding *new_binding =
206 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
208 if (__builtin_expect (new_binding == NULL, 0))
211 memcpy (new_binding->domainname, domainname, len);
215 const char *dirname = *dirnamep;
218 /* The default value. */
219 dirname = _nl_default_dirname;
222 if (strcmp (dirname, _nl_default_dirname) == 0)
223 dirname = _nl_default_dirname;
227 #if defined _LIBC || defined HAVE_STRDUP
228 result = strdup (dirname);
229 if (__builtin_expect (result == NULL, 0))
232 size_t len = strlen (dirname) + 1;
233 result = (char *) malloc (len);
234 if (__builtin_expect (result == NULL, 0))
236 memcpy (result, dirname, len);
242 new_binding->dirname = (char *) dirname;
245 /* The default value. */
246 new_binding->dirname = (char *) _nl_default_dirname;
250 const char *codeset = *codesetp;
256 #if defined _LIBC || defined HAVE_STRDUP
257 result = strdup (codeset);
258 if (__builtin_expect (result == NULL, 0))
261 size_t len = strlen (codeset) + 1;
262 result = (char *) malloc (len);
263 if (__builtin_expect (result == NULL, 0))
265 memcpy (result, codeset, len);
270 new_binding->codeset = (char *) codeset;
273 new_binding->codeset = NULL;
275 /* Now enqueue it. */
276 if (_nl_domain_bindings == NULL
277 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
279 new_binding->next = _nl_domain_bindings;
280 _nl_domain_bindings = new_binding;
284 binding = _nl_domain_bindings;
285 while (binding->next != NULL
286 && strcmp (domainname, binding->next->domainname) > 0)
287 binding = binding->next;
289 new_binding->next = binding->next;
290 binding->next = new_binding;
295 /* Here we deal with memory allocation failures. */
299 if (new_binding->dirname != _nl_default_dirname)
300 free (new_binding->dirname);
311 /* If we modified any binding, we flush the caches. */
315 gl_rwlock_unlock (_nl_state_lock);
318 /* Specify that the DOMAINNAME message catalog will be found
319 in DIRNAME rather than in the system locale data base. */
321 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
323 set_binding_values (domainname, &dirname, NULL);
324 return (char *) dirname;
327 /* Specify the character encoding in which the messages from the
328 DOMAINNAME message catalog will be returned. */
330 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
332 set_binding_values (domainname, NULL, &codeset);
333 return (char *) codeset;
337 /* Aliases for function names in GNU C Library. */
338 weak_alias (__bindtextdomain, bindtextdomain);
339 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);