1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
19 *
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
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 2012-2014 ARM Ltd
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
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
47 * permission.
48 *
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.
59 */
60
61 /*
62 FUNCTION
63 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
64
65 INDEX
66 vfprintf
67 INDEX
68 _vfprintf_r
69 INDEX
70 vprintf
71 INDEX
72 _vprintf_r
73 INDEX
74 vsprintf
75 INDEX
76 _vsprintf_r
77 INDEX
78 vsnprintf
79 INDEX
80 _vsnprintf_r
81 INDEX
82 vasprintf
83 INDEX
84 _vasprintf_r
85 INDEX
86 vasnprintf
87 INDEX
88 _vasnprintf_r
89
90 SYNOPSIS
91 #include <stdio.h>
92 #include <stdarg.h>
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]>,
97 va_list <[list]>);
98 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
99 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
100 va_list <[list]>);
101
102 int vprintf( const char *<[fmt]>,
103 va_list <[list]>);
104 int vfprintf( FILE *<[fp]>,
105 const char *<[fmt]>, va_list <[list]>);
106 int vsprintf( char *<[str]>,
107 const char *<[fmt]>, va_list <[list]>);
108 int vasprintf( char **<[str]>,
109 const char *<[fmt]>, va_list <[list]>);
110 int vsnprintf( char *<[str]>,
111 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
112 char *vasnprintf( char *<[str]>,
113 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
114
115 DESCRIPTION
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>>.
123
124 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
125 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
126 above.
127
128 RETURNS
129 The return values are consistent with the corresponding functions.
130
131 PORTABILITY
132 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
133 <<vsnprintf>>. The remaining functions are newlib extensions.
134
135 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
136 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
137 */
138
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 */
143
144 /* Actual printf innards.
145 This code is large and complicated... */
146
147 #ifdef STRING_ONLY
148 # define VFPRINTF svfprintf
149 #else
150 # define VFPRINTF vfprintf
151 #endif
152
153 #define _DEFAULT_SOURCE
154 #include <stdio.h>
155 #include <stdlib.h>
156 #include <string.h>
157 #include <limits.h>
158 #include <stdint.h>
159 #include <wchar.h>
160 #include <sys/lock.h>
161 #include <stdarg.h>
162 #include "local.h"
163 #include "../stdlib/local.h"
164 #include "fvwrite.h"
165 #include "vfieeefp.h"
166 #include "nano-vfprintf_local.h"
167
168 /* The _ssputs function is shared between all versions of vfprintf
169 and vfwprintf. */
170 #ifdef STRING_ONLY
171 int
_ssputs(FILE * fp,const char * buf,size_t len)172 _ssputs (
173 FILE *fp,
174 const char *buf,
175 size_t len)
176 {
177 register size_t w;
178
179 w = fp->_w;
180 if (len >= w && fp->_flags & (__SMBF | __SOPT))
181 {
182 /* Must be asprintf family. */
183 unsigned char *str;
184 int curpos = (fp->_p - fp->_bf._base);
185 /* Choose a geometric growth factor to avoid
186 * quadratic realloc behavior, but use a rate less
187 * than (1+sqrt(5))/2 to accomodate malloc
188 * overhead. asprintf EXPECTS us to overallocate, so
189 * that it can add a trailing \0 without
190 * reallocating. The new allocation should thus be
191 * max(prev_size*1.5, curpos+len+1). */
192 size_t newsize = fp->_bf._size * 3 / 2;
193 if (newsize < curpos + len + 1)
194 newsize = curpos + len + 1;
195 if (fp->_flags & __SOPT)
196 {
197 /* asnprintf leaves original buffer alone. */
198 str = (unsigned char *)malloc (newsize);
199 if (!str)
200 {
201 _REENT_ERRNO(ptr) = ENOMEM;
202 goto err;
203 }
204 memcpy (str, fp->_bf._base, curpos);
205 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
206 }
207 else
208 {
209 str = (unsigned char *)realloc (fp->_bf._base, newsize);
210 if (!str)
211 {
212 /* Free unneeded buffer. */
213 free (fp->_bf._base);
214 /* Ensure correct errno, even if free changed it. */
215 _REENT_ERRNO(ptr) = ENOMEM;
216 goto err;
217 }
218 }
219 fp->_bf._base = str;
220 fp->_p = str + curpos;
221 fp->_bf._size = newsize;
222 w = len;
223 fp->_w = newsize - curpos;
224 }
225 if (len < w)
226 w = len;
227
228 (void)memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
229 fp->_w -= w;
230 fp->_p += w;
231 return 0;
232
233 err:
234 fp->_flags |= __SERR;
235 return EOF;
236 }
237 /* _ssprint is the original implementation of _SPRINT. In nano
238 version formatted IO it is reimplemented as _ssputs for non-wide
239 char output, but _ssprint cannot be discarded because it is used
240 by a serial of functions like svfwprintf for wide char output. */
241 int
_ssprint(FILE * fp,register struct __suio * uio)242 _ssprint (
243 FILE *fp,
244 register struct __suio *uio)
245 {
246 register size_t len;
247 register size_t w;
248 register struct __siov *iov;
249 register const char *p = NULL;
250
251 iov = uio->uio_iov;
252 len = 0;
253
254 if (uio->uio_resid == 0)
255 {
256 uio->uio_iovcnt = 0;
257 return (0);
258 }
259
260 do
261 {
262 while (len == 0)
263 {
264 p = iov->iov_base;
265 len = iov->iov_len;
266 iov++;
267 }
268 w = fp->_w;
269 if (len >= w && fp->_flags & (__SMBF | __SOPT))
270 {
271 /* Must be asprintf family. */
272 unsigned char *str;
273 int curpos = (fp->_p - fp->_bf._base);
274 /* Choose a geometric growth factor to avoid
275 * quadratic realloc behavior, but use a rate less
276 * than (1+sqrt(5))/2 to accomodate malloc
277 * overhead. asprintf EXPECTS us to overallocate, so
278 * that it can add a trailing \0 without
279 * reallocating. The new allocation should thus be
280 * max(prev_size*1.5, curpos+len+1). */
281 size_t newsize = fp->_bf._size * 3 / 2;
282 if (newsize < curpos + len + 1)
283 newsize = curpos + len + 1;
284
285 if (fp->_flags & __SOPT)
286 {
287 /* asnprintf leaves original buffer alone. */
288 str = (unsigned char *)malloc (newsize);
289 if (!str)
290 {
291 _REENT_ERRNO(ptr) = ENOMEM;
292 goto err;
293 }
294 memcpy (str, fp->_bf._base, curpos);
295 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
296 }
297 else
298 {
299 str = (unsigned char *)realloc (fp->_bf._base,
300 newsize);
301 if (!str)
302 {
303 /* Free unneeded buffer. */
304 free (fp->_bf._base);
305 /* Ensure correct errno, even if free changed it. */
306 _REENT_ERRNO(ptr) = ENOMEM;
307 goto err;
308 }
309 }
310 fp->_bf._base = str;
311 fp->_p = str + curpos;
312 fp->_bf._size = newsize;
313 w = len;
314 fp->_w = newsize - curpos;
315 }
316 if (len < w)
317 w = len;
318
319 (void)memmove ((void *) fp->_p, (void *) p, (size_t) (w));
320 fp->_w -= w;
321 fp->_p += w;
322 /* Pretend we copied all. */
323 w = len;
324 p += w;
325 len -= w;
326 }
327 while ((uio->uio_resid -= w) != 0);
328
329 uio->uio_resid = 0;
330 uio->uio_iovcnt = 0;
331 return 0;
332
333 err:
334 fp->_flags |= __SERR;
335 uio->uio_resid = 0;
336 uio->uio_iovcnt = 0;
337 return EOF;
338 }
339 #else
340 /* As __ssputs_r, __sprint_r is used by output functions for wide char,
341 like vfwprint. */
342 /* Flush out all the vectors defined by the given uio,
343 then reset it so that it can be reused. */
344 int
_sprint(FILE * fp,register struct __suio * uio)345 _sprint (
346 FILE *fp,
347 register struct __suio *uio)
348 {
349 register int err = 0;
350
351 if (uio->uio_resid == 0)
352 {
353 uio->uio_iovcnt = 0;
354 return 0;
355 }
356 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
357 if (fp->_flags2 & __SWID)
358 {
359 struct __siov *iov;
360 wchar_t *p;
361 int i, len;
362
363 iov = uio->uio_iov;
364 for (; uio->uio_resid != 0;
365 uio->uio_resid -= len * sizeof (wchar_t), iov++)
366 {
367 p = (wchar_t *) iov->iov_base;
368 len = iov->iov_len / sizeof (wchar_t);
369 for (i = 0; i < len; i++)
370 {
371 if (fputwc ( p[i], fp) == WEOF)
372 {
373 err = -1;
374 goto out;
375 }
376 }
377 }
378 }
379 else
380 #endif
381 err = _sfvwrite( fp, uio);
382 goto out;
383 out:
384 uio->uio_resid = 0;
385 uio->uio_iovcnt = 0;
386 return err;
387 }
388
389 _NOINLINE_STATIC int
_sfputc(int c,FILE * fp)390 _sfputc (
391 int c,
392 FILE *fp)
393 {
394 if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && (char)c != '\n'))
395 return (*fp->_p++ = c);
396 else
397 return (_swbuf( c, fp));
398 }
399
400 int
_sfputs(FILE * fp,const char * buf,size_t len)401 _sfputs (
402 FILE *fp,
403 const char *buf,
404 size_t len)
405 {
406 register size_t i;
407
408 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
409 if (fp->_flags2 & __SWID)
410 {
411 wchar_t *p;
412
413 p = (wchar_t *) buf;
414 for (i = 0; i < (len / sizeof (wchar_t)); i++)
415 {
416 if (fputwc ( p[i], fp) == WEOF)
417 return -1;
418 }
419 }
420 else
421 #endif
422 {
423 for (i = 0; i < len; i++)
424 {
425 /* Call __sfputc_r to skip _fputc_r. */
426 if (_sfputc ( (int)buf[i], fp) == EOF)
427 return -1;
428 }
429 }
430 return (0);
431 }
432 #endif /* STRING_ONLY. */
433
434 #ifdef STRING_ONLY
435 # define __SPRINT _ssputs
436 #else
437 # define __SPRINT _sfputs
438 #endif
439
440 /* Do not need FLUSH for all sprintf functions. */
441 #ifdef STRING_ONLY
442 # define FLUSH()
443 #else
444 # define FLUSH()
445 #endif
446
447 int
VFPRINTF(FILE * fp,const char * fmt0,va_list ap)448 VFPRINTF (
449 FILE * fp,
450 const char *fmt0,
451 va_list ap)
452 {
453 register char *fmt; /* Format string. */
454 register int n, m; /* Handy integers (short term usage). */
455 register char *cp; /* Handy char pointer (short term usage). */
456 const char *flag_chars;
457 struct _prt_data_t prt_data; /* All data for decoding format string. */
458 va_list ap_copy;
459
460 /* Output function pointer. */
461 int (*pfunc)(FILE *, const char *, size_t len);
462
463 pfunc = __SPRINT;
464
465 #ifndef STRING_ONLY
466 /* Initialize std streams if not dealing with sprintf family. */
467 CHECK_INIT (data, fp);
468 _newlib_flockfile_start (fp);
469
470 /* Sorry, fprintf(read_only_file, "") returns EOF, not 0. */
471 if (cantwrite (data, fp))
472 {
473 _newlib_flockfile_exit (fp);
474 return (EOF);
475 }
476
477 #else
478 /* Create initial buffer if we are called by asprintf family. */
479 if (fp->_flags & __SMBF && !fp->_bf._base)
480 {
481 fp->_bf._base = fp->_p = malloc (64);
482 if (!fp->_p)
483 {
484 _REENT_ERRNO(data) = ENOMEM;
485 return EOF;
486 }
487 fp->_bf._size = 64;
488 }
489 #endif
490
491 fmt = (char *)fmt0;
492 prt_data.ret = 0;
493 prt_data.blank = ' ';
494 prt_data.zero = '0';
495
496 /* GCC PR 14577 at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557 */
497 va_copy (ap_copy, ap);
498
499 /* Scan the format for conversions (`%' character). */
500 for (;;)
501 {
502 cp = fmt;
503 while (*fmt != '\0' && *fmt != '%')
504 fmt += 1;
505
506 if ((m = fmt - cp) != 0)
507 {
508 PRINT (cp, m);
509 prt_data.ret += m;
510 }
511 if (*fmt == '\0')
512 goto done;
513
514 fmt++; /* Skip over '%'. */
515
516 prt_data.flags = 0;
517 prt_data.width = 0;
518 prt_data.prec = -1;
519 prt_data.dprec = 0;
520 prt_data.l_buf[0] = '\0';
521 #ifdef FLOATING_POINT
522 prt_data.lead = 0;
523 #endif
524 /* The flags. */
525 /*
526 * ``Note that 0 is taken as a flag, not as the
527 * beginning of a field width.''
528 * -- ANSI X3J11
529 */
530 flag_chars = "#-0+ ";
531 for (; (cp = memchr (flag_chars, *fmt, 5)); fmt++)
532 prt_data.flags |= (1 << (cp - flag_chars));
533
534 if (prt_data.flags & SPACESGN)
535 prt_data.l_buf[0] = ' ';
536
537 /*
538 * ``If the space and + flags both appear, the space
539 * flag will be ignored.''
540 * -- ANSI X3J11
541 */
542 if (prt_data.flags & PLUSSGN)
543 prt_data.l_buf[0] = '+';
544
545 /* The width. */
546 if (*fmt == '*')
547 {
548 /*
549 * ``A negative field width argument is taken as a
550 * - flag followed by a positive field width.''
551 * -- ANSI X3J11
552 * They don't exclude field widths read from args.
553 */
554 prt_data.width = GET_ARG (n, ap_copy, int);
555 if (prt_data.width < 0)
556 {
557 prt_data.width = -prt_data.width;
558 prt_data.flags |= LADJUST;
559 }
560 fmt++;
561 }
562 else
563 {
564 for (; is_digit (*fmt); fmt++)
565 prt_data.width = 10 * prt_data.width + to_digit (*fmt);
566 }
567
568 /* The precision. */
569 if (*fmt == '.')
570 {
571 fmt++;
572 if (*fmt == '*')
573 {
574 fmt++;
575 prt_data.prec = GET_ARG (n, ap_copy, int);
576 if (prt_data.prec < 0)
577 prt_data.prec = -1;
578 }
579 else
580 {
581 prt_data.prec = 0;
582 for (; is_digit (*fmt); fmt++)
583 prt_data.prec = 10 * prt_data.prec + to_digit (*fmt);
584 }
585 }
586
587 /* The length modifiers. */
588 flag_chars = "hlL";
589 if ((cp = memchr (flag_chars, *fmt, 3)) != NULL)
590 {
591 prt_data.flags |= (SHORTINT << (cp - flag_chars));
592 fmt++;
593 }
594
595 /* The conversion specifiers. */
596 prt_data.code = *fmt++;
597 cp = memchr ("efgEFG", prt_data.code, 6);
598 #ifdef FLOATING_POINT
599 /* If cp is not NULL, we are facing FLOATING POINT NUMBER. */
600 if (cp)
601 {
602 /* Consume floating point argument if _printf_float is not
603 linked. */
604 if (_printf_float == NULL)
605 {
606 if (prt_data.flags & LONGDBL)
607 GET_ARG (N, ap_copy, _LONG_DOUBLE);
608 else
609 GET_ARG (N, ap_copy, double);
610 }
611 else
612 n = _printf_float (data, &prt_data, fp, pfunc, &ap_copy);
613 }
614 else
615 #endif
616 n = _printf_i (&prt_data, fp, pfunc, &ap_copy);
617
618 if (n == -1)
619 goto error;
620
621 prt_data.ret += n;
622 }
623 done:
624 FLUSH ();
625 error:
626 #ifndef STRING_ONLY
627 _newlib_flockfile_end (fp);
628 #endif
629 va_end (ap_copy);
630 return (__sferror (fp) ? EOF : prt_data.ret);
631 }
632
633 #ifdef STRING_ONLY
634 int __nonnull((1))
635 svfiprintf ( FILE *, const char *, __VALIST)
636 _ATTRIBUTE ((__alias__("svfprintf")));
637 #else
638 int __nonnull((1))
639 vfiprintf ( FILE *, const char *, __VALIST)
640 _ATTRIBUTE ((__alias__("vfprintf")));
641 #endif
642