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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 if (binding->codeset != NULL)
201 free (binding->codeset);
203 binding->codeset = result;
204 binding->codeset_cntr++;
212 else if ((dirnamep == NULL || *dirnamep == NULL)
213 && (codesetp == NULL || *codesetp == NULL))
215 /* Simply return the default values. */
217 *dirnamep = INTUSE(_nl_default_dirname);
223 /* We have to create a new binding. */
224 size_t len = strlen (domainname) + 1;
225 struct binding *new_binding =
226 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
228 if (__builtin_expect (new_binding == NULL, 0))
231 memcpy (new_binding->domainname, domainname, len);
235 const char *dirname = *dirnamep;
238 /* The default value. */
239 dirname = INTUSE(_nl_default_dirname);
242 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
243 dirname = INTUSE(_nl_default_dirname);
247 #if defined _LIBC || defined HAVE_STRDUP
248 result = strdup (dirname);
249 if (__builtin_expect (result == NULL, 0))
252 size_t len = strlen (dirname) + 1;
253 result = (char *) malloc (len);
254 if (__builtin_expect (result == NULL, 0))
256 memcpy (result, dirname, len);
262 new_binding->dirname = (char *) dirname;
265 /* The default value. */
266 new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
268 new_binding->codeset_cntr = 0;
272 const char *codeset = *codesetp;
278 #if defined _LIBC || defined HAVE_STRDUP
279 result = strdup (codeset);
280 if (__builtin_expect (result == NULL, 0))
283 size_t len = strlen (codeset) + 1;
284 result = (char *) malloc (len);
285 if (__builtin_expect (result == NULL, 0))
287 memcpy (result, codeset, len);
290 new_binding->codeset_cntr++;
293 new_binding->codeset = (char *) codeset;
296 new_binding->codeset = NULL;
298 /* Now enqueue it. */
299 if (_nl_domain_bindings == NULL
300 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
302 new_binding->next = _nl_domain_bindings;
303 _nl_domain_bindings = new_binding;
307 binding = _nl_domain_bindings;
308 while (binding->next != NULL
309 && strcmp (domainname, binding->next->domainname) > 0)
310 binding = binding->next;
312 new_binding->next = binding->next;
313 binding->next = new_binding;
318 /* Here we deal with memory allocation failures. */
322 if (new_binding->dirname != INTUSE(_nl_default_dirname))
323 free (new_binding->dirname);
334 /* If we modified any binding, we flush the caches. */
338 __libc_rwlock_unlock (_nl_state_lock);
341 /* Specify that the DOMAINNAME message catalog will be found
342 in DIRNAME rather than in the system locale data base. */
344 BINDTEXTDOMAIN (const char *domainname, const char *dirname)
346 set_binding_values (domainname, &dirname, NULL);
347 return (char *) dirname;
350 /* Specify the character encoding in which the messages from the
351 DOMAINNAME message catalog will be returned. */
353 BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
355 set_binding_values (domainname, NULL, &codeset);
356 return (char *) codeset;
360 /* Aliases for function names in GNU C Library. */
361 weak_alias (__bindtextdomain, bindtextdomain);
362 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);