/* Formatted output to strings, using POSIX/XSI format strings with positions.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2007, 2009 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software; you can redistribute it and/or modify it
You should have received a copy of the GNU Library General Public
License along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA. */
#ifdef HAVE_CONFIG_H
#if !HAVE_POSIX_PRINTF
+#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
/* When building a DLL, we must export some functions. Note that because
the functions are only defined for binary backward compatibility, we
don't need to use __declspec(dllimport) in any case. */
-#if defined _MSC_VER && BUILDING_DLL
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
# define DLL_EXPORTED __declspec(dllexport)
#else
# define DLL_EXPORTED
#define STATIC static
+/* This needs to be consistent with libgnuintl.h.in. */
+#if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
+/* Don't break __attribute__((format(printf,M,N))).
+ This redefinition is only possible because the libc in NetBSD, Cygwin,
+ mingw does not have a function __printf__. */
+# define libintl_printf __printf__
+#endif
+
/* Define auxiliary functions declared in "printf-args.h". */
#include "printf-args.c"
char *result = libintl_vasnprintf (NULL, &length, format, args);
int retval = -1;
if (result != NULL)
- {
- if (fwrite (result, 1, length, stream) == length)
- retval = length;
- free (result);
- }
+ {
+ size_t written = fwrite (result, 1, length, stream);
+ free (result);
+ if (written == length)
+ {
+ if (length > INT_MAX)
+ errno = EOVERFLOW;
+ else
+ retval = length;
+ }
+ }
return retval;
}
}
size_t length = (size_t) ~0 / (4 * sizeof (char));
char *result = libintl_vasnprintf (resultbuf, &length, format, args);
if (result != resultbuf)
- {
- free (result);
- return -1;
- }
+ {
+ free (result);
+ return -1;
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
else
- return length;
+ return length;
}
}
size_t maxlength = length;
char *result = libintl_vasnprintf (resultbuf, &length, format, args);
if (result != resultbuf)
- {
- if (maxlength > 0)
- {
- if (length < maxlength)
- abort ();
- memcpy (resultbuf, result, maxlength - 1);
- resultbuf[maxlength - 1] = '\0';
- }
- free (result);
- return -1;
- }
+ {
+ if (maxlength > 0)
+ {
+ size_t pruned_length =
+ (length < maxlength ? length : maxlength - 1);
+ memcpy (resultbuf, result, pruned_length);
+ resultbuf[pruned_length] = '\0';
+ }
+ free (result);
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
else
- return length;
+ return length;
}
}
char *result = libintl_vasnprintf (NULL, &length, format, args);
if (result == NULL)
return -1;
+ if (length > INT_MAX)
+ {
+ free (result);
+ errno = EOVERFLOW;
+ return -1;
+ }
*resultp = result;
return length;
}
#define WIDE_CHAR_VERSION 1
+#include "wprintf-parse.h"
/* Define auxiliary functions declared in "wprintf-parse.h". */
+#define CHAR_T wchar_t
+#define DIRECTIVE wchar_t_directive
+#define DIRECTIVES wchar_t_directives
+#define PRINTF_PARSE wprintf_parse
#include "printf-parse.c"
/* Define functions declared in "vasnprintf.h". */
wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
int retval = -1;
if (result != NULL)
- {
- size_t i;
- for (i = 0; i < length; i++)
- if (fputwc (result[i], stream) == WEOF)
- break;
- if (i == length)
- retval = length;
- free (result);
- }
+ {
+ size_t i;
+ for (i = 0; i < length; i++)
+ if (fputwc (result[i], stream) == WEOF)
+ break;
+ free (result);
+ if (i == length)
+ {
+ if (length > INT_MAX)
+ errno = EOVERFLOW;
+ else
+ retval = length;
+ }
+ }
return retval;
}
}
size_t maxlength = length;
wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
if (result != resultbuf)
- {
- if (maxlength > 0)
- {
- if (length < maxlength)
- abort ();
- memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t));
- resultbuf[maxlength - 1] = 0;
- }
- free (result);
- return -1;
- }
+ {
+ if (maxlength > 0)
+ {
+ size_t pruned_length =
+ (length < maxlength ? length : maxlength - 1);
+ memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
+ resultbuf[pruned_length] = 0;
+ }
+ free (result);
+ /* Unlike vsnprintf, which has to return the number of character that
+ would have been produced if the resultbuf had been sufficiently
+ large, the vswprintf function has to return a negative value if
+ the resultbuf was not sufficiently large. */
+ if (length >= maxlength)
+ return -1;
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
else
- return length;
+ return length;
}
}