1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000-2003 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,
30 # include "libgnuintl.h"
35 /* We have to handle multi-threaded applications. */
36 # include <bits/libc-lock.h>
38 /* Provide dummy implementation if this is outside glibc. */
39 # define __libc_rwlock_define(CLASS, NAME)
40 # define __libc_rwlock_wrlock(NAME)
41 # define __libc_rwlock_unlock(NAME)
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 extern const char _nl_default_dirname_internal[] attribute_hidden;
64 # define INTUSE(name) name
67 /* List with bindings of specific domains. */
68 extern struct binding *_nl_domain_bindings;
70 /* Lock variable to protect the global data in the gettext implementation. */
71 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
74 /* Names for the libintl functions are a problem. They must not clash
75 with existing names and they should follow ANSI C. But this source
76 code is also used in GNU C Library where the names have a __
77 prefix. So we have to make a difference here. */
79 # define BINDTEXTDOMAIN __bindtextdomain
80 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
82 # define strdup(str) __strdup (str)
85 # define BINDTEXTDOMAIN libintl_bindtextdomain
86 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
89 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
90 to be used for the DOMAINNAME message catalog.
91 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
92 modified, only the current value is returned.
93 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
94 modified nor returned. */
96 set_binding_values (const char *domainname,
97 const char **dirnamep, const char **codesetp)
99 struct binding *binding;
102 /* Some sanity checks. */
103 if (domainname == NULL || domainname[0] == '\0')
112 __libc_rwlock_wrlock (_nl_state_lock);
116 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
118 int compare = strcmp (domainname, binding->domainname);
124 /* It is not in the list. */
134 const char *dirname = *dirnamep;
137 /* The current binding has be to returned. */
138 *dirnamep = binding->dirname;
141 /* The domain is already bound. If the new value and the old
142 one are equal we simply do nothing. Otherwise replace the
144 char *result = binding->dirname;
145 if (strcmp (dirname, result) != 0)
147 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
148 result = (char *) INTUSE(_nl_default_dirname);
151 #if defined _LIBC || defined HAVE_STRDUP
152 result = strdup (dirname);
154 size_t len = strlen (dirname) + 1;
155 result = (char *) malloc (len);
156 if (__builtin_expect (result != NULL, 1))
157 memcpy (result, dirname, len);
161 if (__builtin_expect (result != NULL, 1))
163 if (binding->dirname != INTUSE(_nl_default_dirname))
164 free (binding->dirname);
166 binding->dirname = result;
176 const char *codeset = *codesetp;
179 /* The current binding has be to returned. */
180 *codesetp = binding->codeset;
183 /* The domain is already bound. If the new value and the old
184 one are equal we simply do nothing. Otherwise replace the
186 char *result = binding->codeset;
187 if (result == NULL || strcmp (codeset, result) != 0)
189 #if defined _LIBC || defined HAVE_STRDUP
190 result = strdup (codeset);
192 size_t len = strlen (codeset) + 1;
193 result = (char *) malloc (len);
194 if (__builtin_expect (result != NULL, 1))
195 memcpy (result, codeset, len);
198 if (__builtin_expect (result != NULL, 1))
200 free (binding->codeset);
202 binding->codeset = result;
203 binding->codeset_cntr++;
211 else if ((dirnamep == NULL || *dirnamep == NULL)
212 && (codesetp == NULL || *codesetp == NULL))
214 /* Simply return the default values. */
216 *dirnamep = INTUSE(_nl_default_dirname);
222 /* We have to create a new binding. */
223 size_t len = strlen (domainname) + 1;
224 struct binding *new_binding =
225 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
227 if (__builtin_expect (new_binding == NULL, 0))
230 memcpy (new_binding->domainname, domainname, len);
234 const char *dirname = *dirnamep;
237 /* The default value. */
238 dirname = INTUSE(_nl_default_dirname);
241 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
242 dirname = INTUSE(_nl_default_dirname);
246 #if defined _LIBC || defined HAVE_STRDUP
247 result = strdup (dirname);
248 if (__builtin_expect (result == NULL, 0))
251 size_t len = strlen (dirname) + 1;
252 result = (char *) malloc (len);
253 if (__builtin_expect (result == NULL, 0))
255 memcpy (result, dirname, len);
261 new_binding->dirname = (char *) dirname;
264 /* The default value. */
265 new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
267 new_binding->codeset_cntr = 0;
271 const char *codeset = *codesetp;
277 #if defined _LIBC || defined HAVE_STRDUP
278 result = strdup (codeset);
279 if (__builtin_expect (result == NULL, 0))
282 size_t len = strlen (codeset) + 1;
283 result = (char *) malloc (len);
284 if (__builtin_expect (result == NULL, 0))
286 memcpy (result, codeset, len);
289 new_binding->codeset_cntr++;
292 new_binding->codeset = (char *) codeset;
295 new_binding->codeset = NULL;
297 /* Now enqueue it. */
298 if (_nl_domain_bindings == NULL
299 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
301 new_binding->next = _nl_domain_bindings;
302 _nl_domain_bindings = new_binding;
306 binding = _nl_domain_bindings;
307 while (binding->next != NULL
308 && strcmp (domainname, binding->next->domainname) > 0)
309 binding = binding->next;
311 new_binding->next = binding->next;
312 binding->next = new_binding;
317 /* Here we deal with memory allocation failures. */
321 if (new_binding->dirname != INTUSE(_nl_default_dirname))
322 free (new_binding->dirname);
333 /* If we modified any binding, we flush the caches. */
337 __libc_rwlock_unlock (_nl_state_lock);
340 /* Specify that the DOMAINNAME message catalog will be found
341 in DIRNAME rather than in the system locale data base. */
343 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
345 set_binding_values (domainname, &dirname, NULL);
346 return (char *) dirname;
349 /* Specify the character encoding in which the messages from the
350 DOMAINNAME message catalog will be returned. */
352 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
354 set_binding_values (domainname, NULL, &codeset);
355 return (char *) codeset;
359 /* Aliases for function names in GNU C Library. */
360 weak_alias (__bindtextdomain, bindtextdomain);
361 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);