* 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:
parent
cab0758eb2
commit
4a825d4145
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) },
|
||||||
|
|
Loading…
Reference in New Issue