1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000-2003, 2005-2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
31 # include "libgnuintl.h"
34 /* Handle multi-threaded applications. */
36 # include <bits/libc-lock.h>
37 # define gl_rwlock_define __libc_rwlock_define
38 # define gl_rwlock_wrlock __libc_rwlock_wrlock
39 # define gl_rwlock_unlock __libc_rwlock_unlock
44 /* The internal variables in the standalone libintl.a must have different
45 names than the internal variables in GNU libc, otherwise programs
46 using libintl.a cannot be linked statically. */
48 # define _nl_default_dirname libintl_nl_default_dirname
49 # define _nl_domain_bindings libintl_nl_domain_bindings
52 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
54 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
57 /* @@ end of prolog @@ */
59 /* Contains the default location of the message catalogs. */
60 extern const char _nl_default_dirname[];
62 libc_hidden_proto (_nl_default_dirname)
65 /* List with bindings of specific domains. */
66 extern struct binding *_nl_domain_bindings;
68 /* Lock variable to protect the global data in the gettext implementation. */
69 gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
72 /* Names for the libintl functions are a problem. They must not clash
73 with existing names and they should follow ANSI C. But this source
74 code is also used in GNU C Library where the names have a __
75 prefix. So we have to make a difference here. */
77 # define BINDTEXTDOMAIN __bindtextdomain
78 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
80 # define strdup(str) __strdup (str)
83 # define BINDTEXTDOMAIN libintl_bindtextdomain
84 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
87 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
88 to be used for the DOMAINNAME message catalog.
89 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
90 modified, only the current value is returned.
91 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
92 modified nor returned. */
94 set_binding_values (const char *domainname,
95 const char **dirnamep, const char **codesetp)
97 struct binding *binding;
100 /* Some sanity checks. */
101 if (domainname == NULL || domainname[0] == '\0')
110 gl_rwlock_wrlock (_nl_state_lock);
114 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
116 int compare = strcmp (domainname, binding->domainname);
122 /* It is not in the list. */
132 const char *dirname = *dirnamep;
135 /* The current binding has be to returned. */
136 *dirnamep = binding->dirname;
139 /* The domain is already bound. If the new value and the old
140 one are equal we simply do nothing. Otherwise replace the
142 char *result = binding->dirname;
143 if (strcmp (dirname, result) != 0)
145 if (strcmp (dirname, _nl_default_dirname) == 0)
146 result = (char *) _nl_default_dirname;
149 #if defined _LIBC || defined HAVE_STRDUP
150 result = strdup (dirname);
152 size_t len = strlen (dirname) + 1;
153 result = (char *) malloc (len);
154 if (__builtin_expect (result != NULL, 1))
155 memcpy (result, dirname, len);
159 if (__builtin_expect (result != NULL, 1))
161 if (binding->dirname != _nl_default_dirname)
162 free (binding->dirname);
164 binding->dirname = result;
174 const char *codeset = *codesetp;
177 /* The current binding has be to returned. */
178 *codesetp = binding->codeset;
181 /* The domain is already bound. If the new value and the old
182 one are equal we simply do nothing. Otherwise replace the
184 char *result = binding->codeset;
185 if (result == NULL || strcmp (codeset, result) != 0)
187 #if defined _LIBC || defined HAVE_STRDUP
188 result = strdup (codeset);
190 size_t len = strlen (codeset) + 1;
191 result = (char *) malloc (len);
192 if (__builtin_expect (result != NULL, 1))
193 memcpy (result, codeset, len);
196 if (__builtin_expect (result != NULL, 1))
198 if (binding->codeset != NULL)
199 free (binding->codeset);
201 binding->codeset = result;
209 else if ((dirnamep == NULL || *dirnamep == NULL)
210 && (codesetp == NULL || *codesetp == NULL))
212 /* Simply return the default values. */
214 *dirnamep = _nl_default_dirname;
220 /* We have to create a new binding. */
221 size_t len = strlen (domainname) + 1;
222 struct binding *new_binding =
223 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
225 if (__builtin_expect (new_binding == NULL, 0))
228 memcpy (new_binding->domainname, domainname, len);
232 const char *dirname = *dirnamep;
235 /* The default value. */
236 dirname = _nl_default_dirname;
239 if (strcmp (dirname, _nl_default_dirname) == 0)
240 dirname = _nl_default_dirname;
244 #if defined _LIBC || defined HAVE_STRDUP
245 result = strdup (dirname);
246 if (__builtin_expect (result == NULL, 0))
249 size_t len = strlen (dirname) + 1;
250 result = (char *) malloc (len);
251 if (__builtin_expect (result == NULL, 0))
253 memcpy (result, dirname, len);
259 new_binding->dirname = (char *) dirname;
262 /* The default value. */
263 new_binding->dirname = (char *) _nl_default_dirname;
267 const char *codeset = *codesetp;
273 #if defined _LIBC || defined HAVE_STRDUP
274 result = strdup (codeset);
275 if (__builtin_expect (result == NULL, 0))
278 size_t len = strlen (codeset) + 1;
279 result = (char *) malloc (len);
280 if (__builtin_expect (result == NULL, 0))
282 memcpy (result, codeset, len);
287 new_binding->codeset = (char *) codeset;
290 new_binding->codeset = NULL;
292 /* Now enqueue it. */
293 if (_nl_domain_bindings == NULL
294 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
296 new_binding->next = _nl_domain_bindings;
297 _nl_domain_bindings = new_binding;
301 binding = _nl_domain_bindings;
302 while (binding->next != NULL
303 && strcmp (domainname, binding->next->domainname) > 0)
304 binding = binding->next;
306 new_binding->next = binding->next;
307 binding->next = new_binding;
312 /* Here we deal with memory allocation failures. */
316 if (new_binding->dirname != _nl_default_dirname)
317 free (new_binding->dirname);
328 /* If we modified any binding, we flush the caches. */
332 gl_rwlock_unlock (_nl_state_lock);
335 /* Specify that the DOMAINNAME message catalog will be found
336 in DIRNAME rather than in the system locale data base. */
338 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
340 set_binding_values (domainname, &dirname, NULL);
341 return (char *) dirname;
344 /* Specify the character encoding in which the messages from the
345 DOMAINNAME message catalog will be returned. */
347 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
349 set_binding_values (domainname, NULL, &codeset);
350 return (char *) codeset;
354 /* Aliases for function names in GNU C Library. */
355 weak_alias (__bindtextdomain, bindtextdomain);
356 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);