diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2009-03-06 09:55:52 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2009-03-06 09:55:52 +0000 |
commit | 6121968b198dcbb93427b0a11453563ebe462bb4 (patch) | |
tree | 1b612b73db2b4572c591bf8644021b2407a8f602 /newlib/libc/stdio/swprintf.c | |
parent | 6e0e5a4fc20a1de8124c454a5c14c616c68e4653 (diff) | |
download | newlib-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.c | 592 |
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 |