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