1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-2014 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, see
17 <http://www.gnu.org/licenses/>. */
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 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 __libc_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 /* Prototypes for local functions. */
88 static void set_binding_values
PARAMS ((const char *domainname
,
89 const char **dirnamep
,
90 const char **codesetp
));
92 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
93 to be used for the DOMAINNAME message catalog.
94 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
95 modified, only the current value is returned.
96 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
97 modified nor returned. */
99 set_binding_values (domainname
, dirnamep
, codesetp
)
100 const char *domainname
;
101 const char **dirnamep
;
102 const char **codesetp
;
104 struct binding
*binding
;
107 /* Some sanity checks. */
108 if (domainname
== NULL
|| domainname
[0] == '\0')
117 __libc_rwlock_wrlock (_nl_state_lock
);
121 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
123 int compare
= strcmp (domainname
, binding
->domainname
);
129 /* It is not in the list. */
139 const char *dirname
= *dirnamep
;
142 /* The current binding has be to returned. */
143 *dirnamep
= binding
->dirname
;
146 /* The domain is already bound. If the new value and the old
147 one are equal we simply do nothing. Otherwise replace the
149 char *result
= binding
->dirname
;
150 if (strcmp (dirname
, result
) != 0)
152 if (strcmp (dirname
, _nl_default_dirname
) == 0)
153 result
= (char *) _nl_default_dirname
;
156 #if defined _LIBC || defined HAVE_STRDUP
157 result
= strdup (dirname
);
159 size_t len
= strlen (dirname
) + 1;
160 result
= (char *) malloc (len
);
161 if (__glibc_likely (result
!= NULL
))
162 memcpy (result
, dirname
, len
);
166 if (__glibc_likely (result
!= NULL
))
168 if (binding
->dirname
!= _nl_default_dirname
)
169 free (binding
->dirname
);
171 binding
->dirname
= result
;
181 const char *codeset
= *codesetp
;
184 /* The current binding has be to returned. */
185 *codesetp
= binding
->codeset
;
188 /* The domain is already bound. If the new value and the old
189 one are equal we simply do nothing. Otherwise replace the
191 char *result
= binding
->codeset
;
192 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
194 #if defined _LIBC || defined HAVE_STRDUP
195 result
= strdup (codeset
);
197 size_t len
= strlen (codeset
) + 1;
198 result
= (char *) malloc (len
);
199 if (__glibc_likely (result
!= NULL
))
200 memcpy (result
, codeset
, len
);
203 if (__glibc_likely (result
!= NULL
))
205 free (binding
->codeset
);
207 binding
->codeset
= result
;
215 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
216 && (codesetp
== NULL
|| *codesetp
== NULL
))
218 /* Simply return the default values. */
220 *dirnamep
= _nl_default_dirname
;
226 /* We have to create a new binding. */
227 size_t len
= strlen (domainname
) + 1;
228 struct binding
*new_binding
=
229 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
231 if (__glibc_unlikely (new_binding
== NULL
))
234 memcpy (new_binding
->domainname
, domainname
, len
);
238 const char *dirname
= *dirnamep
;
241 /* The default value. */
242 dirname
= _nl_default_dirname
;
245 if (strcmp (dirname
, _nl_default_dirname
) == 0)
246 dirname
= _nl_default_dirname
;
250 #if defined _LIBC || defined HAVE_STRDUP
251 result
= strdup (dirname
);
252 if (__glibc_unlikely (result
== NULL
))
255 size_t len
= strlen (dirname
) + 1;
256 result
= (char *) malloc (len
);
257 if (__glibc_unlikely (result
== NULL
))
259 memcpy (result
, dirname
, len
);
265 new_binding
->dirname
= (char *) dirname
;
268 /* The default value. */
269 new_binding
->dirname
= (char *) _nl_default_dirname
;
273 const char *codeset
= *codesetp
;
279 #if defined _LIBC || defined HAVE_STRDUP
280 result
= strdup (codeset
);
281 if (__glibc_unlikely (result
== NULL
))
284 size_t len
= strlen (codeset
) + 1;
285 result
= (char *) malloc (len
);
286 if (__glibc_unlikely (result
== NULL
))
288 memcpy (result
, codeset
, len
);
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
!= _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 (domainname
, dirname
)
345 const char *domainname
;
348 set_binding_values (domainname
, &dirname
, NULL
);
349 return (char *) dirname
;
352 /* Specify the character encoding in which the messages from the
353 DOMAINNAME message catalog will be returned. */
355 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
356 const char *domainname
;
359 set_binding_values (domainname
, NULL
, &codeset
);
360 return (char *) codeset
;
364 /* Aliases for function names in GNU C Library. */
365 weak_alias (__bindtextdomain
, bindtextdomain
);
366 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);