1*16dce513Schristos /* Implementation of the bindtextdomain(3) function
2*16dce513Schristos Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3*16dce513Schristos
4*16dce513Schristos This program is free software; you can redistribute it and/or modify it
5*16dce513Schristos under the terms of the GNU Library General Public License as published
6*16dce513Schristos by the Free Software Foundation; either version 2, or (at your option)
7*16dce513Schristos any later version.
8*16dce513Schristos
9*16dce513Schristos This program is distributed in the hope that it will be useful,
10*16dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
11*16dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12*16dce513Schristos Library General Public License for more details.
13*16dce513Schristos
14*16dce513Schristos You should have received a copy of the GNU Library General Public
15*16dce513Schristos License along with this program; if not, write to the Free Software
16*16dce513Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
17*16dce513Schristos USA. */
18*16dce513Schristos
19*16dce513Schristos #ifdef HAVE_CONFIG_H
20*16dce513Schristos # include <config.h>
21*16dce513Schristos #endif
22*16dce513Schristos
23*16dce513Schristos #include <stddef.h>
24*16dce513Schristos #include <stdlib.h>
25*16dce513Schristos #include <string.h>
26*16dce513Schristos
27*16dce513Schristos #ifdef _LIBC
28*16dce513Schristos # include <libintl.h>
29*16dce513Schristos #else
30*16dce513Schristos # include "libgnuintl.h"
31*16dce513Schristos #endif
32*16dce513Schristos #include "gettextP.h"
33*16dce513Schristos
34*16dce513Schristos #ifdef _LIBC
35*16dce513Schristos /* We have to handle multi-threaded applications. */
36*16dce513Schristos # include <bits/libc-lock.h>
37*16dce513Schristos #else
38*16dce513Schristos /* Provide dummy implementation if this is outside glibc. */
39*16dce513Schristos # define __libc_rwlock_define(CLASS, NAME)
40*16dce513Schristos # define __libc_rwlock_wrlock(NAME)
41*16dce513Schristos # define __libc_rwlock_unlock(NAME)
42*16dce513Schristos #endif
43*16dce513Schristos
44*16dce513Schristos /* The internal variables in the standalone libintl.a must have different
45*16dce513Schristos names than the internal variables in GNU libc, otherwise programs
46*16dce513Schristos using libintl.a cannot be linked statically. */
47*16dce513Schristos #if !defined _LIBC
48*16dce513Schristos # define _nl_default_dirname libintl_nl_default_dirname
49*16dce513Schristos # define _nl_domain_bindings libintl_nl_domain_bindings
50*16dce513Schristos #endif
51*16dce513Schristos
52*16dce513Schristos /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
53*16dce513Schristos #ifndef offsetof
54*16dce513Schristos # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
55*16dce513Schristos #endif
56*16dce513Schristos
57*16dce513Schristos /* @@ end of prolog @@ */
58*16dce513Schristos
59*16dce513Schristos /* Contains the default location of the message catalogs. */
60*16dce513Schristos extern const char _nl_default_dirname[];
61*16dce513Schristos #ifdef _LIBC
62*16dce513Schristos extern const char _nl_default_dirname_internal[] attribute_hidden;
63*16dce513Schristos #else
64*16dce513Schristos # define INTUSE(name) name
65*16dce513Schristos #endif
66*16dce513Schristos
67*16dce513Schristos /* List with bindings of specific domains. */
68*16dce513Schristos extern struct binding *_nl_domain_bindings;
69*16dce513Schristos
70*16dce513Schristos /* Lock variable to protect the global data in the gettext implementation. */
71*16dce513Schristos __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
72*16dce513Schristos
73*16dce513Schristos
74*16dce513Schristos /* Names for the libintl functions are a problem. They must not clash
75*16dce513Schristos with existing names and they should follow ANSI C. But this source
76*16dce513Schristos code is also used in GNU C Library where the names have a __
77*16dce513Schristos prefix. So we have to make a difference here. */
78*16dce513Schristos #ifdef _LIBC
79*16dce513Schristos # define BINDTEXTDOMAIN __bindtextdomain
80*16dce513Schristos # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
81*16dce513Schristos # ifndef strdup
82*16dce513Schristos # define strdup(str) __strdup (str)
83*16dce513Schristos # endif
84*16dce513Schristos #else
85*16dce513Schristos # define BINDTEXTDOMAIN libintl_bindtextdomain
86*16dce513Schristos # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
87*16dce513Schristos #endif
88*16dce513Schristos
89*16dce513Schristos /* Prototypes for local functions. */
90*16dce513Schristos static void set_binding_values PARAMS ((const char *domainname,
91*16dce513Schristos const char **dirnamep,
92*16dce513Schristos const char **codesetp));
93*16dce513Schristos
94*16dce513Schristos /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
95*16dce513Schristos to be used for the DOMAINNAME message catalog.
96*16dce513Schristos If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
97*16dce513Schristos modified, only the current value is returned.
98*16dce513Schristos If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
99*16dce513Schristos modified nor returned. */
100*16dce513Schristos static void
set_binding_values(domainname,dirnamep,codesetp)101*16dce513Schristos set_binding_values (domainname, dirnamep, codesetp)
102*16dce513Schristos const char *domainname;
103*16dce513Schristos const char **dirnamep;
104*16dce513Schristos const char **codesetp;
105*16dce513Schristos {
106*16dce513Schristos struct binding *binding;
107*16dce513Schristos int modified;
108*16dce513Schristos
109*16dce513Schristos /* Some sanity checks. */
110*16dce513Schristos if (domainname == NULL || domainname[0] == '\0')
111*16dce513Schristos {
112*16dce513Schristos if (dirnamep)
113*16dce513Schristos *dirnamep = NULL;
114*16dce513Schristos if (codesetp)
115*16dce513Schristos *codesetp = NULL;
116*16dce513Schristos return;
117*16dce513Schristos }
118*16dce513Schristos
119*16dce513Schristos __libc_rwlock_wrlock (_nl_state_lock);
120*16dce513Schristos
121*16dce513Schristos modified = 0;
122*16dce513Schristos
123*16dce513Schristos for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
124*16dce513Schristos {
125*16dce513Schristos int compare = strcmp (domainname, binding->domainname);
126*16dce513Schristos if (compare == 0)
127*16dce513Schristos /* We found it! */
128*16dce513Schristos break;
129*16dce513Schristos if (compare < 0)
130*16dce513Schristos {
131*16dce513Schristos /* It is not in the list. */
132*16dce513Schristos binding = NULL;
133*16dce513Schristos break;
134*16dce513Schristos }
135*16dce513Schristos }
136*16dce513Schristos
137*16dce513Schristos if (binding != NULL)
138*16dce513Schristos {
139*16dce513Schristos if (dirnamep)
140*16dce513Schristos {
141*16dce513Schristos const char *dirname = *dirnamep;
142*16dce513Schristos
143*16dce513Schristos if (dirname == NULL)
144*16dce513Schristos /* The current binding has be to returned. */
145*16dce513Schristos *dirnamep = binding->dirname;
146*16dce513Schristos else
147*16dce513Schristos {
148*16dce513Schristos /* The domain is already bound. If the new value and the old
149*16dce513Schristos one are equal we simply do nothing. Otherwise replace the
150*16dce513Schristos old binding. */
151*16dce513Schristos char *result = binding->dirname;
152*16dce513Schristos if (strcmp (dirname, result) != 0)
153*16dce513Schristos {
154*16dce513Schristos if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
155*16dce513Schristos result = (char *) INTUSE(_nl_default_dirname);
156*16dce513Schristos else
157*16dce513Schristos {
158*16dce513Schristos #if defined _LIBC || defined HAVE_STRDUP
159*16dce513Schristos result = strdup (dirname);
160*16dce513Schristos #else
161*16dce513Schristos size_t len = strlen (dirname) + 1;
162*16dce513Schristos result = (char *) malloc (len);
163*16dce513Schristos if (__builtin_expect (result != NULL, 1))
164*16dce513Schristos memcpy (result, dirname, len);
165*16dce513Schristos #endif
166*16dce513Schristos }
167*16dce513Schristos
168*16dce513Schristos if (__builtin_expect (result != NULL, 1))
169*16dce513Schristos {
170*16dce513Schristos if (binding->dirname != INTUSE(_nl_default_dirname))
171*16dce513Schristos free (binding->dirname);
172*16dce513Schristos
173*16dce513Schristos binding->dirname = result;
174*16dce513Schristos modified = 1;
175*16dce513Schristos }
176*16dce513Schristos }
177*16dce513Schristos *dirnamep = result;
178*16dce513Schristos }
179*16dce513Schristos }
180*16dce513Schristos
181*16dce513Schristos if (codesetp)
182*16dce513Schristos {
183*16dce513Schristos const char *codeset = *codesetp;
184*16dce513Schristos
185*16dce513Schristos if (codeset == NULL)
186*16dce513Schristos /* The current binding has be to returned. */
187*16dce513Schristos *codesetp = binding->codeset;
188*16dce513Schristos else
189*16dce513Schristos {
190*16dce513Schristos /* The domain is already bound. If the new value and the old
191*16dce513Schristos one are equal we simply do nothing. Otherwise replace the
192*16dce513Schristos old binding. */
193*16dce513Schristos char *result = binding->codeset;
194*16dce513Schristos if (result == NULL || strcmp (codeset, result) != 0)
195*16dce513Schristos {
196*16dce513Schristos #if defined _LIBC || defined HAVE_STRDUP
197*16dce513Schristos result = strdup (codeset);
198*16dce513Schristos #else
199*16dce513Schristos size_t len = strlen (codeset) + 1;
200*16dce513Schristos result = (char *) malloc (len);
201*16dce513Schristos if (__builtin_expect (result != NULL, 1))
202*16dce513Schristos memcpy (result, codeset, len);
203*16dce513Schristos #endif
204*16dce513Schristos
205*16dce513Schristos if (__builtin_expect (result != NULL, 1))
206*16dce513Schristos {
207*16dce513Schristos if (binding->codeset != NULL)
208*16dce513Schristos free (binding->codeset);
209*16dce513Schristos
210*16dce513Schristos binding->codeset = result;
211*16dce513Schristos binding->codeset_cntr++;
212*16dce513Schristos modified = 1;
213*16dce513Schristos }
214*16dce513Schristos }
215*16dce513Schristos *codesetp = result;
216*16dce513Schristos }
217*16dce513Schristos }
218*16dce513Schristos }
219*16dce513Schristos else if ((dirnamep == NULL || *dirnamep == NULL)
220*16dce513Schristos && (codesetp == NULL || *codesetp == NULL))
221*16dce513Schristos {
222*16dce513Schristos /* Simply return the default values. */
223*16dce513Schristos if (dirnamep)
224*16dce513Schristos *dirnamep = INTUSE(_nl_default_dirname);
225*16dce513Schristos if (codesetp)
226*16dce513Schristos *codesetp = NULL;
227*16dce513Schristos }
228*16dce513Schristos else
229*16dce513Schristos {
230*16dce513Schristos /* We have to create a new binding. */
231*16dce513Schristos size_t len = strlen (domainname) + 1;
232*16dce513Schristos struct binding *new_binding =
233*16dce513Schristos (struct binding *) malloc (offsetof (struct binding, domainname) + len);
234*16dce513Schristos
235*16dce513Schristos if (__builtin_expect (new_binding == NULL, 0))
236*16dce513Schristos goto failed;
237*16dce513Schristos
238*16dce513Schristos memcpy (new_binding->domainname, domainname, len);
239*16dce513Schristos
240*16dce513Schristos if (dirnamep)
241*16dce513Schristos {
242*16dce513Schristos const char *dirname = *dirnamep;
243*16dce513Schristos
244*16dce513Schristos if (dirname == NULL)
245*16dce513Schristos /* The default value. */
246*16dce513Schristos dirname = INTUSE(_nl_default_dirname);
247*16dce513Schristos else
248*16dce513Schristos {
249*16dce513Schristos if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
250*16dce513Schristos dirname = INTUSE(_nl_default_dirname);
251*16dce513Schristos else
252*16dce513Schristos {
253*16dce513Schristos char *result;
254*16dce513Schristos #if defined _LIBC || defined HAVE_STRDUP
255*16dce513Schristos result = strdup (dirname);
256*16dce513Schristos if (__builtin_expect (result == NULL, 0))
257*16dce513Schristos goto failed_dirname;
258*16dce513Schristos #else
259*16dce513Schristos size_t len = strlen (dirname) + 1;
260*16dce513Schristos result = (char *) malloc (len);
261*16dce513Schristos if (__builtin_expect (result == NULL, 0))
262*16dce513Schristos goto failed_dirname;
263*16dce513Schristos memcpy (result, dirname, len);
264*16dce513Schristos #endif
265*16dce513Schristos dirname = result;
266*16dce513Schristos }
267*16dce513Schristos }
268*16dce513Schristos *dirnamep = dirname;
269*16dce513Schristos new_binding->dirname = (char *) dirname;
270*16dce513Schristos }
271*16dce513Schristos else
272*16dce513Schristos /* The default value. */
273*16dce513Schristos new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
274*16dce513Schristos
275*16dce513Schristos new_binding->codeset_cntr = 0;
276*16dce513Schristos
277*16dce513Schristos if (codesetp)
278*16dce513Schristos {
279*16dce513Schristos const char *codeset = *codesetp;
280*16dce513Schristos
281*16dce513Schristos if (codeset != NULL)
282*16dce513Schristos {
283*16dce513Schristos char *result;
284*16dce513Schristos
285*16dce513Schristos #if defined _LIBC || defined HAVE_STRDUP
286*16dce513Schristos result = strdup (codeset);
287*16dce513Schristos if (__builtin_expect (result == NULL, 0))
288*16dce513Schristos goto failed_codeset;
289*16dce513Schristos #else
290*16dce513Schristos size_t len = strlen (codeset) + 1;
291*16dce513Schristos result = (char *) malloc (len);
292*16dce513Schristos if (__builtin_expect (result == NULL, 0))
293*16dce513Schristos goto failed_codeset;
294*16dce513Schristos memcpy (result, codeset, len);
295*16dce513Schristos #endif
296*16dce513Schristos codeset = result;
297*16dce513Schristos new_binding->codeset_cntr++;
298*16dce513Schristos }
299*16dce513Schristos *codesetp = codeset;
300*16dce513Schristos new_binding->codeset = (char *) codeset;
301*16dce513Schristos }
302*16dce513Schristos else
303*16dce513Schristos new_binding->codeset = NULL;
304*16dce513Schristos
305*16dce513Schristos /* Now enqueue it. */
306*16dce513Schristos if (_nl_domain_bindings == NULL
307*16dce513Schristos || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
308*16dce513Schristos {
309*16dce513Schristos new_binding->next = _nl_domain_bindings;
310*16dce513Schristos _nl_domain_bindings = new_binding;
311*16dce513Schristos }
312*16dce513Schristos else
313*16dce513Schristos {
314*16dce513Schristos binding = _nl_domain_bindings;
315*16dce513Schristos while (binding->next != NULL
316*16dce513Schristos && strcmp (domainname, binding->next->domainname) > 0)
317*16dce513Schristos binding = binding->next;
318*16dce513Schristos
319*16dce513Schristos new_binding->next = binding->next;
320*16dce513Schristos binding->next = new_binding;
321*16dce513Schristos }
322*16dce513Schristos
323*16dce513Schristos modified = 1;
324*16dce513Schristos
325*16dce513Schristos /* Here we deal with memory allocation failures. */
326*16dce513Schristos if (0)
327*16dce513Schristos {
328*16dce513Schristos failed_codeset:
329*16dce513Schristos if (new_binding->dirname != INTUSE(_nl_default_dirname))
330*16dce513Schristos free (new_binding->dirname);
331*16dce513Schristos failed_dirname:
332*16dce513Schristos free (new_binding);
333*16dce513Schristos failed:
334*16dce513Schristos if (dirnamep)
335*16dce513Schristos *dirnamep = NULL;
336*16dce513Schristos if (codesetp)
337*16dce513Schristos *codesetp = NULL;
338*16dce513Schristos }
339*16dce513Schristos }
340*16dce513Schristos
341*16dce513Schristos /* If we modified any binding, we flush the caches. */
342*16dce513Schristos if (modified)
343*16dce513Schristos ++_nl_msg_cat_cntr;
344*16dce513Schristos
345*16dce513Schristos __libc_rwlock_unlock (_nl_state_lock);
346*16dce513Schristos }
347*16dce513Schristos
348*16dce513Schristos /* Specify that the DOMAINNAME message catalog will be found
349*16dce513Schristos in DIRNAME rather than in the system locale data base. */
350*16dce513Schristos char *
BINDTEXTDOMAIN(domainname,dirname)351*16dce513Schristos BINDTEXTDOMAIN (domainname, dirname)
352*16dce513Schristos const char *domainname;
353*16dce513Schristos const char *dirname;
354*16dce513Schristos {
355*16dce513Schristos set_binding_values (domainname, &dirname, NULL);
356*16dce513Schristos return (char *) dirname;
357*16dce513Schristos }
358*16dce513Schristos
359*16dce513Schristos /* Specify the character encoding in which the messages from the
360*16dce513Schristos DOMAINNAME message catalog will be returned. */
361*16dce513Schristos char *
BIND_TEXTDOMAIN_CODESET(domainname,codeset)362*16dce513Schristos BIND_TEXTDOMAIN_CODESET (domainname, codeset)
363*16dce513Schristos const char *domainname;
364*16dce513Schristos const char *codeset;
365*16dce513Schristos {
366*16dce513Schristos set_binding_values (domainname, NULL, &codeset);
367*16dce513Schristos return (char *) codeset;
368*16dce513Schristos }
369*16dce513Schristos
370*16dce513Schristos #ifdef _LIBC
371*16dce513Schristos /* Aliases for function names in GNU C Library. */
372*16dce513Schristos weak_alias (__bindtextdomain, bindtextdomain);
373*16dce513Schristos weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
374*16dce513Schristos #endif
375