* 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.
This commit is contained in:
Corinna Vinschen 2009-03-12 10:27:10 +00:00
parent cab0758eb2
commit 4a825d4145
6 changed files with 210 additions and 140 deletions

View File

@ -1,3 +1,19 @@
2009-03-09 Craig Howland <howland@LGSInnovations.com>
* 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.
2009-03-11 Corinna Vinschen <corinna@vinschen.de> 2009-03-11 Corinna Vinschen <corinna@vinschen.de>
* libc/include/wchar.h (wcscasecmp, wcsncasecmp): Declare. * libc/include/wchar.h (wcscasecmp, wcsncasecmp): Declare.

View File

@ -134,6 +134,8 @@ DESCRIPTION
arguments must be requested somewhere within <[format]>. If arguments must be requested somewhere within <[format]>. If
positional parameters are used, then all conversion positional parameters are used, then all conversion
specifications except for <<%%>> must specify a position. 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]> o <[flags]>
@ -147,12 +149,13 @@ DESCRIPTION
o+ o+
o ' o '
Since newlib only supports the C locale, this A POSIX extension to the C standard. However, this
flag has no effect in this implementation. implementation presently treats it as a no-op, which
But in other locales, when <[type]> is <<i>>, is the default behavior for the C locale, anyway. (If
<<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, it did what it is supposed to, when <[type]> were <<i>>,
the locale-dependent thousand's separator is <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, the
inserted prior to zero padding. integer portion of the conversion would be formatted
with thousands' grouping wide characters.)
o - o -
The result of the conversion is left The result of the conversion is left
@ -180,7 +183,7 @@ DESCRIPTION
o 0 o 0
If the <[type]> character is <<d>>, <<i>>, If the <[type]> character is <<d>>, <<i>>,
<<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>, <<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 zeros are used to pad the field width
(following any indication of sign or base); no (following any indication of sign or base); no
spaces are used for padding. If the zero spaces are used for padding. If the zero
@ -353,11 +356,10 @@ DESCRIPTION
o z o z
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
<<X>>, specifies that the argument is a <<X>>, specifies that the argument is a <<size_t>>.
<<ssize_t>> or <<size_t>>.
With <<n>>, specifies that the argument is a With <<n>>, specifies that the argument is a
pointer to a <<ssize_t>>. pointer to a <<size_t>>.
o t o t
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
@ -389,7 +391,7 @@ DESCRIPTION
character is printed. character is printed.
o C o C
Short for <<%lc>>. Short for <<%lc>>. A POSIX extension to the C standard.
o s o s
Prints the elements of a pointer to <<char>> Prints the elements of a pointer to <<char>>
@ -400,13 +402,13 @@ DESCRIPTION
multibyte characters before printing. multibyte characters before printing.
o S o S
Short for <<%ls>>. Short for <<%ls>>. A POSIX extension to the C standard.
o d or i o d or i
Prints a signed decimal integer; takes an Prints a signed decimal integer; takes an
<<int>>. Leading zeros are inserted as <<int>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o D o D
Newlib extension, short for <<%ld>>. Newlib extension, short for <<%ld>>.
@ -414,8 +416,8 @@ DESCRIPTION
o o o o
Prints an unsigned octal integer; takes an Prints an unsigned octal integer; takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o O o O
Newlib extension, short for <<%lo>>. Newlib extension, short for <<%lo>>.
@ -423,8 +425,8 @@ DESCRIPTION
o u o u
Prints an unsigned decimal integer; takes an Prints an unsigned decimal integer; takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o U o U
Newlib extension, short for <<%lu>>. Newlib extension, short for <<%lu>>.
@ -433,8 +435,8 @@ DESCRIPTION
Prints an unsigned hexadecimal integer (using Prints an unsigned hexadecimal integer (using
<<abcdef>> as digits beyond <<9>>); takes an <<abcdef>> as digits beyond <<9>>); takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o X o X
Like <<x>>, but uses <<ABCDEF>> as digits 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 to ENOMEM if allocation fails, and for <<snprintf>>, <<errno>> may be
set to EOVERFLOW if <[size]> or the output length exceeds INT_MAX. 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 PORTABILITY
ANSI C requires <<printf>>, <<fprintf>>, <<sprintf>>, and ANSI C requires <<printf>>, <<fprintf>>, <<sprintf>>, and
<<snprintf>>. <<asprintf>> and <<asnprintf>> are newlib extensions. <<snprintf>>. <<asprintf>> and <<asnprintf>> are newlib extensions.
@ -595,7 +600,7 @@ _sprintf_r(ptr, str, fmt, va_alist)
#endif #endif
ret = _svfprintf_r (ptr, &f, fmt, ap); ret = _svfprintf_r (ptr, &f, fmt, ap);
va_end (ap); va_end (ap);
*f._p = 0; *f._p = '\0'; /* terminate the string */
return (ret); return (ret);
} }
@ -628,7 +633,7 @@ sprintf(str, fmt, va_alist)
#endif #endif
ret = _svfprintf_r (_REENT, &f, fmt, ap); ret = _svfprintf_r (_REENT, &f, fmt, ap);
va_end (ap); va_end (ap);
*f._p = 0; *f._p = '\0'; /* terminate the string */
return (ret); return (ret);
} }

View File

@ -33,25 +33,27 @@ INDEX
_swprintf_r _swprintf_r
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdio.h> #include <wchar.h>
int wprintf(const wchar_t *<[format]>, ...); int wprintf(const wchar_t *<[format]>, ...);
int fwprintf(FILE *<[fd]>, 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 _wprintf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...);
int _fwprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>, 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]>, int _swprintf_r(struct _reent *<[ptr]>, wchar_t *<[str]>,
const wchar_t *<[format]>, ...); size_t <[size]>, const wchar_t *<[format]>, ...);
DESCRIPTION DESCRIPTION
<<wprintf>> accepts a series of arguments, applies to each a <<wprintf>> accepts a series of arguments, applies to each a
format specifier from <<*<[format]>>>, and writes the format specifier from <<*<[format]>>>, and writes the
formatted data to <<stdout>>, without a terminating NUL formatted data to <<stdout>>, without a terminating NUL
wide character. The behavior of <<wprintf>> is undefined if there wide character. The behavior of <<wprintf>> is undefined if there
are not enough arguments for the format. <<wprintf>> returns are not enough arguments for the format or if any argument is not the
when it reaches the end of the format string. If there are 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 more arguments than the format requires, excess arguments are
ignored. ignored.
@ -59,10 +61,14 @@ DESCRIPTION
to the stream <[fd]> rather than <<stdout>>. to the stream <[fd]> rather than <<stdout>>.
<<swprintf>> is like <<wprintf>>, except that output is directed <<swprintf>> is like <<wprintf>>, except that output is directed
to the buffer <[str]>, and the resulting string length is limited to the buffer <[str]> with a terminating wide <<NUL>>, and the
to at most <[size]> wide characters, including the terminating resulting string length is limited to at most <[size]> wide characters,
<<NUL>>. As a special case, if <[size]> is 0, <[str]> can be NULL, including the terminating <<NUL>>. It is considered an error if the
and <<swprintf>> merely calculates how many bytes would be printed. 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 For <<swprintf>> the behavior is undefined if the output
<<*<[str]>>> overlaps with one of the arguments. Behavior is also <<*<[str]>>> overlaps with one of the arguments. Behavior is also
@ -95,6 +101,8 @@ DESCRIPTION
arguments must be requested somewhere within <[format]>. If arguments must be requested somewhere within <[format]>. If
positional parameters are used, then all conversion positional parameters are used, then all conversion
specifications except for <<%%>> must specify a position. 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]> o <[flags]>
@ -108,12 +116,13 @@ DESCRIPTION
o+ o+
o ' o '
Since newlib only supports the C locale, this A POSIX extension to the C standard. However, this
flag has no effect in this implementation. implementation presently treats it as a no-op, which
But in other locales, when <[type]> is <<i>>, is the default behavior for the C locale, anyway. (If
<<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, it did what it is supposed to, when <[type]> were <<i>>,
the locale-dependent thousand's separator is <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, the
inserted prior to zero padding. integer portion of the conversion would be formatted
with thousands' grouping wide characters.)
o - o -
The result of the conversion is left The result of the conversion is left
@ -141,7 +150,7 @@ DESCRIPTION
o 0 o 0
If the <[type]> character is <<d>>, <<i>>, If the <[type]> character is <<d>>, <<i>>,
<<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>, <<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 zeros are used to pad the field width
(following any indication of sign or base); no (following any indication of sign or base); no
spaces are used for padding. If the zero spaces are used for padding. If the zero
@ -314,11 +323,10 @@ DESCRIPTION
o z o z
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
<<X>>, specifies that the argument is a <<X>>, specifies that the argument is a <<size_t>>.
<<ssize_t>> or <<size_t>>.
With <<n>>, specifies that the argument is a With <<n>>, specifies that the argument is a
pointer to a <<ssize_t>>. pointer to a <<size_t>>.
o t o t
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
@ -352,7 +360,7 @@ DESCRIPTION
shall be converted to wchar_t, and written. shall be converted to wchar_t, and written.
o C o C
Short for <<%lc>>. Short for <<%lc>>. A POSIX extension to the C standard.
o s o s
If no <<l>> qualifier is present, the application If no <<l>> qualifier is present, the application
@ -383,32 +391,32 @@ DESCRIPTION
written. written.
o S o S
Short for <<%ls>>. Short for <<%ls>>. A POSIX extension to the C standard.
o d or i o d or i
Prints a signed decimal integer; takes an Prints a signed decimal integer; takes an
<<int>>. Leading zeros are inserted as <<int>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o o o o
Prints an unsigned octal integer; takes an Prints an unsigned octal integer; takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o u o u
Prints an unsigned decimal integer; takes an Prints an unsigned decimal integer; takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o x o x
Prints an unsigned hexadecimal integer (using Prints an unsigned hexadecimal integer (using
<<abcdef>> as digits beyond <<9>>); takes an <<abcdef>> as digits beyond <<9>>); takes an
<<unsigned>>. Leading zeros are inserted as <<unsigned>>. Leading zeros are inserted as
necessary to reach the precision. A precision necessary to reach the precision. A value of 0 with
of 0 produces an empty string. a precision of 0 produces an empty string.
o X o X
Like <<x>>, but uses <<ABCDEF>> as digits 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 If an error occurs, the result of <<wprintf>>, <<fwprintf>>, and
<<swprintf>> is a negative value. For <<wprintf>> and <<fwprintf>>, <<swprintf>> is a negative value. For <<wprintf>> and <<fwprintf>>,
<<errno>> may be set according to <<fputwc>>. For <<snwprintf>>, <<errno>> <<errno>> may be set according to <<fputwc>>. For <<swprintf>>, <<errno>>
may be set to EOVERFLOW if <[size]> or the output length exceeds may be set to EOVERFLOW if <[size]> is greater than INT_MAX / sizeof (wchar_t),
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 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 Depending on how newlib was configured, not all format specifiers are
supported. supported.
@ -527,6 +539,10 @@ Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
#include <errno.h> #include <errno.h>
#include "local.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 int
_DEFUN(_swprintf_r, (ptr, str, size, fmt), _DEFUN(_swprintf_r, (ptr, str, size, fmt),
struct _reent *ptr _AND struct _reent *ptr _AND
@ -540,7 +556,7 @@ _DEFUN(_swprintf_r, (ptr, str, size, fmt),
if (size > INT_MAX / sizeof (wchar_t)) if (size > INT_MAX / sizeof (wchar_t))
{ {
ptr->_errno = EOVERFLOW; ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF; return EOF;
} }
f._flags = __SWR | __SSTR; f._flags = __SWR | __SSTR;
@ -550,10 +566,19 @@ _DEFUN(_swprintf_r, (ptr, str, size, fmt),
va_start (ap, fmt); va_start (ap, fmt);
ret = _svfwprintf_r (ptr, &f, fmt, ap); ret = _svfwprintf_r (ptr, &f, fmt, ap);
va_end (ap); va_end (ap);
if (ret < EOF) /* _svfwprintf_r() does not put in a terminating NUL, so add one if
ptr->_errno = EOVERFLOW; * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
if (size > 0) * after n-1, so always just put at the end. */
*f._p = 0; 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); return (ret);
} }
@ -572,7 +597,7 @@ _DEFUN(swprintf, (str, size, fmt),
if (size > INT_MAX / sizeof (wchar_t)) if (size > INT_MAX / sizeof (wchar_t))
{ {
ptr->_errno = EOVERFLOW; ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF; return EOF;
} }
f._flags = __SWR | __SSTR; f._flags = __SWR | __SSTR;
@ -582,10 +607,19 @@ _DEFUN(swprintf, (str, size, fmt),
va_start (ap, fmt); va_start (ap, fmt);
ret = _svfwprintf_r (ptr, &f, fmt, ap); ret = _svfwprintf_r (ptr, &f, fmt, ap);
va_end (ap); va_end (ap);
if (ret < EOF) /* _svfwprintf_r() does not put in a terminating NUL, so add one if
ptr->_errno = EOVERFLOW; * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
if (size > 0) * after n-1, so always just put at the end. */
*f._p = 0; 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); return (ret);
} }

View File

@ -50,17 +50,18 @@ INDEX
ANSI_SYNOPSIS ANSI_SYNOPSIS
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <wchar.h>
int vwprintf(const wchar_t *<[fmt]>, va_list <[list]>); int vwprintf(const wchar_t *<[fmt]>, va_list <[list]>);
int vfwprintf(FILE *<[fp]>, 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]>, int vswprintf(wchar_t *<[str]>, size_t <[size]>, const wchar_t *<[fmt]>,
va_list <[list]>); va_list <[list]>);
int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>, int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>,
va_list <[list]>); va_list <[list]>);
int _vfwprintf_r(struct _reent *<[reent]>, FILE *<[fp]>, 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]>, 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 DESCRIPTION
<<vwprintf>>, <<vfwprintf>> and <<vswprintf>> are (respectively) variants <<vwprintf>>, <<vfwprintf>> and <<vswprintf>> are (respectively) variants
@ -76,10 +77,13 @@ RETURNS
The return values are consistent with the corresponding functions. The return values are consistent with the corresponding functions.
PORTABILITY PORTABILITY
POSIX-1.2008 POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>. <<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 mantissa, this would be 29 characters). %e, %f, and %g use
reentrant storage shared with mprec. All other formats that use reentrant storage shared with mprec. All other formats that use
buf get by with fewer characters. Making BUF slightly bigger 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. */ long strings are processed. */
#define BUF 40 #define BUF 40
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
@ -396,7 +400,7 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
#define NIOV 8 #define NIOV 8
struct __suio uio; /* output information: summary */ struct __suio uio; /* output information: summary */
struct __siov iov[NIOV];/* ... and individual io vectors */ 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 ox[2]; /* space for 0x hex-prefix */
wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */ wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */
@ -576,10 +580,7 @@ reswitch: switch (ch) {
#ifdef _WANT_IO_C99_FORMATS #ifdef _WANT_IO_C99_FORMATS
case L'\'': case L'\'':
/* The ' flag is required by POSIX, but not C99. /* The ' flag is required by POSIX, but not C99.
In the C locale, LC_NUMERIC requires FIXME: this flag is currently a no-op. */
thousands_sep to be the empty string. And since
no other locales are supported (yet), this flag
is currently a no-op. */
goto rflag; goto rflag;
#endif #endif
case L' ': case L' ':
@ -742,7 +743,7 @@ reswitch: switch (ch) {
#endif #endif
flags |= LONGINT; flags |= LONGINT;
goto rflag; goto rflag;
case L'q': /* extension */ case L'q': /* GNU extension */
flags |= QUADINT; flags |= QUADINT;
goto rflag; goto rflag;
#ifdef _WANT_IO_C99_FORMATS #ifdef _WANT_IO_C99_FORMATS
@ -783,7 +784,7 @@ reswitch: switch (ch) {
have ptrdiff_t as wide as long long. */ have ptrdiff_t as wide as long long. */
flags |= QUADINT; flags |= QUADINT;
goto rflag; goto rflag;
case L'C': case L'C': /* POSIX extension */
#endif /* _WANT_IO_C99_FORMATS */ #endif /* _WANT_IO_C99_FORMATS */
case L'c': case L'c':
cp = buf; cp = buf;
@ -1001,7 +1002,7 @@ reswitch: switch (ch) {
goto nosign; goto nosign;
case L's': case L's':
#ifdef _WANT_IO_C99_FORMATS #ifdef _WANT_IO_C99_FORMATS
case L'S': case L'S': /* POSIX extension */
#endif #endif
sign = '\0'; sign = '\0';
cp = GET_ARG (N, ap, wchar_ptr_t); 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; break;
case L's': case L's':
# ifdef _WANT_IO_C99_FORMATS # ifdef _WANT_IO_C99_FORMATS
case L'S': case L'S': /* POSIX extension */
# endif # endif
case L'p': case L'p':
case L'n': case L'n':
@ -1655,7 +1656,7 @@ _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
spec_type = INT; spec_type = INT;
break; break;
# ifdef _WANT_IO_C99_FORMATS # ifdef _WANT_IO_C99_FORMATS
case L'C': case L'C': /* POSIX extension */
spec_type = WIDE_CHAR; spec_type = WIDE_CHAR;
break; break;
# endif # endif

View File

@ -27,6 +27,7 @@ static char sccsid[] = "%W% (Berkeley) %G%";
#include <limits.h> #include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <errno.h> #include <errno.h>
#include "local.h" #include "local.h"
int int
@ -42,7 +43,7 @@ _DEFUN(_vswprintf_r, (ptr, str, size, fmt, ap),
if (size > INT_MAX / sizeof (wchar_t)) if (size > INT_MAX / sizeof (wchar_t))
{ {
ptr->_errno = EOVERFLOW; ptr->_errno = EOVERFLOW; /* POSIX extension */
return EOF; return EOF;
} }
f._flags = __SWR | __SSTR; 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._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0);
f._file = -1; /* No file. */ f._file = -1; /* No file. */
ret = _svfwprintf_r (ptr, &f, fmt, ap); ret = _svfwprintf_r (ptr, &f, fmt, ap);
if (ret < EOF) /* _svfwprintf_r() does not put in a terminating NUL, so add one if
ptr->_errno = EOVERFLOW; * appropriate, which is whenever size is > 0. _svfwprintf_r() stops
if (size > 0) * after n-1, so always just put at the end. */
*f._p = 0; 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; return ret;
} }

View File

@ -251,6 +251,10 @@ This implementation does not support <<s>> being NULL, nor overlapping
<<s>> and <<format>>. <<s>> and <<format>>.
<<strftime>> requires no supporting OS subroutines. <<strftime>> requires no supporting OS subroutines.
BUGS
<<strftime>> ignores the LC_TIME category of the current locale, hard-coding
the "C" locale settings.
*/ */
#include <stddef.h> #include <stddef.h>
@ -356,7 +360,7 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
_CONST struct tm *tim_p) _CONST struct tm *tim_p)
{ {
size_t count = 0; size_t count = 0;
int i; int i, len;
for (;;) for (;;)
{ {
@ -455,28 +459,27 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
int century = tim_p->tm_year >= 0 int century = tim_p->tm_year >= 0
? tim_p->tm_year / 100 + YEAR_BASE / 100 ? tim_p->tm_year / 100 + YEAR_BASE / 100
: abs (tim_p->tm_year + YEAR_BASE) / 100; : abs (tim_p->tm_year + YEAR_BASE) / 100;
count += snprintf (&s[count], maxsize - count, CQ("%s%.*d"), len = snprintf (&s[count], maxsize - count, CQ("%s%.*d"),
neg ? CQ("-") : CQ(""), 2 - neg, century); neg ? CQ("-") : CQ(""), 2 - neg, century);
if (count >= maxsize) if (len < 0 || (count+=len) >= maxsize) return 0;
return 0;
} }
break; break;
case CQ('d'): case CQ('d'):
case CQ('e'): case CQ('e'):
count += snprintf (&s[count], maxsize - count, len = snprintf (&s[count], maxsize - count,
*format == CQ('d') ? CQ("%.2d") : CQ("%2d"), *format == CQ('d') ? CQ("%.2d") : CQ("%2d"),
tim_p->tm_mday); tim_p->tm_mday);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('D'): case CQ('D'):
case CQ('x'): case CQ('x'):
/* %m/%d/%y */ /* %m/%d/%y */
count += snprintf (&s[count], maxsize - count, len = snprintf (&s[count], maxsize - count,
CQ("%.2d/%.2d/%.2d"), CQ("%.2d/%.2d/%.2d"),
tim_p->tm_mon + 1, tim_p->tm_mday, tim_p->tm_mon + 1, tim_p->tm_mday,
tim_p->tm_year >= 0 ? tim_p->tm_year % 100 tim_p->tm_year >= 0 ? tim_p->tm_year % 100
: abs (tim_p->tm_year + YEAR_BASE) % 100); : abs (tim_p->tm_year + YEAR_BASE) % 100);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('F'): case CQ('F'):
{ /* %F is equivalent to "%Y-%m-%d" */ { /* %F is equivalent to "%Y-%m-%d" */
@ -500,9 +503,9 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
adjust = 1; adjust = 1;
else if (adjust > 0 && tim_p->tm_year < -YEAR_BASE) else if (adjust > 0 && tim_p->tm_year < -YEAR_BASE)
adjust = -1; adjust = -1;
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
((year + adjust) % 100 + 100) % 100); ((year + adjust) % 100 + 100) % 100);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('G'): case CQ('G'):
@ -532,18 +535,18 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
year = 0; year = 0;
++century; ++century;
} }
count += snprintf (&s[count], maxsize - count, CQ("%s%.*d%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%s%.*d%.2d"),
neg ? CQ("-") : CQ(""), 2 - neg, century, year); neg ? CQ("-") : CQ(""), 2 - neg, century, year);
if (count >= maxsize) if (len < 0 || (count+=len) >= maxsize)
return 0; return 0;
} }
break; break;
case CQ('H'): case CQ('H'):
case CQ('k'): /* newlib extension */ case CQ('k'): /* newlib extension */
count += snprintf (&s[count], maxsize - count, len = snprintf (&s[count], maxsize - count,
*format == CQ('k') ? CQ("%2d") : CQ("%.2d"), *format == CQ('k') ? CQ("%2d") : CQ("%.2d"),
tim_p->tm_hour); tim_p->tm_hour);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('I'): case CQ('I'):
case CQ('l'): /* newlib extension */ case CQ('l'): /* newlib extension */
@ -551,26 +554,26 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
register int h12; register int h12;
h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12) ? h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12) ?
12 : tim_p->tm_hour % 12; 12 : tim_p->tm_hour % 12;
count += snprintf (&s[count], maxsize - count, len = snprintf (&s[count], maxsize - count,
*format == CQ('I') ? CQ("%.2d") : CQ("%2d"), *format == CQ('I') ? CQ("%.2d") : CQ("%2d"),
h12); h12);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('j'): case CQ('j'):
count += snprintf (&s[count], maxsize - count, CQ("%.3d"), len = snprintf (&s[count], maxsize - count, CQ("%.3d"),
tim_p->tm_yday + 1); tim_p->tm_yday + 1);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('m'): case CQ('m'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
tim_p->tm_mon + 1); tim_p->tm_mon + 1);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('M'): case CQ('M'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
tim_p->tm_min); tim_p->tm_min);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('n'): case CQ('n'):
if (count < maxsize - 1) if (count < maxsize - 1)
@ -598,24 +601,24 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
register int h12; register int h12;
h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12) ? h12 = (tim_p->tm_hour == 0 || tim_p->tm_hour == 12) ?
12 : tim_p->tm_hour % 12; 12 : tim_p->tm_hour % 12;
count += snprintf (&s[count], maxsize - count, len = snprintf (&s[count], maxsize - count,
CQ("%.2d:%.2d:%.2d %cM"), CQ("%.2d:%.2d:%.2d %cM"),
h12, h12,
tim_p->tm_min, tim_p->tm_min,
tim_p->tm_sec, tim_p->tm_sec,
(tim_p->tm_hour < 12) ? CQ('A') : CQ('P')); (tim_p->tm_hour < 12) ? CQ('A') : CQ('P'));
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('R'): case CQ('R'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d"),
tim_p->tm_hour, tim_p->tm_min); tim_p->tm_hour, tim_p->tm_min);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('S'): case CQ('S'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
tim_p->tm_sec); tim_p->tm_sec);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('t'): case CQ('t'):
if (count < maxsize - 1) if (count < maxsize - 1)
@ -625,9 +628,9 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
break; break;
case CQ('T'): case CQ('T'):
case CQ('X'): case CQ('X'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d:%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d:%.2d:%.2d"),
tim_p->tm_hour, tim_p->tm_min, tim_p->tm_sec); tim_p->tm_hour, tim_p->tm_min, tim_p->tm_sec);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('u'): case CQ('u'):
if (count < maxsize - 1) if (count < maxsize - 1)
@ -641,10 +644,10 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
return 0; return 0;
break; break;
case CQ('U'): case CQ('U'):
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
(tim_p->tm_yday + 7 - (tim_p->tm_yday + 7 -
tim_p->tm_wday) / 7); tim_p->tm_wday) / 7);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('V'): case CQ('V'):
{ {
@ -662,8 +665,8 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
+ (YEAR_BASE - 1 + (YEAR_BASE - 1
- (tim_p->tm_year < 0 - (tim_p->tm_year < 0
? 0 : 2000))))); ? 0 : 2000)))));
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), week); len = snprintf (&s[count], maxsize - count, CQ("%.2d"), week);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('w'): case CQ('w'):
@ -675,9 +678,9 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
case CQ('W'): case CQ('W'):
{ {
int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6; int wday = (tim_p->tm_wday) ? tim_p->tm_wday - 1 : 6;
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), len = snprintf (&s[count], maxsize - count, CQ("%.2d"),
(tim_p->tm_yday + 7 - wday) / 7); (tim_p->tm_yday + 7 - wday) / 7);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('y'): case CQ('y'):
@ -686,8 +689,8 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
the asymmetric range of years. */ the asymmetric range of years. */
int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100 int year = tim_p->tm_year >= 0 ? tim_p->tm_year % 100
: abs (tim_p->tm_year + YEAR_BASE) % 100; : abs (tim_p->tm_year + YEAR_BASE) % 100;
count += snprintf (&s[count], maxsize - count, CQ("%.2d"), year); len = snprintf (&s[count], maxsize - count, CQ("%.2d"), year);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('Y'): case CQ('Y'):
@ -695,17 +698,17 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
* gives at least 4 digits, with leading zeros as needed. */ * gives at least 4 digits, with leading zeros as needed. */
if(tim_p->tm_year <= INT_MAX-YEAR_BASE) { if(tim_p->tm_year <= INT_MAX-YEAR_BASE) {
/* For normal, non-overflow case. */ /* For normal, non-overflow case. */
count += snprintf (&s[count], maxsize - count, CQ("%04d"), len = snprintf (&s[count], maxsize - count, CQ("%04d"),
tim_p->tm_year + YEAR_BASE); tim_p->tm_year + YEAR_BASE);
} }
else { else {
/* int would overflow, so use unsigned instead. */ /* int would overflow, so use unsigned instead. */
register unsigned year; register unsigned year;
year = (unsigned) tim_p->tm_year + (unsigned) YEAR_BASE; year = (unsigned) tim_p->tm_year + (unsigned) YEAR_BASE;
count += snprintf (&s[count], maxsize - count, CQ("%04u"), len = snprintf (&s[count], maxsize - count, CQ("%04u"),
tim_p->tm_year + YEAR_BASE); tim_p->tm_year + YEAR_BASE);
} }
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
break; break;
case CQ('z'): case CQ('z'):
if (tim_p->tm_isdst >= 0) if (tim_p->tm_isdst >= 0)
@ -718,10 +721,10 @@ _DEFUN (strftime, (s, maxsize, format, tim_p),
but have to use __tzrule for daylight savings. */ but have to use __tzrule for daylight savings. */
offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset; offset = -tz->__tzrule[tim_p->tm_isdst > 0].offset;
TZ_UNLOCK; TZ_UNLOCK;
count += snprintf (&s[count], maxsize - count, CQ("%+03ld%.2ld"), len = snprintf (&s[count], maxsize - count, CQ("%+03ld%.2ld"),
offset / SECSPERHOUR, offset / SECSPERHOUR,
labs (offset / SECSPERMIN) % 60L); labs (offset / SECSPERMIN) % 60L);
if (count >= maxsize) return 0; if (len < 0 || (count+=len) >= maxsize) return 0;
} }
break; break;
case CQ('Z'): case CQ('Z'):
@ -803,7 +806,7 @@ const struct test Vec0[] = {
/* Testing fields one at a time, expecting to pass, using exact /* Testing fields one at a time, expecting to pass, using exact
* allowed length as what is needed. */ * allowed length as what is needed. */
/* Using tm0 for time: */ /* Using tm0 for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%a"), 3+1, EXP(CQ("Tue")) }, { CQ("%a"), 3+1, EXP(CQ("Tue")) },
{ CQ("%A"), 7+1, EXP(CQ("Tuesday")) }, { CQ("%A"), 7+1, EXP(CQ("Tuesday")) },
{ CQ("%b"), 3+1, EXP(CQ("Dec")) }, { CQ("%b"), 3+1, EXP(CQ("Dec")) },
@ -862,8 +865,8 @@ const struct tm tm1 = {
const struct test Vec1[] = { const struct test Vec1[] = {
/* Testing fields one at a time, expecting to pass, using exact /* Testing fields one at a time, expecting to pass, using exact
* allowed length as what is needed. */ * allowed length as what is needed. */
/* Using tm0 for time: */ /* Using tm1 for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%a"), 3+1, EXP(CQ("Wed")) }, { CQ("%a"), 3+1, EXP(CQ("Wed")) },
{ CQ("%A"), 9+1, EXP(CQ("Wednesday")) }, { CQ("%A"), 9+1, EXP(CQ("Wednesday")) },
{ CQ("%b"), 3+1, EXP(CQ("Jul")) }, { CQ("%b"), 3+1, EXP(CQ("Jul")) },
@ -904,10 +907,11 @@ const struct test Vec1[] = {
{ CQ("%Z"), 3+1, EXP(CQ("EDT")) }, { CQ("%Z"), 3+1, EXP(CQ("EDT")) },
{ CQ("%%"), 1+1, EXP(CQ("%")) }, { CQ("%%"), 1+1, EXP(CQ("%")) },
#undef EXP #undef EXP
#define VEC(s) s, sizeof(s), sizeof(s)-1, s #define VEC(s) s, sizeof(s)/sizeof(CHAR), sizeof(s)/sizeof(CHAR)-1, s
#define EXP(s) sizeof(s), sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR), sizeof(s)/sizeof(CHAR)-1, s
{ VEC(CQ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) }, { VEC(CQ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) },
{ CQ("0123456789%%%h:`~"), EXP(CQ("0123456789%Jul:`~")) }, { CQ("0123456789%%%h:`~"), EXP(CQ("0123456789%Jul:`~")) },
{ CQ("%R%h:`~ %x %w"), EXP(CQ("23:01Jul:`~ 07/02/08 3")) },
#undef VEC #undef VEC
#undef EXP #undef EXP
}; };
@ -949,7 +953,7 @@ const struct test Vecyr0[] = {
/* Testing fields one at a time, expecting to pass, using a larger /* Testing fields one at a time, expecting to pass, using a larger
* allowed length than what is needed. */ * allowed length than what is needed. */
/* Using tmyr0 for time: */ /* Using tmyr0 for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%C"), OUTSIZE, EXP(CENT) }, { CQ("%C"), OUTSIZE, EXP(CENT) },
{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:13 ")YEAR) }, { CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:13 ")YEAR) },
{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) }, { CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
@ -995,7 +999,7 @@ const struct test Vecyr1[] = {
/* Testing fields one at a time, expecting to pass, using a larger /* Testing fields one at a time, expecting to pass, using a larger
* allowed length than what is needed. */ * allowed length than what is needed. */
/* Using tmyr1 for time: */ /* Using tmyr1 for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%C"), OUTSIZE, EXP(CENT) }, { CQ("%C"), OUTSIZE, EXP(CENT) },
{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:13 ")YEAR) }, { CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:13 ")YEAR) },
{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) }, { CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
@ -1032,7 +1036,7 @@ const struct test Vecyrzp[] = {
/* Testing fields one at a time, expecting to pass, using a larger /* Testing fields one at a time, expecting to pass, using a larger
* allowed length than what is needed. */ * allowed length than what is needed. */
/* Using tmyrzp for time: */ /* Using tmyrzp for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%C"), OUTSIZE, EXP(CENT) }, { CQ("%C"), OUTSIZE, EXP(CENT) },
{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:60 ")YEAR) }, { CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:60 ")YEAR) },
{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) }, { CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },
@ -1067,7 +1071,7 @@ const struct test Vecyrzn[] = {
/* Testing fields one at a time, expecting to pass, using a larger /* Testing fields one at a time, expecting to pass, using a larger
* allowed length than what is needed. */ * allowed length than what is needed. */
/* Using tmyrzn for time: */ /* Using tmyrzn for time: */
#define EXP(s) sizeof(s)-1, s #define EXP(s) sizeof(s)/sizeof(CHAR)-1, s
{ CQ("%C"), OUTSIZE, EXP(CENT) }, { CQ("%C"), OUTSIZE, EXP(CENT) },
{ CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:00 ")YEAR) }, { CQ("%c"), OUTSIZE, EXP(CQ("Wed Jul 2 23:01:00 ")YEAR) },
{ CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) }, { CQ("%D"), OUTSIZE, EXP(CQ("07/02/")Year) },