summaryrefslogtreecommitdiffstats
path: root/gl/vasnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r--gl/vasnprintf.c140
1 files changed, 90 insertions, 50 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
index e618901b..5267b1bb 100644
--- a/gl/vasnprintf.c
+++ b/gl/vasnprintf.c
@@ -1,5 +1,5 @@
1/* vsprintf with automatic memory allocation. 1/* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2002-2013 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -12,8 +12,7 @@
12 GNU General Public License for more details. 12 GNU General Public License for more details.
13 13
14 You should have received a copy of the GNU General Public License along 14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, 15 with this program; if not, see <http://www.gnu.org/licenses/>. */
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17 16
18/* This file can be parametrized with the following macros: 17/* This file can be parametrized with the following macros:
19 VASNPRINTF The name of the function being defined. 18 VASNPRINTF The name of the function being defined.
@@ -88,6 +87,8 @@
88/* Checked size_t computations. */ 87/* Checked size_t computations. */
89#include "xsize.h" 88#include "xsize.h"
90 89
90#include "verify.h"
91
91#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL 92#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
92# include <math.h> 93# include <math.h>
93# include "float+.h" 94# include "float+.h"
@@ -274,10 +275,10 @@ decimal_point_char (void)
274{ 275{
275 const char *point; 276 const char *point;
276 /* Determine it in a multithread-safe way. We know nl_langinfo is 277 /* Determine it in a multithread-safe way. We know nl_langinfo is
277 multithread-safe on glibc systems and MacOS X systems, but is not required 278 multithread-safe on glibc systems and Mac OS X systems, but is not required
278 to be multithread-safe by POSIX. sprintf(), however, is multithread-safe. 279 to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
279 localeconv() is rarely multithread-safe. */ 280 localeconv() is rarely multithread-safe. */
280# if HAVE_NL_LANGINFO && (__GLIBC__ || (defined __APPLE__ && defined __MACH__)) 281# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
281 point = nl_langinfo (RADIXCHAR); 282 point = nl_langinfo (RADIXCHAR);
282# elif 1 283# elif 1
283 char pointbuf[5]; 284 char pointbuf[5];
@@ -322,11 +323,11 @@ is_infinite_or_zerol (long double x)
322 323
323typedef unsigned int mp_limb_t; 324typedef unsigned int mp_limb_t;
324# define GMP_LIMB_BITS 32 325# define GMP_LIMB_BITS 32
325typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1]; 326verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
326 327
327typedef unsigned long long mp_twolimb_t; 328typedef unsigned long long mp_twolimb_t;
328# define GMP_TWOLIMB_BITS 64 329# define GMP_TWOLIMB_BITS 64
329typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1]; 330verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
330 331
331/* Representation of a bignum >= 0. */ 332/* Representation of a bignum >= 0. */
332typedef struct 333typedef struct
@@ -551,32 +552,61 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
551 size_t s; 552 size_t s;
552 { 553 {
553 mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ 554 mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
554 s = 31; 555 /* Determine s = GMP_LIMB_BITS - integer_length (msd).
555 if (msd >= 0x10000) 556 Code copied from gnulib's integer_length.c. */
556 { 557# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
557 msd = msd >> 16; 558 s = __builtin_clz (msd);
558 s -= 16; 559# else
559 } 560# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
560 if (msd >= 0x100) 561 if (GMP_LIMB_BITS <= DBL_MANT_BIT)
561 {
562 msd = msd >> 8;
563 s -= 8;
564 }
565 if (msd >= 0x10)
566 {
567 msd = msd >> 4;
568 s -= 4;
569 }
570 if (msd >= 0x4)
571 { 562 {
572 msd = msd >> 2; 563 /* Use 'double' operations.
573 s -= 2; 564 Assumes an IEEE 754 'double' implementation. */
565# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
566# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1)
567# define NWORDS \
568 ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
569 union { double value; unsigned int word[NWORDS]; } m;
570
571 /* Use a single integer to floating-point conversion. */
572 m.value = msd;
573
574 s = GMP_LIMB_BITS
575 - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK)
576 - DBL_EXP_BIAS);
574 } 577 }
575 if (msd >= 0x2) 578 else
579# undef NWORDS
580# endif
576 { 581 {
577 msd = msd >> 1; 582 s = 31;
578 s -= 1; 583 if (msd >= 0x10000)
584 {
585 msd = msd >> 16;
586 s -= 16;
587 }
588 if (msd >= 0x100)
589 {
590 msd = msd >> 8;
591 s -= 8;
592 }
593 if (msd >= 0x10)
594 {
595 msd = msd >> 4;
596 s -= 4;
597 }
598 if (msd >= 0x4)
599 {
600 msd = msd >> 2;
601 s -= 2;
602 }
603 if (msd >= 0x2)
604 {
605 msd = msd >> 1;
606 s -= 1;
607 }
579 } 608 }
609# endif
580 } 610 }
581 /* 0 <= s < GMP_LIMB_BITS. 611 /* 0 <= s < GMP_LIMB_BITS.
582 Copy b, shifting it left by s bits. */ 612 Copy b, shifting it left by s bits. */
@@ -883,9 +913,9 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
883 y = frexpl (x, &exp); 913 y = frexpl (x, &exp);
884 if (!(y >= 0.0L && y < 1.0L)) 914 if (!(y >= 0.0L && y < 1.0L))
885 abort (); 915 abort ();
886 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the 916 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
887 latter is an integer. */ 917 latter is an integer. */
888 /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs. 918 /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs.
889 I'm not sure whether it's safe to cast a 'long double' value between 919 I'm not sure whether it's safe to cast a 'long double' value between
890 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only 920 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
891 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int', 921 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
@@ -933,11 +963,11 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
933 abort (); 963 abort ();
934 m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; 964 m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
935 } 965 }
936#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess 966# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
937 precision. */ 967 precision. */
938 if (!(y == 0.0L)) 968 if (!(y == 0.0L))
939 abort (); 969 abort ();
940#endif 970# endif
941 /* Normalise. */ 971 /* Normalise. */
942 while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) 972 while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
943 m.nlimbs--; 973 m.nlimbs--;
@@ -971,9 +1001,9 @@ decode_double (double x, int *ep, mpn_t *mp)
971 y = frexp (x, &exp); 1001 y = frexp (x, &exp);
972 if (!(y >= 0.0 && y < 1.0)) 1002 if (!(y >= 0.0 && y < 1.0))
973 abort (); 1003 abort ();
974 /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the 1004 /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
975 latter is an integer. */ 1005 latter is an integer. */
976 /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs. 1006 /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs.
977 I'm not sure whether it's safe to cast a 'double' value between 1007 I'm not sure whether it's safe to cast a 'double' value between
978 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only 1008 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
979 'double' values between 0 and 2^16 (to 'unsigned int' or 'int', 1009 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
@@ -1500,7 +1530,7 @@ is_borderline (const char *digits, size_t precision)
1500 1530
1501/* Returns the number of TCHAR_T units needed as temporary space for the result 1531/* Returns the number of TCHAR_T units needed as temporary space for the result
1502 of sprintf or SNPRINTF of a single conversion directive. */ 1532 of sprintf or SNPRINTF of a single conversion directive. */
1503static inline size_t 1533static size_t
1504MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, 1534MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1505 arg_type type, int flags, size_t width, int has_precision, 1535 arg_type type, int flags, size_t width, int has_precision,
1506 size_t precision, int pad_ourselves) 1536 size_t precision, int pad_ourselves)
@@ -1751,8 +1781,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
1751 return NULL; 1781 return NULL;
1752 1782
1753#define CLEANUP() \ 1783#define CLEANUP() \
1754 free (d.dir); \ 1784 if (d.dir != d.direct_alloc_dir) \
1755 if (a.arg) \ 1785 free (d.dir); \
1786 if (a.arg != a.direct_alloc_arg) \
1756 free (a.arg); 1787 free (a.arg);
1757 1788
1758 if (PRINTF_FETCHARGS (args, &a) < 0) 1789 if (PRINTF_FETCHARGS (args, &a) < 0)
@@ -2621,7 +2652,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2621 size_t characters; 2652 size_t characters;
2622# if !DCHAR_IS_TCHAR 2653# if !DCHAR_IS_TCHAR
2623 /* This code assumes that TCHAR_T is 'char'. */ 2654 /* This code assumes that TCHAR_T is 'char'. */
2624 typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1]; 2655 verify (sizeof (TCHAR_T) == 1);
2625 TCHAR_T *tmpsrc; 2656 TCHAR_T *tmpsrc;
2626 DCHAR_T *tmpdst; 2657 DCHAR_T *tmpdst;
2627 size_t tmpdst_len; 2658 size_t tmpdst_len;
@@ -2782,7 +2813,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2782 if (has_width) 2813 if (has_width)
2783 { 2814 {
2784# if ENABLE_UNISTDIO 2815# if ENABLE_UNISTDIO
2785 /* Outside POSIX, it's preferrable to compare the width 2816 /* Outside POSIX, it's preferable to compare the width
2786 against the number of _characters_ of the converted 2817 against the number of _characters_ of the converted
2787 value. */ 2818 value. */
2788 w = DCHAR_MBSNLEN (result + length, characters); 2819 w = DCHAR_MBSNLEN (result + length, characters);
@@ -4597,6 +4628,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4597 TCHAR_T *fbp; 4628 TCHAR_T *fbp;
4598 unsigned int prefix_count; 4629 unsigned int prefix_count;
4599 int prefixes[2] IF_LINT (= { 0 }); 4630 int prefixes[2] IF_LINT (= { 0 });
4631 int orig_errno;
4600#if !USE_SNPRINTF 4632#if !USE_SNPRINTF
4601 size_t tmp_length; 4633 size_t tmp_length;
4602 TCHAR_T tmpbuf[700]; 4634 TCHAR_T tmpbuf[700];
@@ -4751,6 +4783,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4751 *fbp++ = ' '; 4783 *fbp++ = ' ';
4752 if (flags & FLAG_ALT) 4784 if (flags & FLAG_ALT)
4753 *fbp++ = '#'; 4785 *fbp++ = '#';
4786#if __GLIBC__ >= 2 && !defined __UCLIBC__
4787 if (flags & FLAG_LOCALIZED)
4788 *fbp++ = 'I';
4789#endif
4754 if (!pad_ourselves) 4790 if (!pad_ourselves)
4755 { 4791 {
4756 if (flags & FLAG_ZERO) 4792 if (flags & FLAG_ZERO)
@@ -4834,20 +4870,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4834#endif 4870#endif
4835 *fbp = dp->conversion; 4871 *fbp = dp->conversion;
4836#if USE_SNPRINTF 4872#if USE_SNPRINTF
4837# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) 4873# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
4838 fbp[1] = '%'; 4874 fbp[1] = '%';
4839 fbp[2] = 'n'; 4875 fbp[2] = 'n';
4840 fbp[3] = '\0'; 4876 fbp[3] = '\0';
4841# else 4877# else
4842 /* On glibc2 systems from glibc >= 2.3 - probably also older 4878 /* On glibc2 systems from glibc >= 2.3 - probably also older
4843 ones - we know that snprintf's returns value conforms to 4879 ones - we know that snprintf's return value conforms to
4844 ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes. 4880 ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
4881 gl_SNPRINTF_TRUNCATION_C99 pass.
4845 Therefore we can avoid using %n in this situation. 4882 Therefore we can avoid using %n in this situation.
4846 On glibc2 systems from 2004-10-18 or newer, the use of %n 4883 On glibc2 systems from 2004-10-18 or newer, the use of %n
4847 in format strings in writable memory may crash the program 4884 in format strings in writable memory may crash the program
4848 (if compiled with _FORTIFY_SOURCE=2), so we should avoid it 4885 (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
4849 in this situation. */ 4886 in this situation. */
4850 /* On native Win32 systems (such as mingw), we can avoid using 4887 /* On native Windows systems (such as mingw), we can avoid using
4851 %n because: 4888 %n because:
4852 - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, 4889 - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
4853 snprintf does not write more than the specified number 4890 snprintf does not write more than the specified number
@@ -4856,7 +4893,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4856 - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf 4893 - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
4857 allows us to recognize the case of an insufficient 4894 allows us to recognize the case of an insufficient
4858 buffer size: it returns -1 in this case. 4895 buffer size: it returns -1 in this case.
4859 On native Win32 systems (such as mingw) where the OS is 4896 On native Windows systems (such as mingw) where the OS is
4860 Windows Vista, the use of %n in format strings by default 4897 Windows Vista, the use of %n in format strings by default
4861 crashes the program. See 4898 crashes the program. See
4862 <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and 4899 <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
@@ -4900,6 +4937,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4900 *(TCHAR_T *) (result + length) = '\0'; 4937 *(TCHAR_T *) (result + length) = '\0';
4901#endif 4938#endif
4902 4939
4940 orig_errno = errno;
4941
4903 for (;;) 4942 for (;;)
4904 { 4943 {
4905 int count = -1; 4944 int count = -1;
@@ -5114,7 +5153,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5114 size_t tmp_length = 5153 size_t tmp_length =
5115 MAX_ROOM_NEEDED (&a, dp->arg_index, 5154 MAX_ROOM_NEEDED (&a, dp->arg_index,
5116 dp->conversion, type, flags, 5155 dp->conversion, type, flags,
5117 width, has_precision, 5156 has_width ? width : 0,
5157 has_precision,
5118 precision, pad_ourselves); 5158 precision, pad_ourselves);
5119 5159
5120 if (maxlen < tmp_length) 5160 if (maxlen < tmp_length)
@@ -5284,8 +5324,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5284 DCHAR_T *tmpdst; 5324 DCHAR_T *tmpdst;
5285 size_t tmpdst_len; 5325 size_t tmpdst_len;
5286 /* This code assumes that TCHAR_T is 'char'. */ 5326 /* This code assumes that TCHAR_T is 'char'. */
5287 typedef int TCHAR_T_verify 5327 verify (sizeof (TCHAR_T) == 1);
5288 [2 * (sizeof (TCHAR_T) == 1) - 1];
5289# if USE_SNPRINTF 5328# if USE_SNPRINTF
5290 tmpsrc = (TCHAR_T *) (result + length); 5329 tmpsrc = (TCHAR_T *) (result + length);
5291# else 5330# else
@@ -5378,7 +5417,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5378 { 5417 {
5379 size_t w; 5418 size_t w;
5380# if ENABLE_UNISTDIO 5419# if ENABLE_UNISTDIO
5381 /* Outside POSIX, it's preferrable to compare the width 5420 /* Outside POSIX, it's preferable to compare the width
5382 against the number of _characters_ of the converted 5421 against the number of _characters_ of the converted
5383 value. */ 5422 value. */
5384 w = DCHAR_MBSNLEN (result + length, count); 5423 w = DCHAR_MBSNLEN (result + length, count);
@@ -5498,6 +5537,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5498 length += count; 5537 length += count;
5499 break; 5538 break;
5500 } 5539 }
5540 errno = orig_errno;
5501#undef pad_ourselves 5541#undef pad_ourselves
5502#undef prec_ourselves 5542#undef prec_ourselves
5503 } 5543 }