extern int sb_ensure_more_bytes (struct string_buffer *buffer,
size_t increment);
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
{
va_list list_copy;
- /* Make a bit of room, so that the probability that the first vsnprintf() call
- succeeds is high. */
+ /* Make a bit of room, so that the probability that the first vsnzprintf()
+ call succeeds is high. */
size_t room = buffer->allocated - buffer->length;
if (room < 64)
{
if (sb_ensure_more_bytes (buffer, 64) < 0)
{
buffer->error = true;
+ errno = ENOMEM;
return -1;
}
room = buffer->allocated - buffer->length;
va_copy (list_copy, list);
- /* First vsnprintf() call. */
- int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, list);
+ /* First vsnzprintf() call. */
+ ptrdiff_t ret = vsnzprintf (buffer->data + buffer->length, room,
+ formatstring, list);
if (ret < 0)
{
- /* Failed. */
+ /* Failed. errno is set. */
buffer->error = true;
ret = -1;
}
else
{
- if ((size_t) ret <= room)
+ if (ret <= room)
{
/* The result has fit into room bytes. */
buffer->length += (size_t) ret;
}
else
{
- /* The result was truncated. Make more room, for a second vsnprintf()
- call. */
+ /* The result was truncated. Make more room, for a second
+ vsnzprintf() call. */
if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
{
buffer->error = true;
+ errno = ENOMEM;
ret = -1;
}
else
{
- /* Second vsnprintf() call. */
+ /* Second vsnzprintf() call. */
room = buffer->allocated - buffer->length;
- ret = vsnprintf (buffer->data + buffer->length, room,
- formatstring, list_copy);
+ ret = vsnzprintf (buffer->data + buffer->length, room,
+ formatstring, list_copy);
if (ret < 0)
{
- /* Failed. */
+ /* Failed. errno is set. */
buffer->error = true;
ret = -1;
}
else
{
- if ((size_t) ret <= room)
+ if (ret <= room)
{
/* The result has fit into room bytes. */
buffer->length += (size_t) ret;
ret = 0;
}
else
- /* The return values of the vsnprintf() calls are not
+ /* The return values of the vsnzprintf() calls are not
consistent. */
abort ();
}
{
va_list args;
- /* Make a bit of room, so that the probability that the first vsnprintf() call
- succeeds is high. */
+ /* Make a bit of room, so that the probability that the first vsnzprintf()
+ call succeeds is high. */
size_t room = buffer->allocated - buffer->length;
if (room < 64)
{
if (sb_ensure_more_bytes (buffer, 64) < 0)
{
buffer->error = true;
+ errno = ENOMEM;
return -1;
}
room = buffer->allocated - buffer->length;
va_start (args, formatstring);
- /* First vsnprintf() call. */
- int ret = vsnprintf (buffer->data + buffer->length, room, formatstring, args);
+ /* First vsnzprintf() call. */
+ ptrdiff_t ret = vsnzprintf (buffer->data + buffer->length, room,
+ formatstring, args);
if (ret < 0)
{
- /* Failed. */
+ /* Failed. errno is set. */
buffer->error = true;
ret = -1;
}
else
{
- if ((size_t) ret <= room)
+ if (ret <= room)
{
/* The result has fit into room bytes. */
buffer->length += (size_t) ret;
}
else
{
- /* The result was truncated. Make more room, for a second vsnprintf()
- call. */
+ /* The result was truncated. Make more room, for a second
+ vsnzprintf() call. */
if (sb_ensure_more_bytes (buffer, (size_t) ret) < 0)
{
buffer->error = true;
+ errno = ENOMEM;
ret = -1;
}
else
{
- /* Second vsnprintf() call. */
+ /* Second vsnzprintf() call. */
room = buffer->allocated - buffer->length;
va_end (args);
va_start (args, formatstring);
- ret = vsnprintf (buffer->data + buffer->length, room,
- formatstring, args);
+ ret = vsnzprintf (buffer->data + buffer->length, room,
+ formatstring, args);
if (ret < 0)
{
- /* Failed. */
+ /* Failed. errno is set. */
buffer->error = true;
ret = -1;
}
else
{
- if ((size_t) ret <= room)
+ if (ret <= room)
{
/* The result has fit into room bytes. */
buffer->length += (size_t) ret;
ret = 0;
}
else
- /* The return values of the vsnprintf() calls are not
+ /* The return values of the vsnzprintf() calls are not
consistent. */
abort ();
}
/* Appends the result of the printf-compatible FORMATSTRING with the argument
list LIST to BUFFER.
- Returns 0, or -1 in case of error. */
+ Returns 0, or -1 with errno set in case of error.
+ Error code EOVERFLOW can only occur when a width > INT_MAX is used.
+ Therefore, if the format string is valid and does not use %ls/%lc
+ directives nor widths, the only possible error code is ENOMEM. */
extern int sb_appendvf (struct string_buffer *buffer,
const char *formatstring, va_list list)
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
/* Appends the result of the printf-compatible FORMATSTRING with the following
arguments to BUFFER.
- Returns 0, or -1 in case of error. */
+ Returns 0, or -1 with errno set in case of error.
+ Error code EOVERFLOW can only occur when a width > INT_MAX is used.
+ Therefore, if the format string is valid and does not use %ls/%lc
+ directives nor widths, the only possible error code is ENOMEM. */
extern int sb_appendf (struct string_buffer *buffer,
const char *formatstring, ...)
#if (__GNUC__ + (__GNUC_MINOR__ >= 4) > 4) && !defined __clang__
#include "string-buffer.h"
+#include <errno.h>
#include <string.h>
#include <wchar.h>
/* Test printf-like formatting failure.
On all systems except AIX, trying to convert the wide-character 0x76543210
to a multibyte string (in the "C" locale) fails.
- On all systems where REPLACE_VSNPRINTF=1 (this includes AIX), i.e. where
- the Gnulib implementation of vsnprintf() is used), invalid format
- directives make the *printf call fail. */
+ On all systems, invalid format directives make the vsnzprintf() call
+ fail. */
{
struct string_buffer buffer;
+ int ret;
sb_init (&buffer);
sb_append (&buffer, "<");
- sb_appendf (&buffer, "%lc", (wint_t) 0x76543210);
+
+ ret = sb_appendf (&buffer, "%lc", (wint_t) 0x76543210);
+ #if !defined _AIX
+ ASSERT (ret < 0);
+ ASSERT (errno == EILSEQ);
+ #endif
+
sb_append (&buffer, "|");
- sb_appendf (&buffer, invalid_format_string_1, 1);
+
+ ret = sb_appendf (&buffer, invalid_format_string_1, 1);
+ ASSERT (ret < 0);
+ ASSERT (errno == EINVAL);
+
sb_append (&buffer, "|");
- sb_appendf (&buffer, invalid_format_string_2, 2);
+
+ ret = sb_appendf (&buffer, invalid_format_string_2, 2);
+ ASSERT (ret < 0);
+ ASSERT (errno == EINVAL);
+
sb_append (&buffer, ">");
char *s = sb_dupfree (&buffer);
ASSERT (s == NULL);