~noskcaj/ubuntu/trusty/libextractor/merge

« back to all changes in this revision

Viewing changes to intl/dcigettext.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-11-10 22:21:49 UTC
  • mfrom: (1.10.3 upstream) (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20081110222149-pr35f3nmqy5cf52i
Tags: 0.5.21+dfsg-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - (Build-)depend on libltdl7-dev (Ubuntu-specific change).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Implementation of the internal dcigettext function.
2
 
   Copyright (C) 1995-1999, 2000-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
 
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
20
 
   This must come before <config.h> because <config.h> may include
21
 
   <features.h>, and once <features.h> has been included, it's too late.  */
22
 
#ifndef _GNU_SOURCE
23
 
# define _GNU_SOURCE    1
24
 
#endif
25
 
 
26
 
#ifdef HAVE_CONFIG_H
27
 
# include <config.h>
28
 
#endif
29
 
 
30
 
/* NL_LOCALE_NAME does not work in glibc-2.4.  Ignore it.  */
31
 
#undef HAVE_NL_LOCALE_NAME
32
 
 
33
 
#include <sys/types.h>
34
 
 
35
 
#ifdef __GNUC__
36
 
# define alloca __builtin_alloca
37
 
# define HAVE_ALLOCA 1
38
 
#else
39
 
# ifdef _MSC_VER
40
 
#  include <malloc.h>
41
 
#  define alloca _alloca
42
 
# else
43
 
#  if defined HAVE_ALLOCA_H || defined _LIBC
44
 
#   include <alloca.h>
45
 
#  else
46
 
#   ifdef _AIX
47
 
 #pragma alloca
48
 
#   else
49
 
#    ifndef alloca
50
 
char *alloca ();
51
 
#    endif
52
 
#   endif
53
 
#  endif
54
 
# endif
55
 
#endif
56
 
 
57
 
#include <errno.h>
58
 
#ifndef errno
59
 
extern int errno;
60
 
#endif
61
 
#ifndef __set_errno
62
 
# define __set_errno(val) errno = (val)
63
 
#endif
64
 
 
65
 
#include <stddef.h>
66
 
#include <stdlib.h>
67
 
#include <string.h>
68
 
 
69
 
#if defined HAVE_UNISTD_H || defined _LIBC
70
 
# include <unistd.h>
71
 
#endif
72
 
 
73
 
#include <locale.h>
74
 
 
75
 
#ifdef _LIBC
76
 
  /* Guess whether integer division by zero raises signal SIGFPE.
77
 
     Set to 1 only if you know for sure.  In case of doubt, set to 0.  */
78
 
# if defined __alpha__ || defined __arm__ || defined __i386__ \
79
 
     || defined __m68k__ || defined __s390__
80
 
#  define INTDIV0_RAISES_SIGFPE 1
81
 
# else
82
 
#  define INTDIV0_RAISES_SIGFPE 0
83
 
# endif
84
 
#endif
85
 
#if !INTDIV0_RAISES_SIGFPE
86
 
# include <signal.h>
87
 
#endif
88
 
 
89
 
#if defined HAVE_SYS_PARAM_H || defined _LIBC
90
 
# include <sys/param.h>
91
 
#endif
92
 
 
93
 
#if !defined _LIBC && HAVE_NL_LOCALE_NAME
94
 
# include <langinfo.h>
95
 
#endif
96
 
 
97
 
#include "gettextP.h"
98
 
#include "plural-exp.h"
99
 
#ifdef _LIBC
100
 
# include <libintl.h>
101
 
#else
102
 
# ifdef IN_LIBGLOCALE
103
 
#  include <libintl.h>
104
 
# endif
105
 
# include "libgnuintl.h"
106
 
#endif
107
 
#include "hash-string.h"
108
 
 
109
 
/* Handle multi-threaded applications.  */
110
 
#ifdef _LIBC
111
 
# include <bits/libc-lock.h>
112
 
# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
113
 
# define gl_rwlock_rdlock __libc_rwlock_rdlock
114
 
# define gl_rwlock_wrlock __libc_rwlock_wrlock
115
 
# define gl_rwlock_unlock __libc_rwlock_unlock
116
 
#else
117
 
# include "lock.h"
118
 
#endif
119
 
 
120
 
/* Alignment of types.  */
121
 
#if defined __GNUC__ && __GNUC__ >= 2
122
 
# define alignof(TYPE) __alignof__ (TYPE)
123
 
#else
124
 
# define alignof(TYPE) \
125
 
    ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
126
 
#endif
127
 
 
128
 
/* The internal variables in the standalone libintl.a must have different
129
 
   names than the internal variables in GNU libc, otherwise programs
130
 
   using libintl.a cannot be linked statically.  */
131
 
#if !defined _LIBC
132
 
# define _nl_default_default_domain libintl_nl_default_default_domain
133
 
# define _nl_current_default_domain libintl_nl_current_default_domain
134
 
# define _nl_default_dirname libintl_nl_default_dirname
135
 
# define _nl_domain_bindings libintl_nl_domain_bindings
136
 
#endif
137
 
 
138
 
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
139
 
#ifndef offsetof
140
 
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
141
 
#endif
142
 
 
143
 
/* @@ end of prolog @@ */
144
 
 
145
 
#ifdef _LIBC
146
 
/* Rename the non ANSI C functions.  This is required by the standard
147
 
   because some ANSI C functions will require linking with this object
148
 
   file and the name space must not be polluted.  */
149
 
# define getcwd __getcwd
150
 
# ifndef stpcpy
151
 
#  define stpcpy __stpcpy
152
 
# endif
153
 
# define tfind __tfind
154
 
#else
155
 
# if !defined HAVE_GETCWD
156
 
char *getwd ();
157
 
#  define getcwd(buf, max) getwd (buf)
158
 
# else
159
 
#  if VMS
160
 
#   define getcwd(buf, max) (getcwd) (buf, max, 0)
161
 
#  else
162
 
char *getcwd ();
163
 
#  endif
164
 
# endif
165
 
# ifndef HAVE_STPCPY
166
 
static char *stpcpy (char *dest, const char *src);
167
 
# endif
168
 
# ifndef HAVE_MEMPCPY
169
 
static void *mempcpy (void *dest, const void *src, size_t n);
170
 
# endif
171
 
#endif
172
 
 
173
 
/* Amount to increase buffer size by in each try.  */
174
 
#define PATH_INCR 32
175
 
 
176
 
/* The following is from pathmax.h.  */
177
 
/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
178
 
   PATH_MAX but might cause redefinition warnings when sys/param.h is
179
 
   later included (as on MORE/BSD 4.3).  */
180
 
#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
181
 
# include <limits.h>
182
 
#endif
183
 
 
184
 
#ifndef _POSIX_PATH_MAX
185
 
# define _POSIX_PATH_MAX 255
186
 
#endif
187
 
 
188
 
#if !defined PATH_MAX && defined _PC_PATH_MAX
189
 
# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
190
 
#endif
191
 
 
192
 
/* Don't include sys/param.h if it already has been.  */
193
 
#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
194
 
# include <sys/param.h>
195
 
#endif
196
 
 
197
 
#if !defined PATH_MAX && defined MAXPATHLEN
198
 
# define PATH_MAX MAXPATHLEN
199
 
#endif
200
 
 
201
 
#ifndef PATH_MAX
202
 
# define PATH_MAX _POSIX_PATH_MAX
203
 
#endif
204
 
 
205
 
/* Pathname support.
206
 
   ISSLASH(C)           tests whether C is a directory separator character.
207
 
   IS_ABSOLUTE_PATH(P)  tests whether P is an absolute path.  If it is not,
208
 
                        it may be concatenated to a directory pathname.
209
 
   IS_PATH_WITH_DIR(P)  tests whether P contains a directory specification.
210
 
 */
211
 
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
212
 
  /* Win32, Cygwin, OS/2, DOS */
213
 
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
214
 
# define HAS_DEVICE(P) \
215
 
    ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
216
 
     && (P)[1] == ':')
217
 
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
218
 
# define IS_PATH_WITH_DIR(P) \
219
 
    (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
220
 
#else
221
 
  /* Unix */
222
 
# define ISSLASH(C) ((C) == '/')
223
 
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
224
 
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
225
 
#endif
226
 
 
227
 
/* Whether to support different locales in different threads.  */
228
 
#if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE
229
 
# define HAVE_PER_THREAD_LOCALE
230
 
#endif
231
 
 
232
 
/* This is the type used for the search tree where known translations
233
 
   are stored.  */
234
 
struct known_translation_t
235
 
{
236
 
  /* Domain in which to search.  */
237
 
  const char *domainname;
238
 
 
239
 
  /* The category.  */
240
 
  int category;
241
 
 
242
 
#ifdef HAVE_PER_THREAD_LOCALE
243
 
  /* Name of the relevant locale category, or "" for the global locale.  */
244
 
  const char *localename;
245
 
#endif
246
 
 
247
 
#ifdef IN_LIBGLOCALE
248
 
  /* The character encoding.  */
249
 
  const char *encoding;
250
 
#endif
251
 
 
252
 
  /* State of the catalog counter at the point the string was found.  */
253
 
  int counter;
254
 
 
255
 
  /* Catalog where the string was found.  */
256
 
  struct loaded_l10nfile *domain;
257
 
 
258
 
  /* And finally the translation.  */
259
 
  const char *translation;
260
 
  size_t translation_length;
261
 
 
262
 
  /* Pointer to the string in question.  */
263
 
  char msgid[ZERO];
264
 
};
265
 
 
266
 
/* Root of the search tree with known translations.  We can use this
267
 
   only if the system provides the `tsearch' function family.  */
268
 
#if defined HAVE_TSEARCH || defined _LIBC
269
 
# include <search.h>
270
 
 
271
 
gl_rwlock_define_initialized (static, tree_lock)
272
 
 
273
 
static void *root;
274
 
 
275
 
# ifdef _LIBC
276
 
#  define tsearch __tsearch
277
 
# endif
278
 
 
279
 
/* Function to compare two entries in the table of known translations.  */
280
 
static int
281
 
transcmp (const void *p1, const void *p2)
282
 
{
283
 
  const struct known_translation_t *s1;
284
 
  const struct known_translation_t *s2;
285
 
  int result;
286
 
 
287
 
  s1 = (const struct known_translation_t *) p1;
288
 
  s2 = (const struct known_translation_t *) p2;
289
 
 
290
 
  result = strcmp (s1->msgid, s2->msgid);
291
 
  if (result == 0)
292
 
    {
293
 
      result = strcmp (s1->domainname, s2->domainname);
294
 
      if (result == 0)
295
 
        {
296
 
#ifdef HAVE_PER_THREAD_LOCALE
297
 
          result = strcmp (s1->localename, s2->localename);
298
 
          if (result == 0)
299
 
#endif
300
 
            {
301
 
#ifdef IN_LIBGLOCALE
302
 
              result = strcmp (s1->encoding, s2->encoding);
303
 
              if (result == 0)
304
 
#endif
305
 
                /* We compare the category last (though this is the cheapest
306
 
                   operation) since it is hopefully always the same (namely
307
 
                   LC_MESSAGES).  */
308
 
                result = s1->category - s2->category;
309
 
            }
310
 
        }
311
 
    }
312
 
 
313
 
  return result;
314
 
}
315
 
#endif
316
 
 
317
 
/* Name of the default domain used for gettext(3) prior any call to
318
 
   textdomain(3).  The default value for this is "messages".  */
319
 
const char _nl_default_default_domain[] attribute_hidden = "messages";
320
 
 
321
 
#ifndef IN_LIBGLOCALE
322
 
/* Value used as the default domain for gettext(3).  */
323
 
const char *_nl_current_default_domain attribute_hidden
324
 
     = _nl_default_default_domain;
325
 
#endif
326
 
 
327
 
/* Contains the default location of the message catalogs.  */
328
 
#if defined __EMX__
329
 
extern const char _nl_default_dirname[];
330
 
#else
331
 
# ifdef _LIBC
332
 
extern const char _nl_default_dirname[];
333
 
libc_hidden_proto (_nl_default_dirname)
334
 
# endif
335
 
const char _nl_default_dirname[] = LOCALEDIR;
336
 
# ifdef _LIBC
337
 
libc_hidden_data_def (_nl_default_dirname)
338
 
# endif
339
 
#endif
340
 
 
341
 
#ifndef IN_LIBGLOCALE
342
 
/* List with bindings of specific domains created by bindtextdomain()
343
 
   calls.  */
344
 
struct binding *_nl_domain_bindings;
345
 
#endif
346
 
 
347
 
/* Prototypes for local functions.  */
348
 
static char *plural_lookup (struct loaded_l10nfile *domain,
349
 
                            unsigned long int n,
350
 
                            const char *translation, size_t translation_len)
351
 
     internal_function;
352
 
 
353
 
#ifdef IN_LIBGLOCALE
354
 
static const char *guess_category_value (int category,
355
 
                                         const char *categoryname,
356
 
                                         const char *localename)
357
 
     internal_function;
358
 
#else
359
 
static const char *guess_category_value (int category,
360
 
                                         const char *categoryname)
361
 
     internal_function;
362
 
#endif
363
 
 
364
 
#ifdef _LIBC
365
 
# include "../locale/localeinfo.h"
366
 
# define category_to_name(category) \
367
 
  _nl_category_names.str + _nl_category_name_idxs[category]
368
 
#else
369
 
static const char *category_to_name (int category) internal_function;
370
 
#endif
371
 
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
372
 
static const char *get_output_charset (struct binding *domainbinding)
373
 
     internal_function;
374
 
#endif
375
 
 
376
 
 
377
 
/* For those loosing systems which don't have `alloca' we have to add
378
 
   some additional code emulating it.  */
379
 
#ifdef HAVE_ALLOCA
380
 
/* Nothing has to be done.  */
381
 
# define freea(p) /* nothing */
382
 
# define ADD_BLOCK(list, address) /* nothing */
383
 
# define FREE_BLOCKS(list) /* nothing */
384
 
#else
385
 
struct block_list
386
 
{
387
 
  void *address;
388
 
  struct block_list *next;
389
 
};
390
 
# define ADD_BLOCK(list, addr)                                                \
391
 
  do {                                                                        \
392
 
    struct block_list *newp = (struct block_list *) malloc (sizeof (*newp));  \
393
 
    /* If we cannot get a free block we cannot add the new element to         \
394
 
       the list.  */                                                          \
395
 
    if (newp != NULL) {                                                       \
396
 
      newp->address = (addr);                                                 \
397
 
      newp->next = (list);                                                    \
398
 
      (list) = newp;                                                          \
399
 
    }                                                                         \
400
 
  } while (0)
401
 
# define FREE_BLOCKS(list)                                                    \
402
 
  do {                                                                        \
403
 
    while (list != NULL) {                                                    \
404
 
      struct block_list *old = list;                                          \
405
 
      list = list->next;                                                      \
406
 
      free (old->address);                                                    \
407
 
      free (old);                                                             \
408
 
    }                                                                         \
409
 
  } while (0)
410
 
# undef alloca
411
 
# define alloca(size) (malloc (size))
412
 
# define freea(p) free (p)
413
 
#endif  /* have alloca */
414
 
 
415
 
 
416
 
#ifdef _LIBC
417
 
/* List of blocks allocated for translations.  */
418
 
typedef struct transmem_list
419
 
{
420
 
  struct transmem_list *next;
421
 
  char data[ZERO];
422
 
} transmem_block_t;
423
 
static struct transmem_list *transmem_list;
424
 
#else
425
 
typedef unsigned char transmem_block_t;
426
 
#endif
427
 
 
428
 
 
429
 
/* Names for the libintl functions are a problem.  They must not clash
430
 
   with existing names and they should follow ANSI C.  But this source
431
 
   code is also used in GNU C Library where the names have a __
432
 
   prefix.  So we have to make a difference here.  */
433
 
#ifdef _LIBC
434
 
# define DCIGETTEXT __dcigettext
435
 
#else
436
 
# define DCIGETTEXT libintl_dcigettext
437
 
#endif
438
 
 
439
 
/* Lock variable to protect the global data in the gettext implementation.  */
440
 
gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
441
 
 
442
 
/* Checking whether the binaries runs SUID must be done and glibc provides
443
 
   easier methods therefore we make a difference here.  */
444
 
#ifdef _LIBC
445
 
# define ENABLE_SECURE __libc_enable_secure
446
 
# define DETERMINE_SECURE
447
 
#else
448
 
# ifndef HAVE_GETUID
449
 
#  define getuid() 0
450
 
# endif
451
 
# ifndef HAVE_GETGID
452
 
#  define getgid() 0
453
 
# endif
454
 
# ifndef HAVE_GETEUID
455
 
#  define geteuid() getuid()
456
 
# endif
457
 
# ifndef HAVE_GETEGID
458
 
#  define getegid() getgid()
459
 
# endif
460
 
static int enable_secure;
461
 
# define ENABLE_SECURE (enable_secure == 1)
462
 
# define DETERMINE_SECURE \
463
 
  if (enable_secure == 0)                                                     \
464
 
    {                                                                         \
465
 
      if (getuid () != geteuid () || getgid () != getegid ())                 \
466
 
        enable_secure = 1;                                                    \
467
 
      else                                                                    \
468
 
        enable_secure = -1;                                                   \
469
 
    }
470
 
#endif
471
 
 
472
 
/* Get the function to evaluate the plural expression.  */
473
 
#include "eval-plural.h"
474
 
 
475
 
/* Look up MSGID in the DOMAINNAME message catalog for the current
476
 
   CATEGORY locale and, if PLURAL is nonzero, search over string
477
 
   depending on the plural form determined by N.  */
478
 
#ifdef IN_LIBGLOCALE
479
 
char *
480
 
gl_dcigettext (const char *domainname,
481
 
               const char *msgid1, const char *msgid2,
482
 
               int plural, unsigned long int n,
483
 
               int category,
484
 
               const char *localename, const char *encoding)
485
 
#else
486
 
char *
487
 
DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
488
 
            int plural, unsigned long int n, int category)
489
 
#endif
490
 
{
491
 
#ifndef HAVE_ALLOCA
492
 
  struct block_list *block_list = NULL;
493
 
#endif
494
 
  struct loaded_l10nfile *domain;
495
 
  struct binding *binding;
496
 
  const char *categoryname;
497
 
  const char *categoryvalue;
498
 
  const char *dirname;
499
 
  char *xdomainname;
500
 
  char *single_locale;
501
 
  char *retval;
502
 
  size_t retlen;
503
 
  int saved_errno;
504
 
#if defined HAVE_TSEARCH || defined _LIBC
505
 
  struct known_translation_t *search;
506
 
  struct known_translation_t **foundp = NULL;
507
 
  size_t msgid_len;
508
 
# if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
509
 
  const char *localename;
510
 
# endif
511
 
#endif
512
 
  size_t domainname_len;
513
 
 
514
 
  /* If no real MSGID is given return NULL.  */
515
 
  if (msgid1 == NULL)
516
 
    return NULL;
517
 
 
518
 
#ifdef _LIBC
519
 
  if (category < 0 || category >= __LC_LAST || category == LC_ALL)
520
 
    /* Bogus.  */
521
 
    return (plural == 0
522
 
            ? (char *) msgid1
523
 
            /* Use the Germanic plural rule.  */
524
 
            : n == 1 ? (char *) msgid1 : (char *) msgid2);
525
 
#endif
526
 
 
527
 
  gl_rwlock_rdlock (_nl_state_lock);
528
 
 
529
 
  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
530
 
     CATEGORY is not LC_MESSAGES this might not make much sense but the
531
 
     definition left this undefined.  */
532
 
  if (domainname == NULL)
533
 
    domainname = _nl_current_default_domain;
534
 
 
535
 
  /* OS/2 specific: backward compatibility with older libintl versions  */
536
 
#ifdef LC_MESSAGES_COMPAT
537
 
  if (category == LC_MESSAGES_COMPAT)
538
 
    category = LC_MESSAGES;
539
 
#endif
540
 
 
541
 
#if defined HAVE_TSEARCH || defined _LIBC
542
 
  msgid_len = strlen (msgid1) + 1;
543
 
 
544
 
  /* Try to find the translation among those which we found at
545
 
     some time.  */
546
 
  search = (struct known_translation_t *)
547
 
           alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
548
 
  memcpy (search->msgid, msgid1, msgid_len);
549
 
  search->domainname = domainname;
550
 
  search->category = category;
551
 
# ifdef HAVE_PER_THREAD_LOCALE
552
 
#  ifndef IN_LIBGLOCALE
553
 
#   ifdef _LIBC
554
 
  localename = __current_locale_name (category);
555
 
#   else
556
 
#    if HAVE_NL_LOCALE_NAME
557
 
  /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4.  */
558
 
  localename = nl_langinfo (NL_LOCALE_NAME (category));
559
 
#    else
560
 
#     if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
561
 
  /* The __names field is not public glibc API and must therefore not be used
562
 
     in code that is installed in public locations.  */
563
 
  {
564
 
    locale_t thread_locale = uselocale (NULL);
565
 
    if (thread_locale != LC_GLOBAL_LOCALE)
566
 
      localename = thread_locale->__names[category];
567
 
    else
568
 
      localename = "";
569
 
  }
570
 
#     endif
571
 
#    endif
572
 
#   endif
573
 
#  endif
574
 
  search->localename = localename;
575
 
#  ifdef IN_LIBGLOCALE
576
 
  search->encoding = encoding;
577
 
#  endif
578
 
# endif
579
 
 
580
 
  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
581
 
     tsearch calls can be fatal.  */
582
 
  gl_rwlock_rdlock (tree_lock);
583
 
 
584
 
  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
585
 
 
586
 
  gl_rwlock_unlock (tree_lock);
587
 
 
588
 
  freea (search);
589
 
  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
590
 
    {
591
 
      /* Now deal with plural.  */
592
 
      if (plural)
593
 
        retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
594
 
                                (*foundp)->translation_length);
595
 
      else
596
 
        retval = (char *) (*foundp)->translation;
597
 
 
598
 
      gl_rwlock_unlock (_nl_state_lock);
599
 
      return retval;
600
 
    }
601
 
#endif
602
 
 
603
 
  /* Preserve the `errno' value.  */
604
 
  saved_errno = errno;
605
 
 
606
 
  /* See whether this is a SUID binary or not.  */
607
 
  DETERMINE_SECURE;
608
 
 
609
 
  /* First find matching binding.  */
610
 
#ifdef IN_LIBGLOCALE
611
 
  /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
612
 
     and _nl_load_domain and _nl_find_domain just pass it through.  */
613
 
  binding = NULL;
614
 
  dirname = bindtextdomain (domainname, NULL);
615
 
#else
616
 
  for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
617
 
    {
618
 
      int compare = strcmp (domainname, binding->domainname);
619
 
      if (compare == 0)
620
 
        /* We found it!  */
621
 
        break;
622
 
      if (compare < 0)
623
 
        {
624
 
          /* It is not in the list.  */
625
 
          binding = NULL;
626
 
          break;
627
 
        }
628
 
    }
629
 
 
630
 
  if (binding == NULL)
631
 
    dirname = _nl_default_dirname;
632
 
  else
633
 
    {
634
 
      dirname = binding->dirname;
635
 
#endif
636
 
      if (!IS_ABSOLUTE_PATH (dirname))
637
 
        {
638
 
          /* We have a relative path.  Make it absolute now.  */
639
 
          size_t dirname_len = strlen (dirname) + 1;
640
 
          size_t path_max;
641
 
          char *resolved_dirname;
642
 
          char *ret;
643
 
 
644
 
          path_max = (unsigned int) PATH_MAX;
645
 
          path_max += 2;                /* The getcwd docs say to do this.  */
646
 
 
647
 
          for (;;)
648
 
            {
649
 
              resolved_dirname = (char *) alloca (path_max + dirname_len);
650
 
              ADD_BLOCK (block_list, tmp_dirname);
651
 
 
652
 
              __set_errno (0);
653
 
              ret = getcwd (resolved_dirname, path_max);
654
 
              if (ret != NULL || errno != ERANGE)
655
 
                break;
656
 
 
657
 
              path_max += path_max / 2;
658
 
              path_max += PATH_INCR;
659
 
            }
660
 
 
661
 
          if (ret == NULL)
662
 
            /* We cannot get the current working directory.  Don't signal an
663
 
               error but simply return the default string.  */
664
 
            goto return_untranslated;
665
 
 
666
 
          stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
667
 
          dirname = resolved_dirname;
668
 
        }
669
 
#ifndef IN_LIBGLOCALE
670
 
    }
671
 
#endif
672
 
 
673
 
  /* Now determine the symbolic name of CATEGORY and its value.  */
674
 
  categoryname = category_to_name (category);
675
 
#ifdef IN_LIBGLOCALE
676
 
  categoryvalue = guess_category_value (category, categoryname, localename);
677
 
#else
678
 
  categoryvalue = guess_category_value (category, categoryname);
679
 
#endif
680
 
 
681
 
  domainname_len = strlen (domainname);
682
 
  xdomainname = (char *) alloca (strlen (categoryname)
683
 
                                 + domainname_len + 5);
684
 
  ADD_BLOCK (block_list, xdomainname);
685
 
 
686
 
  stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
687
 
                  domainname, domainname_len),
688
 
          ".mo");
689
 
 
690
 
  /* Creating working area.  */
691
 
  single_locale = (char *) alloca (strlen (categoryvalue) + 1);
692
 
  ADD_BLOCK (block_list, single_locale);
693
 
 
694
 
 
695
 
  /* Search for the given string.  This is a loop because we perhaps
696
 
     got an ordered list of languages to consider for the translation.  */
697
 
  while (1)
698
 
    {
699
 
      /* Make CATEGORYVALUE point to the next element of the list.  */
700
 
      while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
701
 
        ++categoryvalue;
702
 
      if (categoryvalue[0] == '\0')
703
 
        {
704
 
          /* The whole contents of CATEGORYVALUE has been searched but
705
 
             no valid entry has been found.  We solve this situation
706
 
             by implicitly appending a "C" entry, i.e. no translation
707
 
             will take place.  */
708
 
          single_locale[0] = 'C';
709
 
          single_locale[1] = '\0';
710
 
        }
711
 
      else
712
 
        {
713
 
          char *cp = single_locale;
714
 
          while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
715
 
            *cp++ = *categoryvalue++;
716
 
          *cp = '\0';
717
 
 
718
 
          /* When this is a SUID binary we must not allow accessing files
719
 
             outside the dedicated directories.  */
720
 
          if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
721
 
            /* Ingore this entry.  */
722
 
            continue;
723
 
        }
724
 
 
725
 
      /* If the current locale value is C (or POSIX) we don't load a
726
 
         domain.  Return the MSGID.  */
727
 
      if (strcmp (single_locale, "C") == 0
728
 
          || strcmp (single_locale, "POSIX") == 0)
729
 
        break;
730
 
 
731
 
      /* Find structure describing the message catalog matching the
732
 
         DOMAINNAME and CATEGORY.  */
733
 
      domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
734
 
 
735
 
      if (domain != NULL)
736
 
        {
737
 
#if defined IN_LIBGLOCALE
738
 
          retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
739
 
#else
740
 
          retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
741
 
#endif
742
 
 
743
 
          if (retval == NULL)
744
 
            {
745
 
              int cnt;
746
 
 
747
 
              for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
748
 
                {
749
 
#if defined IN_LIBGLOCALE
750
 
                  retval = _nl_find_msg (domain->successor[cnt], binding,
751
 
                                         encoding, msgid1, &retlen);
752
 
#else
753
 
                  retval = _nl_find_msg (domain->successor[cnt], binding,
754
 
                                         msgid1, 1, &retlen);
755
 
#endif
756
 
 
757
 
                  if (retval != NULL)
758
 
                    {
759
 
                      domain = domain->successor[cnt];
760
 
                      break;
761
 
                    }
762
 
                }
763
 
            }
764
 
 
765
 
          /* Returning -1 means that some resource problem exists
766
 
             (likely memory) and that the strings could not be
767
 
             converted.  Return the original strings.  */
768
 
          if (__builtin_expect (retval == (char *) -1, 0))
769
 
            break;
770
 
 
771
 
          if (retval != NULL)
772
 
            {
773
 
              /* Found the translation of MSGID1 in domain DOMAIN:
774
 
                 starting at RETVAL, RETLEN bytes.  */
775
 
              FREE_BLOCKS (block_list);
776
 
#if defined HAVE_TSEARCH || defined _LIBC
777
 
              if (foundp == NULL)
778
 
                {
779
 
                  /* Create a new entry and add it to the search tree.  */
780
 
                  size_t size;
781
 
                  struct known_translation_t *newp;
782
 
 
783
 
                  size = offsetof (struct known_translation_t, msgid)
784
 
                         + msgid_len + domainname_len + 1;
785
 
# ifdef HAVE_PER_THREAD_LOCALE
786
 
                  size += strlen (localename) + 1;
787
 
# endif
788
 
                  newp = (struct known_translation_t *) malloc (size);
789
 
                  if (newp != NULL)
790
 
                    {
791
 
                      char *new_domainname;
792
 
# ifdef HAVE_PER_THREAD_LOCALE
793
 
                      char *new_localename;
794
 
# endif
795
 
 
796
 
                      new_domainname = mempcpy (newp->msgid, msgid1, msgid_len);
797
 
                      memcpy (new_domainname, domainname, domainname_len + 1);
798
 
# ifdef HAVE_PER_THREAD_LOCALE
799
 
                      new_localename = new_domainname + domainname_len + 1;
800
 
                      strcpy (new_localename, localename);
801
 
# endif
802
 
                      newp->domainname = new_domainname;
803
 
                      newp->category = category;
804
 
# ifdef HAVE_PER_THREAD_LOCALE
805
 
                      newp->localename = new_localename;
806
 
# endif
807
 
# ifdef IN_LIBGLOCALE
808
 
                      newp->encoding = encoding;
809
 
# endif
810
 
                      newp->counter = _nl_msg_cat_cntr;
811
 
                      newp->domain = domain;
812
 
                      newp->translation = retval;
813
 
                      newp->translation_length = retlen;
814
 
 
815
 
                      gl_rwlock_wrlock (tree_lock);
816
 
 
817
 
                      /* Insert the entry in the search tree.  */
818
 
                      foundp = (struct known_translation_t **)
819
 
                        tsearch (newp, &root, transcmp);
820
 
 
821
 
                      gl_rwlock_unlock (tree_lock);
822
 
 
823
 
                      if (foundp == NULL
824
 
                          || __builtin_expect (*foundp != newp, 0))
825
 
                        /* The insert failed.  */
826
 
                        free (newp);
827
 
                    }
828
 
                }
829
 
              else
830
 
                {
831
 
                  /* We can update the existing entry.  */
832
 
                  (*foundp)->counter = _nl_msg_cat_cntr;
833
 
                  (*foundp)->domain = domain;
834
 
                  (*foundp)->translation = retval;
835
 
                  (*foundp)->translation_length = retlen;
836
 
                }
837
 
#endif
838
 
              __set_errno (saved_errno);
839
 
 
840
 
              /* Now deal with plural.  */
841
 
              if (plural)
842
 
                retval = plural_lookup (domain, n, retval, retlen);
843
 
 
844
 
              gl_rwlock_unlock (_nl_state_lock);
845
 
              return retval;
846
 
            }
847
 
        }
848
 
    }
849
 
 
850
 
 return_untranslated:
851
 
  /* Return the untranslated MSGID.  */
852
 
  FREE_BLOCKS (block_list);
853
 
  gl_rwlock_unlock (_nl_state_lock);
854
 
#ifndef _LIBC
855
 
  if (!ENABLE_SECURE)
856
 
    {
857
 
      extern void _nl_log_untranslated (const char *logfilename,
858
 
                                        const char *domainname,
859
 
                                        const char *msgid1, const char *msgid2,
860
 
                                        int plural);
861
 
      const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
862
 
 
863
 
      if (logfilename != NULL && logfilename[0] != '\0')
864
 
        _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
865
 
    }
866
 
#endif
867
 
  __set_errno (saved_errno);
868
 
  return (plural == 0
869
 
          ? (char *) msgid1
870
 
          /* Use the Germanic plural rule.  */
871
 
          : n == 1 ? (char *) msgid1 : (char *) msgid2);
872
 
}
873
 
 
874
 
 
875
 
/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
876
 
   Return it if found.  Return NULL if not found or in case of a conversion
877
 
   failure (problem in the particular message catalog).  Return (char *) -1
878
 
   in case of a memory allocation failure during conversion (only if
879
 
   ENCODING != NULL resp. CONVERT == true).  */
880
 
char *
881
 
internal_function
882
 
#ifdef IN_LIBGLOCALE
883
 
_nl_find_msg (struct loaded_l10nfile *domain_file,
884
 
              struct binding *domainbinding, const char *encoding,
885
 
              const char *msgid,
886
 
              size_t *lengthp)
887
 
#else
888
 
_nl_find_msg (struct loaded_l10nfile *domain_file,
889
 
              struct binding *domainbinding,
890
 
              const char *msgid, int convert,
891
 
              size_t *lengthp)
892
 
#endif
893
 
{
894
 
  struct loaded_domain *domain;
895
 
  nls_uint32 nstrings;
896
 
  size_t act;
897
 
  char *result;
898
 
  size_t resultlen;
899
 
 
900
 
  if (domain_file->decided <= 0)
901
 
    _nl_load_domain (domain_file, domainbinding);
902
 
 
903
 
  if (domain_file->data == NULL)
904
 
    return NULL;
905
 
 
906
 
  domain = (struct loaded_domain *) domain_file->data;
907
 
 
908
 
  nstrings = domain->nstrings;
909
 
 
910
 
  /* Locate the MSGID and its translation.  */
911
 
  if (domain->hash_tab != NULL)
912
 
    {
913
 
      /* Use the hashing table.  */
914
 
      nls_uint32 len = strlen (msgid);
915
 
      nls_uint32 hash_val = __hash_string (msgid);
916
 
      nls_uint32 idx = hash_val % domain->hash_size;
917
 
      nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
918
 
 
919
 
      while (1)
920
 
        {
921
 
          nls_uint32 nstr =
922
 
            W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
923
 
 
924
 
          if (nstr == 0)
925
 
            /* Hash table entry is empty.  */
926
 
            return NULL;
927
 
 
928
 
          nstr--;
929
 
 
930
 
          /* Compare msgid with the original string at index nstr.
931
 
             We compare the lengths with >=, not ==, because plural entries
932
 
             are represented by strings with an embedded NUL.  */
933
 
          if (nstr < nstrings
934
 
              ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
935
 
                && (strcmp (msgid,
936
 
                            domain->data + W (domain->must_swap,
937
 
                                              domain->orig_tab[nstr].offset))
938
 
                    == 0)
939
 
              : domain->orig_sysdep_tab[nstr - nstrings].length > len
940
 
                && (strcmp (msgid,
941
 
                            domain->orig_sysdep_tab[nstr - nstrings].pointer)
942
 
                    == 0))
943
 
            {
944
 
              act = nstr;
945
 
              goto found;
946
 
            }
947
 
 
948
 
          if (idx >= domain->hash_size - incr)
949
 
            idx -= domain->hash_size - incr;
950
 
          else
951
 
            idx += incr;
952
 
        }
953
 
      /* NOTREACHED */
954
 
    }
955
 
  else
956
 
    {
957
 
      /* Try the default method:  binary search in the sorted array of
958
 
         messages.  */
959
 
      size_t top, bottom;
960
 
 
961
 
      bottom = 0;
962
 
      top = nstrings;
963
 
      while (bottom < top)
964
 
        {
965
 
          int cmp_val;
966
 
 
967
 
          act = (bottom + top) / 2;
968
 
          cmp_val = strcmp (msgid, (domain->data
969
 
                                    + W (domain->must_swap,
970
 
                                         domain->orig_tab[act].offset)));
971
 
          if (cmp_val < 0)
972
 
            top = act;
973
 
          else if (cmp_val > 0)
974
 
            bottom = act + 1;
975
 
          else
976
 
            goto found;
977
 
        }
978
 
      /* No translation was found.  */
979
 
      return NULL;
980
 
    }
981
 
 
982
 
 found:
983
 
  /* The translation was found at index ACT.  If we have to convert the
984
 
     string to use a different character set, this is the time.  */
985
 
  if (act < nstrings)
986
 
    {
987
 
      result = (char *)
988
 
        (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
989
 
      resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
990
 
    }
991
 
  else
992
 
    {
993
 
      result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
994
 
      resultlen = domain->trans_sysdep_tab[act - nstrings].length;
995
 
    }
996
 
 
997
 
#if defined _LIBC || HAVE_ICONV
998
 
# ifdef IN_LIBGLOCALE
999
 
  if (encoding != NULL)
1000
 
# else
1001
 
  if (convert)
1002
 
# endif
1003
 
    {
1004
 
      /* We are supposed to do a conversion.  */
1005
 
# ifndef IN_LIBGLOCALE
1006
 
      const char *encoding = get_output_charset (domainbinding);
1007
 
# endif
1008
 
 
1009
 
      /* Search whether a table with converted translations for this
1010
 
         encoding has already been allocated.  */
1011
 
      size_t nconversions = domain->nconversions;
1012
 
      struct converted_domain *convd = NULL;
1013
 
      size_t i;
1014
 
 
1015
 
      for (i = nconversions; i > 0; )
1016
 
        {
1017
 
          i--;
1018
 
          if (strcmp (domain->conversions[i].encoding, encoding) == 0)
1019
 
            {
1020
 
              convd = &domain->conversions[i];
1021
 
              break;
1022
 
            }
1023
 
        }
1024
 
 
1025
 
      if (convd == NULL)
1026
 
        {
1027
 
          /* Allocate a table for the converted translations for this
1028
 
             encoding.  */
1029
 
          struct converted_domain *new_conversions =
1030
 
            (struct converted_domain *)
1031
 
            (domain->conversions != NULL
1032
 
             ? realloc (domain->conversions,
1033
 
                        (nconversions + 1) * sizeof (struct converted_domain))
1034
 
             : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
1035
 
 
1036
 
          if (__builtin_expect (new_conversions == NULL, 0))
1037
 
            /* Nothing we can do, no more memory.  We cannot use the
1038
 
               translation because it might be encoded incorrectly.  */
1039
 
            return (char *) -1;
1040
 
 
1041
 
          domain->conversions = new_conversions;
1042
 
 
1043
 
          /* Copy the 'encoding' string to permanent storage.  */
1044
 
          encoding = strdup (encoding);
1045
 
          if (__builtin_expect (encoding == NULL, 0))
1046
 
            /* Nothing we can do, no more memory.  We cannot use the
1047
 
               translation because it might be encoded incorrectly.  */
1048
 
            return (char *) -1;
1049
 
 
1050
 
          convd = &new_conversions[nconversions];
1051
 
          convd->encoding = encoding;
1052
 
 
1053
 
          /* Find out about the character set the file is encoded with.
1054
 
             This can be found (in textual form) in the entry "".  If this
1055
 
             entry does not exist or if this does not contain the 'charset='
1056
 
             information, we will assume the charset matches the one the
1057
 
             current locale and we don't have to perform any conversion.  */
1058
 
# ifdef _LIBC
1059
 
          convd->conv = (__gconv_t) -1;
1060
 
# else
1061
 
#  if HAVE_ICONV
1062
 
          convd->conv = (iconv_t) -1;
1063
 
#  endif
1064
 
# endif
1065
 
          {
1066
 
            char *nullentry;
1067
 
            size_t nullentrylen;
1068
 
 
1069
 
            /* Get the header entry.  This is a recursion, but it doesn't
1070
 
               reallocate domain->conversions because we pass
1071
 
               encoding = NULL or convert = 0, respectively.  */
1072
 
            nullentry =
1073
 
# ifdef IN_LIBGLOCALE
1074
 
              _nl_find_msg (domain_file, domainbinding, NULL, "",
1075
 
                            &nullentrylen);
1076
 
# else
1077
 
              _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1078
 
# endif
1079
 
 
1080
 
            if (nullentry != NULL)
1081
 
              {
1082
 
                const char *charsetstr;
1083
 
 
1084
 
                charsetstr = strstr (nullentry, "charset=");
1085
 
                if (charsetstr != NULL)
1086
 
                  {
1087
 
                    size_t len;
1088
 
                    char *charset;
1089
 
                    const char *outcharset;
1090
 
 
1091
 
                    charsetstr += strlen ("charset=");
1092
 
                    len = strcspn (charsetstr, " \t\n");
1093
 
 
1094
 
                    charset = (char *) alloca (len + 1);
1095
 
# if defined _LIBC || HAVE_MEMPCPY
1096
 
                    *((char *) mempcpy (charset, charsetstr, len)) = '\0';
1097
 
# else
1098
 
                    memcpy (charset, charsetstr, len);
1099
 
                    charset[len] = '\0';
1100
 
# endif
1101
 
 
1102
 
                    outcharset = encoding;
1103
 
 
1104
 
# ifdef _LIBC
1105
 
                    /* We always want to use transliteration.  */
1106
 
                    outcharset = norm_add_slashes (outcharset, "TRANSLIT");
1107
 
                    charset = norm_add_slashes (charset, "");
1108
 
                    int r = __gconv_open (outcharset, charset, &convd->conv,
1109
 
                                          GCONV_AVOID_NOCONV);
1110
 
                    if (__builtin_expect (r != __GCONV_OK, 0))
1111
 
                      {
1112
 
                        /* If the output encoding is the same there is
1113
 
                           nothing to do.  Otherwise do not use the
1114
 
                           translation at all.  */
1115
 
                        if (__builtin_expect (r != __GCONV_NOCONV, 1))
1116
 
                          return NULL;
1117
 
 
1118
 
                        convd->conv = (__gconv_t) -1;
1119
 
                      }
1120
 
# else
1121
 
#  if HAVE_ICONV
1122
 
                    /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
1123
 
                       we want to use transliteration.  */
1124
 
#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
1125
 
       || _LIBICONV_VERSION >= 0x0105
1126
 
                    if (strchr (outcharset, '/') == NULL)
1127
 
                      {
1128
 
                        char *tmp;
1129
 
 
1130
 
                        len = strlen (outcharset);
1131
 
                        tmp = (char *) alloca (len + 10 + 1);
1132
 
                        memcpy (tmp, outcharset, len);
1133
 
                        memcpy (tmp + len, "//TRANSLIT", 10 + 1);
1134
 
                        outcharset = tmp;
1135
 
 
1136
 
                        convd->conv = iconv_open (outcharset, charset);
1137
 
 
1138
 
                        freea (outcharset);
1139
 
                      }
1140
 
                    else
1141
 
#   endif
1142
 
                      convd->conv = iconv_open (outcharset, charset);
1143
 
#  endif
1144
 
# endif
1145
 
 
1146
 
                    freea (charset);
1147
 
                  }
1148
 
              }
1149
 
          }
1150
 
          convd->conv_tab = NULL;
1151
 
          /* Here domain->conversions is still == new_conversions.  */
1152
 
          domain->nconversions++;
1153
 
        }
1154
 
 
1155
 
      if (
1156
 
# ifdef _LIBC
1157
 
          convd->conv != (__gconv_t) -1
1158
 
# else
1159
 
#  if HAVE_ICONV
1160
 
          convd->conv != (iconv_t) -1
1161
 
#  endif
1162
 
# endif
1163
 
          )
1164
 
        {
1165
 
          /* We are supposed to do a conversion.  First allocate an
1166
 
             appropriate table with the same structure as the table
1167
 
             of translations in the file, where we can put the pointers
1168
 
             to the converted strings in.
1169
 
             There is a slight complication with plural entries.  They
1170
 
             are represented by consecutive NUL terminated strings.  We
1171
 
             handle this case by converting RESULTLEN bytes, including
1172
 
             NULs.  */
1173
 
 
1174
 
          if (convd->conv_tab == NULL
1175
 
              && ((convd->conv_tab =
1176
 
                    (char **) calloc (nstrings + domain->n_sysdep_strings,
1177
 
                                      sizeof (char *)))
1178
 
                  == NULL))
1179
 
            /* Mark that we didn't succeed allocating a table.  */
1180
 
            convd->conv_tab = (char **) -1;
1181
 
 
1182
 
          if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
1183
 
            /* Nothing we can do, no more memory.  We cannot use the
1184
 
               translation because it might be encoded incorrectly.  */
1185
 
            return (char *) -1;
1186
 
 
1187
 
          if (convd->conv_tab[act] == NULL)
1188
 
            {
1189
 
              /* We haven't used this string so far, so it is not
1190
 
                 translated yet.  Do this now.  */
1191
 
              /* We use a bit more efficient memory handling.
1192
 
                 We allocate always larger blocks which get used over
1193
 
                 time.  This is faster than many small allocations.   */
1194
 
              __libc_lock_define_initialized (static, lock)
1195
 
# define INITIAL_BLOCK_SIZE     4080
1196
 
              static unsigned char *freemem;
1197
 
              static size_t freemem_size;
1198
 
 
1199
 
              const unsigned char *inbuf;
1200
 
              unsigned char *outbuf;
1201
 
              int malloc_count;
1202
 
# ifndef _LIBC
1203
 
              transmem_block_t *transmem_list = NULL;
1204
 
# endif
1205
 
 
1206
 
              __libc_lock_lock (lock);
1207
 
 
1208
 
              inbuf = (const unsigned char *) result;
1209
 
              outbuf = freemem + sizeof (size_t);
1210
 
 
1211
 
              malloc_count = 0;
1212
 
              while (1)
1213
 
                {
1214
 
                  transmem_block_t *newmem;
1215
 
# ifdef _LIBC
1216
 
                  size_t non_reversible;
1217
 
                  int res;
1218
 
 
1219
 
                  if (freemem_size < sizeof (size_t))
1220
 
                    goto resize_freemem;
1221
 
 
1222
 
                  res = __gconv (convd->conv,
1223
 
                                 &inbuf, inbuf + resultlen,
1224
 
                                 &outbuf,
1225
 
                                 outbuf + freemem_size - sizeof (size_t),
1226
 
                                 &non_reversible);
1227
 
 
1228
 
                  if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1229
 
                    break;
1230
 
 
1231
 
                  if (res != __GCONV_FULL_OUTPUT)
1232
 
                    {
1233
 
                      /* We should not use the translation at all, it
1234
 
                         is incorrectly encoded.  */
1235
 
                      __libc_lock_unlock (lock);
1236
 
                      return NULL;
1237
 
                    }
1238
 
 
1239
 
                  inbuf = (const unsigned char *) result;
1240
 
# else
1241
 
#  if HAVE_ICONV
1242
 
                  const char *inptr = (const char *) inbuf;
1243
 
                  size_t inleft = resultlen;
1244
 
                  char *outptr = (char *) outbuf;
1245
 
                  size_t outleft;
1246
 
 
1247
 
                  if (freemem_size < sizeof (size_t))
1248
 
                    goto resize_freemem;
1249
 
 
1250
 
                  outleft = freemem_size - sizeof (size_t);
1251
 
                  if (iconv (convd->conv,
1252
 
                             (ICONV_CONST char **) &inptr, &inleft,
1253
 
                             &outptr, &outleft)
1254
 
                      != (size_t) (-1))
1255
 
                    {
1256
 
                      outbuf = (unsigned char *) outptr;
1257
 
                      break;
1258
 
                    }
1259
 
                  if (errno != E2BIG)
1260
 
                    {
1261
 
                      __libc_lock_unlock (lock);
1262
 
                      return NULL;
1263
 
                    }
1264
 
#  endif
1265
 
# endif
1266
 
 
1267
 
                resize_freemem:
1268
 
                  /* We must allocate a new buffer or resize the old one.  */
1269
 
                  if (malloc_count > 0)
1270
 
                    {
1271
 
                      ++malloc_count;
1272
 
                      freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1273
 
                      newmem = (transmem_block_t *) realloc (transmem_list,
1274
 
                                                             freemem_size);
1275
 
# ifdef _LIBC
1276
 
                      if (newmem != NULL)
1277
 
                        transmem_list = transmem_list->next;
1278
 
                      else
1279
 
                        {
1280
 
                          struct transmem_list *old = transmem_list;
1281
 
 
1282
 
                          transmem_list = transmem_list->next;
1283
 
                          free (old);
1284
 
                        }
1285
 
# endif
1286
 
                    }
1287
 
                  else
1288
 
                    {
1289
 
                      malloc_count = 1;
1290
 
                      freemem_size = INITIAL_BLOCK_SIZE;
1291
 
                      newmem = (transmem_block_t *) malloc (freemem_size);
1292
 
                    }
1293
 
                  if (__builtin_expect (newmem == NULL, 0))
1294
 
                    {
1295
 
                      freemem = NULL;
1296
 
                      freemem_size = 0;
1297
 
                      __libc_lock_unlock (lock);
1298
 
                      return (char *) -1;
1299
 
                    }
1300
 
 
1301
 
# ifdef _LIBC
1302
 
                  /* Add the block to the list of blocks we have to free
1303
 
                     at some point.  */
1304
 
                  newmem->next = transmem_list;
1305
 
                  transmem_list = newmem;
1306
 
 
1307
 
                  freemem = (unsigned char *) newmem->data;
1308
 
                  freemem_size -= offsetof (struct transmem_list, data);
1309
 
# else
1310
 
                  transmem_list = newmem;
1311
 
                  freemem = newmem;
1312
 
# endif
1313
 
 
1314
 
                  outbuf = freemem + sizeof (size_t);
1315
 
                }
1316
 
 
1317
 
              /* We have now in our buffer a converted string.  Put this
1318
 
                 into the table of conversions.  */
1319
 
              *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1320
 
              convd->conv_tab[act] = (char *) freemem;
1321
 
              /* Shrink freemem, but keep it aligned.  */
1322
 
              freemem_size -= outbuf - freemem;
1323
 
              freemem = outbuf;
1324
 
              freemem += freemem_size & (alignof (size_t) - 1);
1325
 
              freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1326
 
 
1327
 
              __libc_lock_unlock (lock);
1328
 
            }
1329
 
 
1330
 
          /* Now convd->conv_tab[act] contains the translation of all
1331
 
             the plural variants.  */
1332
 
          result = convd->conv_tab[act] + sizeof (size_t);
1333
 
          resultlen = *(size_t *) convd->conv_tab[act];
1334
 
        }
1335
 
    }
1336
 
 
1337
 
  /* The result string is converted.  */
1338
 
 
1339
 
#endif /* _LIBC || HAVE_ICONV */
1340
 
 
1341
 
  *lengthp = resultlen;
1342
 
  return result;
1343
 
}
1344
 
 
1345
 
 
1346
 
/* Look up a plural variant.  */
1347
 
static char *
1348
 
internal_function
1349
 
plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
1350
 
               const char *translation, size_t translation_len)
1351
 
{
1352
 
  struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1353
 
  unsigned long int index;
1354
 
  const char *p;
1355
 
 
1356
 
  index = plural_eval (domaindata->plural, n);
1357
 
  if (index >= domaindata->nplurals)
1358
 
    /* This should never happen.  It means the plural expression and the
1359
 
       given maximum value do not match.  */
1360
 
    index = 0;
1361
 
 
1362
 
  /* Skip INDEX strings at TRANSLATION.  */
1363
 
  p = translation;
1364
 
  while (index-- > 0)
1365
 
    {
1366
 
#ifdef _LIBC
1367
 
      p = __rawmemchr (p, '\0');
1368
 
#else
1369
 
      p = strchr (p, '\0');
1370
 
#endif
1371
 
      /* And skip over the NUL byte.  */
1372
 
      p++;
1373
 
 
1374
 
      if (p >= translation + translation_len)
1375
 
        /* This should never happen.  It means the plural expression
1376
 
           evaluated to a value larger than the number of variants
1377
 
           available for MSGID1.  */
1378
 
        return (char *) translation;
1379
 
    }
1380
 
  return (char *) p;
1381
 
}
1382
 
 
1383
 
#ifndef _LIBC
1384
 
/* Return string representation of locale CATEGORY.  */
1385
 
static const char *
1386
 
internal_function
1387
 
category_to_name (int category)
1388
 
{
1389
 
  const char *retval;
1390
 
 
1391
 
  switch (category)
1392
 
  {
1393
 
#ifdef LC_COLLATE
1394
 
  case LC_COLLATE:
1395
 
    retval = "LC_COLLATE";
1396
 
    break;
1397
 
#endif
1398
 
#ifdef LC_CTYPE
1399
 
  case LC_CTYPE:
1400
 
    retval = "LC_CTYPE";
1401
 
    break;
1402
 
#endif
1403
 
#ifdef LC_MONETARY
1404
 
  case LC_MONETARY:
1405
 
    retval = "LC_MONETARY";
1406
 
    break;
1407
 
#endif
1408
 
#ifdef LC_NUMERIC
1409
 
  case LC_NUMERIC:
1410
 
    retval = "LC_NUMERIC";
1411
 
    break;
1412
 
#endif
1413
 
#ifdef LC_TIME
1414
 
  case LC_TIME:
1415
 
    retval = "LC_TIME";
1416
 
    break;
1417
 
#endif
1418
 
#ifdef LC_MESSAGES
1419
 
  case LC_MESSAGES:
1420
 
    retval = "LC_MESSAGES";
1421
 
    break;
1422
 
#endif
1423
 
#ifdef LC_RESPONSE
1424
 
  case LC_RESPONSE:
1425
 
    retval = "LC_RESPONSE";
1426
 
    break;
1427
 
#endif
1428
 
#ifdef LC_ALL
1429
 
  case LC_ALL:
1430
 
    /* This might not make sense but is perhaps better than any other
1431
 
       value.  */
1432
 
    retval = "LC_ALL";
1433
 
    break;
1434
 
#endif
1435
 
  default:
1436
 
    /* If you have a better idea for a default value let me know.  */
1437
 
    retval = "LC_XXX";
1438
 
  }
1439
 
 
1440
 
  return retval;
1441
 
}
1442
 
#endif
1443
 
 
1444
 
/* Guess value of current locale from value of the environment variables
1445
 
   or system-dependent defaults.  */
1446
 
static const char *
1447
 
internal_function
1448
 
#ifdef IN_LIBGLOCALE
1449
 
guess_category_value (int category, const char *categoryname,
1450
 
                      const char *locale)
1451
 
 
1452
 
#else
1453
 
guess_category_value (int category, const char *categoryname)
1454
 
#endif
1455
 
{
1456
 
  const char *language;
1457
 
#ifndef IN_LIBGLOCALE
1458
 
  const char *locale;
1459
 
# ifndef _LIBC
1460
 
  const char *language_default;
1461
 
  int locale_defaulted;
1462
 
# endif
1463
 
#endif
1464
 
 
1465
 
  /* We use the settings in the following order:
1466
 
     1. The value of the environment variable 'LANGUAGE'.  This is a GNU
1467
 
        extension.  Its value can be a colon-separated list of locale names.
1468
 
     2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
1469
 
        More precisely, the first among these that is set to a non-empty value.
1470
 
        This is how POSIX specifies it.  The value is a single locale name.
1471
 
     3. A system-dependent preference list of languages.  Its value can be a
1472
 
        colon-separated list of locale names.
1473
 
     4. A system-dependent default locale name.
1474
 
     This way:
1475
 
       - System-dependent settings can be overridden by environment variables.
1476
 
       - If the system provides both a list of languages and a default locale,
1477
 
         the former is used.  */
1478
 
 
1479
 
#ifndef IN_LIBGLOCALE
1480
 
  /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
1481
 
     `LC_xxx', and `LANG'.  On some systems this can be done by the
1482
 
     `setlocale' function itself.  */
1483
 
# ifdef _LIBC
1484
 
  locale = __current_locale_name (category);
1485
 
# else
1486
 
#  if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
1487
 
  /* The __names field is not public glibc API and must therefore not be used
1488
 
     in code that is installed in public locations.  */
1489
 
  locale_t thread_locale = uselocale (NULL);
1490
 
  if (thread_locale != LC_GLOBAL_LOCALE)
1491
 
    {
1492
 
      locale = thread_locale->__names[category];
1493
 
      locale_defaulted = 0;
1494
 
    }
1495
 
  else
1496
 
#  endif
1497
 
    {
1498
 
      locale = _nl_locale_name_posix (category, categoryname);
1499
 
      locale_defaulted = 0;
1500
 
      if (locale == NULL)
1501
 
        {
1502
 
          locale = _nl_locale_name_default ();
1503
 
          locale_defaulted = 1;
1504
 
        }
1505
 
    }
1506
 
# endif
1507
 
#endif
1508
 
 
1509
 
  /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
1510
 
     to "C" because
1511
 
     1. "C" locale usually uses the ASCII encoding, and most international
1512
 
        messages use non-ASCII characters. These characters get displayed
1513
 
        as question marks (if using glibc's iconv()) or as invalid 8-bit
1514
 
        characters (because other iconv()s refuse to convert most non-ASCII
1515
 
        characters to ASCII). In any case, the output is ugly.
1516
 
     2. The precise output of some programs in the "C" locale is specified
1517
 
        by POSIX and should not depend on environment variables like
1518
 
        "LANGUAGE" or system-dependent information.  We allow such programs
1519
 
        to use gettext().  */
1520
 
  if (strcmp (locale, "C") == 0)
1521
 
    return locale;
1522
 
 
1523
 
  /* The highest priority value is the value of the 'LANGUAGE' environment
1524
 
     variable.  */
1525
 
  language = getenv ("LANGUAGE");
1526
 
  if (language != NULL && language[0] != '\0')
1527
 
    return language;
1528
 
#if !defined IN_LIBGLOCALE && !defined _LIBC
1529
 
  /* The next priority value is the locale name, if not defaulted.  */
1530
 
  if (locale_defaulted)
1531
 
    {
1532
 
      /* The next priority value is the default language preferences list. */
1533
 
      language_default = _nl_language_preferences_default ();
1534
 
      if (language_default != NULL)
1535
 
        return language_default;
1536
 
    }
1537
 
  /* The least priority value is the locale name, if defaulted.  */
1538
 
#endif
1539
 
  return locale;
1540
 
}
1541
 
 
1542
 
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
1543
 
/* Returns the output charset.  */
1544
 
static const char *
1545
 
internal_function
1546
 
get_output_charset (struct binding *domainbinding)
1547
 
{
1548
 
  /* The output charset should normally be determined by the locale.  But
1549
 
     sometimes the locale is not used or not correctly set up, so we provide
1550
 
     a possibility for the user to override this: the OUTPUT_CHARSET
1551
 
     environment variable.  Moreover, the value specified through
1552
 
     bind_textdomain_codeset overrides both.  */
1553
 
  if (domainbinding != NULL && domainbinding->codeset != NULL)
1554
 
    return domainbinding->codeset;
1555
 
  else
1556
 
    {
1557
 
      /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1558
 
         once.  This is a user variable that is not supposed to change
1559
 
         during a program run.  */
1560
 
      static char *output_charset_cache;
1561
 
      static int output_charset_cached;
1562
 
 
1563
 
      if (!output_charset_cached)
1564
 
        {
1565
 
          const char *value = getenv ("OUTPUT_CHARSET");
1566
 
 
1567
 
          if (value != NULL && value[0] != '\0')
1568
 
            {
1569
 
              size_t len = strlen (value) + 1;
1570
 
              char *value_copy = (char *) malloc (len);
1571
 
 
1572
 
              if (value_copy != NULL)
1573
 
                memcpy (value_copy, value, len);
1574
 
              output_charset_cache = value_copy;
1575
 
            }
1576
 
          output_charset_cached = 1;
1577
 
        }
1578
 
 
1579
 
      if (output_charset_cache != NULL)
1580
 
        return output_charset_cache;
1581
 
      else
1582
 
        {
1583
 
# ifdef _LIBC
1584
 
          return _NL_CURRENT (LC_CTYPE, CODESET);
1585
 
# else
1586
 
#  if HAVE_ICONV
1587
 
          extern const char *locale_charset (void);
1588
 
          return locale_charset ();
1589
 
#  endif
1590
 
# endif
1591
 
        }
1592
 
    }
1593
 
}
1594
 
#endif
1595
 
 
1596
 
/* @@ begin of epilog @@ */
1597
 
 
1598
 
/* We don't want libintl.a to depend on any other library.  So we
1599
 
   avoid the non-standard function stpcpy.  In GNU C Library this
1600
 
   function is available, though.  Also allow the symbol HAVE_STPCPY
1601
 
   to be defined.  */
1602
 
#if !_LIBC && !HAVE_STPCPY
1603
 
static char *
1604
 
stpcpy (char *dest, const char *src)
1605
 
{
1606
 
  while ((*dest++ = *src++) != '\0')
1607
 
    /* Do nothing. */ ;
1608
 
  return dest - 1;
1609
 
}
1610
 
#endif
1611
 
 
1612
 
#if !_LIBC && !HAVE_MEMPCPY
1613
 
static void *
1614
 
mempcpy (void *dest, const void *src, size_t n)
1615
 
{
1616
 
  return (void *) ((char *) memcpy (dest, src, n) + n);
1617
 
}
1618
 
#endif
1619
 
 
1620
 
 
1621
 
#ifdef _LIBC
1622
 
/* If we want to free all resources we have to do some work at
1623
 
   program's end.  */
1624
 
libc_freeres_fn (free_mem)
1625
 
{
1626
 
  void *old;
1627
 
 
1628
 
  while (_nl_domain_bindings != NULL)
1629
 
    {
1630
 
      struct binding *oldp = _nl_domain_bindings;
1631
 
      _nl_domain_bindings = _nl_domain_bindings->next;
1632
 
      if (oldp->dirname != _nl_default_dirname)
1633
 
        /* Yes, this is a pointer comparison.  */
1634
 
        free (oldp->dirname);
1635
 
      free (oldp->codeset);
1636
 
      free (oldp);
1637
 
    }
1638
 
 
1639
 
  if (_nl_current_default_domain != _nl_default_default_domain)
1640
 
    /* Yes, again a pointer comparison.  */
1641
 
    free ((char *) _nl_current_default_domain);
1642
 
 
1643
 
  /* Remove the search tree with the known translations.  */
1644
 
  __tdestroy (root, free);
1645
 
  root = NULL;
1646
 
 
1647
 
  while (transmem_list != NULL)
1648
 
    {
1649
 
      old = transmem_list;
1650
 
      transmem_list = transmem_list->next;
1651
 
      free (old);
1652
 
    }
1653
 
}
1654
 
#endif