1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
23 #if defined STDC_HEADERS || defined _LIBC
33 #if defined HAVE_STRING_H || defined _LIBC
38 # define memcpy(Dst, Src, Num) (bcopy (Src, Dst, Num), (Dst))
45 # include "libgnuintl.h"
50 /* We have to handle multi-threaded applications. */
51 # include <bits/libc-lock.h>
53 /* Provide dummy implementation if this is outside glibc. */
54 # define __libc_rwlock_define(CLASS, NAME)
55 # define __libc_rwlock_wrlock(NAME)
56 # define __libc_rwlock_unlock(NAME)
59 /* The internal variables in the standalone libintl.a must have different
60 names than the internal variables in GNU libc, otherwise programs
61 using libintl.a cannot be linked statically. */
63 # define _nl_default_dirname _nl_default_dirname__
64 # define _nl_domain_bindings _nl_domain_bindings__
67 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
69 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
72 /* @@ end of prolog @@ */
74 /* Contains the default location of the message catalogs. */
75 extern const char _nl_default_dirname
[];
77 /* List with bindings of specific domains. */
78 extern struct binding
*_nl_domain_bindings
;
80 /* Lock variable to protect the global data in the gettext implementation. */
81 __libc_rwlock_define (extern, _nl_state_lock
)
84 /* Names for the libintl functions are a problem. They must not clash
85 with existing names and they should follow ANSI C. But this source
86 code is also used in GNU C Library where the names have a __
87 prefix. So we have to make a difference here. */
89 # define BINDTEXTDOMAIN __bindtextdomain
90 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
92 # define strdup(str) __strdup (str)
95 # define BINDTEXTDOMAIN bindtextdomain__
96 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
99 /* Prototypes for local functions. */
100 static void set_binding_values
PARAMS ((const char *domainname
,
101 const char **dirnamep
,
102 const char **codesetp
));
104 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
105 to be used for the DOMAINNAME message catalog.
106 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
107 modified, only the current value is returned.
108 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
109 modified nor returned. */
111 set_binding_values (domainname
, dirnamep
, codesetp
)
112 const char *domainname
;
113 const char **dirnamep
;
114 const char **codesetp
;
116 struct binding
*binding
;
119 /* Some sanity checks. */
120 if (domainname
== NULL
|| domainname
[0] == '\0')
129 __libc_rwlock_wrlock (_nl_state_lock
);
133 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
135 int compare
= strcmp (domainname
, binding
->domainname
);
141 /* It is not in the list. */
151 const char *dirname
= *dirnamep
;
154 /* The current binding has be to returned. */
155 *dirnamep
= binding
->dirname
;
158 /* The domain is already bound. If the new value and the old
159 one are equal we simply do nothing. Otherwise replace the
161 char *result
= binding
->dirname
;
162 if (strcmp (dirname
, result
) != 0)
164 if (strcmp (dirname
, _nl_default_dirname
) == 0)
165 result
= (char *) _nl_default_dirname
;
168 #if defined _LIBC || defined HAVE_STRDUP
169 result
= strdup (dirname
);
171 size_t len
= strlen (dirname
) + 1;
172 result
= (char *) malloc (len
);
173 if (__builtin_expect (result
!= NULL
, 1))
174 memcpy (result
, dirname
, len
);
178 if (__builtin_expect (result
!= NULL
, 1))
180 if (binding
->dirname
!= _nl_default_dirname
)
181 free (binding
->dirname
);
183 binding
->dirname
= result
;
193 const char *codeset
= *codesetp
;
196 /* The current binding has be to returned. */
197 *codesetp
= binding
->codeset
;
200 /* The domain is already bound. If the new value and the old
201 one are equal we simply do nothing. Otherwise replace the
203 char *result
= binding
->codeset
;
204 if (result
== NULL
|| strcmp (codeset
, result
) != 0)
206 #if defined _LIBC || defined HAVE_STRDUP
207 result
= strdup (codeset
);
209 size_t len
= strlen (codeset
) + 1;
210 result
= (char *) malloc (len
);
211 if (__builtin_expect (result
!= NULL
, 1))
212 memcpy (result
, codeset
, len
);
215 if (__builtin_expect (result
!= NULL
, 1))
217 if (binding
->codeset
!= NULL
)
218 free (binding
->codeset
);
220 binding
->codeset
= result
;
228 else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
229 && (codesetp
== NULL
|| *codesetp
== NULL
))
231 /* Simply return the default values. */
233 *dirnamep
= _nl_default_dirname
;
239 /* We have to create a new binding. */
240 size_t len
= strlen (domainname
) + 1;
241 struct binding
*new_binding
=
242 (struct binding
*) malloc (offsetof (struct binding
, domainname
) + len
);
244 if (__builtin_expect (new_binding
== NULL
, 0))
247 memcpy (new_binding
->domainname
, domainname
, len
);
251 const char *dirname
= *dirnamep
;
254 /* The default value. */
255 dirname
= _nl_default_dirname
;
258 if (strcmp (dirname
, _nl_default_dirname
) == 0)
259 dirname
= _nl_default_dirname
;
263 #if defined _LIBC || defined HAVE_STRDUP
264 result
= strdup (dirname
);
265 if (__builtin_expect (result
== NULL
, 0))
268 size_t len
= strlen (dirname
) + 1;
269 result
= (char *) malloc (len
);
270 if (__builtin_expect (result
== NULL
, 0))
272 memcpy (result
, dirname
, len
);
278 new_binding
->dirname
= (char *) dirname
;
281 /* The default value. */
282 new_binding
->dirname
= (char *) _nl_default_dirname
;
286 const char *codeset
= *codesetp
;
292 #if defined _LIBC || defined HAVE_STRDUP
293 result
= strdup (codeset
);
294 if (__builtin_expect (result
== NULL
, 0))
297 size_t len
= strlen (codeset
) + 1;
298 result
= (char *) malloc (len
);
299 if (__builtin_expect (result
== NULL
, 0))
301 memcpy (result
, codeset
, len
);
306 new_binding
->codeset
= (char *) codeset
;
309 new_binding
->codeset
= NULL
;
311 /* Now enqueue it. */
312 if (_nl_domain_bindings
== NULL
313 || strcmp (domainname
, _nl_domain_bindings
->domainname
) < 0)
315 new_binding
->next
= _nl_domain_bindings
;
316 _nl_domain_bindings
= new_binding
;
320 binding
= _nl_domain_bindings
;
321 while (binding
->next
!= NULL
322 && strcmp (domainname
, binding
->next
->domainname
) > 0)
323 binding
= binding
->next
;
325 new_binding
->next
= binding
->next
;
326 binding
->next
= new_binding
;
331 /* Here we deal with memory allocation failures. */
335 if (new_binding
->dirname
!= _nl_default_dirname
)
336 free (new_binding
->dirname
);
347 /* If we modified any binding, we flush the caches. */
351 __libc_rwlock_unlock (_nl_state_lock
);
354 /* Specify that the DOMAINNAME message catalog will be found
355 in DIRNAME rather than in the system locale data base. */
357 BINDTEXTDOMAIN (domainname
, dirname
)
358 const char *domainname
;
361 set_binding_values (domainname
, &dirname
, NULL
);
362 return (char *) dirname
;
365 /* Specify the character encoding in which the messages from the
366 DOMAINNAME message catalog will be returned. */
368 BIND_TEXTDOMAIN_CODESET (domainname
, codeset
)
369 const char *domainname
;
372 set_binding_values (domainname
, NULL
, &codeset
);
373 return (char *) codeset
;
377 /* Aliases for function names in GNU C Library. */
378 weak_alias (__bindtextdomain
, bindtextdomain
);
379 weak_alias (__bind_textdomain_codeset
, bind_textdomain_codeset
);