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