newlib: wide char support
git-svn-id: svn://kolibrios.org@6607 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
635
contrib/sdk/sources/newlib/libc/stdio/swprintf.c
Normal file
635
contrib/sdk/sources/newlib/libc/stdio/swprintf.c
Normal file
@@ -0,0 +1,635 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 2007 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
<<swprintf>>, <<fwprintf>>, <<wprintf>>---wide character format output
|
||||
|
||||
INDEX
|
||||
fwprintf
|
||||
INDEX
|
||||
_fwprintf_r
|
||||
INDEX
|
||||
wprintf
|
||||
INDEX
|
||||
_wprintf_r
|
||||
INDEX
|
||||
swprintf
|
||||
INDEX
|
||||
_swprintf_r
|
||||
|
||||
ANSI_SYNOPSIS
|
||||
#include <wchar.h>
|
||||
|
||||
int wprintf(const wchar_t *<[format]>, ...);
|
||||
int fwprintf(FILE *__restrict <[fd]>,
|
||||
const wchar_t *__restrict <[format]>, ...);
|
||||
int swprintf(wchar_t *__restrict <[str]>, size_t <[size]>,
|
||||
const wchar_t *__restrict <[format]>, ...);
|
||||
|
||||
int _wprintf_r(struct _reent *<[ptr]>, const wchar_t *<[format]>, ...);
|
||||
int _fwprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>,
|
||||
const wchar_t *<[format]>, ...);
|
||||
int _swprintf_r(struct _reent *<[ptr]>, wchar_t *<[str]>,
|
||||
size_t <[size]>, const wchar_t *<[format]>, ...);
|
||||
|
||||
DESCRIPTION
|
||||
<<wprintf>> accepts a series of arguments, applies to each a
|
||||
format specifier from <<*<[format]>>>, and writes the
|
||||
formatted data to <<stdout>>, without a terminating NUL
|
||||
wide character. The behavior of <<wprintf>> is undefined if there
|
||||
are not enough arguments for the format or if any argument is not the
|
||||
right type for the corresponding conversion specifier. <<wprintf>>
|
||||
returns when it reaches the end of the format string. If there are
|
||||
more arguments than the format requires, excess arguments are
|
||||
ignored.
|
||||
|
||||
<<fwprintf>> is like <<wprintf>>, except that output is directed
|
||||
to the stream <[fd]> rather than <<stdout>>.
|
||||
|
||||
<<swprintf>> is like <<wprintf>>, except that output is directed
|
||||
to the buffer <[str]> with a terminating wide <<NUL>>, and the
|
||||
resulting string length is limited to at most <[size]> wide characters,
|
||||
including the terminating <<NUL>>. It is considered an error if the
|
||||
output (including the terminating wide-<<NULL>>) does not fit into
|
||||
<[size]> wide characters. (This error behavior is not the same as for
|
||||
<<snprintf>>, which <<swprintf>> is otherwise completely analogous to.
|
||||
While <<snprintf>> allows the needed size to be known simply by giving
|
||||
<[size]>=0, <<swprintf>> does not, giving an error instead.)
|
||||
|
||||
For <<swprintf>> the behavior is undefined if the output
|
||||
<<*<[str]>>> overlaps with one of the arguments. Behavior is also
|
||||
undefined if the argument for <<%n>> within <<*<[format]>>>
|
||||
overlaps another argument.
|
||||
|
||||
<[format]> is a pointer to a wide character string containing two
|
||||
types of objects: ordinary characters (other than <<%>>),
|
||||
which are copied unchanged to the output, and conversion
|
||||
specifications, each of which is introduced by <<%>>. (To
|
||||
include <<%>> in the output, use <<%%>> in the format string.)
|
||||
A conversion specification has the following form:
|
||||
|
||||
. %[<[pos]>][<[flags]>][<[width]>][.<[prec]>][<[size]>]<[type]>
|
||||
|
||||
The fields of the conversion specification have the following
|
||||
meanings:
|
||||
|
||||
O+
|
||||
o <[pos]>
|
||||
|
||||
Conversions normally consume arguments in the order that they
|
||||
are presented. However, it is possible to consume arguments
|
||||
out of order, and reuse an argument for more than one
|
||||
conversion specification (although the behavior is undefined
|
||||
if the same argument is requested with different types), by
|
||||
specifying <[pos]>, which is a decimal integer followed by
|
||||
'$'. The integer must be between 1 and <NL_ARGMAX> from
|
||||
limits.h, and if argument <<%n$>> is requested, all earlier
|
||||
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]>
|
||||
|
||||
<[flags]> is an optional sequence of characters which control
|
||||
output justification, numeric signs, decimal points, trailing
|
||||
zeros, and octal and hex prefixes. The flag characters are
|
||||
minus (<<->>), plus (<<+>>), space ( ), zero (<<0>>), sharp
|
||||
(<<#>>), and quote (<<'>>). They can appear in any
|
||||
combination, although not all flags can be used for all
|
||||
conversion specification types.
|
||||
|
||||
o+
|
||||
o '
|
||||
A POSIX extension to the C standard. However, this
|
||||
implementation presently treats it as a no-op, which
|
||||
is the default behavior for the C locale, anyway. (If
|
||||
it did what it is supposed to, when <[type]> were <<i>>,
|
||||
<<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>, the
|
||||
integer portion of the conversion would be formatted
|
||||
with thousands' grouping wide characters.)
|
||||
|
||||
o -
|
||||
The result of the conversion is left
|
||||
justified, and the right is padded with
|
||||
blanks. If you do not use this flag, the
|
||||
result is right justified, and padded on the
|
||||
left.
|
||||
|
||||
o +
|
||||
The result of a signed conversion (as
|
||||
determined by <[type]> of <<d>>, <<i>>, <<a>>,
|
||||
<<A>>, <<e>>, <<E>>, <<f>>, <<F>>, <<g>>, or
|
||||
<<G>>) will always begin with a plus or minus
|
||||
sign. (If you do not use this flag, positive
|
||||
values do not begin with a plus sign.)
|
||||
|
||||
o " " (space)
|
||||
If the first character of a signed conversion
|
||||
specification is not a sign, or if a signed
|
||||
conversion results in no characters, the
|
||||
result will begin with a space. If the space
|
||||
( ) flag and the plus (<<+>>) flag both
|
||||
appear, the space flag is ignored.
|
||||
|
||||
o 0
|
||||
If the <[type]> character is <<d>>, <<i>>,
|
||||
<<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>,
|
||||
<<e>>, <<E>>, <<f>>, <<F>>, <<g>>, or <<G>>: leading
|
||||
zeros are used to pad the field width
|
||||
(following any indication of sign or base); no
|
||||
spaces are used for padding. If the zero
|
||||
(<<0>>) and minus (<<->>) flags both appear,
|
||||
the zero (<<0>>) flag will be ignored. For
|
||||
<<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>
|
||||
conversions, if a precision <[prec]> is
|
||||
specified, the zero (<<0>>) flag is ignored.
|
||||
|
||||
Note that <<0>> is interpreted as a flag, not
|
||||
as the beginning of a field width.
|
||||
|
||||
o #
|
||||
The result is to be converted to an
|
||||
alternative form, according to the <[type]>
|
||||
character.
|
||||
o-
|
||||
|
||||
The alternative form output with the # flag depends on the <[type]>
|
||||
character:
|
||||
|
||||
o+
|
||||
o o
|
||||
Increases precision to force the first
|
||||
digit of the result to be a zero.
|
||||
|
||||
o x
|
||||
A non-zero result will have a <<0x>>
|
||||
prefix.
|
||||
|
||||
o X
|
||||
A non-zero result will have a <<0X>>
|
||||
prefix.
|
||||
|
||||
o a, A, e, E, f, or F
|
||||
The result will always contain a
|
||||
decimal point even if no digits follow
|
||||
the point. (Normally, a decimal point
|
||||
appears only if a digit follows it.)
|
||||
Trailing zeros are removed.
|
||||
|
||||
o g or G
|
||||
The result will always contain a
|
||||
decimal point even if no digits follow
|
||||
the point. Trailing zeros are not
|
||||
removed.
|
||||
|
||||
o all others
|
||||
Undefined.
|
||||
|
||||
o-
|
||||
|
||||
|
||||
o <[width]>
|
||||
|
||||
<[width]> is an optional minimum field width. You can
|
||||
either specify it directly as a decimal integer, or
|
||||
indirectly by using instead an asterisk (<<*>>), in
|
||||
which case an <<int>> argument is used as the field
|
||||
width. If positional arguments are used, then the
|
||||
width must also be specified positionally as <<*m$>>,
|
||||
with m as a decimal integer. Negative field widths
|
||||
are treated as specifying the minus (<<->>) flag for
|
||||
left justfication, along with a positive field width.
|
||||
The resulting format may be wider than the specified
|
||||
width.
|
||||
|
||||
o <[prec]>
|
||||
|
||||
<[prec]> is an optional field; if present, it is
|
||||
introduced with `<<.>>' (a period). You can specify
|
||||
the precision either directly as a decimal integer or
|
||||
indirectly by using an asterisk (<<*>>), in which case
|
||||
an <<int>> argument is used as the precision. If
|
||||
positional arguments are used, then the precision must
|
||||
also be specified positionally as <<*m$>>, with m as a
|
||||
decimal integer. Supplying a negative precision is
|
||||
equivalent to omitting the precision. If only a
|
||||
period is specified the precision is zero. The effect
|
||||
depends on the conversion <[type]>.
|
||||
|
||||
o+
|
||||
o d, i, o, u, x, or X
|
||||
Minimum number of digits to appear. If no
|
||||
precision is given, defaults to 1.
|
||||
|
||||
o a or A
|
||||
Number of digits to appear after the decimal
|
||||
point. If no precision is given, the
|
||||
precision defaults to the minimum needed for
|
||||
an exact representation.
|
||||
|
||||
o e, E, f or F
|
||||
Number of digits to appear after the decimal
|
||||
point. If no precision is given, the
|
||||
precision defaults to 6.
|
||||
|
||||
o g or G
|
||||
Maximum number of significant digits. A
|
||||
precision of 0 is treated the same as a
|
||||
precision of 1. If no precision is given, the
|
||||
precision defaults to 6.
|
||||
|
||||
o s or S
|
||||
Maximum number of characters to print from the
|
||||
string. If no precision is given, the entire
|
||||
string is printed.
|
||||
|
||||
o all others
|
||||
undefined.
|
||||
|
||||
o-
|
||||
|
||||
o <[size]>
|
||||
|
||||
<[size]> is an optional modifier that changes the data
|
||||
type that the corresponding argument has. Behavior is
|
||||
unspecified if a size is given that does not match the
|
||||
<[type]>.
|
||||
|
||||
o+
|
||||
o hh
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument should be
|
||||
converted to a <<signed char>> or <<unsigned
|
||||
char>> before printing.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<signed char>>.
|
||||
|
||||
o h
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument should be
|
||||
converted to a <<short>> or <<unsigned short>>
|
||||
before printing.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<short>>.
|
||||
|
||||
o l
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument is a
|
||||
<<long>> or <<unsigned long>>.
|
||||
|
||||
With <<c>>, specifies that the argument has
|
||||
type <<wint_t>>.
|
||||
|
||||
With <<s>>, specifies that the argument is a
|
||||
pointer to <<wchar_t>>.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<long>>.
|
||||
|
||||
With <<a>>, <<A>>, <<e>>, <<E>>, <<f>>, <<F>>,
|
||||
<<g>>, or <<G>>, has no effect (because of
|
||||
vararg promotion rules, there is no need to
|
||||
distinguish between <<float>> and <<double>>).
|
||||
|
||||
o ll
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument is a
|
||||
<<long long>> or <<unsigned long long>>.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<long long>>.
|
||||
|
||||
o j
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument is an
|
||||
<<intmax_t>> or <<uintmax_t>>.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to an <<intmax_t>>.
|
||||
|
||||
o z
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument is a <<size_t>>.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<size_t>>.
|
||||
|
||||
o t
|
||||
With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
|
||||
<<X>>, specifies that the argument is a
|
||||
<<ptrdiff_t>>.
|
||||
|
||||
With <<n>>, specifies that the argument is a
|
||||
pointer to a <<ptrdiff_t>>.
|
||||
|
||||
o L
|
||||
With <<a>>, <<A>>, <<e>>, <<E>>, <<f>>, <<F>>,
|
||||
<<g>>, or <<G>>, specifies that the argument
|
||||
is a <<long double>>.
|
||||
|
||||
o-
|
||||
|
||||
o <[type]>
|
||||
|
||||
<[type]> specifies what kind of conversion <<wprintf>>
|
||||
performs. Here is a table of these:
|
||||
|
||||
o+
|
||||
o %
|
||||
Prints the percent character (<<%>>).
|
||||
|
||||
o c
|
||||
If no <<l>> qualifier is present, the int argument shall
|
||||
be converted to a wide character as if by calling
|
||||
the btowc() function and the resulting wide character
|
||||
shall be written. Otherwise, the wint_t argument
|
||||
shall be converted to wchar_t, and written.
|
||||
|
||||
o C
|
||||
Short for <<%lc>>. A POSIX extension to the C standard.
|
||||
|
||||
o s
|
||||
If no <<l>> qualifier is present, the application
|
||||
shall ensure that the argument is a pointer to a
|
||||
character array containing a character sequence
|
||||
beginning in the initial shift state. Characters
|
||||
from the array shall be converted as if by repeated
|
||||
calls to the mbrtowc() function, with the conversion
|
||||
state described by an mbstate_t object initialized to
|
||||
zero before the first character is converted, and
|
||||
written up to (but not including) the terminating
|
||||
null wide character. If the precision is specified,
|
||||
no more than that many wide characters shall be
|
||||
written. If the precision is not specified, or is
|
||||
greater than the size of the array, the application
|
||||
shall ensure that the array contains a null wide
|
||||
character.
|
||||
|
||||
If an <<l>> qualifier is present, the application
|
||||
shall ensure that the argument is a pointer to an
|
||||
array of type wchar_t. Wide characters from the array
|
||||
shall be written up to (but not including) a
|
||||
terminating null wide character. If no precision is
|
||||
specified, or is greater than the size of the array,
|
||||
the application shall ensure that the array contains
|
||||
a null wide character. If a precision is specified,
|
||||
no more than that many wide characters shall be
|
||||
written.
|
||||
|
||||
o S
|
||||
Short for <<%ls>>. A POSIX extension to the C standard.
|
||||
|
||||
o d or i
|
||||
Prints a signed decimal integer; takes an
|
||||
<<int>>. Leading zeros are inserted as
|
||||
necessary to reach the precision. A value of 0 with
|
||||
a precision of 0 produces an empty string.
|
||||
|
||||
o o
|
||||
Prints an unsigned octal integer; takes an
|
||||
<<unsigned>>. Leading zeros are inserted as
|
||||
necessary to reach the precision. A value of 0 with
|
||||
a precision of 0 produces an empty string.
|
||||
|
||||
o u
|
||||
Prints an unsigned decimal integer; takes an
|
||||
<<unsigned>>. Leading zeros are inserted as
|
||||
necessary to reach the precision. A value of 0 with
|
||||
a precision of 0 produces an empty string.
|
||||
|
||||
o x
|
||||
Prints an unsigned hexadecimal integer (using
|
||||
<<abcdef>> as digits beyond <<9>>); takes an
|
||||
<<unsigned>>. Leading zeros are inserted as
|
||||
necessary to reach the precision. A value of 0 with
|
||||
a precision of 0 produces an empty string.
|
||||
|
||||
o X
|
||||
Like <<x>>, but uses <<ABCDEF>> as digits
|
||||
beyond <<9>>.
|
||||
|
||||
o f
|
||||
Prints a signed value of the form
|
||||
<<[-]9999.9999>>, with the precision
|
||||
determining how many digits follow the decimal
|
||||
point; takes a <<double>> (remember that
|
||||
<<float>> promotes to <<double>> as a vararg).
|
||||
The low order digit is rounded to even. If
|
||||
the precision results in at most DECIMAL_DIG
|
||||
digits, the result is rounded correctly; if
|
||||
more than DECIMAL_DIG digits are printed, the
|
||||
result is only guaranteed to round back to the
|
||||
original value.
|
||||
|
||||
If the value is infinite, the result is
|
||||
<<inf>>, and no zero padding is performed. If
|
||||
the value is not a number, the result is
|
||||
<<nan>>, and no zero padding is performed.
|
||||
|
||||
o F
|
||||
Like <<f>>, but uses <<INF>> and <<NAN>> for
|
||||
non-finite numbers.
|
||||
|
||||
o e
|
||||
Prints a signed value of the form
|
||||
<<[-]9.9999e[+|-]999>>; takes a <<double>>.
|
||||
The digit before the decimal point is non-zero
|
||||
if the value is non-zero. The precision
|
||||
determines how many digits appear between
|
||||
<<.>> and <<e>>, and the exponent always
|
||||
contains at least two digits. The value zero
|
||||
has an exponent of zero. If the value is not
|
||||
finite, it is printed like <<f>>.
|
||||
|
||||
o E
|
||||
Like <<e>>, but using <<E>> to introduce the
|
||||
exponent, and like <<F>> for non-finite
|
||||
values.
|
||||
|
||||
o g
|
||||
Prints a signed value in either <<f>> or <<e>>
|
||||
form, based on the given value and
|
||||
precision---an exponent less than -4 or
|
||||
greater than the precision selects the <<e>>
|
||||
form. Trailing zeros and the decimal point
|
||||
are printed only if necessary; takes a
|
||||
<<double>>.
|
||||
|
||||
o G
|
||||
Like <<g>>, except use <<F>> or <<E>> form.
|
||||
|
||||
o a
|
||||
Prints a signed value of the form
|
||||
<<[-]0x1.ffffp[+|-]9>>; takes a <<double>>.
|
||||
The letters <<abcdef>> are used for digits
|
||||
beyond <<9>>. The precision determines how
|
||||
many digits appear after the decimal point.
|
||||
The exponent contains at least one digit, and
|
||||
is a decimal value representing the power of
|
||||
2; a value of 0 has an exponent of 0.
|
||||
Non-finite values are printed like <<f>>.
|
||||
|
||||
o A
|
||||
Like <<a>>, except uses <<X>>, <<P>>, and
|
||||
<<ABCDEF>> instead of lower case.
|
||||
|
||||
o n
|
||||
Takes a pointer to <<int>>, and stores a count
|
||||
of the number of bytes written so far. No
|
||||
output is created.
|
||||
|
||||
o p
|
||||
Takes a pointer to <<void>>, and prints it in
|
||||
an implementation-defined format. This
|
||||
implementation is similar to <<%#tx>>), except
|
||||
that <<0x>> appears even for the NULL pointer.
|
||||
|
||||
o m
|
||||
Prints the output of <<strerror(errno)>>; no
|
||||
argument is required. A GNU extension.
|
||||
|
||||
o-
|
||||
O-
|
||||
|
||||
<<_wprintf_r>>, <<_fwprintf_r>>, <<_swprintf_r>>, are simply
|
||||
reentrant versions of the functions above.
|
||||
|
||||
RETURNS
|
||||
On success, <<swprintf>> return the number of wide characters in
|
||||
the output string, except the concluding <<NUL>> is not counted.
|
||||
<<wprintf>> and <<fwprintf>> return the number of characters transmitted.
|
||||
|
||||
If an error occurs, the result of <<wprintf>>, <<fwprintf>>, and
|
||||
<<swprintf>> is a negative value. For <<wprintf>> and <<fwprintf>>,
|
||||
<<errno>> may be set according to <<fputwc>>. For <<swprintf>>, <<errno>>
|
||||
may be set to EOVERFLOW if <[size]> is greater than INT_MAX / sizeof (wchar_t),
|
||||
or when the output does not fit into <[size]> wide characters (including the
|
||||
terminating wide <<NULL>>).
|
||||
|
||||
BUGS
|
||||
The ``''' (quote) flag does not work when locale's thousands_sep is not empty.
|
||||
|
||||
PORTABILITY
|
||||
POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
|
||||
|
||||
Depending on how newlib was configured, not all format specifiers are
|
||||
supported.
|
||||
|
||||
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
|
||||
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
|
||||
*/
|
||||
|
||||
|
||||
#include <_ansi.h>
|
||||
#include <reent.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include "local.h"
|
||||
|
||||
/* NOTE: _swprintf_r() should be identical to swprintf() except for the
|
||||
* former having ptr as a parameter and the latter needing to declare it as
|
||||
* a variable set to _REENT. */
|
||||
|
||||
int
|
||||
_DEFUN(_swprintf_r, (ptr, str, size, fmt),
|
||||
struct _reent *ptr _AND
|
||||
wchar_t *str _AND
|
||||
size_t size _AND
|
||||
_CONST wchar_t *fmt _DOTS)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
FILE f;
|
||||
|
||||
if (size > INT_MAX / sizeof (wchar_t))
|
||||
{
|
||||
ptr->_errno = EOVERFLOW; /* POSIX extension */
|
||||
return EOF;
|
||||
}
|
||||
f._flags = __SWR | __SSTR;
|
||||
f._bf._base = f._p = (unsigned char *) str;
|
||||
f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0);
|
||||
f._file = -1; /* No file. */
|
||||
va_start (ap, fmt);
|
||||
ret = _svfwprintf_r (ptr, &f, fmt, ap);
|
||||
va_end (ap);
|
||||
/* _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);
|
||||
}
|
||||
|
||||
#ifndef _REENT_ONLY
|
||||
|
||||
int
|
||||
_DEFUN(swprintf, (str, size, fmt),
|
||||
wchar_t *__restrict str _AND
|
||||
size_t size _AND
|
||||
_CONST wchar_t *__restrict fmt _DOTS)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
FILE f;
|
||||
struct _reent *ptr = _REENT;
|
||||
|
||||
if (size > INT_MAX / sizeof (wchar_t))
|
||||
{
|
||||
ptr->_errno = EOVERFLOW; /* POSIX extension */
|
||||
return EOF;
|
||||
}
|
||||
f._flags = __SWR | __SSTR;
|
||||
f._bf._base = f._p = (unsigned char *) str;
|
||||
f._bf._size = f._w = (size > 0 ? (size - 1) * sizeof (wchar_t) : 0);
|
||||
f._file = -1; /* No file. */
|
||||
va_start (ap, fmt);
|
||||
ret = _svfwprintf_r (ptr, &f, fmt, ap);
|
||||
va_end (ap);
|
||||
/* _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);
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user