From 4a825d4145f7a4d409f355b478781fa6742fabbf Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 12 Mar 2009 10:27:10 +0000 Subject: * libc/stdio/swprintf.c (_swprintf_r, swprintf): correct how terminating L'\0' is added; change return to match standard for when output does not fit; some corrections and enhancements to the docs. * libc/stdio/vswprintf.c (_vswprintf_r): ditto, except for docs. * libc/stdio/vfwprintf.c: some corrections to the docs and some enhancements to comments. (No code changes.) * libc/time/strftime.c: Correct some problems that made wcsftime() not work correctly: work properly with swprintf returns that are different from snprintf returns, correct test vector lengths for when sizeof(wchar_t) > 1. * libc/stdio/sprintf.c: Some documentation and comment corrections and enhancements to match those done to swprintf.c. --- newlib/libc/stdio/swprintf.c | 122 +++++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 44 deletions(-) (limited to 'newlib/libc/stdio/swprintf.c') 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 + #include 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 <> accepts a series of arguments, applies to each a format specifier from <<*<[format]>>>, and writes the formatted data to <>, without a terminating NUL wide character. The behavior of <> is undefined if there - are not enough arguments for the format. <> 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. <> + 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 <>. <> is like <>, 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 - <>. As a special case, if <[size]> is 0, <[str]> can be NULL, - and <> merely calculates how many bytes would be printed. + to the buffer <[str]> with a terminating wide <>, and the + resulting string length is limited to at most <[size]> wide characters, + including the terminating <>. It is considered an error if the + output (including the terminating wide-<>) does not fit into + <[size]> wide characters. (This error behavior is not the same as for + <>, which <> is otherwise completely analogous to. + While <> allows the needed size to be known simply by giving + <[size]>=0, <> does not, giving an error instead.) For <> 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 <>, - <>, <>, <>, <>, <>, or <>, - 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 <>, + <>, <>, <>, <>, <>, or <>, 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 <>, <>, <>, <>, <>, <>, <>, <>, - <>, <>, <>, <>, or <>: leading + <>, <>, <>, <>, <>, or <>: 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 <>, <>, <>, <>, <>, or - <>, specifies that the argument is a - <> or <>. + <>, specifies that the argument is a <>. With <>, specifies that the argument is a - pointer to a <>. + pointer to a <>. o t With <>, <>, <>, <>, <>, 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 <> 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 <>. 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 <>. 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 <>. 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 <> as digits beyond <<9>>); takes an <>. 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 <>, but uses <> as digits @@ -503,12 +511,16 @@ the output string, except the concluding <> is not counted. If an error occurs, the result of <>, <>, and <> is a negative value. For <> and <>, -<> may be set according to <>. For <>, <> -may be set to EOVERFLOW if <[size]> or the output length exceeds -INT_MAX / sizeof (wchar_t). +<> may be set according to <>. For <>, <> +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 <>). + +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: <>, <>, <>, #include #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); } -- cgit v1.2.3