X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fvasnprintf.c;h=e11f1e998306151821a900287727e9832fcd55ab;hb=5d0b385594bc914e6233988bfb6bc1b92a2184b5;hp=75d33b347ea583c6a2b0edc864dd2705900a349c;hpb=cdaeb6bb213d6042df46e0b3584718ede9f18511;p=gnulib.git diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 75d33b347..e11f1e998 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -41,6 +41,9 @@ #include /* errno */ #include /* CHAR_BIT */ #include /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if HAVE_NL_LANGINFO +# include +#endif #if WIDE_CHAR_VERSION # include "wprintf-parse.h" #else @@ -51,14 +54,12 @@ #include "xsize.h" #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL -# include "float+.h" +# include # include "isnan.h" # include "printf-frexp.h" -# if HAVE_LONG_DOUBLE -# include "isnanl-nolibm.h" -# include "printf-frexpl.h" -# include "fpucw.h" -# endif +# include "isnanl-nolibm.h" +# include "printf-frexpl.h" +# include "fpucw.h" #endif /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ @@ -124,6 +125,33 @@ local_wcslen (const wchar_t *s) /* Here we need to call the native sprintf, not rpl_sprintf. */ #undef sprintf +#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL +/* Determine the decimal-point character according to the current locale. */ +# ifndef decimal_point_char_defined +# define decimal_point_char_defined 1 +static char +decimal_point_char () +{ + const char *point; + /* Determine it in a multithread-safe way. We know nl_langinfo is + multithread-safe on glibc systems, but is not required to be multithread- + safe by POSIX. sprintf(), however, is multithread-safe. localeconv() + is rarely multithread-safe. */ +# if HAVE_NL_LANGINFO && __GLIBC__ + point = nl_langinfo (RADIXCHAR); +# elif 1 + char pointbuf[5]; + sprintf (pointbuf, "%#.0f", 1.0); + point = &pointbuf[1]; +# else + point = localeconv () -> decimal_point; +# endif + /* The decimal point is always a single byte: either '.' or ','. */ + return (point[0] != '\0' ? point[0] : '.'); +} +# endif +#endif + CHAR_T * VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) { @@ -356,7 +384,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } /* Allocate a temporary buffer of sufficient size. */ -# if HAVE_LONG_DOUBLE if (type == TYPE_LONGDOUBLE) tmp_length = (unsigned int) ((LDBL_DIG + 1) @@ -364,7 +391,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar ) + 1; /* turn floor into ceil */ else -# endif tmp_length = (unsigned int) ((DBL_DIG + 1) * 0.831 /* decimal -> hexadecimal */ @@ -397,7 +423,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar pad_ptr = NULL; p = tmp; -# if HAVE_LONG_DOUBLE if (type == TYPE_LONGDOUBLE) { long double arg = a.arg[dp->arg_index].a.a_longdouble; @@ -420,22 +445,11 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar BEGIN_LONG_DOUBLE_ROUNDING (); - if (arg < 0.0L) + if (signbit (arg)) /* arg < 0.0L or negative zero */ { sign = -1; arg = -arg; } - else if (arg == 0.0L) - { - /* Distinguish 0.0L and -0.0L. */ - static long double plus_zero = 0.0L; - long double arg_mem = arg; - if (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0) - { - sign = -1; - arg = -arg; - } - } if (sign < 0) *p++ = '-'; @@ -507,11 +521,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if ((flags & FLAG_ALT) || mantissa > 0.0L || precision > 0) { - const char *point = - localeconv () -> decimal_point; - /* The decimal point is always a single byte: - either '.' or ','. */ - *p++ = (point[0] != '\0' ? point[0] : '.'); + *p++ = decimal_point_char (); /* This loop terminates because we assume that FLT_RADIX is a power of 2. */ while (mantissa > 0.0L) @@ -534,15 +544,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } } *p++ = dp->conversion - 'A' + 'P'; -# if WIDE_CHAR_VERSION +# if WIDE_CHAR_VERSION { static const wchar_t decimal_format[] = { '%', '+', 'd', '\0' }; SNPRINTF (p, 6 + 1, decimal_format, exponent); } -# else +# else sprintf (p, "%+d", exponent); -# endif +# endif while (*p != '\0') p++; } @@ -551,7 +561,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } } else -# endif { double arg = a.arg[dp->arg_index].a.a_double; @@ -570,22 +579,11 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { int sign = 0; - if (arg < 0.0) + if (signbit (arg)) /* arg < 0.0 or negative zero */ { sign = -1; arg = -arg; } - else if (arg == 0.0) - { - /* Distinguish 0.0 and -0.0. */ - static double plus_zero = 0.0; - double arg_mem = arg; - if (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0) - { - sign = -1; - arg = -arg; - } - } if (sign < 0) *p++ = '-'; @@ -657,11 +655,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if ((flags & FLAG_ALT) || mantissa > 0.0 || precision > 0) { - const char *point = - localeconv () -> decimal_point; - /* The decimal point is always a single byte: - either '.' or ','. */ - *p++ = (point[0] != '\0' ? point[0] : '.'); + *p++ = decimal_point_char (); /* This loop terminates because we assume that FLT_RADIX is a power of 2. */ while (mantissa > 0.0) @@ -910,7 +904,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar break; case 'f': case 'F': -# if HAVE_LONG_DOUBLE if (type == TYPE_LONGDOUBLE) tmp_length = (unsigned int) (LDBL_MAX_EXP @@ -920,7 +913,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar + 1 /* turn floor into ceil */ + 10; /* sign, decimal point etc. */ else -# endif tmp_length = (unsigned int) (DBL_MAX_EXP * 0.30103 /* binary -> decimal */ @@ -938,7 +930,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar break; case 'a': case 'A': -# if HAVE_LONG_DOUBLE if (type == TYPE_LONGDOUBLE) tmp_length = (unsigned int) (LDBL_DIG @@ -946,7 +937,6 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar ) + 1; /* turn floor into ceil */ else -# endif tmp_length = (unsigned int) (DBL_DIG * 0.831 /* decimal -> hexadecimal */ @@ -1065,15 +1055,18 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar #endif *p++ = 'l'; break; -#if HAVE_LONG_DOUBLE case TYPE_LONGDOUBLE: *p++ = 'L'; break; -#endif default: break; } - *p = dp->conversion; +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + *p = 'f'; + else +#endif + *p = dp->conversion; #if USE_SNPRINTF p[1] = '%'; p[2] = 'n'; @@ -1226,14 +1219,12 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar SNPRINTF_BUF (arg); } break; -#if HAVE_LONG_DOUBLE case TYPE_LONGDOUBLE: { long double arg = a.arg[dp->arg_index].a.a_longdouble; SNPRINTF_BUF (arg); } break; -#endif case TYPE_CHAR: { int arg = a.arg[dp->arg_index].a.a_char; @@ -1362,6 +1353,18 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar free (tmp); #endif +#if NEED_PRINTF_DIRECTIVE_F + if (dp->conversion == 'F') + { + /* Convert the %f result to upper case for %F. */ + CHAR_T *rp = result + length; + size_t rc; + for (rc = count; rc > 0; rc--, rp++) + if (*rp >= 'a' && *rp <= 'z') + *rp = *rp - 'a' + 'A'; + } +#endif + length += count; break; }