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