summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdio')
-rw-r--r--newlib/libc/stdio/sprintf.c49
-rw-r--r--newlib/libc/stdio/swprintf.c122
-rw-r--r--newlib/libc/stdio/vfwprintf.c35
-rw-r--r--newlib/libc/stdio/vswprintf.c20
4 files changed, 138 insertions, 88 deletions
diff --git a/newlib/libc/stdio/sprintf.c b/newlib/libc/stdio/sprintf.c
index 1d81ebdf9..072622e75 100644
--- a/newlib/libc/stdio/sprintf.c
+++ b/newlib/libc/stdio/sprintf.c
@@ -134,6 +134,8 @@ DESCRIPTION
arguments must be requested somewhere within <[format]>. If
positional parameters are used, then all conversion
specifications except for <<%%>> must specify a position.
+ This positional parameters method is a POSIX extension to the C
+ standard definition for the functions.
o <[flags]>
@@ -147,12 +149,13 @@ DESCRIPTION
o+
o '
- Since newlib only supports the C locale, this
- flag has no effect in this implementation.
- But in other locales, when <[type]> is <<i>>,
- <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>,
- the locale-dependent thousand's separator is
- inserted prior to zero padding.
+ A POSIX extension to the C standard. However, this
+ implementation presently treats it as a no-op, which
+ is the default behavior for the C locale, anyway. (If
+ it did what it is supposed to, when <[type]> were <<i>>,
+ <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, the
+ integer portion of the conversion would be formatted
+ with thousands' grouping wide characters.)
o -
The result of the conversion is left
@@ -180,7 +183,7 @@ DESCRIPTION
o 0
If the <[type]> character is <<d>>, <<i>>,
<<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>,
- <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading
+ <<e>>, <<E>>, <<f>>, <<F>>, <<g>>, or <<G>>: leading
zeros are used to pad the field width
(following any indication of sign or base); no
spaces are used for padding. If the zero
@@ -353,11 +356,10 @@ DESCRIPTION
o z
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
- <<X>>, specifies that the argument is a
- <<ssize_t>> or <<size_t>>.
+ <<X>>, specifies that the argument is a <<size_t>>.
With <<n>>, specifies that the argument is a
- pointer to a <<ssize_t>>.
+ pointer to a <<size_t>>.
o t
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
@@ -389,7 +391,7 @@ DESCRIPTION
character is printed.
o C
- Short for <<%lc>>.
+ Short for <<%lc>>. A POSIX extension to the C standard.
o s
Prints the elements of a pointer to <<char>>
@@ -400,13 +402,13 @@ DESCRIPTION
multibyte characters before printing.
o S
- Short for <<%ls>>.
+ Short for <<%ls>>. A POSIX extension to the C standard.
o d or i
Prints a signed decimal integer; takes an
<<int>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o D
Newlib extension, short for <<%ld>>.
@@ -414,8 +416,8 @@ DESCRIPTION
o o
Prints an unsigned octal integer; takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o O
Newlib extension, short for <<%lo>>.
@@ -423,8 +425,8 @@ DESCRIPTION
o u
Prints an unsigned decimal integer; takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o U
Newlib extension, short for <<%lu>>.
@@ -433,8 +435,8 @@ DESCRIPTION
Prints an unsigned hexadecimal integer (using
<<abcdef>> as digits beyond <<9>>); takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o X
Like <<x>>, but uses <<ABCDEF>> as digits
@@ -540,6 +542,9 @@ If an error occurs, the result of <<printf>>, <<fprintf>>,
to ENOMEM if allocation fails, and for <<snprintf>>, <<errno>> may be
set to EOVERFLOW if <[size]> or the output length exceeds INT_MAX.
+BUGS
+The ``''' (quote) flag does not work when locale's thousands_sep is not empty.
+
PORTABILITY
ANSI C requires <<printf>>, <<fprintf>>, <<sprintf>>, and
<<snprintf>>. <<asprintf>> and <<asnprintf>> are newlib extensions.
@@ -595,7 +600,7 @@ _sprintf_r(ptr, str, fmt, va_alist)
#endif
ret = _svfprintf_r (ptr, &f, fmt, ap);
va_end (ap);
- *f._p = 0;
+ *f._p = '\0'; /* terminate the string */
return (ret);
}
@@ -628,7 +633,7 @@ sprintf(str, fmt, va_alist)
#endif
ret = _svfprintf_r (_REENT, &f, fmt, ap);
va_end (ap);
- *f._p = 0;
+ *f._p = '\0'; /* terminate the string */
return (ret);
}
diff --git a/newlib/libc/stdio/swprintf.c b/newlib/libc/stdio/swprintf.c
index 0d0e4d933..63480176a 100644
--- a/newlib/libc/stdio/swprintf.c
+++ b/newlib/libc/stdio/swprintf.c
@@ -33,25 +33,27 @@ INDEX
_swprintf_r
ANSI_SYNOPSIS
- #include <stdio.h>
+ #include <wchar.h>
int wprintf(const wchar_t *<[format]>, ...);
int fwprintf(FILE *<[fd]>, const wchar_t *<[format]>, ...);
- int swprintf(wchar_t *<[str]>, const wchar_t *<[format]>, ...);
+ int swprintf(wchar_t *<[str]>, size_t <[size]>,
+ const wchar_t *<[format]>, ...);
int _wprintf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...);
int _fwprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>,
- const wchar_t *<[format]>, ...);
+ const wchar_t *<[format]>, ...);
int _swprintf_r(struct _reent *<[ptr]>, wchar_t *<[str]>,
- const wchar_t *<[format]>, ...);
+ size_t <[size]>, const wchar_t *<[format]>, ...);
DESCRIPTION
<<wprintf>> accepts a series of arguments, applies to each a
format specifier from <<*<[format]>>>, and writes the
formatted data to <<stdout>>, without a terminating NUL
wide character. The behavior of <<wprintf>> is undefined if there
- are not enough arguments for the format. <<wprintf>> returns
- when it reaches the end of the format string. If there are
+ are not enough arguments for the format or if any argument is not the
+ right type for the corresponding conversion specifier. <<wprintf>>
+ returns when it reaches the end of the format string. If there are
more arguments than the format requires, excess arguments are
ignored.
@@ -59,10 +61,14 @@ DESCRIPTION
to the stream <[fd]> rather than <<stdout>>.
<<swprintf>> is like <<wprintf>>, except that output is directed
- to the buffer <[str]>, and the resulting string length is limited
- to at most <[size]> wide characters, including the terminating
- <<NUL>>. As a special case, if <[size]> is 0, <[str]> can be NULL,
- and <<swprintf>> merely calculates how many bytes would be printed.
+ to the buffer <[str]> with a terminating wide <<NUL>>, and the
+ resulting string length is limited to at most <[size]> wide characters,
+ including the terminating <<NUL>>. It is considered an error if the
+ output (including the terminating wide-<<NULL>>) does not fit into
+ <[size]> wide characters. (This error behavior is not the same as for
+ <<snprintf>>, which <<swprintf>> is otherwise completely analogous to.
+ While <<snprintf>> allows the needed size to be known simply by giving
+ <[size]>=0, <<swprintf>> does not, giving an error instead.)
For <<swprintf>> the behavior is undefined if the output
<<*<[str]>>> overlaps with one of the arguments. Behavior is also
@@ -95,6 +101,8 @@ DESCRIPTION
arguments must be requested somewhere within <[format]>. If
positional parameters are used, then all conversion
specifications except for <<%%>> must specify a position.
+ This positional parameters method is a POSIX extension to the C
+ standard definition for the functions.
o <[flags]>
@@ -108,12 +116,13 @@ DESCRIPTION
o+
o '
- Since newlib only supports the C locale, this
- flag has no effect in this implementation.
- But in other locales, when <[type]> is <<i>>,
- <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>,
- the locale-dependent thousand's separator is
- inserted prior to zero padding.
+ A POSIX extension to the C standard. However, this
+ implementation presently treats it as a no-op, which
+ is the default behavior for the C locale, anyway. (If
+ it did what it is supposed to, when <[type]> were <<i>>,
+ <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, the
+ integer portion of the conversion would be formatted
+ with thousands' grouping wide characters.)
o -
The result of the conversion is left
@@ -141,7 +150,7 @@ DESCRIPTION
o 0
If the <[type]> character is <<d>>, <<i>>,
<<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>,
- <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading
+ <<e>>, <<E>>, <<f>>, <<F>>, <<g>>, or <<G>>: leading
zeros are used to pad the field width
(following any indication of sign or base); no
spaces are used for padding. If the zero
@@ -314,11 +323,10 @@ DESCRIPTION
o z
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
- <<X>>, specifies that the argument is a
- <<ssize_t>> or <<size_t>>.
+ <<X>>, specifies that the argument is a <<size_t>>.
With <<n>>, specifies that the argument is a
- pointer to a <<ssize_t>>.
+ pointer to a <<size_t>>.
o t
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
@@ -352,7 +360,7 @@ DESCRIPTION
shall be converted to wchar_t, and written.
o C
- Short for <<%lc>>.
+ Short for <<%lc>>. A POSIX extension to the C standard.
o s
If no <<l>> qualifier is present, the application
@@ -383,32 +391,32 @@ DESCRIPTION
written.
o S
- Short for <<%ls>>.
+ Short for <<%ls>>. A POSIX extension to the C standard.
o d or i
Prints a signed decimal integer; takes an
<<int>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o o
Prints an unsigned octal integer; takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o u
Prints an unsigned decimal integer; takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o x
Prints an unsigned hexadecimal integer (using
<<abcdef>> as digits beyond <<9>>); takes an
<<unsigned>>. Leading zeros are inserted as
- necessary to reach the precision. A precision
- of 0 produces an empty string.
+ necessary to reach the precision. A value of 0 with
+ a precision of 0 produces an empty string.
o X
Like <<x>>, but uses <<ABCDEF>> as digits
@@ -503,12 +511,16 @@ the output string, except the concluding <<NUL>> is not counted.
If an error occurs, the result of <<wprintf>>, <<fwprintf>>, and
<<swprintf>> is a negative value. For <<wprintf>> and <<fwprintf>>,
-<<errno>> may be set according to <<fputwc>>. For <<snwprintf>>, <<errno>>
-may be set to EOVERFLOW if <[size]> or the output length exceeds
-INT_MAX / sizeof (wchar_t).
+<<errno>> may be set according to <<fputwc>>. For <<swprintf>>, <<errno>>
+may be set to EOVERFLOW if <[size]> is greater than INT_MAX / sizeof (wchar_t),
+or when the output does not fit into <[size]> wide characters (including the
+terminating wide <<NULL>>).
+
+BUGS
+The ``''' (quote) flag does not work when locale's thousands_sep is not empty.
PORTABILITY
-POSIX-1.2008
+POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
Depending on how newlib was configured, not all format specifiers are
supported.
@@ -527,6 +539,10 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <errno.h>
#include "local.h"
+/* NOTE: _swprintf_r() should be identical to swprintf() except for the
+ * former having ptr as a parameter and the latter needing to declare it as
+ * a variable set to _REENT. */
+
int
_DEFUN(_swprintf_r, (ptr, str, size, fmt),
struct _reent *ptr _AND
@@ -540,7 +556,7 @@ _DEFUN(_swprintf_r, (ptr, str, size, fmt),
if (size > INT_MAX / sizeof (wchar_t))
{
- ptr->_errno = EOVERFLOW;
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF;
}
f._flags = __SWR | __SSTR;
@@ -550,10 +566,19 @@ _DEFUN(_swprintf_r, (ptr, str, size, fmt),
va_start (ap, fmt);
ret = _svfwprintf_r (ptr, &f, fmt, ap);
va_end (ap);
- if (ret < EOF)
- ptr->_errno = EOVERFLOW;
- if (size > 0)
- *f._p = 0;
+ /* _svfwprintf_r() does not put in a terminating NUL, so add one if
+ * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
+ * after n-1, so always just put at the end. */
+ if (size > 0) {
+ *(wchar_t *)f._p = L'\0'; /* terminate the string */
+ }
+ if(ret >= size) {
+ /* _svfwprintf_r() returns how many wide characters it would have printed
+ * if there were enough space. Return an error if too big to fit in str,
+ * unlike snprintf, which returns the size needed. */
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
+ ret = -1;
+ }
return (ret);
}
@@ -572,7 +597,7 @@ _DEFUN(swprintf, (str, size, fmt),
if (size > INT_MAX / sizeof (wchar_t))
{
- ptr->_errno = EOVERFLOW;
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF;
}
f._flags = __SWR | __SSTR;
@@ -582,10 +607,19 @@ _DEFUN(swprintf, (str, size, fmt),
va_start (ap, fmt);
ret = _svfwprintf_r (ptr, &f, fmt, ap);
va_end (ap);
- if (ret < EOF)
- ptr->_errno = EOVERFLOW;
- if (size > 0)
- *f._p = 0;
+ /* _svfwprintf_r() does not put in a terminating NUL, so add one if
+ * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
+ * after n-1, so always just put at the end. */
+ if (size > 0) {
+ *(wchar_t *)f._p = L'\0'; /* terminate the string */
+ }
+ if(ret >= size) {
+ /* _svfwprintf_r() returns how many wide characters it would have printed
+ * if there were enough space. Return an error if too big to fit in str,
+ * unlike snprintf, which returns the size needed. */
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
+ ret = -1;
+ }
return (ret);
}
diff --git a/newlib/libc/stdio/vfwprintf.c b/newlib/libc/stdio/vfwprintf.c
index 991a2d52f..68e92a8a6 100644
--- a/newlib/libc/stdio/vfwprintf.c
+++ b/newlib/libc/stdio/vfwprintf.c
@@ -50,17 +50,18 @@ INDEX
ANSI_SYNOPSIS
#include <stdio.h>
#include <stdarg.h>
+ #include <wchar.h>
int vwprintf(const wchar_t *<[fmt]>, va_list <[list]>);
int vfwprintf(FILE *<[fp]>, const wchar_t *<[fmt]>, va_list <[list]>);
- int vswprintf(wchar_t *<[str]>, const wchar_t *<[fmt]>,
- va_list <[list]>);
+ int vswprintf(wchar_t *<[str]>, size_t <[size]>, const wchar_t *<[fmt]>,
+ va_list <[list]>);
int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>,
- va_list <[list]>);
+ va_list <[list]>);
int _vfwprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
- const wchar_t *<[fmt]>, va_list <[list]>);
+ const wchar_t *<[fmt]>, va_list <[list]>);
int _vswprintf_r(struct _reent *<[reent]>, wchar_t *<[str]>,
- const wchar_t *<[fmt]>, va_list <[list]>);
+ size_t <[size]>, const wchar_t *<[fmt]>, va_list <[list]>);
DESCRIPTION
<<vwprintf>>, <<vfwprintf>> and <<vswprintf>> are (respectively) variants
@@ -76,10 +77,13 @@ RETURNS
The return values are consistent with the corresponding functions.
PORTABILITY
-POSIX-1.2008
+POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
+
+SEEALSO
+<<wprintf>>, <<fwprintf>> and <<swprintf>>.
*/
/*
@@ -244,7 +248,7 @@ static int wexponent(wchar_t *, int, int);
mantissa, this would be 29 characters). %e, %f, and %g use
reentrant storage shared with mprec. All other formats that use
buf get by with fewer characters. Making BUF slightly bigger
- reduces the need for malloc in %.*a and %S, when large precision or
+ reduces the need for malloc in %.*a and %ls/%S, when large precision or
long strings are processed. */
#define BUF 40
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
@@ -396,7 +400,7 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
#define NIOV 8
struct __suio uio; /* output information: summary */
struct __siov iov[NIOV];/* ... and individual io vectors */
- wchar_t buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */
+ wchar_t buf[BUF]; /* space for %c, %ls/%S, %[diouxX], %[aA] */
wchar_t ox[2]; /* space for 0x hex-prefix */
wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */
@@ -576,10 +580,7 @@ reswitch: switch (ch) {
#ifdef _WANT_IO_C99_FORMATS
case L'\'':
/* The ' flag is required by POSIX, but not C99.
- In the C locale, LC_NUMERIC requires
- thousands_sep to be the empty string. And since
- no other locales are supported (yet), this flag
- is currently a no-op. */
+ FIXME: this flag is currently a no-op. */
goto rflag;
#endif
case L' ':
@@ -742,7 +743,7 @@ reswitch: switch (ch) {
#endif
flags |= LONGINT;
goto rflag;
- case L'q': /* extension */
+ case L'q': /* GNU extension */
flags |= QUADINT;
goto rflag;
#ifdef _WANT_IO_C99_FORMATS
@@ -783,7 +784,7 @@ reswitch: switch (ch) {
have ptrdiff_t as wide as long long. */
flags |= QUADINT;
goto rflag;
- case L'C':
+ case L'C': /* POSIX extension */
#endif /* _WANT_IO_C99_FORMATS */
case L'c':
cp = buf;
@@ -1001,7 +1002,7 @@ reswitch: switch (ch) {
goto nosign;
case L's':
#ifdef _WANT_IO_C99_FORMATS
- case L'S':
+ case L'S': /* POSIX extension */
#endif
sign = '\0';
cp = GET_ARG (N, ap, wchar_ptr_t);
@@ -1640,7 +1641,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
break;
case L's':
# ifdef _WANT_IO_C99_FORMATS
- case L'S':
+ case L'S': /* POSIX extension */
# endif
case L'p':
case L'n':
@@ -1655,7 +1656,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
spec_type = INT;
break;
# ifdef _WANT_IO_C99_FORMATS
- case L'C':
+ case L'C': /* POSIX extension */
spec_type = WIDE_CHAR;
break;
# endif
diff --git a/newlib/libc/stdio/vswprintf.c b/newlib/libc/stdio/vswprintf.c
index aebb20a00..2d9096c15 100644
--- a/newlib/libc/stdio/vswprintf.c
+++ b/newlib/libc/stdio/vswprintf.c
@@ -27,6 +27,7 @@ static char sccsid[] = "%W% (Berkeley) %G%";
#include <limits.h>
#include <stdarg.h>
#include <errno.h>
+
#include "local.h"
int
@@ -42,7 +43,7 @@ _DEFUN(_vswprintf_r, (ptr, str, size, fmt, ap),
if (size > INT_MAX / sizeof (wchar_t))
{
- ptr->_errno = EOVERFLOW;
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF;
}
f._flags = __SWR | __SSTR;
@@ -50,10 +51,19 @@ _DEFUN(_vswprintf_r, (ptr, str, size, fmt, ap),
f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0);
f._file = -1; /* No file. */
ret = _svfwprintf_r (ptr, &f, fmt, ap);
- if (ret < EOF)
- ptr->_errno = EOVERFLOW;
- if (size > 0)
- *f._p = 0;
+ /* _svfwprintf_r() does not put in a terminating NUL, so add one if
+ * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
+ * after n-1, so always just put at the end. */
+ if (size > 0) {
+ *(wchar_t *)f._p = L'\0'; /* terminate the string */
+ }
+ if(ret >= size) {
+ /* _svfwprintf_r() returns how many wide characters it would have printed
+ * if there were enough space. Return an error if too big to fit in str,
+ * unlike snprintf, which returns the size needed. */
+ ptr->_errno = EOVERFLOW; /* POSIX extension */
+ ret = -1;
+ }
return ret;
}