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.
63 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
93 int vprintf(const char *<[fmt]>, va_list <[list]>);
94 int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
95 int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
96 int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
98 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
99 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
102 int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
104 int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
105 const char *<[fmt]>, va_list <[list]>);
106 int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
107 const char *<[fmt]>, va_list <[list]>);
108 int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
109 const char *<[fmt]>, va_list <[list]>);
110 int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
111 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
112 char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
113 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
116 <<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
117 and <<vasnprintf>> are (respectively) variants of <<printf>>,
118 <<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
119 <<asnprintf>>. They differ only in allowing their caller to pass the
120 variable argument list as a <<va_list>> object (initialized by
121 <<va_start>>) rather than directly accepting a variable number of
122 arguments. The caller is responsible for calling <<va_end>>.
124 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
125 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
129 The return values are consistent with the corresponding functions.
132 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
133 <<vsnprintf>>. The remaining functions are newlib extensions.
135 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
136 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
139 #if defined(LIBC_SCCS) && !defined(lint)
140 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
141 static char *rcsid
= "$Id$";
142 #endif /* LIBC_SCCS and not lint */
144 /* Actual printf innards.
145 This code is large and complicated... */
148 #define VFPRINTF vfprintf
150 # define _VFPRINTF_R _svfprintf_r
152 # define _VFPRINTF_R _vfprintf_r
163 #include <sys/lock.h>
166 #include "../stdlib/local.h"
168 #include "vfieeefp.h"
169 #include "nano-vfprintf_local.h"
171 /* The __ssputs_r function is shared between all versions of vfprintf
175 __ssputs_r (struct _reent
*ptr
,
183 if (len
>= w
&& fp
->_flags
& (__SMBF
| __SOPT
))
185 /* Must be asprintf family. */
187 int curpos
= (fp
->_p
- fp
->_bf
._base
);
188 /* Choose a geometric growth factor to avoid
189 * quadratic realloc behavior, but use a rate less
190 * than (1+sqrt(5))/2 to accomodate malloc
191 * overhead. asprintf EXPECTS us to overallocate, so
192 * that it can add a trailing \0 without
193 * reallocating. The new allocation should thus be
194 * max(prev_size*1.5, curpos+len+1). */
195 int newsize
= fp
->_bf
._size
* 3 / 2;
196 if (newsize
< curpos
+ len
+ 1)
197 newsize
= curpos
+ len
+ 1;
198 if (fp
->_flags
& __SOPT
)
200 /* asnprintf leaves original buffer alone. */
201 str
= (unsigned char *)_malloc_r (ptr
, newsize
);
204 _REENT_ERRNO(ptr
) = ENOMEM
;
207 memcpy (str
, fp
->_bf
._base
, curpos
);
208 fp
->_flags
= (fp
->_flags
& ~__SOPT
) | __SMBF
;
212 str
= (unsigned char *)_realloc_r (ptr
, fp
->_bf
._base
, newsize
);
215 /* Free unneeded buffer. */
216 _free_r (ptr
, fp
->_bf
._base
);
217 /* Ensure correct errno, even if free changed it. */
218 _REENT_ERRNO(ptr
) = ENOMEM
;
223 fp
->_p
= str
+ curpos
;
224 fp
->_bf
._size
= newsize
;
226 fp
->_w
= newsize
- curpos
;
231 (void)memmove ((void *) fp
->_p
, (void *) buf
, (size_t) (w
));
237 fp
->_flags
|= __SERR
;
240 /* __ssprint_r is the original implementation of __SPRINT. In nano
241 version formatted IO it is reimplemented as __ssputs_r for non-wide
242 char output, but __ssprint_r cannot be discarded because it is used
243 by a serial of functions like svfwprintf for wide char output. */
245 __ssprint_r (struct _reent
*ptr
,
247 register struct __suio
*uio
)
251 register struct __siov
*iov
;
252 register const char *p
= NULL
;
257 if (uio
->uio_resid
== 0)
272 if (len
>= w
&& fp
->_flags
& (__SMBF
| __SOPT
))
274 /* Must be asprintf family. */
276 int curpos
= (fp
->_p
- fp
->_bf
._base
);
277 /* Choose a geometric growth factor to avoid
278 * quadratic realloc behavior, but use a rate less
279 * than (1+sqrt(5))/2 to accomodate malloc
280 * overhead. asprintf EXPECTS us to overallocate, so
281 * that it can add a trailing \0 without
282 * reallocating. The new allocation should thus be
283 * max(prev_size*1.5, curpos+len+1). */
284 int newsize
= fp
->_bf
._size
* 3 / 2;
285 if (newsize
< curpos
+ len
+ 1)
286 newsize
= curpos
+ len
+ 1;
288 if (fp
->_flags
& __SOPT
)
290 /* asnprintf leaves original buffer alone. */
291 str
= (unsigned char *)_malloc_r (ptr
, newsize
);
294 _REENT_ERRNO(ptr
) = ENOMEM
;
297 memcpy (str
, fp
->_bf
._base
, curpos
);
298 fp
->_flags
= (fp
->_flags
& ~__SOPT
) | __SMBF
;
302 str
= (unsigned char *)_realloc_r (ptr
, fp
->_bf
._base
,
306 /* Free unneeded buffer. */
307 _free_r (ptr
, fp
->_bf
._base
);
308 /* Ensure correct errno, even if free changed it. */
309 _REENT_ERRNO(ptr
) = ENOMEM
;
314 fp
->_p
= str
+ curpos
;
315 fp
->_bf
._size
= newsize
;
317 fp
->_w
= newsize
- curpos
;
322 (void)memmove ((void *) fp
->_p
, (void *) p
, (size_t) (w
));
325 /* Pretend we copied all. */
330 while ((uio
->uio_resid
-= w
) != 0);
337 fp
->_flags
|= __SERR
;
343 /* As __ssputs_r, __sprint_r is used by output functions for wide char,
345 /* Flush out all the vectors defined by the given uio,
346 then reset it so that it can be reused. */
348 __sprint_r (struct _reent
*ptr
,
350 register struct __suio
*uio
)
352 register int err
= 0;
354 if (uio
->uio_resid
== 0)
359 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
360 if (fp
->_flags2
& __SWID
)
367 for (; uio
->uio_resid
!= 0;
368 uio
->uio_resid
-= len
* sizeof (wchar_t), iov
++)
370 p
= (wchar_t *) iov
->iov_base
;
371 len
= iov
->iov_len
/ sizeof (wchar_t);
372 for (i
= 0; i
< len
; i
++)
374 if (_fputwc_r (ptr
, p
[i
], fp
) == WEOF
)
384 err
= __sfvwrite_r(ptr
, fp
, uio
);
392 __sfputc_r (struct _reent
*ptr
,
396 if (--fp
->_w
>= 0 || (fp
->_w
>= fp
->_lbfsize
&& (char)c
!= '\n'))
397 return (*fp
->_p
++ = c
);
399 return (__swbuf_r(ptr
, c
, fp
));
403 __sfputs_r (struct _reent
*ptr
,
410 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
411 if (fp
->_flags2
& __SWID
)
416 for (i
= 0; i
< (len
/ sizeof (wchar_t)); i
++)
418 if (_fputwc_r (ptr
, p
[i
], fp
) == WEOF
)
425 for (i
= 0; i
< len
; i
++)
427 /* Call __sfputc_r to skip _fputc_r. */
428 if (__sfputc_r (ptr
, (int)buf
[i
], fp
) == EOF
)
434 #endif /* STRING_ONLY. */
436 int _VFPRINTF_R (struct _reent
*, FILE *, const char *, va_list);
445 result
= _VFPRINTF_R (_REENT
, fp
, fmt0
, ap
);
450 vfiprintf (FILE *, const char *, __VALIST
)
451 _ATTRIBUTE ((__alias__("vfprintf")));
455 # define __SPRINT __ssputs_r
457 # define __SPRINT __sfputs_r
460 /* Do not need FLUSH for all sprintf functions. */
468 _VFPRINTF_R (struct _reent
*data
,
473 register char *fmt
; /* Format string. */
474 register int n
, m
; /* Handy integers (short term usage). */
475 register char *cp
; /* Handy char pointer (short term usage). */
476 const char *flag_chars
;
477 struct _prt_data_t prt_data
; /* All data for decoding format string. */
480 /* Output function pointer. */
481 int (*pfunc
)(struct _reent
*, FILE *, const char *, size_t len
);
486 /* Initialize std streams if not dealing with sprintf family. */
487 CHECK_INIT (data
, fp
);
488 _newlib_flockfile_start (fp
);
490 /* Sorry, fprintf(read_only_file, "") returns EOF, not 0. */
491 if (cantwrite (data
, fp
))
493 _newlib_flockfile_exit (fp
);
498 /* Create initial buffer if we are called by asprintf family. */
499 if (fp
->_flags
& __SMBF
&& !fp
->_bf
._base
)
501 fp
->_bf
._base
= fp
->_p
= _malloc_r (data
, 64);
504 _REENT_ERRNO(data
) = ENOMEM
;
513 prt_data
.blank
= ' ';
516 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
517 va_copy (ap_copy
, ap
);
519 /* Scan the format for conversions (`%' character). */
523 while (*fmt
!= '\0' && *fmt
!= '%')
526 if ((m
= fmt
- cp
) != 0)
534 fmt
++; /* Skip over '%'. */
540 prt_data
.l_buf
[0] = '\0';
541 #ifdef FLOATING_POINT
546 * ``Note that 0 is taken as a flag, not as the
547 * beginning of a field width.''
550 flag_chars
= "#-0+ ";
551 for (; cp
= memchr (flag_chars
, *fmt
, 5); fmt
++)
552 prt_data
.flags
|= (1 << (cp
- flag_chars
));
554 if (prt_data
.flags
& SPACESGN
)
555 prt_data
.l_buf
[0] = ' ';
558 * ``If the space and + flags both appear, the space
559 * flag will be ignored.''
562 if (prt_data
.flags
& PLUSSGN
)
563 prt_data
.l_buf
[0] = '+';
569 * ``A negative field width argument is taken as a
570 * - flag followed by a positive field width.''
572 * They don't exclude field widths read from args.
574 prt_data
.width
= GET_ARG (n
, ap_copy
, int);
575 if (prt_data
.width
< 0)
577 prt_data
.width
= -prt_data
.width
;
578 prt_data
.flags
|= LADJUST
;
584 for (; is_digit (*fmt
); fmt
++)
585 prt_data
.width
= 10 * prt_data
.width
+ to_digit (*fmt
);
595 prt_data
.prec
= GET_ARG (n
, ap_copy
, int);
596 if (prt_data
.prec
< 0)
602 for (; is_digit (*fmt
); fmt
++)
603 prt_data
.prec
= 10 * prt_data
.prec
+ to_digit (*fmt
);
607 /* The length modifiers. */
609 if ((cp
= memchr (flag_chars
, *fmt
, 3)) != NULL
)
611 prt_data
.flags
|= (SHORTINT
<< (cp
- flag_chars
));
615 /* The conversion specifiers. */
616 prt_data
.code
= *fmt
++;
617 cp
= memchr ("efgEFG", prt_data
.code
, 6);
618 #ifdef FLOATING_POINT
619 /* If cp is not NULL, we are facing FLOATING POINT NUMBER. */
622 /* Consume floating point argument if _printf_float is not
624 if (_printf_float
== NULL
)
626 if (prt_data
.flags
& LONGDBL
)
627 GET_ARG (N
, ap_copy
, _LONG_DOUBLE
);
629 GET_ARG (N
, ap_copy
, double);
632 n
= _printf_float (data
, &prt_data
, fp
, pfunc
, &ap_copy
);
636 n
= _printf_i (data
, &prt_data
, fp
, pfunc
, &ap_copy
);
647 _newlib_flockfile_end (fp
);
650 return (__sferror (fp
) ? EOF
: prt_data
.ret
);
655 _svfiprintf_r (struct _reent
*, FILE *, const char *, __VALIST
)
656 _ATTRIBUTE ((__alias__("_svfprintf_r")));
659 _vfiprintf_r (struct _reent
*, FILE *, const char *, __VALIST
)
660 _ATTRIBUTE ((__alias__("_vfprintf_r")));