1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31 # include "libgnuintl.h"
36 /* We have to handle multi-threaded applications. */
37 # include <bits/libc-lock.h>
39 /* Provide dummy implementation if this is outside glibc. */
40 # define __libc_rwlock_define(CLASS, NAME)
41 # define __libc_rwlock_wrlock(NAME)
42 # define __libc_rwlock_unlock(NAME)
45 /* The internal variables in the standalone libintl.a must have different
46 names than the internal variables in GNU libc, otherwise programs
47 using libintl.a cannot be linked statically. */
49 # define _nl_default_dirname _nl_default_dirname__
50 # define _nl_domain_bindings _nl_domain_bindings__
53 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
55 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
58 /* @@ end of prolog @@ */
60 /* Contains the default location of the message catalogs. */
61 extern const char _nl_default_dirname[];
63 /* List with bindings of specific domains. */
64 extern struct binding *_nl_domain_bindings;
66 /* Lock variable to protect the global data in the gettext implementation. */
67 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
70 /* Names for the libintl functions are a problem. They must not clash
71 with existing names and they should follow ANSI C. But this source
72 code is also used in GNU C Library where the names have a __
73 prefix. So we have to make a difference here. */
75 # define BINDTEXTDOMAIN __bindtextdomain
76 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
78 # define strdup(str) __strdup (str)
81 # define BINDTEXTDOMAIN bindtextdomain__
82 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
85 /* Prototypes for local functions. */
86 static void set_binding_values PARAMS ((const char *domainname,
87 const char **dirnamep,
88 const char **codesetp));
90 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
91 to be used for the DOMAINNAME message catalog.
92 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
93 modified, only the current value is returned.
94 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
95 modified nor returned. */
97 set_binding_values (domainname, dirnamep, codesetp)
98 const char *domainname;
99 const char **dirnamep;
100 const char **codesetp;
102 struct binding *binding;
105 /* Some sanity checks. */
106 if (domainname == NULL || domainname[0] == '\0')
115 __libc_rwlock_wrlock (_nl_state_lock);
119 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
121 int compare = strcmp (domainname, binding->domainname);
127 /* It is not in the list. */
137 const char *dirname = *dirnamep;
140 /* The current binding has be to returned. */
141 *dirnamep = binding->dirname;
144 /* The domain is already bound. If the new value and the old
145 one are equal we simply do nothing. Otherwise replace the
147 char *result = binding->dirname;
148 if (strcmp (dirname, result) != 0)
150 if (strcmp (dirname, _nl_default_dirname) == 0)
151 result = (char *) _nl_default_dirname;
154 #if defined _LIBC || defined HAVE_STRDUP
155 result = strdup (dirname);
157 size_t len = strlen (dirname) + 1;
158 result = (char *) malloc (len);
159 if (__builtin_expect (result != NULL, 1))
160 memcpy (result, dirname, len);
164 if (__builtin_expect (result != NULL, 1))
166 if (binding->dirname != _nl_default_dirname)
167 free (binding->dirname);
169 binding->dirname = result;
179 const char *codeset = *codesetp;
182 /* The current binding has be to returned. */
183 *codesetp = binding->codeset;
186 /* The domain is already bound. If the new value and the old
187 one are equal we simply do nothing. Otherwise replace the
189 char *result = binding->codeset;
190 if (result == NULL || strcmp (codeset, result) != 0)
192 #if defined _LIBC || defined HAVE_STRDUP
193 result = strdup (codeset);
195 size_t len = strlen (codeset) + 1;
196 result = (char *) malloc (len);
197 if (__builtin_expect (result != NULL, 1))
198 memcpy (result, codeset, len);
201 if (__builtin_expect (result != NULL, 1))
203 if (binding->codeset != NULL)
204 free (binding->codeset);
206 binding->codeset = result;
207 ++binding->codeset_cntr;
215 else if ((dirnamep == NULL || *dirnamep == NULL)
216 && (codesetp == NULL || *codesetp == NULL))
218 /* Simply return the default values. */
220 *dirnamep = _nl_default_dirname;
226 /* We have to create a new binding. */
227 size_t len = strlen (domainname) + 1;
228 struct binding *new_binding =
229 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
231 if (__builtin_expect (new_binding == NULL, 0))
234 memcpy (new_binding->domainname, domainname, len);
238 const char *dirname = *dirnamep;
241 /* The default value. */
242 dirname = _nl_default_dirname;
245 if (strcmp (dirname, _nl_default_dirname) == 0)
246 dirname = _nl_default_dirname;
250 #if defined _LIBC || defined HAVE_STRDUP
251 result = strdup (dirname);
252 if (__builtin_expect (result == NULL, 0))
255 size_t len = strlen (dirname) + 1;
256 result = (char *) malloc (len);
257 if (__builtin_expect (result == NULL, 0))
259 memcpy (result, dirname, len);
265 new_binding->dirname = (char *) dirname;
268 /* The default value. */
269 new_binding->dirname = (char *) _nl_default_dirname;
271 new_binding->codeset_cntr = 0;
275 const char *codeset = *codesetp;
281 #if defined _LIBC || defined HAVE_STRDUP
282 result = strdup (codeset);
283 if (__builtin_expect (result == NULL, 0))
286 size_t len = strlen (codeset) + 1;
287 result = (char *) malloc (len);
288 if (__builtin_expect (result == NULL, 0))
290 memcpy (result, codeset, len);
293 ++new_binding->codeset_cntr;
296 new_binding->codeset = (char *) codeset;
299 new_binding->codeset = NULL;
301 /* Now enqueue it. */
302 if (_nl_domain_bindings == NULL
303 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
305 new_binding->next = _nl_domain_bindings;
306 _nl_domain_bindings = new_binding;
310 binding = _nl_domain_bindings;
311 while (binding->next != NULL
312 && strcmp (domainname, binding->next->domainname) > 0)
313 binding = binding->next;
315 new_binding->next = binding->next;
316 binding->next = new_binding;
321 /* Here we deal with memory allocation failures. */
325 if (new_binding->dirname != _nl_default_dirname)
326 free (new_binding->dirname);
337 /* If we modified any binding, we flush the caches. */
341 __libc_rwlock_unlock (_nl_state_lock);
344 /* Specify that the DOMAINNAME message catalog will be found
345 in DIRNAME rather than in the system locale data base. */
347 BINDTEXTDOMAIN (domainname, dirname)
348 const char *domainname;
351 set_binding_values (domainname, &dirname, NULL);
352 return (char *) dirname;
355 /* Specify the character encoding in which the messages from the
356 DOMAINNAME message catalog will be returned. */
358 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
359 const char *domainname;
362 set_binding_values (domainname, NULL, &codeset);
363 return (char *) codeset;
367 /* Aliases for function names in GNU C Library. */
368 weak_alias (__bindtextdomain, bindtextdomain);
369 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);