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
/* 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
libc_hidden_proto (_nl_default_dirname)
65
/* List with bindings of specific domains. */
66
extern struct binding *_nl_domain_bindings;
68
/* Lock variable to protect the global data in the gettext implementation. */
69
gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
72
/* Names for the libintl functions are a problem. They must not clash
73
with existing names and they should follow ANSI C. But this source
74
code is also used in GNU C Library where the names have a __
75
prefix. So we have to make a difference here. */
77
# define BINDTEXTDOMAIN __bindtextdomain
78
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
80
# define strdup(str) __strdup (str)
83
# define BINDTEXTDOMAIN libintl_bindtextdomain
84
# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
87
/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
88
to be used for the DOMAINNAME message catalog.
89
If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
90
modified, only the current value is returned.
91
If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
92
modified nor returned. */
94
set_binding_values (const char *domainname,
95
const char **dirnamep, const char **codesetp)
97
struct binding *binding;
100
/* Some sanity checks. */
101
if (domainname == NULL || domainname[0] == '\0')
110
gl_rwlock_wrlock (_nl_state_lock);
114
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
116
int compare = strcmp (domainname, binding->domainname);
122
/* It is not in the list. */
132
const char *dirname = *dirnamep;
135
/* The current binding has be to returned. */
136
*dirnamep = binding->dirname;
139
/* The domain is already bound. If the new value and the old
140
one are equal we simply do nothing. Otherwise replace the
142
char *result = binding->dirname;
143
if (strcmp (dirname, result) != 0)
145
if (strcmp (dirname, _nl_default_dirname) == 0)
146
result = (char *) _nl_default_dirname;
149
#if defined _LIBC || defined HAVE_STRDUP
150
result = strdup (dirname);
152
size_t len = strlen (dirname) + 1;
153
result = (char *) malloc (len);
154
if (__builtin_expect (result != NULL, 1))
155
memcpy (result, dirname, len);
159
if (__builtin_expect (result != NULL, 1))
161
if (binding->dirname != _nl_default_dirname)
162
free (binding->dirname);
164
binding->dirname = result;
174
const char *codeset = *codesetp;
177
/* The current binding has be to returned. */
178
*codesetp = binding->codeset;
181
/* The domain is already bound. If the new value and the old
182
one are equal we simply do nothing. Otherwise replace the
184
char *result = binding->codeset;
185
if (result == NULL || strcmp (codeset, result) != 0)
187
#if defined _LIBC || defined HAVE_STRDUP
188
result = strdup (codeset);
190
size_t len = strlen (codeset) + 1;
191
result = (char *) malloc (len);
192
if (__builtin_expect (result != NULL, 1))
193
memcpy (result, codeset, len);
196
if (__builtin_expect (result != NULL, 1))
198
if (binding->codeset != NULL)
199
free (binding->codeset);
201
binding->codeset = result;
209
else if ((dirnamep == NULL || *dirnamep == NULL)
210
&& (codesetp == NULL || *codesetp == NULL))
212
/* Simply return the default values. */
214
*dirnamep = _nl_default_dirname;
220
/* We have to create a new binding. */
221
size_t len = strlen (domainname) + 1;
222
struct binding *new_binding =
223
(struct binding *) malloc (offsetof (struct binding, domainname) + len);
225
if (__builtin_expect (new_binding == NULL, 0))
228
memcpy (new_binding->domainname, domainname, len);
232
const char *dirname = *dirnamep;
235
/* The default value. */
236
dirname = _nl_default_dirname;
239
if (strcmp (dirname, _nl_default_dirname) == 0)
240
dirname = _nl_default_dirname;
244
#if defined _LIBC || defined HAVE_STRDUP
245
result = strdup (dirname);
246
if (__builtin_expect (result == NULL, 0))
249
size_t len = strlen (dirname) + 1;
250
result = (char *) malloc (len);
251
if (__builtin_expect (result == NULL, 0))
253
memcpy (result, dirname, len);
259
new_binding->dirname = (char *) dirname;
262
/* The default value. */
263
new_binding->dirname = (char *) _nl_default_dirname;
267
const char *codeset = *codesetp;
273
#if defined _LIBC || defined HAVE_STRDUP
274
result = strdup (codeset);
275
if (__builtin_expect (result == NULL, 0))
278
size_t len = strlen (codeset) + 1;
279
result = (char *) malloc (len);
280
if (__builtin_expect (result == NULL, 0))
282
memcpy (result, codeset, len);
287
new_binding->codeset = (char *) codeset;
290
new_binding->codeset = NULL;
292
/* Now enqueue it. */
293
if (_nl_domain_bindings == NULL
294
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
296
new_binding->next = _nl_domain_bindings;
297
_nl_domain_bindings = new_binding;
301
binding = _nl_domain_bindings;
302
while (binding->next != NULL
303
&& strcmp (domainname, binding->next->domainname) > 0)
304
binding = binding->next;
306
new_binding->next = binding->next;
307
binding->next = new_binding;
312
/* Here we deal with memory allocation failures. */
316
if (new_binding->dirname != _nl_default_dirname)
317
free (new_binding->dirname);
328
/* If we modified any binding, we flush the caches. */
332
gl_rwlock_unlock (_nl_state_lock);
335
/* Specify that the DOMAINNAME message catalog will be found
336
in DIRNAME rather than in the system locale data base. */
338
BINDTEXTDOMAIN (const char *domainname, const char *dirname)
340
set_binding_values (domainname, &dirname, NULL);
341
return (char *) dirname;
344
/* Specify the character encoding in which the messages from the
345
DOMAINNAME message catalog will be returned. */
347
BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
349
set_binding_values (domainname, NULL, &codeset);
350
return (char *) codeset;
354
/* Aliases for function names in GNU C Library. */
355
weak_alias (__bindtextdomain, bindtextdomain);
356
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);