1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 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
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
29 # include "libgnuintl.h"
34 /* We have to handle multi-threaded applications. */
35 # include <bits/libc-lock.h>
37 /* Provide dummy implementation if this is outside glibc. */
38 # define __libc_rwlock_define(CLASS, NAME)
39 # define __libc_rwlock_wrlock(NAME)
40 # define __libc_rwlock_unlock(NAME)
43 /* The internal variables in the standalone libintl.a must have different
44 names than the internal variables in GNU libc, otherwise programs
45 using libintl.a cannot be linked statically. */
47 # define _nl_default_dirname _nl_default_dirname__
48 # define _nl_domain_bindings _nl_domain_bindings__
51 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
53 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
56 /* @@ end of prolog @@ */
58 /* Contains the default location of the message catalogs. */
59 extern const char _nl_default_dirname[];
61 /* List with bindings of specific domains. */
62 extern struct binding *_nl_domain_bindings;
64 /* Lock variable to protect the global data in the gettext implementation. */
65 __libc_rwlock_define (extern, _nl_state_lock)
68 /* Names for the libintl functions are a problem. They must not clash
69 with existing names and they should follow ANSI C. But this source
70 code is also used in GNU C Library where the names have a __
71 prefix. So we have to make a difference here. */
73 # define BINDTEXTDOMAIN __bindtextdomain
74 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
76 # define strdup(str) __strdup (str)
79 # define BINDTEXTDOMAIN bindtextdomain__
80 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
83 /* Prototypes for local functions. */
84 static void set_binding_values PARAMS ((const char *domainname,
85 const char **dirnamep,
86 const char **codesetp));
88 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
89 to be used for the DOMAINNAME message catalog.
90 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
91 modified, only the current value is returned.
92 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
93 modified nor returned. */
95 set_binding_values (domainname, dirnamep, codesetp)
96 const char *domainname;
97 const char **dirnamep;
98 const char **codesetp;
100 struct binding *binding;
103 /* Some sanity checks. */
104 if (domainname == NULL || domainname[0] == '\0')
113 __libc_rwlock_wrlock (_nl_state_lock);
117 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
119 int compare = strcmp (domainname, binding->domainname);
125 /* It is not in the list. */
135 const char *dirname = *dirnamep;
138 /* The current binding has be to returned. */
139 *dirnamep = binding->dirname;
142 /* The domain is already bound. If the new value and the old
143 one are equal we simply do nothing. Otherwise replace the
145 char *result = binding->dirname;
146 if (strcmp (dirname, result) != 0)
148 if (strcmp (dirname, _nl_default_dirname) == 0)
149 result = (char *) _nl_default_dirname;
152 #if defined _LIBC || defined HAVE_STRDUP
153 result = strdup (dirname);
155 size_t len = strlen (dirname) + 1;
156 result = (char *) malloc (len);
157 if (__builtin_expect (result != NULL, 1))
158 memcpy (result, dirname, len);
162 if (__builtin_expect (result != NULL, 1))
164 if (binding->dirname != _nl_default_dirname)
165 free (binding->dirname);
167 binding->dirname = result;
177 const char *codeset = *codesetp;
180 /* The current binding has be to returned. */
181 *codesetp = binding->codeset;
184 /* The domain is already bound. If the new value and the old
185 one are equal we simply do nothing. Otherwise replace the
187 char *result = binding->codeset;
188 if (result == NULL || strcmp (codeset, result) != 0)
190 #if defined _LIBC || defined HAVE_STRDUP
191 result = strdup (codeset);
193 size_t len = strlen (codeset) + 1;
194 result = (char *) malloc (len);
195 if (__builtin_expect (result != NULL, 1))
196 memcpy (result, codeset, len);
199 if (__builtin_expect (result != NULL, 1))
201 if (binding->codeset != NULL)
202 free (binding->codeset);
204 binding->codeset = result;
205 binding->codeset_cntr++;
213 else if ((dirnamep == NULL || *dirnamep == NULL)
214 && (codesetp == NULL || *codesetp == NULL))
216 /* Simply return the default values. */
218 *dirnamep = _nl_default_dirname;
224 /* We have to create a new binding. */
225 size_t len = strlen (domainname) + 1;
226 struct binding *new_binding =
227 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
229 if (__builtin_expect (new_binding == NULL, 0))
232 memcpy (new_binding->domainname, domainname, len);
236 const char *dirname = *dirnamep;
239 /* The default value. */
240 dirname = _nl_default_dirname;
243 if (strcmp (dirname, _nl_default_dirname) == 0)
244 dirname = _nl_default_dirname;
248 #if defined _LIBC || defined HAVE_STRDUP
249 result = strdup (dirname);
250 if (__builtin_expect (result == NULL, 0))
253 size_t len = strlen (dirname) + 1;
254 result = (char *) malloc (len);
255 if (__builtin_expect (result == NULL, 0))
257 memcpy (result, dirname, len);
263 new_binding->dirname = (char *) dirname;
266 /* The default value. */
267 new_binding->dirname = (char *) _nl_default_dirname;
269 new_binding->codeset_cntr = 0;
273 const char *codeset = *codesetp;
279 #if defined _LIBC || defined HAVE_STRDUP
280 result = strdup (codeset);
281 if (__builtin_expect (result == NULL, 0))
284 size_t len = strlen (codeset) + 1;
285 result = (char *) malloc (len);
286 if (__builtin_expect (result == NULL, 0))
288 memcpy (result, codeset, len);
291 new_binding->codeset_cntr++;
294 new_binding->codeset = (char *) codeset;
297 new_binding->codeset = NULL;
299 /* Now enqueue it. */
300 if (_nl_domain_bindings == NULL
301 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
303 new_binding->next = _nl_domain_bindings;
304 _nl_domain_bindings = new_binding;
308 binding = _nl_domain_bindings;
309 while (binding->next != NULL
310 && strcmp (domainname, binding->next->domainname) > 0)
311 binding = binding->next;
313 new_binding->next = binding->next;
314 binding->next = new_binding;
319 /* Here we deal with memory allocation failures. */
323 if (new_binding->dirname != _nl_default_dirname)
324 free (new_binding->dirname);
335 /* If we modified any binding, we flush the caches. */
339 __libc_rwlock_unlock (_nl_state_lock);
342 /* Specify that the DOMAINNAME message catalog will be found
343 in DIRNAME rather than in the system locale data base. */
345 BINDTEXTDOMAIN (domainname, dirname)
346 const char *domainname;
349 set_binding_values (domainname, &dirname, NULL);
350 return (char *) dirname;
353 /* Specify the character encoding in which the messages from the
354 DOMAINNAME message catalog will be returned. */
356 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
357 const char *domainname;
360 set_binding_values (domainname, NULL, &codeset);
361 return (char *) codeset;
365 /* Aliases for function names in GNU C Library. */
366 weak_alias (__bindtextdomain, bindtextdomain);
367 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);