Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix grouping when rounding increases number of integer digits.
  • Loading branch information
Ulrich Drepper committed Jan 13, 2011
1 parent f257bbd commit f57e41a
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 12 deletions.
6 changes: 3 additions & 3 deletions NEWS
@@ -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/>
Expand All @@ -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

Expand Down
5 changes: 3 additions & 2 deletions stdio-common/Makefile
@@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
23 changes: 16 additions & 7 deletions stdio-common/printf_fp.c
@@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down
83 changes: 83 additions & 0 deletions stdio-common/tst-grouping.c
@@ -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"

0 comments on commit f57e41a

Please sign in to comment.