1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001, 2002, 2005 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 libintl_nl_default_dirname
50 # define _nl_domain_bindings libintl_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 libc_hidden_proto (_nl_default_dirname
)
66 /* List with bindings of specific domains. */
67 extern struct binding
*_nl_domain_bindings
;
69 /* Lock variable to protect the global data in the gettext implementation. */
70 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden
)
73 /* Names for the libintl functions are a problem. They must not clash
74 with existing names and they should follow ANSI C. But this source
75 code is also used in GNU C Library where the names have a __
76 prefix. So we have to make a difference here. */
78 # define BINDTEXTDOMAIN __bindtextdomain
79 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
81 # define strdup(str) __strdup (str)
84 # define BINDTEXTDOMAIN libintl_bindtextdomain
85 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
88 /* Prototypes for local functions. */
89 static void set_binding_values
PARAMS ((const char *domainname
,
90 const char **dirnamep
,
91 const char **codesetp
));
93 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
94 to be used for the DOMAINNAME message catalog.
95 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
96 modified, only the current value is returned.
97 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
98 modified nor returned. */
100 set_binding_values (domainname
, dirnamep
, codesetp
)
101 const char *domainname
;
102 const char **dirnamep
;
103 const char **codesetp
;
105 struct binding
*binding
;
108 /* Some sanity checks. */
109 if (domainname
== NULL
|| domainname
[0] == '\0')
118 __libc_rwlock_wrlock (_nl_state_lock
);
122 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
124 int compare
= strcmp (domainname
, binding
->domainname
);
130 /* It is not in the list. */
140 const char *dirname
= *dirnamep
;
143 /* The current binding has be to returned. */
144 *dirnamep
= binding
->dirname
;
147 /* The domain is already bound. If the new value and the old
148 one are equal we simply do nothing. Otherwise replace the
150 char *result
= binding
->dirname
;
151 if (strcmp (dirname
, result
) != 0)
153 if (strcmp (dirname
, _nl_default_dirname
) == 0)
154 result
= (char *) _nl_default_dirname
;
157 #if defined _LIBC || defined HAVE_STRDUP
158 result
= strdup (dirname
);
160 size_t len
= strlen (dirname
) + 1;
161 result
= (char *) malloc (len
);
162 if (__builtin_expect (result
!= NULL
, 1))
163 memcpy (result
, dirname
, len
);
167 if (__builtin_expect (result
!= NULL
, 1))
169 if (binding
->dirname
!= _nl_default_dirname
)
170 free (binding
->dirname
);
172 binding
->dirname
= result
;
182 const char *codeset
= *codesetp
;
185 /* The current binding has be to returned. */
186 *codesetp
= binding
->codeset
;
189 /* The domain is already bound. If the new value and the old
190 one are equal we simply do nothing. Otherwise replace the
192 char *result
= binding
->codeset
;
193 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
195 #if defined _LIBC || defined HAVE_STRDUP
196 result
= strdup (codeset
);
198 size_t len
= strlen (codeset
) + 1;
199 result
= (char *) malloc (len
);
200 if (__builtin_expect (result
!= NULL
, 1))
201 memcpy (result
, codeset
, len
);
204 if (__builtin_expect (result
!= NULL
, 1))
206 if (binding
->codeset
!= NULL
)
207 free (binding
->codeset
);
209 binding
->codeset
= result
;
217 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
218 && (codesetp
== NULL
|| *codesetp
== NULL
))
220 /* Simply return the default values. */
222 *dirnamep
= _nl_default_dirname
;
228 /* We have to create a new binding. */
229 size_t len
= strlen (domainname
) + 1;
230 struct binding
*new_binding
=
231 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
233 if (__builtin_expect (new_binding
== NULL
, 0))
236 memcpy (new_binding
->domainname
, domainname
, len
);
240 const char *dirname
= *dirnamep
;
243 /* The default value. */
244 dirname
= _nl_default_dirname
;
247 if (strcmp (dirname
, _nl_default_dirname
) == 0)
248 dirname
= _nl_default_dirname
;
252 #if defined _LIBC || defined HAVE_STRDUP
253 result
= strdup (dirname
);
254 if (__builtin_expect (result
== NULL
, 0))
257 size_t len
= strlen (dirname
) + 1;
258 result
= (char *) malloc (len
);
259 if (__builtin_expect (result
== NULL
, 0))
261 memcpy (result
, dirname
, len
);
267 new_binding
->dirname
= (char *) dirname
;
270 /* The default value. */
271 new_binding
->dirname
= (char *) _nl_default_dirname
;
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
);
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
);