1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001, 2002 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
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 extern const char _nl_default_dirname_internal
[] attribute_hidden
;
64 # define INTUSE(name) name
67 /* List with bindings of specific domains. */
68 extern struct binding
*_nl_domain_bindings
;
70 /* Lock variable to protect the global data in the gettext implementation. */
71 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden
)
74 /* Names for the libintl functions are a problem. They must not clash
75 with existing names and they should follow ANSI C. But this source
76 code is also used in GNU C Library where the names have a __
77 prefix. So we have to make a difference here. */
79 # define BINDTEXTDOMAIN __bindtextdomain
80 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
82 # define strdup(str) __strdup (str)
85 # define BINDTEXTDOMAIN libintl_bindtextdomain
86 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
89 /* Prototypes for local functions. */
90 static void set_binding_values
PARAMS ((const char *domainname
,
91 const char **dirnamep
,
92 const char **codesetp
));
94 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
95 to be used for the DOMAINNAME message catalog.
96 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
97 modified, only the current value is returned.
98 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
99 modified nor returned. */
101 set_binding_values (domainname
, dirnamep
, codesetp
)
102 const char *domainname
;
103 const char **dirnamep
;
104 const char **codesetp
;
106 struct binding
*binding
;
109 /* Some sanity checks. */
110 if (domainname
== NULL
|| domainname
[0] == '\0')
119 __libc_rwlock_wrlock (_nl_state_lock
);
123 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
125 int compare
= strcmp (domainname
, binding
->domainname
);
131 /* It is not in the list. */
141 const char *dirname
= *dirnamep
;
144 /* The current binding has be to returned. */
145 *dirnamep
= binding
->dirname
;
148 /* The domain is already bound. If the new value and the old
149 one are equal we simply do nothing. Otherwise replace the
151 char *result
= binding
->dirname
;
152 if (strcmp (dirname
, result
) != 0)
154 if (strcmp (dirname
, INTUSE(_nl_default_dirname
)) == 0)
155 result
= (char *) INTUSE(_nl_default_dirname
);
158 #if defined _LIBC || defined HAVE_STRDUP
159 result
= strdup (dirname
);
161 size_t len
= strlen (dirname
) + 1;
162 result
= (char *) malloc (len
);
163 if (__builtin_expect (result
!= NULL
, 1))
164 memcpy (result
, dirname
, len
);
168 if (__builtin_expect (result
!= NULL
, 1))
170 if (binding
->dirname
!= INTUSE(_nl_default_dirname
))
171 free (binding
->dirname
);
173 binding
->dirname
= result
;
183 const char *codeset
= *codesetp
;
186 /* The current binding has be to returned. */
187 *codesetp
= binding
->codeset
;
190 /* The domain is already bound. If the new value and the old
191 one are equal we simply do nothing. Otherwise replace the
193 char *result
= binding
->codeset
;
194 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
196 #if defined _LIBC || defined HAVE_STRDUP
197 result
= strdup (codeset
);
199 size_t len
= strlen (codeset
) + 1;
200 result
= (char *) malloc (len
);
201 if (__builtin_expect (result
!= NULL
, 1))
202 memcpy (result
, codeset
, len
);
205 if (__builtin_expect (result
!= NULL
, 1))
207 if (binding
->codeset
!= NULL
)
208 free (binding
->codeset
);
210 binding
->codeset
= result
;
211 binding
->codeset_cntr
++;
219 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
220 && (codesetp
== NULL
|| *codesetp
== NULL
))
222 /* Simply return the default values. */
224 *dirnamep
= INTUSE(_nl_default_dirname
);
230 /* We have to create a new binding. */
231 size_t len
= strlen (domainname
) + 1;
232 struct binding
*new_binding
=
233 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
235 if (__builtin_expect (new_binding
== NULL
, 0))
238 memcpy (new_binding
->domainname
, domainname
, len
);
242 const char *dirname
= *dirnamep
;
245 /* The default value. */
246 dirname
= INTUSE(_nl_default_dirname
);
249 if (strcmp (dirname
, INTUSE(_nl_default_dirname
)) == 0)
250 dirname
= INTUSE(_nl_default_dirname
);
254 #if defined _LIBC || defined HAVE_STRDUP
255 result
= strdup (dirname
);
256 if (__builtin_expect (result
== NULL
, 0))
259 size_t len
= strlen (dirname
) + 1;
260 result
= (char *) malloc (len
);
261 if (__builtin_expect (result
== NULL
, 0))
263 memcpy (result
, dirname
, len
);
269 new_binding
->dirname
= (char *) dirname
;
272 /* The default value. */
273 new_binding
->dirname
= (char *) INTUSE(_nl_default_dirname
);
275 new_binding
->codeset_cntr
= 0;
279 const char *codeset
= *codesetp
;
285 #if defined _LIBC || defined HAVE_STRDUP
286 result
= strdup (codeset
);
287 if (__builtin_expect (result
== NULL
, 0))
290 size_t len
= strlen (codeset
) + 1;
291 result
= (char *) malloc (len
);
292 if (__builtin_expect (result
== NULL
, 0))
294 memcpy (result
, codeset
, len
);
297 new_binding
->codeset_cntr
++;
300 new_binding
->codeset
= (char *) codeset
;
303 new_binding
->codeset
= NULL
;
305 /* Now enqueue it. */
306 if (_nl_domain_bindings
== NULL
307 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
309 new_binding
->next
= _nl_domain_bindings
;
310 _nl_domain_bindings
= new_binding
;
314 binding
= _nl_domain_bindings
;
315 while (binding
->next
!= NULL
316 && strcmp (domainname
, binding
->next
->domainname
) > 0)
317 binding
= binding
->next
;
319 new_binding
->next
= binding
->next
;
320 binding
->next
= new_binding
;
325 /* Here we deal with memory allocation failures. */
329 if (new_binding
->dirname
!= INTUSE(_nl_default_dirname
))
330 free (new_binding
->dirname
);
341 /* If we modified any binding, we flush the caches. */
345 __libc_rwlock_unlock (_nl_state_lock
);
348 /* Specify that the DOMAINNAME message catalog will be found
349 in DIRNAME rather than in the system locale data base. */
351 BINDTEXTDOMAIN (domainname
, dirname
)
352 const char *domainname
;
355 set_binding_values (domainname
, &dirname
, NULL
);
356 return (char *) dirname
;
359 /* Specify the character encoding in which the messages from the
360 DOMAINNAME message catalog will be returned. */
362 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
363 const char *domainname
;
366 set_binding_values (domainname
, NULL
, &codeset
);
367 return (char *) codeset
;
371 /* Aliases for function names in GNU C Library. */
372 weak_alias (__bindtextdomain
, bindtextdomain
);
373 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);