3 /* Implementation of the bindtextdomain(3) function
4 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published
8 by the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 _nl_default_dirname__
51 # define _nl_domain_bindings _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 /* List with bindings of specific domains. */
65 extern struct binding
*_nl_domain_bindings
;
67 /* Lock variable to protect the global data in the gettext implementation. */
68 __libc_rwlock_define (extern, _nl_state_lock
)
71 /* Names for the libintl functions are a problem. They must not clash
72 with existing names and they should follow ANSI C. But this source
73 code is also used in GNU C Library where the names have a __
74 prefix. So we have to make a difference here. */
76 # define BINDTEXTDOMAIN __bindtextdomain
77 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
79 # define strdup(str) __strdup (str)
82 # define BINDTEXTDOMAIN bindtextdomain__
83 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
86 /* Prototypes for local functions. */
87 static void set_binding_values
PARAMS ((const char *domainname
,
88 const char **dirnamep
,
89 const char **codesetp
));
91 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
92 to be used for the DOMAINNAME message catalog.
93 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
94 modified, only the current value is returned.
95 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
96 modified nor returned. */
98 set_binding_values (domainname
, dirnamep
, codesetp
)
99 const char *domainname
;
100 const char **dirnamep
;
101 const char **codesetp
;
103 struct binding
*binding
;
106 /* Some sanity checks. */
107 if (domainname
== NULL
|| domainname
[0] == '\0')
116 __libc_rwlock_wrlock (_nl_state_lock
);
120 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
122 int compare
= strcmp (domainname
, binding
->domainname
);
128 /* It is not in the list. */
138 const char *dirname
= *dirnamep
;
141 /* The current binding has be to returned. */
142 *dirnamep
= binding
->dirname
;
145 /* The domain is already bound. If the new value and the old
146 one are equal we simply do nothing. Otherwise replace the
148 char *result
= binding
->dirname
;
149 if (strcmp (dirname
, result
) != 0)
151 if (strcmp (dirname
, _nl_default_dirname
) == 0)
152 result
= (char *) _nl_default_dirname
;
155 #if defined _LIBC || defined HAVE_STRDUP
156 result
= strdup (dirname
);
158 size_t len
= strlen (dirname
) + 1;
159 result
= (char *) malloc (len
);
160 if (__builtin_expect (result
!= NULL
, 1))
161 memcpy (result
, dirname
, len
);
165 if (__builtin_expect (result
!= NULL
, 1))
167 if (binding
->dirname
!= _nl_default_dirname
)
168 free (binding
->dirname
);
170 binding
->dirname
= result
;
180 const char *codeset
= *codesetp
;
183 /* The current binding has be to returned. */
184 *codesetp
= binding
->codeset
;
187 /* The domain is already bound. If the new value and the old
188 one are equal we simply do nothing. Otherwise replace the
190 char *result
= binding
->codeset
;
191 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
193 #if defined _LIBC || defined HAVE_STRDUP
194 result
= strdup (codeset
);
196 size_t len
= strlen (codeset
) + 1;
197 result
= (char *) malloc (len
);
198 if (__builtin_expect (result
!= NULL
, 1))
199 memcpy (result
, codeset
, len
);
202 if (__builtin_expect (result
!= NULL
, 1))
204 if (binding
->codeset
!= NULL
)
205 free (binding
->codeset
);
207 binding
->codeset
= result
;
208 binding
->codeset_cntr
++;
216 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
217 && (codesetp
== NULL
|| *codesetp
== NULL
))
219 /* Simply return the default values. */
221 *dirnamep
= _nl_default_dirname
;
227 /* We have to create a new binding. */
228 size_t len
= strlen (domainname
) + 1;
229 struct binding
*new_binding
=
230 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
232 if (__builtin_expect (new_binding
== NULL
, 0))
235 memcpy (new_binding
->domainname
, domainname
, len
);
239 const char *dirname
= *dirnamep
;
242 /* The default value. */
243 dirname
= _nl_default_dirname
;
246 if (strcmp (dirname
, _nl_default_dirname
) == 0)
247 dirname
= _nl_default_dirname
;
251 #if defined _LIBC || defined HAVE_STRDUP
252 result
= strdup (dirname
);
253 if (__builtin_expect (result
== NULL
, 0))
256 size_t len
= strlen (dirname
) + 1;
257 result
= (char *) malloc (len
);
258 if (__builtin_expect (result
== NULL
, 0))
260 memcpy (result
, dirname
, len
);
266 new_binding
->dirname
= (char *) dirname
;
269 /* The default value. */
270 new_binding
->dirname
= (char *) _nl_default_dirname
;
272 new_binding
->codeset_cntr
= 0;
276 const char *codeset
= *codesetp
;
282 #if defined _LIBC || defined HAVE_STRDUP
283 result
= strdup (codeset
);
284 if (__builtin_expect (result
== NULL
, 0))
287 size_t len
= strlen (codeset
) + 1;
288 result
= (char *) malloc (len
);
289 if (__builtin_expect (result
== NULL
, 0))
291 memcpy (result
, codeset
, len
);
294 new_binding
->codeset_cntr
++;
297 new_binding
->codeset
= (char *) codeset
;
300 new_binding
->codeset
= NULL
;
302 /* Now enqueue it. */
303 if (_nl_domain_bindings
== NULL
304 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
306 new_binding
->next
= _nl_domain_bindings
;
307 _nl_domain_bindings
= new_binding
;
311 binding
= _nl_domain_bindings
;
312 while (binding
->next
!= NULL
313 && strcmp (domainname
, binding
->next
->domainname
) > 0)
314 binding
= binding
->next
;
316 new_binding
->next
= binding
->next
;
317 binding
->next
= new_binding
;
322 /* Here we deal with memory allocation failures. */
326 if (new_binding
->dirname
!= _nl_default_dirname
)
327 free (new_binding
->dirname
);
338 /* If we modified any binding, we flush the caches. */
342 __libc_rwlock_unlock (_nl_state_lock
);
345 /* Specify that the DOMAINNAME message catalog will be found
346 in DIRNAME rather than in the system locale data base. */
348 BINDTEXTDOMAIN (domainname
, dirname
)
349 const char *domainname
;
352 set_binding_values (domainname
, &dirname
, NULL
);
353 return (char *) dirname
;
356 /* Specify the character encoding in which the messages from the
357 DOMAINNAME message catalog will be returned. */
359 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
360 const char *domainname
;
363 set_binding_values (domainname
, NULL
, &codeset
);
364 return (char *) codeset
;
368 /* Aliases for function names in GNU C Library. */
369 weak_alias (__bindtextdomain
, bindtextdomain
);
370 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);