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