2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright (c) 2012-2014 ARM Ltd
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. The name of the company may not be used to endorse or promote
46 * products derived from this software without specific prior written
49 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
54 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
56 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
57 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
58 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 #if defined(LIBC_SCCS) && !defined(lint)
62 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
63 static char *rcsid
= "$Id$";
64 #endif /* LIBC_SCCS and not lint */
78 #include "../../stdio/local.h"
79 #include "../../stdlib/local.h"
80 #include "../../stdio/fvwrite.h"
81 #include "../../stdio/nano-vfprintf_local.h"
83 /* Bypass *putc* fns called by the default _sfputs_r to save code size.
84 Among other things, this means there is no buffering of the string before
85 it is sent to <<write>>, but <<write>> does its own buffering so we won't
86 lose chars when buf is larger than sizeof(CIOBUF). */
88 __tiny__sfputs_r (struct _reent
*ptr
,
93 return write (1, buf
, len
);
96 /* VFPRINTF_R from nano-vfprintf.c but:
97 - No support for reentrancy
98 - No support for streams
99 - __SINGLE_THREAD__ assumed.
100 - No STRING_ONLY variant (either way the formatted string would end up
101 being sent to <<write>> via <<__tiny__sfputs_r>>.
102 Basically, format the string as normal, and send it to write. */
104 __tiny_vfprintf_r (struct _reent
*data
,
109 register char *fmt
; /* Format string. */
110 register int n
, m
; /* Handy integers (short term usage). */
111 register char *cp
; /* Handy char pointer (short term usage). */
112 const char *flag_chars
;
113 struct _prt_data_t prt_data
; /* All data for decoding format string. */
116 /* Output function pointer. */
117 int (*pfunc
)(struct _reent
*, FILE *, const char *, size_t len
);
119 pfunc
= __tiny__sfputs_r
;
123 prt_data
.blank
= ' ';
126 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
127 va_copy (ap_copy
, ap
);
129 /* Scan the format for conversions (`%' character). */
133 while (*fmt
!= '\0' && *fmt
!= '%')
136 if ((m
= fmt
- cp
) != 0)
144 fmt
++; /* Skip over '%'. */
150 prt_data
.l_buf
[0] = '\0';
151 #ifdef FLOATING_POINT
156 * ``Note that 0 is taken as a flag, not as the
157 * beginning of a field width.''
160 flag_chars
= "#-0+ ";
161 for (; cp
= memchr (flag_chars
, *fmt
, 5); fmt
++)
162 prt_data
.flags
|= (1 << (cp
- flag_chars
));
164 if (prt_data
.flags
& SPACESGN
)
165 prt_data
.l_buf
[0] = ' ';
168 * ``If the space and + flags both appear, the space
169 * flag will be ignored.''
172 if (prt_data
.flags
& PLUSSGN
)
173 prt_data
.l_buf
[0] = '+';
179 * ``A negative field width argument is taken as a
180 * - flag followed by a positive field width.''
182 * They don't exclude field widths read from args.
184 prt_data
.width
= GET_ARG (n
, ap_copy
, int);
185 if (prt_data
.width
< 0)
187 prt_data
.width
= -prt_data
.width
;
188 prt_data
.flags
|= LADJUST
;
194 for (; is_digit (*fmt
); fmt
++)
195 prt_data
.width
= 10 * prt_data
.width
+ to_digit (*fmt
);
205 prt_data
.prec
= GET_ARG (n
, ap_copy
, int);
206 if (prt_data
.prec
< 0)
212 for (; is_digit (*fmt
); fmt
++)
213 prt_data
.prec
= 10 * prt_data
.prec
+ to_digit (*fmt
);
217 /* The length modifiers. */
219 if ((cp
= memchr (flag_chars
, *fmt
, 3)) != NULL
)
221 prt_data
.flags
|= (SHORTINT
<< (cp
- flag_chars
));
225 /* The conversion specifiers. */
226 prt_data
.code
= *fmt
++;
227 cp
= memchr ("efgEFG", prt_data
.code
, 6);
228 #ifdef FLOATING_POINT
229 /* If cp is not NULL, we are facing FLOATING POINT NUMBER. */
232 /* Consume floating point argument if _printf_float is not
234 if (_printf_float
== NULL
)
236 if (prt_data
.flags
& LONGDBL
)
237 GET_ARG (N
, ap_copy
, _LONG_DOUBLE
);
239 GET_ARG (N
, ap_copy
, double);
242 n
= _printf_float (data
, &prt_data
, fp
, pfunc
, &ap_copy
);
246 n
= _printf_i (data
, &prt_data
, fp
, pfunc
, &ap_copy
);
256 return (__sferror (fp
) ? EOF
: prt_data
.ret
);
260 __wrap_printf (const char *__restrict fmt
, ...)
264 struct _reent
*ptr
= _REENT
;
267 ret
= __tiny_vfprintf_r (ptr
, _stdout_r (ptr
), fmt
, ap
);
272 int printf (const char *__restrict fmt
, ...) __attribute__ ((weak
, alias ("__wrap_printf")));