1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001 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
24 #if defined STDC_HEADERS || defined _LIBC
34 #if defined HAVE_STRING_H || defined _LIBC
39 # define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
46 # include "libgnuintl.h"
51 /* We have to handle multi-threaded applications. */
52 # include <bits/libc-lock.h>
54 /* Provide dummy implementation if this is outside glibc. */
55 # define __libc_rwlock_define(CLASS, NAME)
56 # define __libc_rwlock_wrlock(NAME)
57 # define __libc_rwlock_unlock(NAME)
60 /* The internal variables in the standalone libintl.a must have different
61 names than the internal variables in GNU libc, otherwise programs
62 using libintl.a cannot be linked statically. */
64 # define _nl_default_dirname _nl_default_dirname__
65 # define _nl_domain_bindings _nl_domain_bindings__
68 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
70 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
73 /* @@ end of prolog @@ */
75 /* Contains the default location of the message catalogs. */
76 extern const char _nl_default_dirname
[];
78 /* List with bindings of specific domains. */
79 extern struct binding
*_nl_domain_bindings
;
81 /* Lock variable to protect the global data in the gettext implementation. */
82 __libc_rwlock_define (extern, _nl_state_lock
)
85 /* Names for the libintl functions are a problem. They must not clash
86 with existing names and they should follow ANSI C. But this source
87 code is also used in GNU C Library where the names have a __
88 prefix. So we have to make a difference here. */
90 # define BINDTEXTDOMAIN __bindtextdomain
91 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
93 # define strdup(str) __strdup (str)
96 # define BINDTEXTDOMAIN bindtextdomain__
97 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
100 /* Prototypes for local functions. */
101 static void set_binding_values
PARAMS ((const char *domainname
,
102 const char **dirnamep
,
103 const char **codesetp
));
105 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
106 to be used for the DOMAINNAME message catalog.
107 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
108 modified, only the current value is returned.
109 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
110 modified nor returned. */
112 set_binding_values (domainname
, dirnamep
, codesetp
)
113 const char *domainname
;
114 const char **dirnamep
;
115 const char **codesetp
;
117 struct binding
*binding
;
120 /* Some sanity checks. */
121 if (domainname
== NULL
|| domainname
[0] == '\0')
130 __libc_rwlock_wrlock (_nl_state_lock
);
134 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
136 int compare
= strcmp (domainname
, binding
->domainname
);
142 /* It is not in the list. */
152 const char *dirname
= *dirnamep
;
155 /* The current binding has be to returned. */
156 *dirnamep
= binding
->dirname
;
159 /* The domain is already bound. If the new value and the old
160 one are equal we simply do nothing. Otherwise replace the
162 char *result
= binding
->dirname
;
163 if (strcmp (dirname
, result
) != 0)
165 if (strcmp (dirname
, _nl_default_dirname
) == 0)
166 result
= (char *) _nl_default_dirname
;
169 #if defined _LIBC || defined HAVE_STRDUP
170 result
= strdup (dirname
);
172 size_t len
= strlen (dirname
) + 1;
173 result
= (char *) malloc (len
);
174 if (__builtin_expect (result
!= NULL
, 1))
175 memcpy (result
, dirname
, len
);
179 if (__builtin_expect (result
!= NULL
, 1))
181 if (binding
->dirname
!= _nl_default_dirname
)
182 free (binding
->dirname
);
184 binding
->dirname
= result
;
194 const char *codeset
= *codesetp
;
197 /* The current binding has be to returned. */
198 *codesetp
= binding
->codeset
;
201 /* The domain is already bound. If the new value and the old
202 one are equal we simply do nothing. Otherwise replace the
204 char *result
= binding
->codeset
;
205 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
207 #if defined _LIBC || defined HAVE_STRDUP
208 result
= strdup (codeset
);
210 size_t len
= strlen (codeset
) + 1;
211 result
= (char *) malloc (len
);
212 if (__builtin_expect (result
!= NULL
, 1))
213 memcpy (result
, codeset
, len
);
216 if (__builtin_expect (result
!= NULL
, 1))
218 if (binding
->codeset
!= NULL
)
219 free (binding
->codeset
);
221 binding
->codeset
= result
;
222 ++binding
->codeset_cntr
;
230 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
231 && (codesetp
== NULL
|| *codesetp
== NULL
))
233 /* Simply return the default values. */
235 *dirnamep
= _nl_default_dirname
;
241 /* We have to create a new binding. */
242 size_t len
= strlen (domainname
) + 1;
243 struct binding
*new_binding
=
244 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
246 if (__builtin_expect (new_binding
== NULL
, 0))
249 memcpy (new_binding
->domainname
, domainname
, len
);
253 const char *dirname
= *dirnamep
;
256 /* The default value. */
257 dirname
= _nl_default_dirname
;
260 if (strcmp (dirname
, _nl_default_dirname
) == 0)
261 dirname
= _nl_default_dirname
;
265 #if defined _LIBC || defined HAVE_STRDUP
266 result
= strdup (dirname
);
267 if (__builtin_expect (result
== NULL
, 0))
270 size_t len
= strlen (dirname
) + 1;
271 result
= (char *) malloc (len
);
272 if (__builtin_expect (result
== NULL
, 0))
274 memcpy (result
, dirname
, len
);
280 new_binding
->dirname
= (char *) dirname
;
283 /* The default value. */
284 new_binding
->dirname
= (char *) _nl_default_dirname
;
286 new_binding
->codeset_cntr
= 0;
290 const char *codeset
= *codesetp
;
296 #if defined _LIBC || defined HAVE_STRDUP
297 result
= strdup (codeset
);
298 if (__builtin_expect (result
== NULL
, 0))
301 size_t len
= strlen (codeset
) + 1;
302 result
= (char *) malloc (len
);
303 if (__builtin_expect (result
== NULL
, 0))
305 memcpy (result
, codeset
, len
);
308 ++new_binding
->codeset_cntr
;
311 new_binding
->codeset
= (char *) codeset
;
314 new_binding
->codeset
= NULL
;
316 /* Now enqueue it. */
317 if (_nl_domain_bindings
== NULL
318 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
320 new_binding
->next
= _nl_domain_bindings
;
321 _nl_domain_bindings
= new_binding
;
325 binding
= _nl_domain_bindings
;
326 while (binding
->next
!= NULL
327 && strcmp (domainname
, binding
->next
->domainname
) > 0)
328 binding
= binding
->next
;
330 new_binding
->next
= binding
->next
;
331 binding
->next
= new_binding
;
336 /* Here we deal with memory allocation failures. */
340 if (new_binding
->dirname
!= _nl_default_dirname
)
341 free (new_binding
->dirname
);
352 /* If we modified any binding, we flush the caches. */
356 __libc_rwlock_unlock (_nl_state_lock
);
359 /* Specify that the DOMAINNAME message catalog will be found
360 in DIRNAME rather than in the system locale data base. */
362 BINDTEXTDOMAIN (domainname
, dirname
)
363 const char *domainname
;
366 set_binding_values (domainname
, &dirname
, NULL
);
367 return (char *) dirname
;
370 /* Specify the character encoding in which the messages from the
371 DOMAINNAME message catalog will be returned. */
373 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
374 const char *domainname
;
377 set_binding_values (domainname
, NULL
, &codeset
);
378 return (char *) codeset
;
382 /* Aliases for function names in GNU C Library. */
383 weak_alias (__bindtextdomain
, bindtextdomain
);
384 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);