* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
-FUNCTION
-<<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
-
-INDEX
- vfprintf
-INDEX
- _vfprintf_r
-INDEX
- vprintf
-INDEX
- _vprintf_r
-INDEX
- vsprintf
-INDEX
- _vsprintf_r
-INDEX
- vsnprintf
-INDEX
- _vsnprintf_r
-INDEX
- vasprintf
-INDEX
- _vasprintf_r
-INDEX
- vasnprintf
-INDEX
- _vasnprintf_r
-
-SYNOPSIS
- #include <stdio.h>
- #include <stdarg.h>
- int vprintf(const char *<[fmt]>, va_list <[list]>);
- int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
- int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
- int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
- va_list <[list]>);
- int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
- char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
- va_list <[list]>);
-
- int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
- va_list <[list]>);
- int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
- const char *<[fmt]>, va_list <[list]>);
- int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
- const char *<[fmt]>, va_list <[list]>);
- int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
- const char *<[fmt]>, va_list <[list]>);
- int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
- size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
- char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
- size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
-
-DESCRIPTION
-<<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
-and <<vasnprintf>> are (respectively) variants of <<printf>>,
-<<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
-<<asnprintf>>. They differ only in allowing their caller to pass the
-variable argument list as a <<va_list>> object (initialized by
-<<va_start>>) rather than directly accepting a variable number of
-arguments. The caller is responsible for calling <<va_end>>.
-
-<<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
-<<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
-above.
-
-RETURNS
-The return values are consistent with the corresponding functions.
-
-PORTABILITY
-ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
-<<vsnprintf>>. The remaining functions are newlib extensions.
-
-Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
-<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
-*/
-
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
static char *rcsid = "$Id$";
#endif /* LIBC_SCCS and not lint */
-/* Actual printf innards.
- This code is large and complicated... */
-#include <newlib.h>
-
-#define VFPRINTF vfprintf
-#ifdef STRING_ONLY
-# define _VFPRINTF_R _svfprintf_r
-#else
-# define _VFPRINTF_R _vfprintf_r
-#endif
-
#include <_ansi.h>
#include <reent.h>
#include <stdio.h>
#include <wchar.h>
#include <sys/lock.h>
#include <stdarg.h>
-#include "local.h"
-#include "../stdlib/local.h"
-#include "fvwrite.h"
-#include "vfieeefp.h"
-#include "nano-vfprintf_local.h"
-
-/* The __ssputs_r function is shared between all versions of vfprintf
- and vfwprintf. */
-#ifdef STRING_ONLY
-int
-__ssputs_r (struct _reent *ptr,
- FILE *fp,
- const char *buf,
- size_t len)
-{
- register int w;
-
- w = fp->_w;
- if (len >= w && fp->_flags & (__SMBF | __SOPT))
- {
- /* Must be asprintf family. */
- unsigned char *str;
- int curpos = (fp->_p - fp->_bf._base);
- /* Choose a geometric growth factor to avoid
- * quadratic realloc behavior, but use a rate less
- * than (1+sqrt(5))/2 to accomodate malloc
- * overhead. asprintf EXPECTS us to overallocate, so
- * that it can add a trailing \0 without
- * reallocating. The new allocation should thus be
- * max(prev_size*1.5, curpos+len+1). */
- int newsize = fp->_bf._size * 3 / 2;
- if (newsize < curpos + len + 1)
- newsize = curpos + len + 1;
- if (fp->_flags & __SOPT)
- {
- /* asnprintf leaves original buffer alone. */
- str = (unsigned char *)_malloc_r (ptr, newsize);
- if (!str)
- {
- ptr->_errno = ENOMEM;
- goto err;
- }
- memcpy (str, fp->_bf._base, curpos);
- fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
- }
- else
- {
- str = (unsigned char *)_realloc_r (ptr, fp->_bf._base, newsize);
- if (!str)
- {
- /* Free unneeded buffer. */
- _free_r (ptr, fp->_bf._base);
- /* Ensure correct errno, even if free changed it. */
- ptr->_errno = ENOMEM;
- goto err;
- }
- }
- fp->_bf._base = str;
- fp->_p = str + curpos;
- fp->_bf._size = newsize;
- w = len;
- fp->_w = newsize - curpos;
- }
- if (len < w)
- w = len;
-
- (void)memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
- fp->_w -= w;
- fp->_p += w;
- return 0;
-
-err:
- fp->_flags |= __SERR;
- return EOF;
-}
-/* __ssprint_r is the original implementation of __SPRINT. In nano
- version formatted IO it is reimplemented as __ssputs_r for non-wide
- char output, but __ssprint_r cannot be discarded because it is used
- by a serial of functions like svfwprintf for wide char output. */
-int
-__ssprint_r (struct _reent *ptr,
- FILE *fp,
- register struct __suio *uio)
-{
- register size_t len;
- register int w;
- register struct __siov *iov;
- register const char *p = NULL;
-
- iov = uio->uio_iov;
- len = 0;
-
- if (uio->uio_resid == 0)
- {
- uio->uio_iovcnt = 0;
- return (0);
- }
-
- do
- {
- while (len == 0)
- {
- p = iov->iov_base;
- len = iov->iov_len;
- iov++;
- }
- w = fp->_w;
- if (len >= w && fp->_flags & (__SMBF | __SOPT))
- {
- /* Must be asprintf family. */
- unsigned char *str;
- int curpos = (fp->_p - fp->_bf._base);
- /* Choose a geometric growth factor to avoid
- * quadratic realloc behavior, but use a rate less
- * than (1+sqrt(5))/2 to accomodate malloc
- * overhead. asprintf EXPECTS us to overallocate, so
- * that it can add a trailing \0 without
- * reallocating. The new allocation should thus be
- * max(prev_size*1.5, curpos+len+1). */
- int newsize = fp->_bf._size * 3 / 2;
- if (newsize < curpos + len + 1)
- newsize = curpos + len + 1;
-
- if (fp->_flags & __SOPT)
- {
- /* asnprintf leaves original buffer alone. */
- str = (unsigned char *)_malloc_r (ptr, newsize);
- if (!str)
- {
- ptr->_errno = ENOMEM;
- goto err;
- }
- memcpy (str, fp->_bf._base, curpos);
- fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
- }
- else
- {
- str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
- newsize);
- if (!str)
- {
- /* Free unneeded buffer. */
- _free_r (ptr, fp->_bf._base);
- /* Ensure correct errno, even if free changed it. */
- ptr->_errno = ENOMEM;
- goto err;
- }
- }
- fp->_bf._base = str;
- fp->_p = str + curpos;
- fp->_bf._size = newsize;
- w = len;
- fp->_w = newsize - curpos;
- }
- if (len < w)
- w = len;
-
- (void)memmove ((void *) fp->_p, (void *) p, (size_t) (w));
- fp->_w -= w;
- fp->_p += w;
- /* Pretend we copied all. */
- w = len;
- p += w;
- len -= w;
- }
- while ((uio->uio_resid -= w) != 0);
-
- uio->uio_resid = 0;
- uio->uio_iovcnt = 0;
- return 0;
-
-err:
- fp->_flags |= __SERR;
- uio->uio_resid = 0;
- uio->uio_iovcnt = 0;
- return EOF;
-}
-#else
-/* As __ssputs_r, __sprint_r is used by output functions for wide char,
- like vfwprint. */
-/* Flush out all the vectors defined by the given uio,
- then reset it so that it can be reused. */
-int
-__sprint_r (struct _reent *ptr,
- FILE *fp,
- register struct __suio *uio)
-{
- register int err = 0;
-
- if (uio->uio_resid == 0)
- {
- uio->uio_iovcnt = 0;
- return 0;
- }
-#ifdef _WIDE_ORIENT
- if (fp->_flags2 & __SWID)
- {
- struct __siov *iov;
- wchar_t *p;
- int i, len;
-
- iov = uio->uio_iov;
- for (; uio->uio_resid != 0;
- uio->uio_resid -= len * sizeof (wchar_t), iov++)
- {
- p = (wchar_t *) iov->iov_base;
- len = iov->iov_len / sizeof (wchar_t);
- for (i = 0; i < len; i++)
- {
- if (_fputwc_r (ptr, p[i], fp) == WEOF)
- {
- err = -1;
- goto out;
- }
- }
- }
- }
- else
-#endif
- err = __sfvwrite_r(ptr, fp, uio);
-out:
- uio->uio_resid = 0;
- uio->uio_iovcnt = 0;
- return err;
-}
-
-_NOINLINE_STATIC int
-__sfputc_r (struct _reent *ptr,
- int c,
- FILE *fp)
-{
- if (--fp->_w >= 0 || (fp->_w >= fp->_lbfsize && (char)c != '\n'))
- return (*fp->_p++ = c);
- else
- return (__swbuf_r(ptr, c, fp));
-}
-
+#include <string.h>
+#include <newlib.h>
+#include "../../stdio/local.h"
+#include "../../stdlib/local.h"
+#include "../../stdio/fvwrite.h"
+#include "../../stdio/nano-vfprintf_local.h"
+
+/* Bypass *putc* fns called by the default _sfputs_r to save code size.
+ Among other things, this means there is no buffering of the string before
+ it is sent to <<write>>, but <<write>> does its own buffering so we won't
+ lose chars when buf is larger than sizeof(CIOBUF). */
int
-__sfputs_r (struct _reent *ptr,
+__tiny__sfputs_r (struct _reent *ptr,
FILE *fp,
const char *buf,
size_t len)
{
- register int i;
-
-#ifdef _WIDE_ORIENT
- if (fp->_flags2 & __SWID)
- {
- wchar_t *p;
-
- p = (wchar_t *) buf;
- for (i = 0; i < (len / sizeof (wchar_t)); i++)
- {
- if (_fputwc_r (ptr, p[i], fp) == WEOF)
- return -1;
- }
- }
- else
-#endif
- {
- for (i = 0; i < len; i++)
- {
- /* Call __sfputc_r to skip _fputc_r. */
- if (__sfputc_r (ptr, (int)buf[i], fp) == EOF)
- return -1;
- }
- }
- return (0);
-}
-#endif /* STRING_ONLY. */
-
-int _VFPRINTF_R (struct _reent *, FILE *, const char *, va_list);
-
-#ifndef STRING_ONLY
-int
-VFPRINTF (FILE * fp,
- const char *fmt0,
- va_list ap)
-{
- int result;
- result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
- return result;
+ return write (1, buf, len);
}
+/* VFPRINTF_R from nano-vfprintf.c but:
+ - No support for reentrancy
+ - No support for streams
+ - __SINGLE_THREAD__ assumed.
+ - No STRING_ONLY variant (either way the formatted string would end up
+ being sent to <<write>> via <<__tiny__sfputs_r>>.
+ Basically, format the string as normal, and send it to write. */
int
-vfiprintf (FILE *, const char *, __VALIST)
- _ATTRIBUTE ((__alias__("vfprintf")));
-#endif
-
-#ifdef STRING_ONLY
-# define __SPRINT __ssputs_r
-#else
-# define __SPRINT __sfputs_r
-#endif
-
-/* Do not need FLUSH for all sprintf functions. */
-#ifdef STRING_ONLY
-# define FLUSH()
-#else
-# define FLUSH()
-#endif
-
-int
-_VFPRINTF_R (struct _reent *data,
+__tiny_vfprintf_r (struct _reent *data,
FILE * fp,
const char *fmt0,
va_list ap)
/* Output function pointer. */
int (*pfunc)(struct _reent *, FILE *, const char *, size_t len);
- pfunc = __SPRINT;
-
-#ifndef STRING_ONLY
- /* Initialize std streams if not dealing with sprintf family. */
- CHECK_INIT (data, fp);
- _newlib_flockfile_start (fp);
-
- /* Sorry, fprintf(read_only_file, "") returns EOF, not 0. */
- if (cantwrite (data, fp))
- {
- _newlib_flockfile_exit (fp);
- return (EOF);
- }
-
-#else
- /* Create initial buffer if we are called by asprintf family. */
- if (fp->_flags & __SMBF && !fp->_bf._base)
- {
- fp->_bf._base = fp->_p = _malloc_r (data, 64);
- if (!fp->_p)
- {
- data->_errno = ENOMEM;
- return EOF;
- }
- fp->_bf._size = 64;
- }
-#endif
+ pfunc = __tiny__sfputs_r;
fmt = (char *)fmt0;
prt_data.ret = 0;
prt_data.ret += n;
}
done:
- FLUSH ();
error:
-#ifndef STRING_ONLY
- _newlib_flockfile_end (fp);
-#endif
va_end (ap_copy);
return (__sferror (fp) ? EOF : prt_data.ret);
}
-#ifdef STRING_ONLY
int
-_svfiprintf_r (struct _reent *, FILE *, const char *, __VALIST)
- _ATTRIBUTE ((__alias__("_svfprintf_r")));
-#else
-int
-_vfiprintf_r (struct _reent *, FILE *, const char *, __VALIST)
- _ATTRIBUTE ((__alias__("_vfprintf_r")));
-#endif
+__wrap_printf (const char *__restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ struct _reent *ptr = _REENT;
+
+ va_start (ap, fmt);
+ ret = __tiny_vfprintf_r (ptr, _stdout_r (ptr), fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+int printf (const char *__restrict fmt, ...) __attribute__ ((weak, alias ("__wrap_printf")));