1
/* Implementation of the bindtextdomain(3) function
2
Copyright (C) 1995-1998, 2000-2003, 2005-2006 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,
31
# include "libgnuintl.h"
34
/* Handle multi-threaded applications. */
36
# include <bits/libc-lock.h>
37
# define gl_rwlock_define __libc_rwlock_define
38
# define gl_rwlock_wrlock __libc_rwlock_wrlock
39
# define gl_rwlock_unlock __libc_rwlock_unlock
44
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
46
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
49
/* @@ end of prolog @@ */
51
/* Lock variable to protect the global data in the gettext implementation. */
52
gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
55
/* Names for the libintl functions are a problem. They must not clash
56
with existing names and they should follow ANSI C. But this source
57
code is also used in GNU C Library where the names have a __
58
prefix. So we have to make a difference here. */
60
# define BINDTEXTDOMAIN __bindtextdomain
61
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
63
# define strdup(str) __strdup (str)
66
# define BINDTEXTDOMAIN libintl_bindtextdomain
67
# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
70
/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
71
to be used for the DOMAINNAME message catalog.
72
If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
73
modified, only the current value is returned.
74
If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
75
modified nor returned. */
77
set_binding_values (const char *domainname,
78
const char **dirnamep, const char **codesetp)
80
struct binding *binding;
83
/* Some sanity checks. */
84
if (domainname == NULL || domainname[0] == '\0')
93
gl_rwlock_wrlock (_nl_state_lock);
97
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
99
int compare = strcmp (domainname, binding->domainname);
105
/* It is not in the list. */
115
const char *dirname = *dirnamep;
118
/* The current binding has be to returned. */
119
*dirnamep = binding->dirname;
122
/* The domain is already bound. If the new value and the old
123
one are equal we simply do nothing. Otherwise replace the
125
char *result = binding->dirname;
126
if (strcmp (dirname, result) != 0)
128
if (strcmp (dirname, _nl_default_dirname) == 0)
129
result = (char *) _nl_default_dirname;
132
#if defined _LIBC || defined HAVE_STRDUP
133
result = strdup (dirname);
135
size_t len = strlen (dirname) + 1;
136
result = (char *) malloc (len);
137
if (__builtin_expect (result != NULL, 1))
138
memcpy (result, dirname, len);
142
if (__builtin_expect (result != NULL, 1))
144
if (binding->dirname != _nl_default_dirname)
145
free (binding->dirname);
147
binding->dirname = result;
157
const char *codeset = *codesetp;
160
/* The current binding has be to returned. */
161
*codesetp = binding->codeset;
164
/* The domain is already bound. If the new value and the old
165
one are equal we simply do nothing. Otherwise replace the
167
char *result = binding->codeset;
168
if (result == NULL || strcmp (codeset, result) != 0)
170
#if defined _LIBC || defined HAVE_STRDUP
171
result = strdup (codeset);
173
size_t len = strlen (codeset) + 1;
174
result = (char *) malloc (len);
175
if (__builtin_expect (result != NULL, 1))
176
memcpy (result, codeset, len);
179
if (__builtin_expect (result != NULL, 1))
181
if (binding->codeset != NULL)
182
free (binding->codeset);
184
binding->codeset = result;
192
else if ((dirnamep == NULL || *dirnamep == NULL)
193
&& (codesetp == NULL || *codesetp == NULL))
195
/* Simply return the default values. */
197
*dirnamep = _nl_default_dirname;
203
/* We have to create a new binding. */
204
size_t len = strlen (domainname) + 1;
205
struct binding *new_binding =
206
(struct binding *) malloc (offsetof (struct binding, domainname) + len);
208
if (__builtin_expect (new_binding == NULL, 0))
211
memcpy (new_binding->domainname, domainname, len);
215
const char *dirname = *dirnamep;
218
/* The default value. */
219
dirname = _nl_default_dirname;
222
if (strcmp (dirname, _nl_default_dirname) == 0)
223
dirname = _nl_default_dirname;
227
#if defined _LIBC || defined HAVE_STRDUP
228
result = strdup (dirname);
229
if (__builtin_expect (result == NULL, 0))
232
size_t len = strlen (dirname) + 1;
233
result = (char *) malloc (len);
234
if (__builtin_expect (result == NULL, 0))
236
memcpy (result, dirname, len);
242
new_binding->dirname = (char *) dirname;
245
/* The default value. */
246
new_binding->dirname = (char *) _nl_default_dirname;
250
const char *codeset = *codesetp;
256
#if defined _LIBC || defined HAVE_STRDUP
257
result = strdup (codeset);
258
if (__builtin_expect (result == NULL, 0))
261
size_t len = strlen (codeset) + 1;
262
result = (char *) malloc (len);
263
if (__builtin_expect (result == NULL, 0))
265
memcpy (result, codeset, len);
270
new_binding->codeset = (char *) codeset;
273
new_binding->codeset = NULL;
275
/* Now enqueue it. */
276
if (_nl_domain_bindings == NULL
277
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
279
new_binding->next = _nl_domain_bindings;
280
_nl_domain_bindings = new_binding;
284
binding = _nl_domain_bindings;
285
while (binding->next != NULL
286
&& strcmp (domainname, binding->next->domainname) > 0)
287
binding = binding->next;
289
new_binding->next = binding->next;
290
binding->next = new_binding;
295
/* Here we deal with memory allocation failures. */
299
if (new_binding->dirname != _nl_default_dirname)
300
free (new_binding->dirname);
311
/* If we modified any binding, we flush the caches. */
315
gl_rwlock_unlock (_nl_state_lock);
318
/* Specify that the DOMAINNAME message catalog will be found
319
in DIRNAME rather than in the system locale data base. */
321
BINDTEXTDOMAIN (const char *domainname, const char *dirname)
323
set_binding_values (domainname, &dirname, NULL);
324
return (char *) dirname;
327
/* Specify the character encoding in which the messages from the
328
DOMAINNAME message catalog will be returned. */
330
BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
332
set_binding_values (domainname, NULL, &codeset);
333
return (char *) codeset;
337
/* Aliases for function names in GNU C Library. */
338
weak_alias (__bindtextdomain, bindtextdomain);
339
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);