1 /* bindtextdom.c - Implementation of the bindtextdomain(3) function */
3 /* Copyright (C) 1995-1998, 2000, 2001, 2002, 2005-2009 Free Software Foundation, Inc.
5 This file is part of GNU Bush.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
32 # include "libgnuintl.h"
37 /* We have to handle multi-threaded applications. */
38 # include <bits/libc-lock.h>
40 /* Provide dummy implementation if this is outside glibc. */
41 # define __libc_rwlock_define(CLASS, NAME)
42 # define __libc_rwlock_wrlock(NAME)
43 # define __libc_rwlock_unlock(NAME)
46 /* The internal variables in the standalone libintl.a must have different
47 names than the internal variables in GNU libc, otherwise programs
48 using libintl.a cannot be linked statically. */
50 # define _nl_default_dirname libintl_nl_default_dirname
51 # define _nl_domain_bindings libintl_nl_domain_bindings
54 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
56 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
59 /* @@ end of prolog @@ */
61 /* Contains the default location of the message catalogs. */
62 extern const char _nl_default_dirname
[];
64 extern const char _nl_default_dirname_internal
[] attribute_hidden
;
66 # define INTUSE(name) name
69 /* List with bindings of specific domains. */
70 extern struct binding
*_nl_domain_bindings
;
72 /* Lock variable to protect the global data in the gettext implementation. */
73 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden
)
76 /* Names for the libintl functions are a problem. They must not clash
77 with existing names and they should follow ANSI C. But this source
78 code is also used in GNU C Library where the names have a __
79 prefix. So we have to make a difference here. */
81 # define BINDTEXTDOMAIN __bindtextdomain
82 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
84 # define strdup(str) __strdup (str)
87 # define BINDTEXTDOMAIN libintl_bindtextdomain
88 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
91 /* Prototypes for local functions. */
92 static void set_binding_values
PARAMS ((const char *domainname
,
93 const char **dirnamep
,
94 const char **codesetp
));
96 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
97 to be used for the DOMAINNAME message catalog.
98 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
99 modified, only the current value is returned.
100 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
101 modified nor returned. */
103 set_binding_values (domainname
, dirnamep
, codesetp
)
104 const char *domainname
;
105 const char **dirnamep
;
106 const char **codesetp
;
108 struct binding
*binding
;
111 /* Some sanity checks. */
112 if (domainname
== NULL
|| domainname
[0] == '\0')
121 __libc_rwlock_wrlock (_nl_state_lock
);
125 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
127 int compare
= strcmp (domainname
, binding
->domainname
);
133 /* It is not in the list. */
143 const char *dirname
= *dirnamep
;
146 /* The current binding has be to returned. */
147 *dirnamep
= binding
->dirname
;
150 /* The domain is already bound. If the new value and the old
151 one are equal we simply do nothing. Otherwise replace the
153 char *result
= binding
->dirname
;
154 if (strcmp (dirname
, result
) != 0)
156 if (strcmp (dirname
, INTUSE(_nl_default_dirname
)) == 0)
157 result
= (char *) INTUSE(_nl_default_dirname
);
160 #if defined _LIBC || defined HAVE_STRDUP
161 result
= strdup (dirname
);
163 size_t len
= strlen (dirname
) + 1;
164 result
= (char *) malloc (len
);
165 if (__builtin_expect (result
!= NULL
, 1))
166 memcpy (result
, dirname
, len
);
170 if (__builtin_expect (result
!= NULL
, 1))
172 if (binding
->dirname
!= INTUSE(_nl_default_dirname
))
173 free (binding
->dirname
);
175 binding
->dirname
= result
;
185 const char *codeset
= *codesetp
;
188 /* The current binding has be to returned. */
189 *codesetp
= binding
->codeset
;
192 /* The domain is already bound. If the new value and the old
193 one are equal we simply do nothing. Otherwise replace the
195 char *result
= binding
->codeset
;
196 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
198 #if defined _LIBC || defined HAVE_STRDUP
199 result
= strdup (codeset
);
201 size_t len
= strlen (codeset
) + 1;
202 result
= (char *) malloc (len
);
203 if (__builtin_expect (result
!= NULL
, 1))
204 memcpy (result
, codeset
, len
);
207 if (__builtin_expect (result
!= NULL
, 1))
209 if (binding
->codeset
!= NULL
)
210 free (binding
->codeset
);
212 binding
->codeset
= result
;
213 binding
->codeset_cntr
++;
221 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
222 && (codesetp
== NULL
|| *codesetp
== NULL
))
224 /* Simply return the default values. */
226 *dirnamep
= INTUSE(_nl_default_dirname
);
232 /* We have to create a new binding. */
233 size_t len
= strlen (domainname
) + 1;
234 struct binding
*new_binding
=
235 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
237 if (__builtin_expect (new_binding
== NULL
, 0))
240 memcpy (new_binding
->domainname
, domainname
, len
);
244 const char *dirname
= *dirnamep
;
247 /* The default value. */
248 dirname
= INTUSE(_nl_default_dirname
);
251 if (strcmp (dirname
, INTUSE(_nl_default_dirname
)) == 0)
252 dirname
= INTUSE(_nl_default_dirname
);
256 #if defined _LIBC || defined HAVE_STRDUP
257 result
= strdup (dirname
);
258 if (__builtin_expect (result
== NULL
, 0))
261 size_t len
= strlen (dirname
) + 1;
262 result
= (char *) malloc (len
);
263 if (__builtin_expect (result
== NULL
, 0))
265 memcpy (result
, dirname
, len
);
271 new_binding
->dirname
= (char *) dirname
;
274 /* The default value. */
275 new_binding
->dirname
= (char *) INTUSE(_nl_default_dirname
);
277 new_binding
->codeset_cntr
= 0;
281 const char *codeset
= *codesetp
;
287 #if defined _LIBC || defined HAVE_STRDUP
288 result
= strdup (codeset
);
289 if (__builtin_expect (result
== NULL
, 0))
292 size_t len
= strlen (codeset
) + 1;
293 result
= (char *) malloc (len
);
294 if (__builtin_expect (result
== NULL
, 0))
296 memcpy (result
, codeset
, len
);
299 new_binding
->codeset_cntr
++;
302 new_binding
->codeset
= (char *) codeset
;
305 new_binding
->codeset
= NULL
;
307 /* Now enqueue it. */
308 if (_nl_domain_bindings
== NULL
309 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
311 new_binding
->next
= _nl_domain_bindings
;
312 _nl_domain_bindings
= new_binding
;
316 binding
= _nl_domain_bindings
;
317 while (binding
->next
!= NULL
318 && strcmp (domainname
, binding
->next
->domainname
) > 0)
319 binding
= binding
->next
;
321 new_binding
->next
= binding
->next
;
322 binding
->next
= new_binding
;
327 /* Here we deal with memory allocation failures. */
331 if (new_binding
->dirname
!= INTUSE(_nl_default_dirname
))
332 free (new_binding
->dirname
);
343 /* If we modified any binding, we flush the caches. */
347 __libc_rwlock_unlock (_nl_state_lock
);
350 /* Specify that the DOMAINNAME message catalog will be found
351 in DIRNAME rather than in the system locale data base. */
353 BINDTEXTDOMAIN (domainname
, dirname
)
354 const char *domainname
;
357 set_binding_values (domainname
, &dirname
, NULL
);
358 return (char *) dirname
;
361 /* Specify the character encoding in which the messages from the
362 DOMAINNAME message catalog will be returned. */
364 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
365 const char *domainname
;
368 set_binding_values (domainname
, NULL
, &codeset
);
369 return (char *) codeset
;
373 /* Aliases for function names in GNU C Library. */
374 weak_alias (__bindtextdomain
, bindtextdomain
);
375 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);