1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-2019 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
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
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
29 # include "libgnuintl.h"
32 /* Handle multi-threaded applications. */
34 # include <libc-lock.h>
35 # define gl_rwlock_define __libc_rwlock_define
36 # define gl_rwlock_wrlock __libc_rwlock_wrlock
37 # define gl_rwlock_unlock __libc_rwlock_unlock
42 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
44 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
47 /* @@ end of prolog @@ */
49 /* Lock variable to protect the global data in the gettext implementation. */
50 gl_rwlock_define (extern, _nl_state_lock attribute_hidden
)
53 /* Names for the libintl functions are a problem. They must not clash
54 with existing names and they should follow ANSI C. But this source
55 code is also used in GNU C Library where the names have a __
56 prefix. So we have to make a difference here. */
58 # define BINDTEXTDOMAIN __bindtextdomain
59 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
61 # define strdup(str) __strdup (str)
64 # define BINDTEXTDOMAIN libintl_bindtextdomain
65 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
68 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
69 to be used for the DOMAINNAME message catalog.
70 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
71 modified, only the current value is returned.
72 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
73 modified nor returned. */
75 set_binding_values (const char *domainname
,
76 const char **dirnamep
, const char **codesetp
)
78 struct binding
*binding
;
81 /* Some sanity checks. */
82 if (domainname
== NULL
|| domainname
[0] == '\0')
91 gl_rwlock_wrlock (_nl_state_lock
);
95 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
97 int compare
= strcmp (domainname
, binding
->domainname
);
103 /* It is not in the list. */
113 const char *dirname
= *dirnamep
;
116 /* The current binding has be to returned. */
117 *dirnamep
= binding
->dirname
;
120 /* The domain is already bound. If the new value and the old
121 one are equal we simply do nothing. Otherwise replace the
123 char *result
= binding
->dirname
;
124 if (strcmp (dirname
, result
) != 0)
126 if (strcmp (dirname
, _nl_default_dirname
) == 0)
127 result
= (char *) _nl_default_dirname
;
130 #if defined _LIBC || defined HAVE_STRDUP
131 result
= strdup (dirname
);
133 size_t len
= strlen (dirname
) + 1;
134 result
= (char *) malloc (len
);
135 if (__builtin_expect (result
!= NULL
, 1))
136 memcpy (result
, dirname
, len
);
140 if (__builtin_expect (result
!= NULL
, 1))
142 if (binding
->dirname
!= _nl_default_dirname
)
143 free (binding
->dirname
);
145 binding
->dirname
= result
;
155 const char *codeset
= *codesetp
;
158 /* The current binding has be to returned. */
159 *codesetp
= binding
->codeset
;
162 /* The domain is already bound. If the new value and the old
163 one are equal we simply do nothing. Otherwise replace the
165 char *result
= binding
->codeset
;
166 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
168 #if defined _LIBC || defined HAVE_STRDUP
169 result
= strdup (codeset
);
171 size_t len
= strlen (codeset
) + 1;
172 result
= (char *) malloc (len
);
173 if (__builtin_expect (result
!= NULL
, 1))
174 memcpy (result
, codeset
, len
);
177 if (__builtin_expect (result
!= NULL
, 1))
179 free (binding
->codeset
);
181 binding
->codeset
= result
;
189 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
190 && (codesetp
== NULL
|| *codesetp
== NULL
))
192 /* Simply return the default values. */
194 *dirnamep
= _nl_default_dirname
;
200 /* We have to create a new binding. */
201 size_t len
= strlen (domainname
) + 1;
202 struct binding
*new_binding
=
203 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
205 if (__builtin_expect (new_binding
== NULL
, 0))
208 memcpy (new_binding
->domainname
, domainname
, len
);
212 const char *dirname
= *dirnamep
;
215 /* The default value. */
216 dirname
= _nl_default_dirname
;
219 if (strcmp (dirname
, _nl_default_dirname
) == 0)
220 dirname
= _nl_default_dirname
;
224 #if defined _LIBC || defined HAVE_STRDUP
225 result
= strdup (dirname
);
226 if (__builtin_expect (result
== NULL
, 0))
229 size_t len
= strlen (dirname
) + 1;
230 result
= (char *) malloc (len
);
231 if (__builtin_expect (result
== NULL
, 0))
233 memcpy (result
, dirname
, len
);
239 new_binding
->dirname
= (char *) dirname
;
242 /* The default value. */
243 new_binding
->dirname
= (char *) _nl_default_dirname
;
247 const char *codeset
= *codesetp
;
253 #if defined _LIBC || defined HAVE_STRDUP
254 result
= strdup (codeset
);
255 if (__builtin_expect (result
== NULL
, 0))
258 size_t len
= strlen (codeset
) + 1;
259 result
= (char *) malloc (len
);
260 if (__builtin_expect (result
== NULL
, 0))
262 memcpy (result
, codeset
, len
);
267 new_binding
->codeset
= (char *) codeset
;
270 new_binding
->codeset
= NULL
;
272 /* Now enqueue it. */
273 if (_nl_domain_bindings
== NULL
274 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
276 new_binding
->next
= _nl_domain_bindings
;
277 _nl_domain_bindings
= new_binding
;
281 binding
= _nl_domain_bindings
;
282 while (binding
->next
!= NULL
283 && strcmp (domainname
, binding
->next
->domainname
) > 0)
284 binding
= binding
->next
;
286 new_binding
->next
= binding
->next
;
287 binding
->next
= new_binding
;
292 /* Here we deal with memory allocation failures. */
296 if (new_binding
->dirname
!= _nl_default_dirname
)
297 free (new_binding
->dirname
);
308 /* If we modified any binding, we flush the caches. */
312 gl_rwlock_unlock (_nl_state_lock
);
315 /* Specify that the DOMAINNAME message catalog will be found
316 in DIRNAME rather than in the system locale data base. */
318 BINDTEXTDOMAIN (const char *domainname
, const char *dirname
)
320 set_binding_values (domainname
, &dirname
, NULL
);
321 return (char *) dirname
;
324 /* Specify the character encoding in which the messages from the
325 DOMAINNAME message catalog will be returned. */
327 BIND_TEXTDOMAIN_CODESET (const char *domainname
, const char *codeset
)
329 set_binding_values (domainname
, NULL
, &codeset
);
330 return (char *) codeset
;
334 /* Aliases for function names in GNU C Library. */
335 weak_alias (__bindtextdomain
, bindtextdomain
);
336 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);