[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: vasnprintf fix
From: |
Bruno Haible |
Subject: |
Re: vasnprintf fix |
Date: |
Tue, 6 Nov 2007 00:45:57 +0100 |
User-agent: |
KMail/1.5.4 |
Hello Eric,
> Something's still fishy. Now I'm getting aborts for test-vasprintf-posix.c
> on
> cygwin, with the following sequence of instructions in vasnprintf.c:
>
> Breakpoint 1, test_function (my_asprintf=0x413052 <my_asprintf>)
> at ../../tests/test-vasprintf-posix.c:173
> 173 int retval =
> my_asprintf (&result, "%a %d", 3.1416015625, 33, 44, 55);
>
>
> 2690 if (type == TYPE_LONGDOUBLE)
> (gdb)
> 3055 double arg = a.arg[dp->arg_index].a.a_double;
> (gdb)
> 3057 if (isnan (arg))
> (gdb)
> 3070 int sign = 0;
> (gdb)
> 3072 if (signbit (arg)) /* arg < 0.0 or negative
> zero */
> (gdb)
> 3078 if (sign < 0)
> (gdb)
> 3080 else if (flags & FLAG_SHOWSIGN)
> (gdb)
> 3082 else if (flags & FLAG_SPACE)
> (gdb)
> 3085 if (arg > 0.0 && arg + arg == arg)
> (gdb)
> 3099 pad_ptr = p;
> (gdb)
> 3101 if (dp->conversion == 'f' || dp->conversion
> == 'F')
> (gdb)
> 3136 else if (dp->conversion == 'e' || dp-
> >conversion == 'E')
> (gdb)
> 3246 else if (dp->conversion == 'g' || dp-
> >conversion == 'G')
> (gdb)
> 3421 abort ();
> (gdb)
Now that you say it, it's obvious what is going on: the code has first
decided that it doesn't need the 'a'/'A' substitute (since Cygwin already
has it) and then decided that it needs to emulate 'A'/'A' (because Cygwin
either crashes in low-memory situations or has a crippled handling of the
precision).
Thanks for the single-stepping. I'm committing this, which will hopefully
fix it (untested).
2007-11-05 Bruno Haible <address@hidden>
* lib/vasnprintf.c (VASNPRINTF): Expand the NEED_PRINTF_DIRECTIVE_A
code when NEED_PRINTF_LONG_DOUBLE or NEED_PRINTF_DOUBLE is set.
Needed on Cygwin, where !NEED_PRINTF_DIRECTIVE_A && NEED_PRINTF_DOUBLE.
Reported by Eric Blake.
*** lib/vasnprintf.c.orig 2007-11-06 00:40:28.000000000 +0100
--- lib/vasnprintf.c 2007-11-06 00:29:22.000000000 +0100
***************
*** 104,113 ****
# include "fpucw.h"
#endif
! #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
# include <math.h>
# include "isnan.h"
# include "printf-frexp.h"
# include "isnanl-nolibm.h"
# include "printf-frexpl.h"
# include "fpucw.h"
--- 104,117 ----
# include "fpucw.h"
#endif
! #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
# include "isnan.h"
# include "printf-frexp.h"
+ #endif
+
+ #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined
IN_LIBINTL
+ # include <math.h>
# include "isnanl-nolibm.h"
# include "printf-frexpl.h"
# include "fpucw.h"
***************
*** 2033,2040 ****
}
}
#endif
! #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
! else if (dp->conversion == 'a' || dp->conversion == 'A')
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
--- 2037,2055 ----
}
}
#endif
! #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE ||
NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
! else if ((dp->conversion == 'a' || dp->conversion == 'A')
! # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE &&
NEED_PRINTF_DOUBLE))
! && (0
! # if NEED_PRINTF_DOUBLE
! || a.arg[dp->arg_index].type == TYPE_DOUBLE
! # endif
! # if NEED_PRINTF_LONG_DOUBLE
! || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
! # endif
! )
! # endif
! )
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
***************
*** 2152,2157 ****
--- 2167,2173 ----
p = tmp;
if (type == TYPE_LONGDOUBLE)
{
+ # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
long double arg = a.arg[dp->arg_index].a.a_longdouble;
if (isnanl (arg))
***************
*** 2271,2277 ****
}
}
*p++ = dp->conversion - 'A' + 'P';
! # if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
--- 2287,2293 ----
}
}
*p++ = dp->conversion - 'A' + 'P';
! # if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
***************
*** 2279,2285 ****
}
while (*p != '\0')
p++;
! # else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
--- 2295,2301 ----
}
while (*p != '\0')
p++;
! # else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
***************
*** 2294,2307 ****
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
! # endif
}
END_LONG_DOUBLE_ROUNDING ();
}
}
else
{
double arg = a.arg[dp->arg_index].a.a_double;
if (isnan (arg))
--- 2310,2327 ----
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
! # endif
}
END_LONG_DOUBLE_ROUNDING ();
}
+ # else
+ abort ();
+ # endif
}
else
{
+ # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
double arg = a.arg[dp->arg_index].a.a_double;
if (isnan (arg))
***************
*** 2418,2424 ****
}
}
*p++ = dp->conversion - 'A' + 'P';
! # if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
--- 2438,2444 ----
}
}
*p++ = dp->conversion - 'A' + 'P';
! # if WIDE_CHAR_VERSION
{
static const wchar_t decimal_format[] =
{ '%', '+', 'd', '\0' };
***************
*** 2426,2432 ****
}
while (*p != '\0')
p++;
! # else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
--- 2446,2452 ----
}
while (*p != '\0')
p++;
! # else
if (sizeof (DCHAR_T) == 1)
{
sprintf ((char *) p, "%+d", exponent);
***************
*** 2441,2449 ****
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
! # endif
}
}
}
/* The generated string now extends from tmp to p, with the
zero padding insertion point being at pad_ptr. */
--- 2461,2472 ----
for (ep = expbuf; (*p = *ep) != '\0'; ep++)
p++;
}
! # endif
}
}
+ # else
+ abort ();
+ # endif
}
/* The generated string now extends from tmp to p, with the
zero padding insertion point being at pad_ptr. */