1
/* Implementation of the bindtextdomain(3) function
2
Copyright (C) 1995-1998, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 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
extern const char _nl_default_dirname_internal[] attribute_hidden;
64
# define INTUSE(name) name
67
/* List with bindings of specific domains. */
68
extern struct binding *_nl_domain_bindings;
70
/* Lock variable to protect the global data in the gettext implementation. */
71
__libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
74
/* Names for the libintl functions are a problem. They must not clash
75
with existing names and they should follow ANSI C. But this source
76
code is also used in GNU C Library where the names have a __
77
prefix. So we have to make a difference here. */
79
# define BINDTEXTDOMAIN __bindtextdomain
80
# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
82
# define strdup(str) __strdup (str)
85
# define BINDTEXTDOMAIN libintl_bindtextdomain
86
# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
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 (const char *domainname,
97
const char **dirnamep, const char **codesetp)
99
struct binding *binding;
102
/* Some sanity checks. */
103
if (domainname == NULL || domainname[0] == '\0')
112
__libc_rwlock_wrlock (_nl_state_lock);
116
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
118
int compare = strcmp (domainname, binding->domainname);
124
/* It is not in the list. */
134
const char *dirname = *dirnamep;
137
/* The current binding has be to returned. */
138
*dirnamep = binding->dirname;
141
/* The domain is already bound. If the new value and the old
142
one are equal we simply do nothing. Otherwise replace the
144
char *result = binding->dirname;
145
if (strcmp (dirname, result) != 0)
147
if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
148
result = (char *) INTUSE(_nl_default_dirname);
151
#if defined _LIBC || defined HAVE_STRDUP
152
result = strdup (dirname);
154
size_t len = strlen (dirname) + 1;
155
result = (char *) malloc (len);
156
if (__builtin_expect (result != NULL, 1))
157
memcpy (result, dirname, len);
161
if (__builtin_expect (result != NULL, 1))
163
if (binding->dirname != INTUSE(_nl_default_dirname))
164
free (binding->dirname);
166
binding->dirname = result;
176
const char *codeset = *codesetp;
179
/* The current binding has be to returned. */
180
*codesetp = binding->codeset;
183
/* The domain is already bound. If the new value and the old
184
one are equal we simply do nothing. Otherwise replace the
186
char *result = binding->codeset;
187
if (result == NULL || strcmp (codeset, result) != 0)
189
#if defined _LIBC || defined HAVE_STRDUP
190
result = strdup (codeset);
192
size_t len = strlen (codeset) + 1;
193
result = (char *) malloc (len);
194
if (__builtin_expect (result != NULL, 1))
195
memcpy (result, codeset, len);
198
if (__builtin_expect (result != NULL, 1))
200
if (binding->codeset != NULL)
201
free (binding->codeset);
203
binding->codeset = result;
204
binding->codeset_cntr++;
212
else if ((dirnamep == NULL || *dirnamep == NULL)
213
&& (codesetp == NULL || *codesetp == NULL))
215
/* Simply return the default values. */
217
*dirnamep = INTUSE(_nl_default_dirname);
223
/* We have to create a new binding. */
224
size_t len = strlen (domainname) + 1;
225
struct binding *new_binding =
226
(struct binding *) malloc (offsetof (struct binding, domainname) + len);
228
if (__builtin_expect (new_binding == NULL, 0))
231
memcpy (new_binding->domainname, domainname, len);
235
const char *dirname = *dirnamep;
238
/* The default value. */
239
dirname = INTUSE(_nl_default_dirname);
242
if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
243
dirname = INTUSE(_nl_default_dirname);
247
#if defined _LIBC || defined HAVE_STRDUP
248
result = strdup (dirname);
249
if (__builtin_expect (result == NULL, 0))
252
size_t len = strlen (dirname) + 1;
253
result = (char *) malloc (len);
254
if (__builtin_expect (result == NULL, 0))
256
memcpy (result, dirname, len);
262
new_binding->dirname = (char *) dirname;
265
/* The default value. */
266
new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
268
new_binding->codeset_cntr = 0;
272
const char *codeset = *codesetp;
278
#if defined _LIBC || defined HAVE_STRDUP
279
result = strdup (codeset);
280
if (__builtin_expect (result == NULL, 0))
283
size_t len = strlen (codeset) + 1;
284
result = (char *) malloc (len);
285
if (__builtin_expect (result == NULL, 0))
287
memcpy (result, codeset, len);
290
new_binding->codeset_cntr++;
293
new_binding->codeset = (char *) codeset;
296
new_binding->codeset = NULL;
298
/* Now enqueue it. */
299
if (_nl_domain_bindings == NULL
300
|| strcmp (domainname, _nl_domain_bindings->domainname) < 0)
302
new_binding->next = _nl_domain_bindings;
303
_nl_domain_bindings = new_binding;
307
binding = _nl_domain_bindings;
308
while (binding->next != NULL
309
&& strcmp (domainname, binding->next->domainname) > 0)
310
binding = binding->next;
312
new_binding->next = binding->next;
313
binding->next = new_binding;
318
/* Here we deal with memory allocation failures. */
322
if (new_binding->dirname != INTUSE(_nl_default_dirname))
323
free (new_binding->dirname);
334
/* If we modified any binding, we flush the caches. */
338
__libc_rwlock_unlock (_nl_state_lock);
341
/* Specify that the DOMAINNAME message catalog will be found
342
in DIRNAME rather than in the system locale data base. */
344
BINDTEXTDOMAIN (const char *domainname, const char *dirname)
346
set_binding_values (domainname, &dirname, NULL);
347
return (char *) dirname;
350
/* Specify the character encoding in which the messages from the
351
DOMAINNAME message catalog will be returned. */
353
BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
355
set_binding_values (domainname, NULL, &codeset);
356
return (char *) codeset;
360
/* Aliases for function names in GNU C Library. */
361
weak_alias (__bindtextdomain, bindtextdomain);
362
weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);