~ubuntu-branches/ubuntu/maverick/texinfo/maverick

« back to all changes in this revision

Viewing changes to intl/dcigettext.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2005-10-28 15:10:30 UTC
  • mto: (2.1.1 dapper) (3.1.4 hardy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051028151030-9nsf2s2k2z3fktjt
Tags: upstream-4.8
ImportĀ upstreamĀ versionĀ 4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Implementation of the internal dcigettext function.
2
 
   Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc.
 
2
   Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
3
3
 
4
4
   This program is free software; you can redistribute it and/or modify it
5
5
   under the terms of the GNU Library General Public License as published
33
33
# define alloca __builtin_alloca
34
34
# define HAVE_ALLOCA 1
35
35
#else
36
 
# if defined HAVE_ALLOCA_H || defined _LIBC
37
 
#  include <alloca.h>
 
36
# ifdef _MSC_VER
 
37
#  include <malloc.h>
 
38
#  define alloca _alloca
38
39
# else
39
 
#  ifdef _AIX
 
40
#  if defined HAVE_ALLOCA_H || defined _LIBC
 
41
#   include <alloca.h>
 
42
#  else
 
43
#   ifdef _AIX
40
44
 #pragma alloca
41
 
#  else
42
 
#   ifndef alloca
 
45
#   else
 
46
#    ifndef alloca
43
47
char *alloca ();
 
48
#    endif
44
49
#   endif
45
50
#  endif
46
51
# endif
64
69
 
65
70
#include <locale.h>
66
71
 
 
72
#ifdef _LIBC
 
73
  /* Guess whether integer division by zero raises signal SIGFPE.
 
74
     Set to 1 only if you know for sure.  In case of doubt, set to 0.  */
 
75
# if defined __alpha__ || defined __arm__ || defined __i386__ \
 
76
     || defined __m68k__ || defined __s390__
 
77
#  define INTDIV0_RAISES_SIGFPE 1
 
78
# else
 
79
#  define INTDIV0_RAISES_SIGFPE 0
 
80
# endif
 
81
#endif
 
82
#if !INTDIV0_RAISES_SIGFPE
 
83
# include <signal.h>
 
84
#endif
 
85
 
67
86
#if defined HAVE_SYS_PARAM_H || defined _LIBC
68
87
# include <sys/param.h>
69
88
#endif
102
121
   names than the internal variables in GNU libc, otherwise programs
103
122
   using libintl.a cannot be linked statically.  */
104
123
#if !defined _LIBC
105
 
# define _nl_default_default_domain _nl_default_default_domain__
106
 
# define _nl_current_default_domain _nl_current_default_domain__
107
 
# define _nl_default_dirname _nl_default_dirname__
108
 
# define _nl_domain_bindings _nl_domain_bindings__
 
124
# define _nl_default_default_domain libintl_nl_default_default_domain
 
125
# define _nl_current_default_domain libintl_nl_current_default_domain
 
126
# define _nl_default_dirname libintl_nl_default_dirname
 
127
# define _nl_domain_bindings libintl_nl_domain_bindings
109
128
#endif
110
129
 
111
130
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
129
148
char *getwd ();
130
149
#  define getcwd(buf, max) getwd (buf)
131
150
# else
 
151
#  if VMS
 
152
#   define getcwd(buf, max) (getcwd) (buf, max, 0)
 
153
#  else
132
154
char *getcwd ();
 
155
#  endif
133
156
# endif
134
157
# ifndef HAVE_STPCPY
135
 
static char *stpcpy PARAMS ((char *dest, const char *src));
 
158
static char *stpcpy (char *dest, const char *src);
136
159
# endif
137
160
# ifndef HAVE_MEMPCPY
138
 
static void *mempcpy PARAMS ((void *dest, const void *src, size_t n));
 
161
static void *mempcpy (void *dest, const void *src, size_t n);
139
162
# endif
140
163
#endif
141
164
 
229
252
# endif
230
253
 
231
254
/* Function to compare two entries in the table of known translations.  */
232
 
static int transcmp PARAMS ((const void *p1, const void *p2));
233
255
static int
234
 
transcmp (p1, p2)
235
 
     const void *p1;
236
 
     const void *p2;
 
256
transcmp (const void *p1, const void *p2)
237
257
{
238
258
  const struct known_translation_t *s1;
239
259
  const struct known_translation_t *s2;
257
277
}
258
278
#endif
259
279
 
 
280
#ifndef INTVARDEF
 
281
# define INTVARDEF(name)
 
282
#endif
 
283
#ifndef INTUSE
 
284
# define INTUSE(name) name
 
285
#endif
 
286
 
260
287
/* Name of the default domain used for gettext(3) prior any call to
261
288
   textdomain(3).  The default value for this is "messages".  */
262
 
const char _nl_default_default_domain[] = "messages";
 
289
const char _nl_default_default_domain[] attribute_hidden = "messages";
263
290
 
264
291
/* Value used as the default domain for gettext(3).  */
265
 
const char *_nl_current_default_domain = _nl_default_default_domain;
 
292
const char *_nl_current_default_domain attribute_hidden
 
293
     = _nl_default_default_domain;
266
294
 
267
295
/* Contains the default location of the message catalogs.  */
268
296
#if defined __EMX__
269
297
extern const char _nl_default_dirname[];
270
298
#else
271
299
const char _nl_default_dirname[] = LOCALEDIR;
 
300
INTVARDEF (_nl_default_dirname)
272
301
#endif
273
302
 
274
303
/* List with bindings of specific domains created by bindtextdomain()
276
305
struct binding *_nl_domain_bindings;
277
306
 
278
307
/* Prototypes for local functions.  */
279
 
static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain,
280
 
                                    unsigned long int n,
281
 
                                    const char *translation,
282
 
                                    size_t translation_len))
283
 
     internal_function;
284
 
static const char *category_to_name PARAMS ((int category)) internal_function;
285
 
static const char *guess_category_value PARAMS ((int category,
286
 
                                                 const char *categoryname))
287
 
     internal_function;
 
308
static char *plural_lookup (struct loaded_l10nfile *domain,
 
309
                            unsigned long int n,
 
310
                            const char *translation, size_t translation_len)
 
311
     internal_function;
 
312
static const char *guess_category_value (int category,
 
313
                                         const char *categoryname)
 
314
     internal_function;
 
315
#ifdef _LIBC
 
316
# include "../locale/localeinfo.h"
 
317
# define category_to_name(category)     _nl_category_names[category]
 
318
#else
 
319
static const char *category_to_name (int category) internal_function;
 
320
#endif
288
321
 
289
322
 
290
323
/* For those loosing systems which don't have `alloca' we have to add
291
324
   some additional code emulating it.  */
292
325
#ifdef HAVE_ALLOCA
293
326
/* Nothing has to be done.  */
 
327
# define freea(p) /* nothing */
294
328
# define ADD_BLOCK(list, address) /* nothing */
295
329
# define FREE_BLOCKS(list) /* nothing */
296
330
#else
315
349
    while (list != NULL) {                                                    \
316
350
      struct block_list *old = list;                                          \
317
351
      list = list->next;                                                      \
 
352
      free (old->address);                                                    \
318
353
      free (old);                                                             \
319
354
    }                                                                         \
320
355
  } while (0)
321
356
# undef alloca
322
357
# define alloca(size) (malloc (size))
 
358
# define freea(p) free (p)
323
359
#endif  /* have alloca */
324
360
 
325
361
 
343
379
#ifdef _LIBC
344
380
# define DCIGETTEXT __dcigettext
345
381
#else
346
 
# define DCIGETTEXT dcigettext__
 
382
# define DCIGETTEXT libintl_dcigettext
347
383
#endif
348
384
 
349
385
/* Lock variable to protect the global data in the gettext implementation.  */
350
386
#ifdef _LIBC
351
 
__libc_rwlock_define_initialized (, _nl_state_lock)
 
387
__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
352
388
#endif
353
389
 
354
390
/* Checking whether the binaries runs SUID must be done and glibc provides
388
424
   CATEGORY locale and, if PLURAL is nonzero, search over string
389
425
   depending on the plural form determined by N.  */
390
426
char *
391
 
DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
392
 
     const char *domainname;
393
 
     const char *msgid1;
394
 
     const char *msgid2;
395
 
     int plural;
396
 
     unsigned long int n;
397
 
     int category;
 
427
DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
 
428
            int plural, unsigned long int n, int category)
398
429
{
399
430
#ifndef HAVE_ALLOCA
400
431
  struct block_list *block_list = NULL;
419
450
  if (msgid1 == NULL)
420
451
    return NULL;
421
452
 
 
453
#ifdef _LIBC
 
454
  if (category < 0 || category >= __LC_LAST || category == LC_ALL)
 
455
    /* Bogus.  */
 
456
    return (plural == 0
 
457
            ? (char *) msgid1
 
458
            /* Use the Germanic plural rule.  */
 
459
            : n == 1 ? (char *) msgid1 : (char *) msgid2);
 
460
#endif
 
461
 
422
462
  __libc_rwlock_rdlock (_nl_state_lock);
423
463
 
424
464
  /* If DOMAINNAME is NULL, we are interested in the default domain.  If
445
485
  search->category = category;
446
486
 
447
487
  foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
 
488
  freea (search);
448
489
  if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
449
490
    {
450
491
      /* Now deal with plural.  */
481
522
    }
482
523
 
483
524
  if (binding == NULL)
484
 
    dirname = (char *) _nl_default_dirname;
 
525
    dirname = (char *) INTUSE(_nl_default_dirname);
485
526
  else if (IS_ABSOLUTE_PATH (binding->dirname))
486
527
    dirname = binding->dirname;
487
528
  else
509
550
        }
510
551
 
511
552
      if (ret == NULL)
512
 
        {
513
 
          /* We cannot get the current working directory.  Don't signal an
514
 
             error but simply return the default string.  */
515
 
          FREE_BLOCKS (block_list);
516
 
          __libc_rwlock_unlock (_nl_state_lock);
517
 
          __set_errno (saved_errno);
518
 
          return (plural == 0
519
 
                  ? (char *) msgid1
520
 
                  /* Use the Germanic plural rule.  */
521
 
                  : n == 1 ? (char *) msgid1 : (char *) msgid2);
522
 
        }
 
553
        /* We cannot get the current working directory.  Don't signal an
 
554
           error but simply return the default string.  */
 
555
        goto return_untranslated;
523
556
 
524
557
      stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname);
525
558
    }
576
609
         domain.  Return the MSGID.  */
577
610
      if (strcmp (single_locale, "C") == 0
578
611
          || strcmp (single_locale, "POSIX") == 0)
579
 
        {
580
 
          FREE_BLOCKS (block_list);
581
 
          __libc_rwlock_unlock (_nl_state_lock);
582
 
          __set_errno (saved_errno);
583
 
          return (plural == 0
584
 
                  ? (char *) msgid1
585
 
                  /* Use the Germanic plural rule.  */
586
 
                  : n == 1 ? (char *) msgid1 : (char *) msgid2);
587
 
        }
588
 
 
 
612
        break;
589
613
 
590
614
      /* Find structure describing the message catalog matching the
591
615
         DOMAINNAME and CATEGORY.  */
617
641
              /* Found the translation of MSGID1 in domain DOMAIN:
618
642
                 starting at RETVAL, RETLEN bytes.  */
619
643
              FREE_BLOCKS (block_list);
620
 
              __set_errno (saved_errno);
621
644
#if defined HAVE_TSEARCH || defined _LIBC
622
645
              if (foundp == NULL)
623
646
                {
656
679
                  (*foundp)->translation_length = retlen;
657
680
                }
658
681
#endif
 
682
              __set_errno (saved_errno);
 
683
 
659
684
              /* Now deal with plural.  */
660
685
              if (plural)
661
686
                retval = plural_lookup (domain, n, retval, retlen);
665
690
            }
666
691
        }
667
692
    }
668
 
  /* NOTREACHED */
 
693
 
 
694
 return_untranslated:
 
695
  /* Return the untranslated MSGID.  */
 
696
  FREE_BLOCKS (block_list);
 
697
  __libc_rwlock_unlock (_nl_state_lock);
 
698
#ifndef _LIBC
 
699
  if (!ENABLE_SECURE)
 
700
    {
 
701
      extern void _nl_log_untranslated (const char *logfilename,
 
702
                                        const char *domainname,
 
703
                                        const char *msgid1, const char *msgid2,
 
704
                                        int plural);
 
705
      const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
 
706
 
 
707
      if (logfilename != NULL && logfilename[0] != '\0')
 
708
        _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
 
709
    }
 
710
#endif
 
711
  __set_errno (saved_errno);
 
712
  return (plural == 0
 
713
          ? (char *) msgid1
 
714
          /* Use the Germanic plural rule.  */
 
715
          : n == 1 ? (char *) msgid1 : (char *) msgid2);
669
716
}
670
717
 
671
718
 
672
719
char *
673
720
internal_function
674
 
_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
675
 
     struct loaded_l10nfile *domain_file;
676
 
     struct binding *domainbinding;
677
 
     const char *msgid;
678
 
     size_t *lengthp;
 
721
_nl_find_msg (struct loaded_l10nfile *domain_file,
 
722
              struct binding *domainbinding, const char *msgid,
 
723
              size_t *lengthp)
679
724
{
680
725
  struct loaded_domain *domain;
 
726
  nls_uint32 nstrings;
681
727
  size_t act;
682
728
  char *result;
683
729
  size_t resultlen;
690
736
 
691
737
  domain = (struct loaded_domain *) domain_file->data;
692
738
 
 
739
  nstrings = domain->nstrings;
 
740
 
693
741
  /* Locate the MSGID and its translation.  */
694
 
  if (domain->hash_size > 2 && domain->hash_tab != NULL)
 
742
  if (domain->hash_tab != NULL)
695
743
    {
696
744
      /* Use the hashing table.  */
697
745
      nls_uint32 len = strlen (msgid);
701
749
 
702
750
      while (1)
703
751
        {
704
 
          nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
 
752
          nls_uint32 nstr =
 
753
            W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
705
754
 
706
755
          if (nstr == 0)
707
756
            /* Hash table entry is empty.  */
708
757
            return NULL;
709
758
 
710
 
          /* Compare msgid with the original string at index nstr-1.
 
759
          nstr--;
 
760
 
 
761
          /* Compare msgid with the original string at index nstr.
711
762
             We compare the lengths with >=, not ==, because plural entries
712
763
             are represented by strings with an embedded NUL.  */
713
 
          if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) >= len
714
 
              && (strcmp (msgid,
715
 
                          domain->data + W (domain->must_swap,
716
 
                                            domain->orig_tab[nstr - 1].offset))
717
 
                  == 0))
 
764
          if (nstr < nstrings
 
765
              ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
 
766
                && (strcmp (msgid,
 
767
                            domain->data + W (domain->must_swap,
 
768
                                              domain->orig_tab[nstr].offset))
 
769
                    == 0)
 
770
              : domain->orig_sysdep_tab[nstr - nstrings].length > len
 
771
                && (strcmp (msgid,
 
772
                            domain->orig_sysdep_tab[nstr - nstrings].pointer)
 
773
                    == 0))
718
774
            {
719
 
              act = nstr - 1;
 
775
              act = nstr;
720
776
              goto found;
721
777
            }
722
778
 
734
790
      size_t top, bottom;
735
791
 
736
792
      bottom = 0;
737
 
      top = domain->nstrings;
 
793
      top = nstrings;
738
794
      while (bottom < top)
739
795
        {
740
796
          int cmp_val;
757
813
 found:
758
814
  /* The translation was found at index ACT.  If we have to convert the
759
815
     string to use a different character set, this is the time.  */
760
 
  result = ((char *) domain->data
761
 
            + W (domain->must_swap, domain->trans_tab[act].offset));
762
 
  resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
 
816
  if (act < nstrings)
 
817
    {
 
818
      result = (char *)
 
819
        (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
 
820
      resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
 
821
    }
 
822
  else
 
823
    {
 
824
      result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
 
825
      resultlen = domain->trans_sysdep_tab[act - nstrings].length;
 
826
    }
763
827
 
764
828
#if defined _LIBC || HAVE_ICONV
765
829
  if (domain->codeset_cntr
792
856
         NULs.  */
793
857
 
794
858
      if (domain->conv_tab == NULL
795
 
          && ((domain->conv_tab = (char **) calloc (domain->nstrings,
796
 
                                                    sizeof (char *)))
 
859
          && ((domain->conv_tab =
 
860
                 (char **) calloc (nstrings + domain->n_sysdep_strings,
 
861
                                   sizeof (char *)))
797
862
              == NULL))
798
863
        /* Mark that we didn't succeed allocating a table.  */
799
864
        domain->conv_tab = (char **) -1;
962
1027
/* Look up a plural variant.  */
963
1028
static char *
964
1029
internal_function
965
 
plural_lookup (domain, n, translation, translation_len)
966
 
     struct loaded_l10nfile *domain;
967
 
     unsigned long int n;
968
 
     const char *translation;
969
 
     size_t translation_len;
 
1030
plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
 
1031
               const char *translation, size_t translation_len)
970
1032
{
971
1033
  struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
972
1034
  unsigned long int index;
999
1061
  return (char *) p;
1000
1062
}
1001
1063
 
1002
 
 
 
1064
#ifndef _LIBC
1003
1065
/* Return string representation of locale CATEGORY.  */
1004
1066
static const char *
1005
1067
internal_function
1006
 
category_to_name (category)
1007
 
     int category;
 
1068
category_to_name (int category)
1008
1069
{
1009
1070
  const char *retval;
1010
1071
 
1059
1120
 
1060
1121
  return retval;
1061
1122
}
 
1123
#endif
1062
1124
 
1063
1125
/* Guess value of current locale from value of the environment variables.  */
1064
1126
static const char *
1065
1127
internal_function
1066
 
guess_category_value (category, categoryname)
1067
 
     int category;
1068
 
     const char *categoryname;
 
1128
guess_category_value (int category, const char *categoryname)
1069
1129
{
1070
1130
  const char *language;
1071
1131
  const char *retval;
1081
1141
     `LC_xxx', and `LANG'.  On some systems this can be done by the
1082
1142
     `setlocale' function itself.  */
1083
1143
#ifdef _LIBC
1084
 
  retval = setlocale (category, NULL);
 
1144
  retval = __current_locale_name (category);
1085
1145
#else
1086
1146
  retval = _nl_locale_name (category, categoryname);
1087
1147
#endif
1106
1166
   to be defined.  */
1107
1167
#if !_LIBC && !HAVE_STPCPY
1108
1168
static char *
1109
 
stpcpy (dest, src)
1110
 
     char *dest;
1111
 
     const char *src;
 
1169
stpcpy (char *dest, const char *src)
1112
1170
{
1113
1171
  while ((*dest++ = *src++) != '\0')
1114
1172
    /* Do nothing. */ ;
1118
1176
 
1119
1177
#if !_LIBC && !HAVE_MEMPCPY
1120
1178
static void *
1121
 
mempcpy (dest, src, n)
1122
 
     void *dest;
1123
 
     const void *src;
1124
 
     size_t n;
 
1179
mempcpy (void *dest, const void *src, size_t n)
1125
1180
{
1126
1181
  return (void *) ((char *) memcpy (dest, src, n) + n);
1127
1182
}
1131
1186
#ifdef _LIBC
1132
1187
/* If we want to free all resources we have to do some work at
1133
1188
   program's end.  */
1134
 
static void __attribute__ ((unused))
1135
 
free_mem (void)
 
1189
libc_freeres_fn (free_mem)
1136
1190
{
1137
1191
  void *old;
1138
1192
 
1140
1194
    {
1141
1195
      struct binding *oldp = _nl_domain_bindings;
1142
1196
      _nl_domain_bindings = _nl_domain_bindings->next;
1143
 
      if (oldp->dirname != _nl_default_dirname)
 
1197
      if (oldp->dirname != INTUSE(_nl_default_dirname))
1144
1198
        /* Yes, this is a pointer comparison.  */
1145
1199
        free (oldp->dirname);
1146
1200
      free (oldp->codeset);
1162
1216
      free (old);
1163
1217
    }
1164
1218
}
1165
 
 
1166
 
text_set_element (__libc_subfreeres, free_mem);
1167
1219
#endif