~ubuntu-branches/ubuntu/jaunty/m17n-lib/jaunty

« back to all changes in this revision

Viewing changes to intl/bindtextdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Harshula Jayasuriya
  • Date: 2008-04-04 23:15:32 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404231532-pys1hr3eq0qv0fcx
Tags: 1.3.4-2
libm17n-dev Depends on libxml2-dev and libthai-dev. (Closes: #473957)

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