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.
This commit is contained in:
Ulrich Drepper 2004-01-14 05:38:11 +00:00
parent 5de90b7c61
commit 083dc54a01
5 changed files with 270 additions and 144 deletions

View File

@ -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.

2
configure vendored
View File

@ -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

View 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;

View 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++)
{
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)
{
/* Invalid. */
freea (sysdep_segment_values);
goto invalid;
}
need += strlen (sysdep_segment_values[sysdepref]);
}
memneed += need;
}
/* 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;
/* 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). */
if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END)
{
/* Only one static segment. */
inmem_orig_sysdep_tab[i].length =
W (domain->must_swap, p->segsize);
inmem_orig_sysdep_tab[i].pointer = static_segments;
}
else
{
inmem_orig_sysdep_tab[i].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_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]);
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 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));
int valid = 1;
size_t needs[2];
for (;;)
for (j = 0; j < 2; j++)
{
if (inmem_hash_tab[idx] == 0)
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++)
{
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)
{
/* Invalid. */
freea (sysdep_segment_values);
goto invalid;
}
if (sysdep_segment_values[sysdepref] == NULL)
{
/* This particular string pair is invalid. */
valid = 0;
break;
}
need += strlen (sysdep_segment_values[sysdepref]);
}
needs[j] = need;
if (!valid)
break;
}
if (valid)
{
n_inmem_sysdep_strings++;
memneed += needs[0] + needs[1];
}
}
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++)
{
int valid = 1;
for (j = 0; j < 2; j++)
{
/* Hash table entry is empty. Use it. */
inmem_hash_tab[idx] = 1 + domain->nstrings + i;
break;
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 (idx >= domain->hash_size - incr)
idx -= domain->hash_size - incr;
else
idx += incr;
if (valid)
{
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]));
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;
}
}
k++;
}
}
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++)
{
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 (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;
}
}
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->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;
}
freea (sysdep_segment_values);
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
{

View 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] = \