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., 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 _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);