/* vsprintf with automatic memory allocation.
- Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002-2011 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/* Checked size_t computations. */
#include "xsize.h"
+#include "verify.h"
+
#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
# include "float+.h"
multithread-safe on glibc systems and MacOS X 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__ || (defined __APPLE__ && defined __MACH__))
+# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
point = nl_langinfo (RADIXCHAR);
# elif 1
char pointbuf[5];
typedef unsigned int mp_limb_t;
# define GMP_LIMB_BITS 32
-typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
+verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
typedef unsigned long long mp_twolimb_t;
# define GMP_TWOLIMB_BITS 64
-typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
+verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
/* Representation of a bignum >= 0. */
typedef struct
abort ();
m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
-#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
- precision. */
+# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
+ precision. */
if (!(y == 0.0L))
abort ();
-#endif
+# endif
/* Normalise. */
while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
m.nlimbs--;
return NULL;
#define CLEANUP() \
- free (d.dir); \
- if (a.arg) \
+ if (d.dir != d.direct_alloc_dir) \
+ free (d.dir); \
+ if (a.arg != a.direct_alloc_arg) \
free (a.arg);
if (PRINTF_FETCHARGS (args, &a) < 0)
size_t characters;
# if !DCHAR_IS_TCHAR
/* This code assumes that TCHAR_T is 'char'. */
- typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
+ verify (sizeof (TCHAR_T) == 1);
TCHAR_T *tmpsrc;
DCHAR_T *tmpdst;
size_t tmpdst_len;
length += n;
}
}
- }
# endif
+ }
#endif
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
else if ((dp->conversion == 'a' || dp->conversion == 'A')
TCHAR_T *fbp;
unsigned int prefix_count;
int prefixes[2] IF_LINT (= { 0 });
+ int orig_errno;
#if !USE_SNPRINTF
size_t tmp_length;
TCHAR_T tmpbuf[700];
*fbp++ = ' ';
if (flags & FLAG_ALT)
*fbp++ = '#';
+#if __GLIBC__ >= 2 && !defined __UCLIBC__
+ if (flags & FLAG_LOCALIZED)
+ *fbp++ = 'I';
+#endif
if (!pad_ourselves)
{
if (flags & FLAG_ZERO)
#endif
*fbp = dp->conversion;
#if USE_SNPRINTF
-# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
fbp[1] = '%';
fbp[2] = 'n';
fbp[3] = '\0';
# else
/* On glibc2 systems from glibc >= 2.3 - probably also older
- ones - we know that snprintf's returns value conforms to
- ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes.
+ ones - we know that snprintf's return value conforms to
+ ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
+ gl_SNPRINTF_TRUNCATION_C99 pass.
Therefore we can avoid using %n in this situation.
On glibc2 systems from 2004-10-18 or newer, the use of %n
in format strings in writable memory may crash the program
*(TCHAR_T *) (result + length) = '\0';
#endif
+ orig_errno = errno;
+
for (;;)
{
int count = -1;
}
#endif
+ errno = 0;
switch (type)
{
case TYPE_SCHAR:
/* Attempt to handle failure. */
if (count < 0)
{
+ /* SNPRINTF or sprintf failed. Save and use the errno
+ that it has set, if any. */
+ int saved_errno = errno;
+
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno =
- (dp->conversion == 'c' || dp->conversion == 's'
- ? EILSEQ
- : EINVAL);
+ (saved_errno != 0
+ ? saved_errno
+ : (dp->conversion == 'c' || dp->conversion == 's'
+ ? EILSEQ
+ : EINVAL));
return NULL;
}
DCHAR_T *tmpdst;
size_t tmpdst_len;
/* This code assumes that TCHAR_T is 'char'. */
- typedef int TCHAR_T_verify
- [2 * (sizeof (TCHAR_T) == 1) - 1];
+ verify (sizeof (TCHAR_T) == 1);
# if USE_SNPRINTF
tmpsrc = (TCHAR_T *) (result + length);
# else
length += count;
break;
}
+ errno = orig_errno;
+#undef pad_ourselves
+#undef prec_ourselves
}
}
}