~ubuntu-branches/ubuntu/lucid/mc/lucid

« back to all changes in this revision

Viewing changes to intl/bindtextdom.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-09-16 10:38:59 UTC
  • mfrom: (3.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080916103859-2uwn8w61xk5mbxxq
Tags: 2:4.6.2~git20080311-4
Corrected fix for odt2txt issue (Closes: #492019) 

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