~ubuntu-branches/ubuntu/wily/alsaplayer/wily

« back to all changes in this revision

Viewing changes to intl/bindtextdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2007-10-10 15:33:10 UTC
  • mto: (9.2.5 sid)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: james.westby@ubuntu.com-20071010153310-h3holq75eu2cigb0
Tags: upstream-0.99.80~rc4
ImportĀ upstreamĀ versionĀ 0.99.80~rc4

Show diffs side-by-side

added added

removed removed

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