Fix grouping when rounding increases number of integer digits.

This commit is contained in:
Ulrich Drepper 2011-01-12 20:37:51 -05:00
parent f257bbd77d
commit f57e41a5b8
4 changed files with 105 additions and 12 deletions

6
NEWS
View file

@ -1,5 +1,5 @@
GNU C Library NEWS -- history of user-visible changes. 2010-12-27
Copyright (C) 1992-2009, 2010 Free Software Foundation, Inc.
GNU C Library NEWS -- history of user-visible changes. 2011-1-12
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
See the end for copying conditions.
Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/>
@ -12,7 +12,7 @@ Version 2.13
3268, 7066, 10085, 10851, 11149, 11155, 11611, 11640, 11655, 11701,
11840, 11856, 11883, 11903, 11904, 11968, 11979, 12005, 12037,
12067, 12077, 12078, 12092, 12093, 12107, 12108, 12113, 12140,
12159, 12167, 12191, 12194, 12201, 12204, 12205, 12207, 12348
12159, 12167, 12191, 12194, 12201, 12204, 12205, 12207, 12348, 12394
* New Linux interfaces: prlimit, prlimit64, fanotify_init, fanotify_mark

View file

@ -1,4 +1,4 @@
# Copyright (C) 1991-2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# Copyright (C) 1991-2009, 2011 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
@ -60,7 +60,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
tst-popen tst-unlockedio tst-fmemopen2 tst-put-error tst-fgets \
tst-fwrite bug16 bug17 tst-swscanf tst-sprintf2 bug18 bug18a \
bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
scanf16 scanf17 tst-setvbuf1
scanf16 scanf17 tst-setvbuf1 tst-grouping
test-srcs = tst-unbputc tst-printf
@ -128,6 +128,7 @@ test-vfprintf-ENV = LOCPATH=$(common-objpfx)localedata
scanf13-ENV = LOCPATH=$(common-objpfx)localedata
bug14-ENV = LOCPATH=$(common-objpfx)localedata
bug15-ENV = LOCPATH=$(common-objpfx)localedata
tst-grouping-ENV = LOCPATH=$(common-objpfx)localedata
ifneq (,$(filter %REENTRANT, $(defines)))
CPPFLAGS += -D_IO_MTSAFE_IO

View file

@ -1,5 +1,5 @@
/* Floating point output for `printf'.
Copyright (C) 1995-2003, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 1995-2003, 2006-2008, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
@ -884,7 +884,9 @@ ___printf_fp (FILE *fp,
/* Guess the number of groups we will make, and thus how
many spaces we need for separator characters. */
ngroups = __guess_grouping (intdig_max, grouping);
chars_needed += ngroups;
/* Allocate one more character in case rounding increases the
number of groups. */
chars_needed += ngroups + 1;
}
/* Allocate buffer for output. We need two more because while rounding
@ -1088,9 +1090,16 @@ ___printf_fp (FILE *fp,
--wcp;
if (grouping)
/* Add in separator characters, overwriting the same buffer. */
wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc,
ngroups);
{
/* Rounding might have changed the number of groups. We allocated
enough memory but we need here the correct number of groups. */
if (intdig_no != intdig_max)
ngroups = __guess_grouping (intdig_no, grouping);
/* Add in separator characters, overwriting the same buffer. */
wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc,
ngroups);
}
/* Write the exponent if it is needed. */
if (type != 'f')
@ -1210,7 +1219,7 @@ ___printf_fp (FILE *fp,
tmpptr = buffer;
if (__builtin_expect (info->i18n, 0))
{
{
#ifdef COMPILE_WPRINTF
wstartp = _i18n_number_rewrite (wstartp, wcp,
wbuffer + wbuffer_to_alloc);
@ -1224,7 +1233,7 @@ ___printf_fp (FILE *fp,
assert ((uintptr_t) buffer <= (uintptr_t) tmpptr);
assert ((uintptr_t) tmpptr < (uintptr_t) buffer_end);
#endif
}
}
PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr);

View file

@ -0,0 +1,83 @@
/* BZ 12394, test by Bruno Haible. */
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int
do_test (void)
{
char buf1[1000];
char buf2[1000];
int result = 0;
if (setlocale (LC_NUMERIC, "de_DE.UTF-8") == NULL)
return 1;
sprintf (buf1, "%'.2f", 999.996);
sprintf (buf2, "%'.2f", 1000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 2;
sprintf (buf1, "%'.2f", 999999.996);
sprintf (buf2, "%'.2f", 1000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 2;
sprintf (buf1, "%'.2f", 999999999.996);
sprintf (buf2, "%'.2f", 1000000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 2;
sprintf (buf1, "%'.2f", 999999999999.996);
sprintf (buf2, "%'.2f", 1000000000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 2;
sprintf (buf1, "%'.2f", 999999999999999.996);
sprintf (buf2, "%'.2f", 1000000000000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 2;
sprintf (buf1, "%'.5g", 999.996);
sprintf (buf2, "%'.5g", 1000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 4;
sprintf (buf1, "%'.4g", 9999.996);
sprintf (buf2, "%'.4g", 10000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 8;
sprintf (buf1, "%'.5g", 99999.996);
sprintf (buf2, "%'.5g", 100000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 8;
sprintf (buf1, "%'.6g", 999999.996);
sprintf (buf2, "%'.6g", 1000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 8;
sprintf (buf1, "%'.7g", 9999999.996);
sprintf (buf2, "%'.7g", 10000000.004);
printf ("%d: \"%s\" vs \"%s\"\n", __LINE__, buf1, buf2);
if (strcmp (buf1, buf2) != 0)
result |= 8;
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"