aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/stdio/swprintf.c
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2009-03-06 09:55:52 +0000
committerCorinna Vinschen <corinna@vinschen.de>2009-03-06 09:55:52 +0000
commit6121968b198dcbb93427b0a11453563ebe462bb4 (patch)
tree1b612b73db2b4572c591bf8644021b2407a8f602 /newlib/libc/stdio/swprintf.c
parent6e0e5a4fc20a1de8124c454a5c14c616c68e4653 (diff)
downloadnewlib-6121968b198dcbb93427b0a11453563ebe462bb4.zip
newlib-6121968b198dcbb93427b0a11453563ebe462bb4.tar.gz
newlib-6121968b198dcbb93427b0a11453563ebe462bb4.tar.bz2
* libc/include/stdio.h (__VALIST): Guard against multiple definition.
* libc/include/wchar.h: Include stdarg.h. (__VALIST): Define conditionally. (fwprintf, swprintf, vfwprintf, vswprintf, vwprintf, wprintf: Declare. (_fwprintf_r, _swprintf_r, _vfwprintf_r, _vswprintf_r, _vwprintf_r, _wprintf_r): Declare. * libc/stdio/Makefile.am: Add new files. * libc/stdio/Makefile.in: Regenerate. * libc/stdio/fwprintf.c: New file. * libc/stdio/local.h (_svfwprintf_r, _svfiwprintf_r): Declare. (__CH_CLASS, __STATE, __ACTION): Move definition from vfprintf.c here and move to the __ namespace. (__chclass, __state_table, __action_table): Declare. * libc/stdio/stdio.tex: Add new documentation references. * libc/stdio/swprintf.c: New file. * libc/stdio/vfprintf.c (__SPRINT): New macro to call the right __sprint_r function according to compilation unit. Use throughout. (__ssprint_r): Rename STRING_ONLY variant from __sprint_r. Make externaly available. Only define if INTEGER_ONLY is defined. (__sprint_r): Make externaly available. Only define if INTEGER_ONLY is defined. Handle stream orientation. (__sbprintf): Copy FILE's _flags2 member as well. (__chclass, __state_table, __action_table): Prepend __ to name and make externally available. * libc/stdio/vfwprintf.c: New file. * libc/stdio/vswprintf.c: New file. * libc/stdio/vwprintf.c: New file. * libc/stdio/wprintf.c: New file.
Diffstat (limited to 'newlib/libc/stdio/swprintf.c')
-rw-r--r--newlib/libc/stdio/swprintf.c592
1 files changed, 592 insertions, 0 deletions
diff --git a/newlib/libc/stdio/swprintf.c b/newlib/libc/stdio/swprintf.c
new file mode 100644
index 0000000..0d0e4d9
--- /dev/null
+++ b/newlib/libc/stdio/swprintf.c
@@ -0,0 +1,592 @@
+/*
+ * 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 <stdio.h>
+
+ int wprintf(const wchar_t *<[format]>, ...);
+ int fwprintf(FILE *<[fd]>, const wchar_t *<[format]>, ...);
+ int swprintf(wchar_t *<[str]>, const wchar_t *<[format]>, ...);
+
+ int _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]>,
+ const wchar_t *<[format]>, ...);
+
+DESCRIPTION
+ <<wprintf>> accepts a series of arguments, applies to each a
+ format specifier from <<*<[format]>>>, and writes the
+ formatted data to <<stdout>>, without a terminating NUL
+ wide character. The behavior of <<wprintf>> is undefined if there
+ are not enough arguments for the format. <<wprintf>> returns
+ when it reaches the end of the format string. If there are
+ 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]>, and the resulting string length is limited
+ to at most <[size]> wide characters, including the terminating
+ <<NUL>>. As a special case, if <[size]> is 0, <[str]> can be NULL,
+ and <<swprintf>> merely calculates how many bytes would be printed.
+
+ 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.
+
+ 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 '
+ Since newlib only supports the C locale, this
+ flag has no effect in this implementation.
+ But in other locales, when <[type]> is <<i>>,
+ <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>,
+ the locale-dependent thousand's separator is
+ inserted prior to zero padding.
+
+ 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>>, <<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+
+ 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-
+
+ 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
+ <<ssize_t>> or <<size_t>>.
+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<ssize_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>>.
+
+ 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>>.
+
+ o d or i
+ Prints a signed decimal integer; takes an
+ <<int>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ o o
+ Prints an unsigned octal integer; takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ o u
+ Prints an unsigned decimal integer; takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ o x
+ Prints an unsigned hexadecimal integer (using
+ <<abcdef>> as digits beyond <<9>>); takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ 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-
+ 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 <<snwprintf>>, <<errno>>
+may be set to EOVERFLOW if <[size]> or the output length exceeds
+INT_MAX / sizeof (wchar_t).
+
+PORTABILITY
+POSIX-1.2008
+
+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"
+
+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;
+ 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);
+ if (ret < EOF)
+ ptr->_errno = EOVERFLOW;
+ if (size > 0)
+ *f._p = 0;
+ return (ret);
+}
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN(swprintf, (str, size, fmt),
+ wchar_t *str _AND
+ size_t size _AND
+ _CONST wchar_t *fmt _DOTS)
+{
+ int ret;
+ va_list ap;
+ FILE f;
+ struct _reent *ptr = _REENT;
+
+ if (size > INT_MAX / sizeof (wchar_t))
+ {
+ ptr->_errno = EOVERFLOW;
+ 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);
+ if (ret < EOF)
+ ptr->_errno = EOVERFLOW;
+ if (size > 0)
+ *f._p = 0;
+ return (ret);
+}
+
+#endif