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 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 _nl_default_dirname__
49 # define _nl_domain_bindings _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 /* List with bindings of specific domains. */
63 extern struct binding *_nl_domain_bindings;
65 /* Lock variable to protect the global data in the gettext implementation. */
66 __libc_rwlock_define (extern, _nl_state_lock)
69 /* Names for the libintl functions are a problem. They must not clash
70 with existing names and they should follow ANSI C. But this source
71 code is also used in GNU C Library where the names have a __
72 prefix. So we have to make a difference here. */
74 # define BINDTEXTDOMAIN __bindtextdomain
75 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
77 # define strdup(str) __strdup (str)
80 # define BINDTEXTDOMAIN bindtextdomain__
81 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
84 /* Prototypes for local functions. */
85 static void set_binding_values PARAMS ((const char *domainname,
86 const char **dirnamep,
87 const char **codesetp));
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 (domainname, dirnamep, codesetp)
97 const char *domainname;
98 const char **dirnamep;
99 const char **codesetp;
101 struct binding *binding;
104 /* Some sanity checks. */
105 if (domainname == NULL || domainname[0] == '\0')
114 __libc_rwlock_wrlock (_nl_state_lock);
118 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
120 int compare = strcmp (domainname, binding->domainname);
126 /* It is not in the list. */
136 const char *dirname = *dirnamep;
139 /* The current binding has be to returned. */
140 *dirnamep = binding->dirname;
143 /* The domain is already bound. If the new value and the old
144 one are equal we simply do nothing. Otherwise replace the
146 char *result = binding->dirname;
147 if (strcmp (dirname, result) != 0)
149 if (strcmp (dirname, _nl_default_dirname) == 0)
150 result = (char *) _nl_default_dirname;
153 #if defined _LIBC || defined HAVE_STRDUP
154 result = strdup (dirname);
156 size_t len = strlen (dirname) + 1;
157 result = (char *) malloc (len);
158 if (__builtin_expect (result != NULL, 1))
159 memcpy (result, dirname, len);
163 if (__builtin_expect (result != NULL, 1))
165 if (binding->dirname != _nl_default_dirname)
166 free (binding->dirname);
168 binding->dirname = result;
178 const char *codeset = *codesetp;
181 /* The current binding has be to returned. */
182 *codesetp = binding->codeset;
185 /* The domain is already bound. If the new value and the old
186 one are equal we simply do nothing. Otherwise replace the
188 char *result = binding->codeset;
189 if (result == NULL || strcmp (codeset, result) != 0)
191 #if defined _LIBC || defined HAVE_STRDUP
192 result = strdup (codeset);
194 size_t len = strlen (codeset) + 1;
195 result = (char *) malloc (len);
196 if (__builtin_expect (result != NULL, 1))
197 memcpy (result, codeset, len);
200 if (__builtin_expect (result != NULL, 1))
202 if (binding->codeset != NULL)
203 free (binding->codeset);
205 binding->codeset = result;
206 binding->codeset_cntr++;
214 else if ((dirnamep == NULL || *dirnamep == NULL)
215 && (codesetp == NULL || *codesetp == NULL))
217 /* Simply return the default values. */
219 *dirnamep = _nl_default_dirname;
225 /* We have to create a new binding. */
226 size_t len = strlen (domainname) + 1;
227 struct binding *new_binding =
228 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
230 if (__builtin_expect (new_binding == NULL, 0))
233 memcpy (new_binding->domainname, domainname, len);
237 const char *dirname = *dirnamep;
240 /* The default value. */
241 dirname = _nl_default_dirname;
244 if (strcmp (dirname, _nl_default_dirname) == 0)
245 dirname = _nl_default_dirname;
249 #if defined _LIBC || defined HAVE_STRDUP
250 result = strdup (dirname);
251 if (__builtin_expect (result == NULL, 0))
254 size_t len = strlen (dirname) + 1;
255 result = (char *) malloc (len);
256 if (__builtin_expect (result == NULL, 0))
258 memcpy (result, dirname, len);
264 new_binding->dirname = (char *) dirname;
267 /* The default value. */
268 new_binding->dirname = (char *) _nl_default_dirname;
270 new_binding->codeset_cntr = 0;
274 const char *codeset = *codesetp;
280 #if defined _LIBC || defined HAVE_STRDUP
281 result = strdup (codeset);
282 if (__builtin_expect (result == NULL, 0))
285 size_t len = strlen (codeset) + 1;
286 result = (char *) malloc (len);
287 if (__builtin_expect (result == NULL, 0))
289 memcpy (result, codeset, len);
292 new_binding->codeset_cntr++;
295 new_binding->codeset = (char *) codeset;
298 new_binding->codeset = NULL;
300 /* Now enqueue it. */
301 if (_nl_domain_bindings == NULL
302 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
304 new_binding->next = _nl_domain_bindings;
305 _nl_domain_bindings = new_binding;
309 binding = _nl_domain_bindings;
310 while (binding->next != NULL
311 && strcmp (domainname, binding->next->domainname) > 0)
312 binding = binding->next;
314 new_binding->next = binding->next;
315 binding->next = new_binding;
320 /* Here we deal with memory allocation failures. */
324 if (new_binding->dirname != _nl_default_dirname)
325 free (new_binding->dirname);
336 /* If we modified any binding, we flush the caches. */
340 __libc_rwlock_unlock (_nl_state_lock);
343 /* Specify that the DOMAINNAME message catalog will be found
344 in DIRNAME rather than in the system locale data base. */
346 BINDTEXTDOMAIN (domainname, dirname)
347 const char *domainname;
350 set_binding_values (domainname, &dirname, NULL);
351 return (char *) dirname;
354 /* Specify the character encoding in which the messages from the
355 DOMAINNAME message catalog will be returned. */
357 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
358 const char *domainname;
361 set_binding_values (domainname, NULL, &codeset);
362 return (char *) codeset;
366 /* Aliases for function names in GNU C Library. */
367 weak_alias (__bindtextdomain, bindtextdomain);
368 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);