From 6121968b198dcbb93427b0a11453563ebe462bb4 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 6 Mar 2009 09:55:52 +0000 Subject: * 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. --- newlib/libc/stdio/swprintf.c | 592 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100644 newlib/libc/stdio/swprintf.c (limited to 'newlib/libc/stdio/swprintf.c') diff --git a/newlib/libc/stdio/swprintf.c b/newlib/libc/stdio/swprintf.c new file mode 100644 index 000000000..0d0e4d933 --- /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 +<>, <>, <>---wide character format output + +INDEX + fwprintf +INDEX + _fwprintf_r +INDEX + wprintf +INDEX + _wprintf_r +INDEX + swprintf +INDEX + _swprintf_r + +ANSI_SYNOPSIS + #include + + 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 + <> accepts a series of arguments, applies to each a + format specifier from <<*<[format]>>>, and writes the + formatted data to <>, without a terminating NUL + wide character. The behavior of <> is undefined if there + are not enough arguments for the format. <> returns + when it reaches the end of the format string. If there are + more arguments than the format requires, excess arguments are + ignored. + + <> is like <>, except that output is directed + to the stream <[fd]> rather than <>. + + <> is like <>, 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 + <>. As a special case, if <[size]> is 0, <[str]> can be NULL, + and <> merely calculates how many bytes would be printed. + + For <> 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 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 <>, + <>, <>, <>, <>, <>, or <>, + 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 <>, <>, <>, + <>, <>, <>, <>, <>, <>, or + <>) 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 <>, <>, + <>, <>, <>, <>, <>, <>, + <>, <>, <>, <>, or <>: 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 + <>, <>, <>, <>, <>, and <> + 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 <> 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 <> 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 <>, <>, <>, <>, <>, or + <>, specifies that the argument should be + converted to a <> or <> before printing. + + With <>, specifies that the argument is a + pointer to a <>. + + o h + With <>, <>, <>, <>, <>, or + <>, specifies that the argument should be + converted to a <> or <> + before printing. + + With <>, specifies that the argument is a + pointer to a <>. + + o l + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <> or <>. + + With <>, specifies that the argument has + type <>. + + With <>, specifies that the argument is a + pointer to <>. + + With <>, specifies that the argument is a + pointer to a <>. + + With <>, <>, <>, <>, <>, <>, + <>, or <>, has no effect (because of + vararg promotion rules, there is no need to + distinguish between <> and <>). + + o ll + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <> or <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o j + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is an + <> or <>. + + With <>, specifies that the argument is a + pointer to an <>. + + o z + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <> or <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o t + With <>, <>, <>, <>, <>, or + <>, specifies that the argument is a + <>. + + With <>, specifies that the argument is a + pointer to a <>. + + o L + With <>, <>, <>, <>, <>, <>, + <>, or <>, specifies that the argument + is a <>. + + o- + + o <[type]> + + <[type]> specifies what kind of conversion <> + performs. Here is a table of these: + + o+ + o % + Prints the percent character (<<%>>). + + o c + If no <> 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 <> 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 <> 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 + <>. 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 + <>. 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 + <>. 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 + <> as digits beyond <<9>>); takes an + <>. Leading zeros are inserted as + necessary to reach the precision. A precision + of 0 produces an empty string. + + o X + Like <>, but uses <> 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 <> (remember that + <> promotes to <> 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 + <>, and no zero padding is performed. If + the value is not a number, the result is + <>, and no zero padding is performed. + + o F + Like <>, but uses <> and <> for + non-finite numbers. + + o e + Prints a signed value of the form + <<[-]9.9999e[+|-]999>>; takes a <>. + The digit before the decimal point is non-zero + if the value is non-zero. The precision + determines how many digits appear between + <<.>> and <>, 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 <>. + + o E + Like <>, but using <> to introduce the + exponent, and like <> for non-finite + values. + + o g + Prints a signed value in either <> or <> + form, based on the given value and + precision---an exponent less than -4 or + greater than the precision selects the <> + form. Trailing zeros and the decimal point + are printed only if necessary; takes a + <>. + + o G + Like <>, except use <> or <> form. + + o a + Prints a signed value of the form + <<[-]0x1.ffffp[+|-]9>>; takes a <>. + The letters <> 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 <>. + + o A + Like <>, except uses <>, <

>, and + <> instead of lower case. + + o n + Takes a pointer to <>, and stores a count + of the number of bytes written so far. No + output is created. + + o p + Takes a pointer to <>, 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, <> return the number of wide characters in +the output string, except the concluding <> is not counted. +<> and <> return the number of characters transmitted. + +If an error occurs, the result of <>, <>, and +<> is a negative value. For <> and <>, +<> may be set according to <>. For <>, <> +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: <>, <>, <>, +<>, <>, <>, <>. +*/ + + +#include <_ansi.h> +#include +#include +#include +#include +#include +#include +#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 -- cgit v1.2.3