diff options
Diffstat (limited to 'newlib/libc/stdio')
-rw-r--r-- | newlib/libc/stdio/sprintf.c | 49 | ||||
-rw-r--r-- | newlib/libc/stdio/swprintf.c | 122 | ||||
-rw-r--r-- | newlib/libc/stdio/vfwprintf.c | 35 | ||||
-rw-r--r-- | newlib/libc/stdio/vswprintf.c | 20 |
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; } |