Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 14 Jan 2004 05:38:11 +0000 (05:38 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 14 Jan 2004 05:38:11 +0000 (05:38 +0000)
2004-01-09  Bruno Haible  <bruno@clisp.org>

* intl/gmo.h (MO_REVISION_NUMBER_WITH_SYSDEP_I): New definition.
* intl/loadmsgcat.c (get_sysdep_segment_value): Handle "I".
(_nl_load_domain): Treat major revision 1 like major revision 0.

2004-01-11  Bruno Haible  <bruno@clisp.org>

* stdio-common/vfprintf.c (vfprintf): Disallow the 'I' flag after
width or precision has been seen.

2004-01-08  Bruno Haible  <bruno@clisp.org>

* intl/loadmsgcat.c (_nl_load_domain): When a string pair uses a system
dependent segment not known to this version of the library, ignore
the string pair instead of crashing.

ChangeLog
configure
intl/gmo.h
intl/loadmsgcat.c
stdio-common/vfprintf.c

index 6219a93..9cb5202 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2004-01-09  Bruno Haible  <bruno@clisp.org>
+
+       * intl/gmo.h (MO_REVISION_NUMBER_WITH_SYSDEP_I): New definition.
+       * intl/loadmsgcat.c (get_sysdep_segment_value): Handle "I".
+       (_nl_load_domain): Treat major revision 1 like major revision 0.
+
+2004-01-11  Bruno Haible  <bruno@clisp.org>
+
+       * stdio-common/vfprintf.c (vfprintf): Disallow the 'I' flag after
+       width or precision has been seen.
+
+2004-01-08  Bruno Haible  <bruno@clisp.org>
+
+       * intl/loadmsgcat.c (_nl_load_domain): When a string pair uses a system
+       dependent segment not known to this version of the library, ignore
+       the string pair instead of crashing.
+
 2004-01-13  Ulrich Drepper  <drepper@redhat.com>
 
        * configure.in: Rewrite test to give gcc to clean up after itself.
index 20c44f4..8f5fa38 100755 (executable)
--- a/configure
+++ b/configure
@@ -6286,7 +6286,7 @@ if { ac_try='$libc_unwind_check >&5'
   (exit $ac_status); }; }
 then
   if $libc_unwind_check -v 2>&1 >/dev/null \
-     | grep -q -- --eh-frame-hdr; then
+     | grep -- --eh-frame-hdr 2>&1 >/dev/null; then
     libc_cv_gcc_dwarf2_unwind_info=no_registry_needed
   else
     libc_cv_gcc_dwarf2_unwind_info=static
index 65e0b27..81003fc 100644 (file)
@@ -1,5 +1,5 @@
 /* Internal header for GNU gettext internationalization functions.
-   Copyright (C) 1995, 1997, 2000-2002 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997, 2000-2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
 
 /* Revision number of the currently used .mo (binary) file format.  */
 #define MO_REVISION_NUMBER 0
+#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1
 
 /* The following contortions are an attempt to use the C preprocessor
    to determine an unsigned integral type that is 32 bits wide.  An
@@ -77,7 +78,7 @@ struct mo_file_header
   /* The revision number of the file format.  */
   nls_uint32 revision;
 
-  /* The following are only used in .mo files with major revision 0.  */
+  /* The following are only used in .mo files with major revision 0 or 1.  */
 
   /* The number of strings pairs.  */
   nls_uint32 nstrings;
index 6a70fec..d70d77e 100644 (file)
@@ -1,5 +1,5 @@
 /* Load needed message catalogs.
-   Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -735,6 +735,18 @@ get_sysdep_segment_value (name)
            }
        }
     }
+  /* Test for a glibc specific printf() format directive flag.  */
+  if (name[0] == 'I' && name[1] == '\0')
+    {
+#if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+      /* The 'I' flag, in numeric format directives, replaces ASCII digits
+        with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
+        used for Farsi (Persian) and maybe Arabic.  */
+      return "I";
+#else
+      return "";
+#endif
+    }
   /* Other system dependent strings are not valid.  */
   return NULL;
 }
@@ -1009,10 +1021,11 @@ _nl_load_domain (domain_file, domainbinding)
 
   /* Fill in the information about the available tables.  */
   revision = W (domain->must_swap, data->revision);
-  /* We support only the major revision 0.  */
+  /* We support only the major revisions 0 and 1.  */
   switch (revision >> 16)
     {
     case 0:
+    case 1:
       domain->nstrings = W (domain->must_swap, data->nstrings);
       domain->orig_tab = (const struct string_desc *)
        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
@@ -1052,12 +1065,13 @@ _nl_load_domain (domain_file, domainbinding)
                const char **sysdep_segment_values;
                const nls_uint32 *orig_sysdep_tab;
                const nls_uint32 *trans_sysdep_tab;
+               nls_uint32 n_inmem_sysdep_strings;
                size_t memneed;
                char *mem;
                struct sysdep_string_desc *inmem_orig_sysdep_tab;
                struct sysdep_string_desc *inmem_trans_sysdep_tab;
                nls_uint32 *inmem_hash_tab;
-               unsigned int i;
+               unsigned int i, j;
 
                /* Get the values of the system dependent segments.  */
                n_sysdep_segments =
@@ -1092,153 +1106,247 @@ _nl_load_domain (domain_file, domainbinding)
                   + W (domain->must_swap, data->trans_sysdep_tab_offset));
 
                /* Compute the amount of additional memory needed for the
-                  system dependent strings and the augmented hash table.  */
-               memneed = 2 * n_sysdep_strings
-                         * sizeof (struct sysdep_string_desc)
-                         + domain->hash_size * sizeof (nls_uint32);
-               for (i = 0; i < 2 * n_sysdep_strings; i++)
+                  system dependent strings and the augmented hash table.
+                  At the same time, also drop string pairs which refer to
+                  an undefined system dependent segment.  */
+               n_inmem_sysdep_strings = 0;
+               memneed = domain->hash_size * sizeof (nls_uint32);
+               for (i = 0; i < n_sysdep_strings; i++)
                  {
-                   const struct sysdep_string *sysdep_string =
-                     (const struct sysdep_string *)
-                     ((char *) data
-                      + W (domain->must_swap,
-                           i < n_sysdep_strings
-                           ? orig_sysdep_tab[i]
-                           : trans_sysdep_tab[i - n_sysdep_strings]));
-                   size_t need = 0;
-                   const struct segment_pair *p = sysdep_string->segments;
-
-                   if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
-                     for (p = sysdep_string->segments;; p++)
-                       {
-                         nls_uint32 sysdepref;
-
-                         need += W (domain->must_swap, p->segsize);
-
-                         sysdepref = W (domain->must_swap, p->sysdepref);
-                         if (sysdepref == SEGMENTS_END)
-                           break;
-
-                         if (sysdepref >= n_sysdep_segments)
+                   int valid = 1;
+                   size_t needs[2];
+
+                   for (j = 0; j < 2; j++)
+                     {
+                       const struct sysdep_string *sysdep_string =
+                         (const struct sysdep_string *)
+                         ((char *) data
+                          + W (domain->must_swap,
+                               j == 0
+                               ? orig_sysdep_tab[i]
+                               : trans_sysdep_tab[i]));
+                       size_t need = 0;
+                       const struct segment_pair *p = sysdep_string->segments;
+
+                       if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
+                         for (p = sysdep_string->segments;; p++)
                            {
-                             /* Invalid.  */
-                             freea (sysdep_segment_values);
-                             goto invalid;
-                           }
+                             nls_uint32 sysdepref;
 
-                         need += strlen (sysdep_segment_values[sysdepref]);
-                       }
+                             need += W (domain->must_swap, p->segsize);
 
-                   memneed += need;
-                 }
+                             sysdepref = W (domain->must_swap, p->sysdepref);
+                             if (sysdepref == SEGMENTS_END)
+                               break;
 
-               /* Allocate additional memory.  */
-               mem = (char *) malloc (memneed);
-               if (mem == NULL)
-                 goto invalid;
-
-               domain->malloced = mem;
-               inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
-               mem += n_sysdep_strings * sizeof (struct sysdep_string_desc);
-               inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
-               mem += n_sysdep_strings * sizeof (struct sysdep_string_desc);
-               inmem_hash_tab = (nls_uint32 *) mem;
-               mem += domain->hash_size * sizeof (nls_uint32);
-
-               /* Compute the system dependent strings.  */
-               for (i = 0; i < 2 * n_sysdep_strings; i++)
-                 {
-                   const struct sysdep_string *sysdep_string =
-                     (const struct sysdep_string *)
-                     ((char *) data
-                      + W (domain->must_swap,
-                           i < n_sysdep_strings
-                           ? orig_sysdep_tab[i]
-                           : trans_sysdep_tab[i - n_sysdep_strings]));
-                   const char *static_segments =
-                     (char *) data
-                     + W (domain->must_swap, sysdep_string->offset);
-                   const struct segment_pair *p = sysdep_string->segments;
+                             if (sysdepref >= n_sysdep_segments)
+                               {
+                                 /* Invalid.  */
+                                 freea (sysdep_segment_values);
+                                 goto invalid;
+                               }
+
+                             if (sysdep_segment_values[sysdepref] == NULL)
+                               {
+                                 /* This particular string pair is invalid.  */
+                                 valid = 0;
+                                 break;
+                               }
 
-                   /* Concatenate the segments, and fill
-                      inmem_orig_sysdep_tab[i] (for i < n_sysdep_strings) and
-                      inmem_trans_sysdep_tab[i-n_sysdep_strings] (for
-                      i >= n_sysdep_strings).  */
+                             need += strlen (sysdep_segment_values[sysdepref]);
+                           }
+
+                       needs[j] = need;
+                       if (!valid)
+                         break;
+                     }
 
-                   if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END)
+                   if (valid)
                      {
-                       /* Only one static segment.  */
-                       inmem_orig_sysdep_tab[i].length =
-                         W (domain->must_swap, p->segsize);
-                       inmem_orig_sysdep_tab[i].pointer = static_segments;
+                       n_inmem_sysdep_strings++;
+                       memneed += needs[0] + needs[1];
                      }
-                   else
+                 }
+               memneed += 2 * n_inmem_sysdep_strings
+                          * sizeof (struct sysdep_string_desc);
+
+               if (n_inmem_sysdep_strings > 0)
+                 {
+                   unsigned int k;
+
+                   /* Allocate additional memory.  */
+                   mem = (char *) malloc (memneed);
+                   if (mem == NULL)
+                     goto invalid;
+
+                   domain->malloced = mem;
+                   inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
+                   mem += n_inmem_sysdep_strings
+                          * sizeof (struct sysdep_string_desc);
+                   inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
+                   mem += n_inmem_sysdep_strings
+                          * sizeof (struct sysdep_string_desc);
+                   inmem_hash_tab = (nls_uint32 *) mem;
+                   mem += domain->hash_size * sizeof (nls_uint32);
+
+                   /* Compute the system dependent strings.  */
+                   k = 0;
+                   for (i = 0; i < n_sysdep_strings; i++)
                      {
-                       inmem_orig_sysdep_tab[i].pointer = mem;
+                       int valid = 1;
 
-                       for (p = sysdep_string->segments;; p++)
+                       for (j = 0; j < 2; j++)
                          {
-                           nls_uint32 segsize =
-                             W (domain->must_swap, p->segsize);
-                           nls_uint32 sysdepref =
-                             W (domain->must_swap, p->sysdepref);
-                           size_t n;
+                           const struct sysdep_string *sysdep_string =
+                             (const struct sysdep_string *)
+                             ((char *) data
+                              + W (domain->must_swap,
+                                   j == 0
+                                   ? orig_sysdep_tab[i]
+                                   : trans_sysdep_tab[i]));
+                           const struct segment_pair *p =
+                             sysdep_string->segments;
+
+                           if (W (domain->must_swap, p->sysdepref)
+                               != SEGMENTS_END)
+                             for (p = sysdep_string->segments;; p++)
+                               {
+                                 nls_uint32 sysdepref;
+
+                                 sysdepref =
+                                   W (domain->must_swap, p->sysdepref);
+                                 if (sysdepref == SEGMENTS_END)
+                                   break;
+
+                                 if (sysdep_segment_values[sysdepref] == NULL)
+                                   {
+                                     /* This particular string pair is
+                                        invalid.  */
+                                     valid = 0;
+                                     break;
+                                   }
+                               }
+
+                           if (!valid)
+                             break;
+                         }
 
-                           if (segsize > 0)
+                       if (valid)
+                         {
+                           for (j = 0; j < 2; j++)
                              {
-                               memcpy (mem, static_segments, segsize);
-                               mem += segsize;
-                               static_segments += segsize;
+                               const struct sysdep_string *sysdep_string =
+                                 (const struct sysdep_string *)
+                                 ((char *) data
+                                  + W (domain->must_swap,
+                                       j == 0
+                                       ? orig_sysdep_tab[i]
+                                       : trans_sysdep_tab[i]));
+                               const char *static_segments =
+                                 (char *) data
+                                 + W (domain->must_swap, sysdep_string->offset);
+                               const struct segment_pair *p =
+                                 sysdep_string->segments;
+
+                               /* Concatenate the segments, and fill
+                                  inmem_orig_sysdep_tab[k] (for j == 0) and
+                                  inmem_trans_sysdep_tab[k] (for j == 1).  */
+
+                               struct sysdep_string_desc *inmem_tab_entry =
+                                 (j == 0
+                                  ? inmem_orig_sysdep_tab
+                                  : inmem_trans_sysdep_tab)
+                                 + k;
+
+                               if (W (domain->must_swap, p->sysdepref)
+                                   == SEGMENTS_END)
+                                 {
+                                   /* Only one static segment.  */
+                                   inmem_tab_entry->length =
+                                     W (domain->must_swap, p->segsize);
+                                   inmem_tab_entry->pointer = static_segments;
+                                 }
+                               else
+                                 {
+                                   inmem_tab_entry->pointer = mem;
+
+                                   for (p = sysdep_string->segments;; p++)
+                                     {
+                                       nls_uint32 segsize =
+                                         W (domain->must_swap, p->segsize);
+                                       nls_uint32 sysdepref =
+                                         W (domain->must_swap, p->sysdepref);
+                                       size_t n;
+
+                                       if (segsize > 0)
+                                         {
+                                           memcpy (mem, static_segments, segsize);
+                                           mem += segsize;
+                                           static_segments += segsize;
+                                         }
+
+                                       if (sysdepref == SEGMENTS_END)
+                                         break;
+
+                                       n = strlen (sysdep_segment_values[sysdepref]);
+                                       memcpy (mem, sysdep_segment_values[sysdepref], n);
+                                       mem += n;
+                                     }
+
+                                   inmem_tab_entry->length =
+                                     mem - inmem_tab_entry->pointer;
+                                 }
                              }
 
-                           if (sysdepref == SEGMENTS_END)
-                             break;
-
-                           n = strlen (sysdep_segment_values[sysdepref]);
-                           memcpy (mem, sysdep_segment_values[sysdepref], n);
-                           mem += n;
+                           k++;
                          }
-
-                       inmem_orig_sysdep_tab[i].length =
-                         mem - inmem_orig_sysdep_tab[i].pointer;
                      }
-                 }
-
-               /* Compute the augmented hash table.  */
-               for (i = 0; i < domain->hash_size; i++)
-                 inmem_hash_tab[i] =
-                   W (domain->must_swap_hash_tab, domain->hash_tab[i]);
-               for (i = 0; i < n_sysdep_strings; i++)
-                 {
-                   const char *msgid = inmem_orig_sysdep_tab[i].pointer;
-                   nls_uint32 hash_val = __hash_string (msgid);
-                   nls_uint32 idx = hash_val % domain->hash_size;
-                   nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
-
-                   for (;;)
+                   if (k != n_inmem_sysdep_strings)
+                     abort ();
+
+                   /* Compute the augmented hash table.  */
+                   for (i = 0; i < domain->hash_size; i++)
+                     inmem_hash_tab[i] =
+                       W (domain->must_swap_hash_tab, domain->hash_tab[i]);
+                   for (i = 0; i < n_inmem_sysdep_strings; i++)
                      {
-                       if (inmem_hash_tab[idx] == 0)
+                       const char *msgid = inmem_orig_sysdep_tab[i].pointer;
+                       nls_uint32 hash_val = __hash_string (msgid);
+                       nls_uint32 idx = hash_val % domain->hash_size;
+                       nls_uint32 incr =
+                         1 + (hash_val % (domain->hash_size - 2));
+
+                       for (;;)
                          {
-                           /* Hash table entry is empty.  Use it.  */
-                           inmem_hash_tab[idx] = 1 + domain->nstrings + i;
-                           break;
-                         }
+                           if (inmem_hash_tab[idx] == 0)
+                             {
+                               /* Hash table entry is empty.  Use it.  */
+                               inmem_hash_tab[idx] = 1 + domain->nstrings + i;
+                               break;
+                             }
 
-                       if (idx >= domain->hash_size - incr)
-                         idx -= domain->hash_size - incr;
-                       else
-                         idx += incr;
+                           if (idx >= domain->hash_size - incr)
+                             idx -= domain->hash_size - incr;
+                           else
+                             idx += incr;
+                         }
                      }
-                 }
 
-               freea (sysdep_segment_values);
+                   domain->n_sysdep_strings = n_inmem_sysdep_strings;
+                   domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
+                   domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
 
-               domain->n_sysdep_strings = n_sysdep_strings;
-               domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
-               domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
+                   domain->hash_tab = inmem_hash_tab;
+                   domain->must_swap_hash_tab = 0;
+                 }
+               else
+                 {
+                   domain->n_sysdep_strings = 0;
+                   domain->orig_sysdep_tab = NULL;
+                   domain->trans_sysdep_tab = NULL;
+                 }
 
-               domain->hash_tab = inmem_hash_tab;
-               domain->must_swap_hash_tab = 0;
+               freea (sysdep_segment_values);
              }
            else
              {
index b84107a..8465680 100644 (file)
@@ -399,7 +399,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_floathex),     /* for 'A', 'a' */                            \
       REF (mod_ptrdiff_t),      /* for 't' */                                \
       REF (mod_intmax_t),       /* for 'j' */                                \
-      REF (flag_i18n)          /* for 'I' */                                 \
+      REF (form_unknown)        /* for 'I' */                                \
     };                                                                       \
     /* Step 2: after processing precision.  */                               \
     static JUMP_TABLE_TYPE step2_jumps[30] =                                 \
@@ -433,7 +433,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
       REF (form_floathex),     /* for 'A', 'a' */                            \
       REF (mod_ptrdiff_t),      /* for 't' */                                \
       REF (mod_intmax_t),       /* for 'j' */                                \
-      REF (flag_i18n)          /* for 'I' */                                 \
+      REF (form_unknown)        /* for 'I' */                                \
     };                                                                       \
     /* Step 3a: after processing first 'h' modifier.  */                     \
     static JUMP_TABLE_TYPE step3a_jumps[30] =                                \