Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdio / nano-vfprintf.c
blob0d42a940f8e797d2e07bd578d812c3891ebe6798
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
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.
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.
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
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.
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.
62 FUNCTION
63 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
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
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]>);
102 int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
103 va_list <[list]>);
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]>);
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>>.
124 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
125 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
126 above.
128 RETURNS
129 The return values are consistent with the corresponding functions.
131 PORTABILITY
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... */
146 #include <newlib.h>
148 #define VFPRINTF vfprintf
149 #ifdef STRING_ONLY
150 # define _VFPRINTF_R _svfprintf_r
151 #else
152 # define _VFPRINTF_R _vfprintf_r
153 #endif
155 #include <_ansi.h>
156 #include <reent.h>
157 #include <stdio.h>
158 #include <stdlib.h>
159 #include <string.h>
160 #include <limits.h>
161 #include <stdint.h>
162 #include <wchar.h>
163 #include <sys/lock.h>
164 #include <stdarg.h>
165 #include "local.h"
166 #include "../stdlib/local.h"
167 #include "fvwrite.h"
168 #include "vfieeefp.h"
169 #include "nano-vfprintf_local.h"
171 /* The __ssputs_r function is shared between all versions of vfprintf
172 and vfwprintf. */
173 #ifdef STRING_ONLY
175 __ssputs_r (struct _reent *ptr,
176 FILE *fp,
177 const char *buf,
178 size_t len)
180 register int w;
182 w = fp->_w;
183 if (len >= w && fp->_flags & (__SMBF | __SOPT))
185 /* Must be asprintf family. */
186 unsigned char *str;
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);
202 if (!str)
204 _REENT_ERRNO(ptr) = ENOMEM;
205 goto err;
207 memcpy (str, fp->_bf._base, curpos);
208 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
210 else
212 str = (unsigned char *)_realloc_r (ptr, fp->_bf._base, newsize);
213 if (!str)
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;
219 goto err;
222 fp->_bf._base = str;
223 fp->_p = str + curpos;
224 fp->_bf._size = newsize;
225 w = len;
226 fp->_w = newsize - curpos;
228 if (len < w)
229 w = len;
231 (void)memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
232 fp->_w -= w;
233 fp->_p += w;
234 return 0;
236 err:
237 fp->_flags |= __SERR;
238 return EOF;
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,
246 FILE *fp,
247 register struct __suio *uio)
249 register size_t len;
250 register int w;
251 register struct __siov *iov;
252 register const char *p = NULL;
254 iov = uio->uio_iov;
255 len = 0;
257 if (uio->uio_resid == 0)
259 uio->uio_iovcnt = 0;
260 return (0);
265 while (len == 0)
267 p = iov->iov_base;
268 len = iov->iov_len;
269 iov++;
271 w = fp->_w;
272 if (len >= w && fp->_flags & (__SMBF | __SOPT))
274 /* Must be asprintf family. */
275 unsigned char *str;
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);
292 if (!str)
294 _REENT_ERRNO(ptr) = ENOMEM;
295 goto err;
297 memcpy (str, fp->_bf._base, curpos);
298 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
300 else
302 str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
303 newsize);
304 if (!str)
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;
310 goto err;
313 fp->_bf._base = str;
314 fp->_p = str + curpos;
315 fp->_bf._size = newsize;
316 w = len;
317 fp->_w = newsize - curpos;
319 if (len < w)
320 w = len;
322 (void)memmove ((void *) fp->_p, (void *) p, (size_t) (w));
323 fp->_w -= w;
324 fp->_p += w;
325 /* Pretend we copied all. */
326 w = len;
327 p += w;
328 len -= w;
330 while ((uio->uio_resid -= w) != 0);
332 uio->uio_resid = 0;
333 uio->uio_iovcnt = 0;
334 return 0;
336 err:
337 fp->_flags |= __SERR;
338 uio->uio_resid = 0;
339 uio->uio_iovcnt = 0;
340 return EOF;
342 #else
343 /* As __ssputs_r, __sprint_r is used by output functions for wide char,
344 like vfwprint. */
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,
349 FILE *fp,
350 register struct __suio *uio)
352 register int err = 0;
354 if (uio->uio_resid == 0)
356 uio->uio_iovcnt = 0;
357 return 0;
359 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
360 if (fp->_flags2 & __SWID)
362 struct __siov *iov;
363 wchar_t *p;
364 int i, len;
366 iov = uio->uio_iov;
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)
376 err = -1;
377 goto out;
382 else
383 #endif
384 err = __sfvwrite_r(ptr, fp, uio);
385 out:
386 uio->uio_resid = 0;
387 uio->uio_iovcnt = 0;
388 return err;
391 _NOINLINE_STATIC int
392 __sfputc_r (struct _reent *ptr,
393 int c,
394 FILE *fp)
396 if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && (char)c != '\n'))
397 return (*fp->_p++ = c);
398 else
399 return (__swbuf_r(ptr, c, fp));
403 __sfputs_r (struct _reent *ptr,
404 FILE *fp,
405 const char *buf,
406 size_t len)
408 register int i;
410 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
411 if (fp->_flags2 & __SWID)
413 wchar_t *p;
415 p = (wchar_t *) buf;
416 for (i = 0; i < (len / sizeof (wchar_t)); i++)
418 if (_fputwc_r (ptr, p[i], fp) == WEOF)
419 return -1;
422 else
423 #endif
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)
429 return -1;
432 return (0);
434 #endif /* STRING_ONLY. */
436 int _VFPRINTF_R (struct _reent *, FILE *, const char *, va_list);
438 #ifndef STRING_ONLY
440 VFPRINTF (FILE * fp,
441 const char *fmt0,
442 va_list ap)
444 int result;
445 result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
446 return result;
450 vfiprintf (FILE *, const char *, __VALIST)
451 _ATTRIBUTE ((__alias__("vfprintf")));
452 #endif
454 #ifdef STRING_ONLY
455 # define __SPRINT __ssputs_r
456 #else
457 # define __SPRINT __sfputs_r
458 #endif
460 /* Do not need FLUSH for all sprintf functions. */
461 #ifdef STRING_ONLY
462 # define FLUSH()
463 #else
464 # define FLUSH()
465 #endif
468 _VFPRINTF_R (struct _reent *data,
469 FILE * fp,
470 const char *fmt0,
471 va_list ap)
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. */
478 va_list ap_copy;
480 /* Output function pointer. */
481 int (*pfunc)(struct _reent *, FILE *, const char *, size_t len);
483 pfunc = __SPRINT;
485 #ifndef STRING_ONLY
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);
494 return (EOF);
497 #else
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);
502 if (!fp->_p)
504 _REENT_ERRNO(data) = ENOMEM;
505 return EOF;
507 fp->_bf._size = 64;
509 #endif
511 fmt = (char *)fmt0;
512 prt_data.ret = 0;
513 prt_data.blank = ' ';
514 prt_data.zero = '0';
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). */
520 for (;;)
522 cp = fmt;
523 while (*fmt != '\0' && *fmt != '%')
524 fmt += 1;
526 if ((m = fmt - cp) != 0)
528 PRINT (cp, m);
529 prt_data.ret += m;
531 if (*fmt == '\0')
532 goto done;
534 fmt++; /* Skip over '%'. */
536 prt_data.flags = 0;
537 prt_data.width = 0;
538 prt_data.prec = -1;
539 prt_data.dprec = 0;
540 prt_data.l_buf[0] = '\0';
541 #ifdef FLOATING_POINT
542 prt_data.lead = 0;
543 #endif
544 /* The flags. */
546 * ``Note that 0 is taken as a flag, not as the
547 * beginning of a field width.''
548 * -- ANSI X3J11
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.''
560 * -- ANSI X3J11
562 if (prt_data.flags & PLUSSGN)
563 prt_data.l_buf[0] = '+';
565 /* The width. */
566 if (*fmt == '*')
569 * ``A negative field width argument is taken as a
570 * - flag followed by a positive field width.''
571 * -- ANSI X3J11
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;
580 fmt++;
582 else
584 for (; is_digit (*fmt); fmt++)
585 prt_data.width = 10 * prt_data.width + to_digit (*fmt);
588 /* The precision. */
589 if (*fmt == '.')
591 fmt++;
592 if (*fmt == '*')
594 fmt++;
595 prt_data.prec = GET_ARG (n, ap_copy, int);
596 if (prt_data.prec < 0)
597 prt_data.prec = -1;
599 else
601 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. */
608 flag_chars = "hlL";
609 if ((cp = memchr (flag_chars, *fmt, 3)) != NULL)
611 prt_data.flags |= (SHORTINT << (cp - flag_chars));
612 fmt++;
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. */
620 if (cp)
622 /* Consume floating point argument if _printf_float is not
623 linked. */
624 if (_printf_float == NULL)
626 if (prt_data.flags & LONGDBL)
627 GET_ARG (N, ap_copy, _LONG_DOUBLE);
628 else
629 GET_ARG (N, ap_copy, double);
631 else
632 n = _printf_float (data, &prt_data, fp, pfunc, &ap_copy);
634 else
635 #endif
636 n = _printf_i (data, &prt_data, fp, pfunc, &ap_copy);
638 if (n == -1)
639 goto error;
641 prt_data.ret += n;
643 done:
644 FLUSH ();
645 error:
646 #ifndef STRING_ONLY
647 _newlib_flockfile_end (fp);
648 #endif
649 va_end (ap_copy);
650 return (__sferror (fp) ? EOF : prt_data.ret);
653 #ifdef STRING_ONLY
655 _svfiprintf_r (struct _reent *, FILE *, const char *, __VALIST)
656 _ATTRIBUTE ((__alias__("_svfprintf_r")));
657 #else
659 _vfiprintf_r (struct _reent *, FILE *, const char *, __VALIST)
660 _ATTRIBUTE ((__alias__("_vfprintf_r")));
661 #endif