This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: implement asnprintf, take 2
- From: Eric Blake <ebb9 at byu dot net>
- To: Jeff Johnston <jjohnstn at redhat dot com>
- Cc: newlib at sources dot redhat dot com
- Date: Sat, 28 Apr 2007 07:56:35 -0600
- Subject: Re: implement asnprintf, take 2
- References: <46291045.8060606@byu.net> <462E5487.2080005@redhat.com>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
According to Jeff Johnston on 4/24/2007 1:03 PM:
> Eric,
>
> A number of issues regarding ELIX_LEVEL. These new functions should be
> level 4. That means you need a new set of ELIX_4_SOURCES and you simply
> verify that the level is not 1, 2, or 3. Add ELIX_4_SOURCES to the list
> of sources below. Very straightforward.
>
> This patch has revealed an error I hadn't spotted before. The dprintf
> family cannot refer to a higher level ELIX function so they must be put
> into the LEVEL 2 sources with asprintf, etc..
>
> Finally, the dprintf changes you have made need to either be left out
> or you need to fork the code based on the ELIX level and call the new
> LEVEL 4 functions when the _ELIX_LEVEL flag is undefined or >3.
This version is a bit bigger, because it also improves the documentation
(let me know if I need to split it into two independent patches). I went
ahead and documented %a, even though it is not implemented yet (I'm still
working on that). This version also fixes Makefile.am to put dprintf and
asnprintf in ELIX_4_SOURCES. I've tested that cygwin can still be built
with this patch.
2007-04-28 Eric Blake <ebb9@byu.net>
Add support for asnprintf, and improve *printf documentation.
* libc/stdio/Makefile.am (ELIX_SOURCES): Rename...
(ELIX_2_SOURCES): ...to this.
(ELIX_4_SOURCES): Add new variable. Build asnprintf.
(GENERAL_SOURCES): Move dprintf to ELIX_4_SOURCES.
(CHEWOUT_FILES): Include diprintf in documentation.
* libc/stdio/diprintf.c: Improve documentation.
* libc/stdio/dprintf.c: Likewise.
* libc/stdio/siprintf.c: Likewise.
* libc/stdio/sprintf.c: Likewise.
* libc/stdio/vfprintf.c: Likewise.
* libc/stdio/viprintf.c: Likewise.
* libc/stdio/vsniprintf.c: Consolidate documentation.
* libc/stdio/asiprintf.c: Refer to documentation.
* libc/stdio/asprintf.c: Likewise.
* libc/stdio/fiprintf.c: Likewise.
* libc/stdio/fprintf.c: Likewise.
* libc/stdio/iprintf.c: Likewise.
* libc/stdio/printf.c: Likewise.
* libc/stdio/sniprintf.c: Likewise.
* libc/stdio/vdiprintf.c: Likewise.
* libc/stdio/vdprintf.c: Likewise.
* libc/stdio/vsiprintf.c: Likewise.
* libc/stdio/fvwrite.c (__sfvwrite_r): Handle asnprintf.
* libc/stdio/asniprintf.c (asniprintf, _asniprintf_r): New file.
* libc/stdio/asnprintf.c (asnprintf, _asnprintf_r): New file.
* libc/stdio/vasniprintf.c (vasniprintf, _vasniprintf_r): New
file.
* libc/stdio/vasnprintf.c (vasnprintf, _vasnprintf_r): New file.
* libc/stdio/vdprintf.c (_vdprintf_r): Rewrite to avoid malloc in
typical case.
* libc/stdio/vdiprintf.c (_vdiprintf_r): Likewise.
* libc/include/stdio.h: Add prototypes for new functions; sort
existing functions.
- --
Don't work too hard, make some time for fun as well!
Eric Blake ebb9@byu.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFGM1KT84KuGfSFAYARAvX4AJ9HpH8BcsJtcyBf11rzU6HjwhFk8wCgzxjX
HF7HgEjdRe5puwXX1tP5r1M=
=irsJ
-----END PGP SIGNATURE-----
Index: libc/include/stdio.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdio.h,v
retrieving revision 1.44
diff -u -p -r1.44 stdio.h
--- libc/include/stdio.h 10 Apr 2007 12:49:18 -0000 1.44
+++ libc/include/stdio.h 28 Apr 2007 13:40:20 -0000
@@ -238,6 +238,10 @@ off_t _EXFUN(ftello, ( FILE *));
#ifndef _REENT_ONLY
int _EXFUN(asiprintf, (char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
+char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 4))));
+char * _EXFUN(asnprintf, (char *, size_t *, const char *, ...)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(asprintf, (char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
#ifndef dprintf
@@ -266,16 +270,16 @@ int _EXFUN(sniprintf, (char *, size_t, c
char * _EXFUN(tempnam, (const char *, const char *));
int _EXFUN(vasiprintf, (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
+char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vasprintf, (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vdiprintf, (int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vdprintf, (int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
-int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
-int _EXFUN(vsnprintf, (char *, size_t, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST)
@@ -284,18 +288,22 @@ int _EXFUN(vfscanf, (FILE *, const char
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(viprintf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 1, 0))));
-int _EXFUN(vsiprintf, (char *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(viscanf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0))));
int _EXFUN(vscanf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0))));
+int _EXFUN(vsiprintf, (char *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vsiscanf, (const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
+int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+int _EXFUN(vsnprintf, (char *, size_t, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vsscanf, (const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
-#endif
-#endif
+#endif /* !_REENT_ONLY */
+#endif /* !__STRICT_ANSI__ */
/*
* Routines in POSIX 1003.1.
@@ -319,7 +327,7 @@ int _EXFUN(ftrylockfile, (FILE *));
void _EXFUN(funlockfile, (FILE *));
int _EXFUN(putc_unlocked, (int, FILE *));
int _EXFUN(putchar_unlocked, (int));
-#endif
+#endif /* ! __STRICT_ANSI__ */
/*
* Recursive versions of the above.
@@ -327,6 +335,10 @@ int _EXFUN(putchar_unlocked, (int));
int _EXFUN(_asiprintf_r, (struct _reent *, char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
+char * _EXFUN(_asniprintf_r, (struct _reent *, char *, size_t *, const char *, ...)
+ _ATTRIBUTE ((__format__ (__printf__, 4, 5))));
+char * _EXFUN(_asnprintf_r, (struct _reent *, char *, size_t *, const char *, ...)
+ _ATTRIBUTE ((__format__ (__printf__, 4, 5))));
int _EXFUN(_asprintf_r, (struct _reent *, char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_diprintf_r, (struct _reent *, int, const char *, ...)
@@ -394,6 +406,10 @@ char * _EXFUN(_tmpnam_r, (struct _reent
int _EXFUN(_ungetc_r, (struct _reent *, int, FILE *));
int _EXFUN(_vasiprintf_r, (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+char * _EXFUN(_vasniprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 4, 0))));
+char * _EXFUN(_vasnprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 4, 0))));
int _EXFUN(_vasprintf_r, (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vdiprintf_r, (struct _reent *, int, const char *, __VALIST)
@@ -402,32 +418,32 @@ int _EXFUN(_vdprintf_r, (struct _reent *
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vfiprintf_r, (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_vfprintf_r, (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+int _EXFUN(_vfscanf_r, (struct _reent *, FILE *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_viprintf_r, (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
+int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(_vprintf_r, (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
+int _EXFUN(_vscanf_r, (struct _reent *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(_vsiprintf_r, (struct _reent *, char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
-int _EXFUN(_vsprintf_r, (struct _reent *, char *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
+int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_vsniprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
int _EXFUN(_vsnprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
-int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
-int _EXFUN(_vfscanf_r, (struct _reent *, FILE *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
-int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
-int _EXFUN(_vscanf_r, (struct _reent *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
+int _EXFUN(_vsprintf_r, (struct _reent *, char *, const char *, __VALIST)
+ _ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vsscanf_r, (struct _reent *, const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
-int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST)
- _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *));
ssize_t _EXFUN(__getline, (char **, size_t *, FILE *));
Index: libc/stdio/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.am,v
retrieving revision 1.23
diff -u -p -r1.23 Makefile.am
--- libc/stdio/Makefile.am 4 Apr 2007 18:32:49 -0000 1.23
+++ libc/stdio/Makefile.am 28 Apr 2007 13:40:20 -0000
@@ -5,105 +5,124 @@ AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
GENERAL_SOURCES = \
- clearerr.c \
- diprintf.c \
- dprintf.c \
- fclose.c \
- fdopen.c \
- feof.c \
- ferror.c \
- fflush.c \
- fgetc.c \
- fgetpos.c \
- fgets.c \
+ clearerr.c \
+ fclose.c \
+ fdopen.c \
+ feof.c \
+ ferror.c \
+ fflush.c \
+ fgetc.c \
+ fgetpos.c \
+ fgets.c \
fileno.c \
- findfp.c \
- fiprintf.c \
- flags.c \
- fopen.c \
- fprintf.c \
- fputc.c \
- fputs.c \
- fread.c \
- freopen.c \
- fscanf.c \
- fiscanf.c \
- fseek.c \
- fsetpos.c \
- ftell.c \
- fvwrite.c \
- fwalk.c \
- fwrite.c \
- getc.c \
- getchar.c \
+ findfp.c \
+ fiprintf.c \
+ flags.c \
+ fopen.c \
+ fprintf.c \
+ fputc.c \
+ fputs.c \
+ fread.c \
+ freopen.c \
+ fscanf.c \
+ fiscanf.c \
+ fseek.c \
+ fsetpos.c \
+ ftell.c \
+ fvwrite.c \
+ fwalk.c \
+ fwrite.c \
+ getc.c \
+ getchar.c \
getc_u.c \
getchar_u.c \
getdelim.c \
getline.c \
- gets.c \
- iprintf.c \
- iscanf.c \
+ gets.c \
+ iprintf.c \
+ iscanf.c \
makebuf.c \
- perror.c \
- printf.c \
- putc.c \
- putchar.c \
+ perror.c \
+ printf.c \
+ putc.c \
+ putchar.c \
putc_u.c \
putchar_u.c \
- puts.c \
- refill.c \
- remove.c \
- rename.c \
- rewind.c \
- rget.c \
- scanf.c \
- sccl.c \
- setbuf.c \
- setbuffer.c \
- setlinebuf.c \
- setvbuf.c \
- siprintf.c \
- siscanf.c \
+ puts.c \
+ refill.c \
+ remove.c \
+ rename.c \
+ rewind.c \
+ rget.c \
+ scanf.c \
+ sccl.c \
+ setbuf.c \
+ setbuffer.c \
+ setlinebuf.c \
+ setvbuf.c \
+ siprintf.c \
+ siscanf.c \
sniprintf.c \
snprintf.c \
- sprintf.c \
- sscanf.c \
- stdio.c \
- tmpfile.c \
- tmpnam.c \
- ungetc.c \
+ sprintf.c \
+ sscanf.c \
+ stdio.c \
+ tmpfile.c \
+ tmpnam.c \
+ ungetc.c \
vdiprintf.c \
vdprintf.c \
- viprintf.c \
+ viprintf.c \
viscanf.c \
- vprintf.c \
+ vprintf.c \
vscanf.c \
- vsiprintf.c \
+ vsiprintf.c \
vsiscanf.c \
vsnprintf.c \
vsniprintf.c \
- vsprintf.c \
+ vsprintf.c \
vsscanf.c \
- wbuf.c \
+ wbuf.c \
wsetup.c
## The following are EL/IX level 2 interfaces
if ELIX_LEVEL_1
-ELIX_SOURCES =
+ELIX_2_SOURCES =
else
-ELIX_SOURCES = \
+ELIX_2_SOURCES = \
asiprintf.c \
asprintf.c \
fcloseall.c \
- fseeko.c \
- ftello.c \
+ fseeko.c \
+ ftello.c \
getw.c \
- mktemp.c \
- putw.c \
+ mktemp.c \
+ putw.c \
vasiprintf.c \
vasprintf.c
endif
+## The following are EL/IX level 2 interfaces
+if ELIX_LEVEL_1
+ELIX_4_SOURCES =
+else
+if ELIX_LEVEL_2
+ELIX_4_SOURCES =
+else
+if ELIX_LEVEL_3
+ELIX_4_SOURCES =
+else
+ELIX_4_SOURCES = \
+ asniprintf.c \
+ asnprintf.c \
+ diprintf.c \
+ dprintf.c \
+ vasniprintf.c \
+ vasnprintf.c
+endif !ELIX_LEVEL_3
+endif !ELIX_LEVEL_2
+endif !ELIX_LEVEL_1
+
LIBADD_OBJS = \
$(lpfx)vfiprintf.$(oext) $(lpfx)vfprintf.$(oext) \
$(lpfx)vfscanf.$(oext) $(lpfx)vfiscanf.$(oext)
@@ -112,14 +131,14 @@ libstdio_la_LDFLAGS = -Xcompiler -nostdl
if USE_LIBTOOL
noinst_LTLIBRARIES = libstdio.la
-libstdio_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+libstdio_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
libstdio_la_LIBADD = $(LIBADD_OBJS)
libstdio_la_DEPENDENCIES = $(LIBADD_OBJS)
LIB_COMPILE = $(LTCOMPILE)
noinst_DATA = objectlist.awk.in
else
noinst_LIBRARIES = lib.a
-lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
lib_a_LIBADD = $(LIBADD_OBJS)
lib_a_CFLAGS = $(AM_CFLAGS)
lib_a_DEPENDENCIES = $(LIBADD_OBJS)
@@ -146,6 +165,7 @@ $(lpfx)vfiscanf.$(oext): vfscanf.c
CHEWOUT_FILES = \
clearerr.def \
+ diprintf.def \
dprintf.def \
fclose.def \
fcloseall.def \
Index: libc/stdio/Makefile.in
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.in,v
retrieving revision 1.34
diff -u -p -r1.34 Makefile.in
Index: libc/stdio/asiprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/asiprintf.c,v
retrieving revision 1.3
diff -u -p -r1.3 asiprintf.c
--- libc/stdio/asiprintf.c 4 Apr 2007 18:32:49 -0000 1.3
+++ libc/stdio/asiprintf.c 28 Apr 2007 13:40:20 -0000
@@ -15,6 +15,7 @@
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* This code was copied from asprintf.c */
+/* doc in siprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/asniprintf.c
===================================================================
RCS file: libc/stdio/asniprintf.c
diff -N libc/stdio/asniprintf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libc/stdio/asniprintf.c 28 Apr 2007 13:40:20 -0000
@@ -0,0 +1,105 @@
+/* Copyright (C) 2007 Eric Blake
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+/* This code was derived from asprintf.c */
+/* doc in siprintf.c */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+char *
+_DEFUN(_asniprintf_r, (ptr, buf, lenp, fmt),
+ struct _reent *ptr _AND
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _DOTS)
+{
+ int ret;
+ va_list ap;
+ FILE f;
+ size_t len = *lenp;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ va_start (ap, fmt);
+ ret = _vfiprintf_r (ptr, &f, fmt, ap);
+ va_end (ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN(asniprintf, (buf, lenp, fmt),
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _DOTS)
+{
+ int ret;
+ va_list ap;
+ FILE f;
+ size_t len = *lenp;
+ struct _reent *ptr = _REENT;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ va_start (ap, fmt);
+ ret = _vfiprintf_r (ptr, &f, fmt, ap);
+ va_end (ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#endif /* ! _REENT_ONLY */
Index: libc/stdio/asnprintf.c
===================================================================
RCS file: libc/stdio/asnprintf.c
diff -N libc/stdio/asnprintf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libc/stdio/asnprintf.c 28 Apr 2007 13:40:20 -0000
@@ -0,0 +1,105 @@
+/* Copyright (C) 2007 Eric Blake
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+/* This code was derived from asprintf.c */
+/* doc in sprintf.c */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+char *
+_DEFUN(_asnprintf_r, (ptr, buf, lenp, fmt),
+ struct _reent *ptr _AND
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _DOTS)
+{
+ int ret;
+ va_list ap;
+ FILE f;
+ size_t len = *lenp;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ va_start (ap, fmt);
+ ret = _vfprintf_r (ptr, &f, fmt, ap);
+ va_end (ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN(asnprintf, (buf, lenp, fmt),
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _DOTS)
+{
+ int ret;
+ va_list ap;
+ FILE f;
+ size_t len = *lenp;
+ struct _reent *ptr = _REENT;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ va_start (ap, fmt);
+ ret = _vfprintf_r (ptr, &f, fmt, ap);
+ va_end (ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#endif /* ! _REENT_ONLY */
Index: libc/stdio/asprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/asprintf.c,v
retrieving revision 1.7
diff -u -p -r1.7 asprintf.c
--- libc/stdio/asprintf.c 4 Apr 2007 18:32:49 -0000 1.7
+++ libc/stdio/asprintf.c 28 Apr 2007 13:40:20 -0000
@@ -15,6 +15,7 @@
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* This code was copied from sprintf.c */
+/* doc in sprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/diprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/diprintf.c,v
retrieving revision 1.1
diff -u -p -r1.1 diprintf.c
--- libc/stdio/diprintf.c 4 Apr 2007 18:32:49 -0000 1.1
+++ libc/stdio/diprintf.c 28 Apr 2007 13:40:20 -0000
@@ -5,7 +5,7 @@
/*
FUNCTION
-<<diprintf>>, <<vdiprintf>>---print to a file descriptor
+<<diprintf>>, <<vdiprintf>>---print to a file descriptor (integer only)
INDEX
diprintf
@@ -26,6 +26,9 @@ DESCRIPTION
<<diprintf>> and <<vdiprintf>> are similar to <<dprintf>> and <<vdprintf>>,
except that only integer format specifiers are processed.
+The functions <<_diprintf_r>> and <<_vdiprintf_r>> are simply
+reentrant versions of the functions above.
+
RETURNS
Similar to <<dprintf>> and <<vdprintf>>.
Index: libc/stdio/dprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/dprintf.c,v
retrieving revision 1.2
diff -u -p -r1.2 dprintf.c
--- libc/stdio/dprintf.c 4 Apr 2007 18:32:49 -0000 1.2
+++ libc/stdio/dprintf.c 28 Apr 2007 13:40:20 -0000
@@ -22,30 +22,6 @@ ANSI_SYNOPSIS
int _vdprintf_r(struct _reent *<[ptr]>, int <[fd]>,
const char *<[format]>, va_list <[ap]>);
-TRAD_SYNOPSIS
- #include <stdio.h>
- #include <varargs.h>
-
- int dprintf(<[fd]>, <[format]> [, <[arg]>, ...])
- int <[fd]>;
- char *<[format]>;
-
- int vdprintf(<[fd]>, <[fmt]>, <[list]>)
- int <[fd]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _dprintf_r(<[ptr]>, <[fd]>, <[format]> [, <[arg]>, ...])
- struct _reent *<[ptr]>;
- int <[fd]>;
- char *<[format]>;
-
- int _vdprintf_r(<[ptr]>, <[fd]>, <[fmt]>, <[list]>)
- struct _reent *<[ptr]>;
- int <[fd]>;
- char *<[fmt]>;
- va_list <[list]>;
-
DESCRIPTION
<<dprintf>> and <<vdprintf>> allow printing a format, similarly to
<<printf>>, but write to a file descriptor instead of to a <<FILE>>
Index: libc/stdio/fiprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fiprintf.c,v
retrieving revision 1.5
diff -u -p -r1.5 fiprintf.c
--- libc/stdio/fiprintf.c 4 Apr 2007 18:32:49 -0000 1.5
+++ libc/stdio/fiprintf.c 28 Apr 2007 13:40:20 -0000
@@ -14,6 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/* doc in siprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/fprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fprintf.c,v
retrieving revision 1.4
diff -u -p -r1.4 fprintf.c
--- libc/stdio/fprintf.c 4 Apr 2007 18:32:49 -0000 1.4
+++ libc/stdio/fprintf.c 28 Apr 2007 13:40:20 -0000
@@ -14,6 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/* doc in sprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/fvwrite.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/fvwrite.c,v
retrieving revision 1.11
diff -u -p -r1.11 fvwrite.c
--- libc/stdio/fvwrite.c 15 Mar 2007 18:40:48 -0000 1.11
+++ libc/stdio/fvwrite.c 28 Apr 2007 13:40:20 -0000
@@ -127,7 +127,7 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
w = fp->_w;
if (fp->_flags & __SSTR)
{
- if (len >= w && fp->_flags & __SMBF)
+ if (len >= w && fp->_flags & (__SMBF | __SOPT))
{ /* must be asprintf family */
unsigned char *str;
int curpos = (fp->_p - fp->_bf._base);
@@ -141,15 +141,30 @@ _DEFUN(__sfvwrite_r, (ptr, fp, uio),
int newsize = fp->_bf._size * 3 / 2;
if (newsize < curpos + len + 1)
newsize = curpos + len + 1;
- str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
- newsize);
- if (!str)
+ if (fp->_flags & __SOPT)
{
- /* Free buffer which is no longer used. */
- _free_r (ptr, fp->_bf._base);
- /* Ensure correct errno, even if free changed it. */
- ptr->_errno = ENOMEM;
- goto err;
+ /* 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 buffer which is no longer used. */
+ _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;
Index: libc/stdio/iprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/iprintf.c,v
retrieving revision 1.8
diff -u -p -r1.8 iprintf.c
--- libc/stdio/iprintf.c 4 Apr 2007 18:32:49 -0000 1.8
+++ libc/stdio/iprintf.c 28 Apr 2007 13:40:20 -0000
@@ -14,6 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/* doc in siprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/printf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/printf.c,v
retrieving revision 1.6
diff -u -p -r1.6 printf.c
--- libc/stdio/printf.c 4 Apr 2007 18:32:49 -0000 1.6
+++ libc/stdio/printf.c 28 Apr 2007 13:40:20 -0000
@@ -14,6 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
+/* doc in sprintf.c */
#include <_ansi.h>
#include <reent.h>
Index: libc/stdio/siprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/siprintf.c,v
retrieving revision 1.7
diff -u -p -r1.7 siprintf.c
--- libc/stdio/siprintf.c 28 Oct 2005 21:38:59 -0000 1.7
+++ libc/stdio/siprintf.c 28 Apr 2007 13:40:20 -0000
@@ -17,18 +17,20 @@
/*
FUNCTION
- <<iprintf>>, <<fiprintf>>, <<asiprintf>>, <<siprintf>>, <<sniprintf>>---format output
+<<iprintf>>, <<fiprintf>>, <<siprintf>>, <<sniprintf>>, <<asiprintf>>, <<asniprintf>>---format output (integer only)
INDEX
fiprintf
INDEX
iprintf
INDEX
- asiprintf
-INDEX
siprintf
INDEX
sniprintf
+INDEX
+ asiprintf
+INDEX
+ asniprintf
ANSI_SYNOPSIS
#include <stdio.h>
@@ -36,50 +38,44 @@ ANSI_SYNOPSIS
int iprintf(const char *<[format]> [, <[arg]>, ...]);
int fiprintf(FILE *<[fd]>, const char *<[format]> [, <[arg]>, ...]);
int siprintf(char *<[str]>, const char *<[format]> [, <[arg]>, ...]);
- int asiprintf(char **<[strp]>, const char *<[format]> [, <[arg]>, ...]);
int sniprintf(char *<[str]>, size_t <[size]>, const char *<[format]>
[, <[arg]>, ...]);
+ int asiprintf(char **<[strp]>, const char *<[format]> [, <[arg]>, ...]);
+ char *asniprintf(char *<[str]>, size_t *<[size]>, const char *<[format]>
+ [, <[arg]>, ...]);
-TRAD_SYNOPSIS
- #include <stdio.h>
-
- int iprintf(<[format]> [, <[arg]>, ...])
- char *<[format]>;
-
- int fiprintf(<[fd]>, <[format]> [, <[arg]>, ...]);
- FILE *<[fd]>;
- char *<[format]>;
-
- int asiprintf(<[strp]>, <[format]> [, <[arg]>, ...]);
- char **<[strp]>;
- char *<[format]>;
-
- int siprintf(<[str]>, <[format]> [, <[arg]>, ...]);
- char *<[str]>;
- char *<[format]>;
-
- int sniprintf(<[str]>, size_t <[size]>, <[format]> [, <[arg]>, ...]);
- char *<[str]>;
- size_t <[size]>;
- char *<[format]>;
+ int _iprintf_r(struct _reent *<[ptr]>, const char *<[format]>
+ [, <[arg]>, ...]);
+ int _fiprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _siprintf_r(struct _reent *<[ptr]>, char *<[str]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _sniprintf_r(struct _reent *<[ptr]>, char *<[str]>, size_t <[size]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _asiprintf_r(struct _reent *<[ptr]>, char **<[strp]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ char *_asniprintf_r(struct _reent *<[ptr]>, char *<[str]>,
+ size_t *<[size]>, const char *<[format]>
+ [, <[arg]>, ...]);
DESCRIPTION
<<iprintf>>, <<fiprintf>>, <<siprintf>>, <<sniprintf>>,
- <<asiprintf>>, are the same as <<printf>>, <<fprintf>>,
- <<sprintf>>, <<snprintf>>, and <<asprintf>>, respectively,
- only that they restrict usage to non-floating-point format
- specifiers.
+ <<asiprintf>>, and <<asniprintf>> are the same as <<printf>>,
+ <<fprintf>>, <<sprintf>>, <<snprintf>>, <<asprintf>>, and
+ <<asnprintf>>, respectively, except that they restrict usage
+ to non-floating-point format specifiers.
+
+ <<_iprintf_r>>, <<_fiprintf_r>>, <<_asiprintf_r>>,
+ <<_siprintf_r>>, <<_sniprintf_r>>, <<_asniprintf_r>> are
+ simply reentrant versions of the functions above.
RETURNS
-<<siprintf>> and <<asiprintf>> return the number of bytes in the output string,
-save that the concluding <<NULL>> is not counted.
-<<iprintf>> and <<fiprintf>> return the number of characters transmitted.
-If an error occurs, <<iprintf>> and <<fiprintf>> return <<EOF>> and
-<<asiprintf>> returns -1. No error returns occur for <<siprintf>>.
+Similar to <<printf>>, <<fprintf>>, <<sprintf>>, <<snprintf>>, <<asprintf>>,
+and <<asnprintf>>.
PORTABILITY
-<<iprintf>>, <<fiprintf>>, <<siprintf>>, <<sniprintf>>, and <<asprintf>>
-are newlib extensions.
+<<iprintf>>, <<fiprintf>>, <<siprintf>>, <<sniprintf>>, <<asiprintf>>,
+and <<asniprintf>> are newlib extensions.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
Index: libc/stdio/sniprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/sniprintf.c,v
retrieving revision 1.3
diff -u -p -r1.3 sniprintf.c
--- libc/stdio/sniprintf.c 15 Mar 2007 18:40:48 -0000 1.3
+++ libc/stdio/sniprintf.c 28 Apr 2007 13:40:20 -0000
@@ -16,6 +16,7 @@
*/
/* This code created by modifying snprintf.c so copyright inherited. */
+/* doc in siprintf.c */
#include <_ansi.h>
#include <reent.h>
@@ -31,10 +32,10 @@
int
#ifdef _HAVE_STDC
-_DEFUN (_sniprintf_r, (ptr, str, size, fmt),
- struct _reent *ptr _AND
- char *str _AND
- size_t size _AND
+_DEFUN (_sniprintf_r, (ptr, str, size, fmt),
+ struct _reent *ptr _AND
+ char *str _AND
+ size_t size _AND
_CONST char *fmt _DOTS)
#else
_sniprintf_r (ptr, str, size, fmt, va_alist)
@@ -76,9 +77,9 @@ _sniprintf_r (ptr, str, size, fmt, va_al
int
#ifdef _HAVE_STDC
-_DEFUN (sniprintf, (str, size, fmt),
- char *str _AND
- size_t size _AND
+_DEFUN (sniprintf, (str, size, fmt),
+ char *str _AND
+ size_t size _AND
_CONST char *fmt _DOTS)
#else
sniprintf (str, size, fmt, va_alist)
Index: libc/stdio/sprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/sprintf.c,v
retrieving revision 1.9
diff -u -p -r1.9 sprintf.c
--- libc/stdio/sprintf.c 28 Oct 2005 21:38:59 -0000 1.9
+++ libc/stdio/sprintf.c 28 Apr 2007 13:40:20 -0000
@@ -17,7 +17,7 @@
/*
FUNCTION
- <<printf>>, <<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>---format output
+<<printf>>, <<fprintf>>, <<sprintf>>, <<snprintf>>, <<asprintf>>, <<asnprintf>>---format output
INDEX
fprintf
@@ -29,6 +29,8 @@ INDEX
sprintf
INDEX
snprintf
+INDEX
+ asnprintf
ANSI_SYNOPSIS
#include <stdio.h>
@@ -36,271 +38,508 @@ ANSI_SYNOPSIS
int printf(const char *<[format]> [, <[arg]>, ...]);
int fprintf(FILE *<[fd]>, const char *<[format]> [, <[arg]>, ...]);
int sprintf(char *<[str]>, const char *<[format]> [, <[arg]>, ...]);
- int asprintf(char **<[strp]>, const char *<[format]> [, <[arg]>, ...]);
int snprintf(char *<[str]>, size_t <[size]>, const char *<[format]>
[, <[arg]>, ...]);
+ int asprintf(char **<[strp]>, const char *<[format]> [, <[arg]>, ...]);
+ char *asnprintf(char *<[str]>, size_t *<[size]>, const char *<[format]>
+ [, <[arg]>, ...]);
-TRAD_SYNOPSIS
- #include <stdio.h>
-
- int printf(<[format]> [, <[arg]>, ...])
- char *<[format]>;
-
- int fprintf(<[fd]>, <[format]> [, <[arg]>, ...]);
- FILE *<[fd]>;
- char *<[format]>;
-
- int asprintf(<[strp]>, <[format]> [, <[arg]>, ...]);
- char **<[strp]>;
- char *<[format]>;
-
- int sprintf(<[str]>, <[format]> [, <[arg]>, ...]);
- char *<[str]>;
- char *<[format]>;
-
- int snprintf(<[str]>, size_t <[size]>, <[format]> [, <[arg]>, ...]);
- char *<[str]>;
- size_t <[size]>;
- char *<[format]>;
+ int _printf_r(struct _reent *<[ptr]>, const char *<[format]>
+ [, <[arg]>, ...]);
+ int _fprintf_r(struct _reent *<[ptr]>, FILE *<[fd]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _sprintf_r(struct _reent *<[ptr]>, char *<[str]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _snprintf_r(struct _reent *<[ptr]>, char *<[str]>, size_t <[size]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ int _asprintf_r(struct _reent *<[ptr]>, char **<[strp]>,
+ const char *<[format]> [, <[arg]>, ...]);
+ char *_asnprintf_r(struct _reent *<[ptr]>, char *<[str]>,
+ size_t *<[size]>, const char *<[format]>
+ [, <[arg]>, ...]);
DESCRIPTION
<<printf>> accepts a series of arguments, applies to each a
format specifier from <<*<[format]>>>, and writes the
- formatted data to <<stdout>>, terminated with a null character.
- The behavior of <<printf>> is undefined if there are not enough
- arguments for the format.
- <<printf>> returns when it reaches the end of the format string.
- If there are more arguments than the format requires, excess
- arguments are ignored.
-
- <<fprintf>>, <<asprintf>>, <<sprintf>> and <<snprintf>> are identical
- to <<printf>>, other than the destination of the formatted output:
- <<fprintf>> sends the output to a specified file <[fd]>, while
- <<asprintf>> stores the output in a dynamically allocated buffer,
- while <<sprintf>> stores the output in the specified char array
- <[str]> and <<snprintf>> limits number of characters written to
- <[str]> to at most <[size]> (including terminating <<0>>). For
- <<sprintf>> and <<snprintf>>, the behavior is undefined if the
- output <<*<[str]>>> overlaps with one of the arguments. For
- <<asprintf>>, <[strp]> points to a pointer to char which is filled
- in with the dynamically allocated buffer. <[format]> is a pointer
- to a charater string containing two types of objects: ordinary
- characters (other than <<%>>), which are copied unchanged to the
- output, and conversion specifications, each of which is introduced
- by <<%>>. (To include <<%>> in the output, use <<%%>> in the format
- string.) A conversion specification has the following form:
+ formatted data to <<stdout>>, without a terminating NUL
+ character. The behavior of <<printf>> is undefined if there
+ are not enough arguments for the format. <<printf>> returns
+ when it reaches the end of the format string. If there are
+ more arguments than the format requires, excess arguments are
+ ignored.
+
+ <<fprintf>> is like <<printf>>, except that output is directed
+ to the stream <[fd]> rather than <<stdout>>.
+
+ <<sprintf>> is like <<printf>>, except that output is directed
+ to the buffer <[str]>, and a terminating NUL is output.
+ Behavior is undefined if more output is generated than the
+ buffer can hold.
+
+ <<snprintf>> is like <<sprintf>>, except that output is
+ limited to at most <[size]> bytes, including the terminating
+ <<NUL>>. As a special case, if <[size]> is 0, <[str]> can be
+ NULL, and <<snprintf>> merely calculates how many bytes would
+ be printed.
+
+ <<asprintf>> is like <<sprintf>>, except that the output is
+ stored in a dynamically allocated buffer, <[pstr]>, which
+ should be freed later with <<free>>.
+
+ <<asnprintf>> is like <<sprintf>>, except that the return type
+ is either the original <[str]> if it was large enough, or a
+ dynamically allocated string if the output exceeds *<[size]>;
+ the length of the result is returned in *<[size]>. When
+ dynamic allocation occurs, the contents of the original
+ <[str]> may have been modified.
+
+ For <<sprintf>>, <<snprintf>>, and <<asnprintf>>, the behavior
+ is undefined if the output <<*<[str]>>> overlaps with one of
+ the arguments. Behavior is also undefined if the argument for
+ <<%n>> within <<*<[format]>>> overlaps another argument.
+
+ <[format]> is a pointer to a character string containing two
+ types of objects: ordinary characters (other than <<%>>),
+ which are copied unchanged to the output, and conversion
+ specifications, each of which is introduced by <<%>>. (To
+ include <<%>> in the output, use <<%%>> in the format string.)
+ A conversion specification has the following form:
-. %[<[flags]>][<[width]>][.<[prec]>][<[size]>][<[type]>]
+. %[<[pos]>][<[flags]>][<[width]>][.<[prec]>][<[size]>]<[type]>
- The fields of the conversion specification have the following meanings:
+ The fields of the conversion specification have the following
+ meanings:
O+
+ o <[pos]>
+
+ Conversions normally consume arguments in the order that they
+ are presented. However, it is possible to consume arguments
+ out of order, and reuse an argument for more than one
+ conversion specification (although the behavior is undefined
+ if the same argument is requested with different types), by
+ specifying <[pos]>, which is a decimal integer followed by
+ '$'. The integer must be between 1 and <NL_ARGMAX> from
+ limits.h, and if argument <<%n$>> is requested, all earlier
+ arguments must be requested somewhere within <[format]>. If
+ positional parameters are used, then all conversion
+ specifications except for <<%%>> must specify a position.
+
o <[flags]>
- an optional sequence of characters which control
- output justification, numeric signs, decimal points,
- trailing zeroes, and octal and hex prefixes.
- The flag characters are minus (<<->>), plus (<<+>>),
- space ( ), zero (<<0>>), and sharp (<<#>>). They can
- appear in any combination.
-
- o+
- o -
- The result of the conversion is left justified, and the right is
- padded with blanks. If you do not use this flag, the result is right
- justified, and padded on the left.
-
- o +
- The result of a signed conversion (as determined by <[type]>)
- will always begin with a plus or minus sign. (If you do not use
- this flag, positive values do not begin with a plus sign.)
-
- o " " (space)
- If the first character of a signed conversion specification
- is not a sign, or if a signed conversion results in no
- characters, the result will begin with a space. If the
- space ( ) flag and the plus (<<+>>) flag both appear,
- the space flag is ignored.
-
- o 0
- If the <[type]> character is <<d>>, <<i>>, <<o>>, <<u>>,
- <<x>>, <<X>>, <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading zeroes,
- are used to pad the field width (following any indication of sign or
- base); no spaces are used for padding. If the zero (<<0>>) and
- minus (<<->>) flags both appear, the zero (<<0>>) flag will
- be ignored. For <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>
- conversions, if a precision <[prec]> is specified, the zero (<<0>>)
- flag is ignored.
-
- Note that <<0>> is interpreted as a flag, not as the beginning
- of a field width.
-
- o #
- The result is to be converted to an alternative form, according
- to the next character:
-
- o+
- o 0
- increases precision to force the first digit
- of the result to be a zero.
+ <[flags]> is an optional sequence of characters which control
+ output justification, numeric signs, decimal points, trailing
+ zeros, and octal and hex prefixes. The flag characters are
+ minus (<<->>), plus (<<+>>), space ( ), zero (<<0>>), sharp
+ (<<#>>), and quote (<<'>>). They can appear in any
+ combination, although not all flags can be used for all
+ conversion specification types.
+
+ o+
+ o '
+ Since newlib only supports the C locale, this
+ flag has no effect in this implementation.
+ But in other locales, when <[type]> is <<i>>,
+ <<d>>, <<u>>, <<f>>, <<F>>, <<g>>, or <<G>>,
+ the locale-dependent thousand's separator is
+ inserted prior to zero padding.
+
+ o -
+ The result of the conversion is left
+ justified, and the right is padded with
+ blanks. If you do not use this flag, the
+ result is right justified, and padded on the
+ left.
+
+ o +
+ The result of a signed conversion (as
+ determined by <[type]> of <<d>>, <<i>>, <<a>>,
+ <<A>>, <<e>>, <<E>>, <<f>>, <<F>>, <<g>>, or
+ <<G>>) will always begin with a plus or minus
+ sign. (If you do not use this flag, positive
+ values do not begin with a plus sign.)
+
+ o " " (space)
+ If the first character of a signed conversion
+ specification is not a sign, or if a signed
+ conversion results in no characters, the
+ result will begin with a space. If the space
+ ( ) flag and the plus (<<+>>) flag both
+ appear, the space flag is ignored.
+
+ o 0
+ If the <[type]> character is <<d>>, <<i>>,
+ <<o>>, <<u>>, <<x>>, <<X>>, <<a>>, <<A>>,
+ <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading
+ zeros are used to pad the field width
+ (following any indication of sign or base); no
+ spaces are used for padding. If the zero
+ (<<0>>) and minus (<<->>) flags both appear,
+ the zero (<<0>>) flag will be ignored. For
+ <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>
+ conversions, if a precision <[prec]> is
+ specified, the zero (<<0>>) flag is ignored.
+
+ Note that <<0>> is interpreted as a flag, not
+ as the beginning of a field width.
+
+ o #
+ The result is to be converted to an
+ alternative form, according to the <[type]>
+ character:
+
+ o+
+ o o
+ Increases precision to force the first
+ digit of the result to be a zero.
o x
- a non-zero result will have a <<0x>> prefix.
+ A non-zero result will have a <<0x>>
+ prefix.
o X
- a non-zero result will have a <<0X>> prefix.
+ A non-zero result will have a <<0X>>
+ prefix.
- o e, E or f
- The result will always contain a decimal point
- even if no digits follow the point.
- (Normally, a decimal point appears only if a
- digit follows it.) Trailing zeroes are removed.
+ o a, A, e, E, f, or F
+ The result will always contain a
+ decimal point even if no digits follow
+ the point. (Normally, a decimal point
+ appears only if a digit follows it.)
+ Trailing zeros are removed.
o g or G
- same as <<e>> or <<E>>, but trailing zeroes
- are not removed.
+ The result will always contain a
+ decimal point even if no digits follow
+ the point. Trailing zeros are not
+ removed.
o all others
- undefined.
+ Undefined.
o-
- o-
+ o-
+
+ o <[width]>
+
+ <[width]> is an optional minimum field width. You can
+ either specify it directly as a decimal integer, or
+ indirectly by using instead an asterisk (<<*>>), in
+ which case an <<int>> argument is used as the field
+ width. If positional arguments are used, then the
+ width must also be specified positionally as <<*m$>>,
+ with m as a decimal integer. Negative field widths
+ are treated as specifying the minus (<<->>) flag for
+ left justfication, along with a positive field width.
+ The resulting format may be wider than the specified
+ width.
+
+ o <[prec]>
+
+ <[prec]> is an optional field; if present, it is
+ introduced with `<<.>>' (a period). You can specify
+ the precision either directly as a decimal integer or
+ indirectly by using an asterisk (<<*>>), in which case
+ an <<int>> argument is used as the precision. If
+ positional arguments are used, then the precision must
+ also be specified positionally as <<*m$>>, with m as a
+ decimal integer. Supplying a negative precision is
+ equivalent to omitting the precision. If only a
+ period is specified the precision is zero. The effect
+ depends on the conversion <[type]>.
+
+ o+
+ o d, i, o, u, x, or X
+ Minimum number of digits to appear. If no
+ precision is given, defaults to 1.
+
+ o a or A
+ Number of digits to appear after the decimal
+ point. If no precision is given, the
+ precision defaults to the minimum needed for
+ an exact representation.
+
+ o e, E, f or F
+ Number of digits to appear after the decimal
+ point. If no precision is given, the
+ precision defaults to 6.
+
+ o g or G
+ Maximum number of significant digits. A
+ precision of 0 is treated the same as a
+ precision of 1. If no precision is given, the
+ precision defaults to 6.
+
+ o s or S
+ Maximum number of characters to print from the
+ string. If no precision is given, the entire
+ string is printed.
+
+ o all others
+ undefined.
+
+ o-
+
+ o <[size]>
+
+ <[size]> is an optional modifier that changes the data
+ type that the corresponding argument has. Behavior is
+ unspecified if a size is given that does not match the
+ <[type]>.
+
+ o+
+ o hh
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument should be
+ converted to a <<signed char>> or <<unsigned
+ char>> before printing.
+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<signed char>>.
+
+ o h
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument should be
+ converted to a <<short>> or <<unsigned short>>
+ before printing.
+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<short>>.
+
+ o l
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument is a
+ <<long>> or <<unsigned long>>.
+
+ With <<c>>, specifies that the argument has
+ type <<wint_t>>.
- o <[width]>
+ With <<s>>, specifies that the argument is a
+ pointer to <<wchar_t>>.
- <[width]> is an optional minimum field width. You can either
- specify it directly as a decimal integer, or indirectly by
- using instead an asterisk (<<*>>), in which case an <<int>>
- argument is used as the field width. Negative field widths
- are not supported; if you attempt to specify a negative field
- width, it is interpreted as a minus (<<->>) flag followed by a
- positive field width.
-
- o <[prec]>
-
- an optional field; if present, it is introduced with `<<.>>'
- (a period). This field gives the maximum number of
- characters to print in a conversion; the minimum number of
- digits of an integer to print, for conversions with <[type]>
- <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>; the maximum number of
- significant digits, for the <<g>> and <<G>> conversions;
- or the number of digits to print after the decimal
- point, for <<e>>, <<E>>, and <<f>> conversions. You can specify
- the precision either directly as a decimal integer or
- indirectly by using an asterisk (<<*>>), in which case
- an <<int>> argument is used as the precision. Supplying a negative
- precision is equivalent to omitting the precision.
- If only a period is specified the precision is zero.
- If a precision appears with any other conversion <[type]>
- than those listed here, the behavior is undefined.
-
- o <[size]>
-
- <<h>>, <<l>>, and <<L>> are optional size characters which
- override the default way that <<printf>> interprets the
- data type of the corresponding argument. <<h>> forces
- the following <<d>>, <<i>>, <<o>>, <<u>>, <<x>> or <<X>> conversion
- <[type]> to apply to a <<short>> or <<unsigned short>>. <<h>> also
- forces a following <<n>> <[type]> to apply to
- a pointer to a <<short>>. Similarily, an
- <<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>,
- <<x>> or <<X>> conversion <[type]> to apply to a <<long>> or
- <<unsigned long>>. <<l>> also forces a following <<n>> <[type]> to
- apply to a pointer to a <<long>>. <<l>> with <<c>>, <<s>> is
- equivalent to <<C>>, <<S>> respectively. If an <<h>>
- or an <<l>> appears with another conversion
- specifier, the behavior is undefined. <<L>> forces a
- following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to
- apply to a <<long double>> argument. If <<L>> appears with
- any other conversion <[type]>, the behavior is undefined.
+ With <<n>>, specifies that the argument is a
+ pointer to a <<long>>.
- o <[type]>
+ With <<a>>, <<A>>, <<e>>, <<E>>, <<f>>, <<F>>,
+ <<g>>, or <<G>>, has no effect (because of
+ vararg promotion rules, there is no need to
+ distinguish between <<float>> and <<double>>).
- <[type]> specifies what kind of conversion <<printf>> performs.
- Here is a table of these:
+ o ll
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument is a
+ <<long long>> or <<unsigned long long>>.
- o+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<long long>>.
+
+ o j
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument is an
+ <<intmax_t>> or <<uintmax_t>>.
+
+ With <<n>>, specifies that the argument is a
+ pointer to an <<intmax_t>>.
+
+ o z
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument is a
+ <<ssize_t>> or <<size_t>>.
+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<ssize_t>>.
+
+ o t
+ With <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, or
+ <<X>>, specifies that the argument is a
+ <<ptrdiff_t>>.
+
+ With <<n>>, specifies that the argument is a
+ pointer to a <<ptrdiff_t>>.
+
+ o L
+ With <<a>>, <<A>>, <<e>>, <<E>>, <<f>>, <<F>>,
+ <<g>>, or <<G>>, specifies that the argument
+ is a <<long double>>.
+
+ o-
+
+ o <[type]>
+
+ <[type]> specifies what kind of conversion <<printf>>
+ performs. Here is a table of these:
+
+ o+
o %
- prints the percent character (<<%>>)
+ Prints the percent character (<<%>>).
o c
- prints <[arg]> as single character
-
+ Prints <[arg]> as single character. If the
+ <<l>> size specifier is in effect, a multibyte
+ character is printed.
+
o C
- prints wchar_t <[arg]> as single multibyte character
-
+ Short for <<%lc>>.
+
o s
- prints characters until precision is reached or a null terminator
- is encountered; takes a string pointer
+ Prints the elements of a pointer to <<char>>
+ until the precision or a null character is
+ reached. If the <<l>> size specifier is in
+ effect, the pointer is to an array of
+ <<wchar_t>>, and the string is converted to
+ multibyte characters before printing.
o S
- converts wchar_t characters to multibyte output characters until
- precision is reached or a null wchar_t terminator
- is encountered; takes a wchar_t pointer
+ Short for <<%ls>>.
- o d
- prints a signed decimal integer; takes an <<int>> (same as <<i>>)
+ o d or i
+ Prints a signed decimal integer; takes an
+ <<int>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
- o i
- prints a signed decimal integer; takes an <<int>> (same as <<d>>)
+ o D
+ Newlib extension, short for <<%ld>>.
o o
- prints a signed octal integer; takes an <<int>>
+ Prints an unsigned octal integer; takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ o O
+ Newlib extension, short for <<%lo>>.
o u
- prints an unsigned decimal integer; takes an <<int>>
+ Prints an unsigned decimal integer; takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
+
+ o U
+ Newlib extension, short for <<%lu>>.
o x
- prints an unsigned hexadecimal integer (using <<abcdef>> as
- digits beyond <<9>>); takes an <<int>>
+ Prints an unsigned hexadecimal integer (using
+ <<abcdef>> as digits beyond <<9>>); takes an
+ <<unsigned>>. Leading zeros are inserted as
+ necessary to reach the precision. A precision
+ of 0 produces an empty string.
o X
- prints an unsigned hexadecimal integer (using <<ABCDEF>> as
- digits beyond <<9>>); takes an <<int>>
+ Like <<x>>, but uses <<ABCDEF>> as digits
+ beyond <<9>>.
o f
- prints a signed value of the form <<[-]9999.9999>>; takes
- a floating-point number
-
+ Prints a signed value of the form
+ <<[-]9999.9999>>, with the precision
+ determining how many digits follow the decimal
+ point; takes a <<double>> (remember that
+ <<float>> promotes to <<double>> as a vararg).
+ The low order digit is rounded to even. If
+ the precision results in at most DECIMAL_DIG
+ digits, the result is rounded correctly; if
+ more than DECIMAL_DIG digits are printed, the
+ result is only guaranteed to round back to the
+ original value.
+
+ If the value is infinite, the result is
+ <<inf>>, and no zero padding is performed. If
+ the value is not a number, the result is
+ <<nan>>, and no zero padding is performed.
+
+ o F
+ Like <<f>>, but uses <<INF>> and <<NAN>> for
+ non-finite numbers.
+
o e
- prints a signed value of the form <<[-]9.9999e[+|-]999>>; takes a
- floating-point number
+ Prints a signed value of the form
+ <<[-]9.9999e[+|-]999>>; takes a <<double>>.
+ The digit before the decimal point is non-zero
+ if the value is non-zero. The precision
+ determines how many digits appear between
+ <<.>> and <<e>>, and the exponent always
+ contains at least two digits. The value zero
+ has an exponent of zero. If the value is not
+ finite, it is printed like <<f>>.
o E
- prints the same way as <<e>>, but using <<E>> to introduce the
- exponent; takes a floating-point number
+ Like <<e>>, but using <<E>> to introduce the
+ exponent, and like <<F>> for non-finite
+ values.
o g
- prints a signed value in either <<f>> or <<e>> form, based on given
- value and precision---trailing zeros and the decimal point are
- printed only if necessary; takes a floating-point number
-
+ Prints a signed value in either <<f>> or <<e>>
+ form, based on the given value and
+ precision---an exponent less than -4 or
+ greater than the precision selects the <<e>>
+ form. Trailing zeros and the decimal point
+ are printed only if necessary; takes a
+ <<double>>.
+
o G
- prints the same way as <<g>>, but using <<E>> for the exponent if an
- exponent is needed; takes a floating-point number
+ Like <<g>>, except use <<F>> or <<E>> form.
+
+ o a
+ Prints a signed value of the form
+ <<[-]0x1.ffffp[+|-]9>>; takes a <<double>>.
+ The letters <<abcdef>> are used for digits
+ beyond <<9>>. The precision determines how
+ many digits appear after the decimal point.
+ The exponent contains at least one digit, and
+ is a decimal value representing the power of
+ 2; a value of 0 has an exponent of 0.
+ Non-finite values are printed like <<f>>.
+
+ o A
+ Like <<a>>, except uses <<X>>, <<P>>, and
+ <<ABCDEF>> instead of lower case.
o n
- stores (in the same object) a count of the characters written;
- takes a pointer to <<int>>
+ Takes a pointer to <<int>>, and stores a count
+ of the number of bytes written so far. No
+ output is created.
o p
- prints a pointer in an implementation-defined format.
- This implementation treats the pointer as an
- <<unsigned long>> (same as <<Lu>>).
- o-
-O-
-
+ Takes a pointer to <<void>>, and prints it in
+ an implementation-defined format. This
+ implementation is similar to <<%#tx>>), except
+ that <<0x>> appears even for the NULL pointer.
+
+ o-
+ O-
+
+ <<_printf_r>>, <<_fprintf_r>>, <<_asprintf_r>>,
+ <<_sprintf_r>>, <<_snprintf_r>>, <<_asnprintf_r>> are simply
+ reentrant versions of the functions above.
RETURNS
-<<sprintf>> and <<asprintf>> return the number of bytes in the output string,
-save that the concluding <<NULL>> is not counted.
-<<printf>> and <<fprintf>> return the number of characters transmitted.
-If an error occurs, <<printf>> and <<fprintf>> return <<EOF>> and
-<<asprintf>> returns -1. No error returns occur for <<sprintf>>.
+On success, <<sprintf>> and <<asprintf>> return the number of bytes in
+the output string, except the concluding <<NUL>> is not counted.
+<<snprintf>> returns the number of bytes that would be in the output
+string, except the concluding <<NUL>> is not counted. <<printf>> and
+<<fprintf>> return the number of characters transmitted.
+<<asnprintf>> returns the original <[str]> if there was enough room,
+otherwise it returns an allocated string.
+
+If an error occurs, the result of <<printf>>, <<fprintf>>,
+<<snprintf>>, and <<asprintf>> is a negative value, and the result of
+<<asnprintf>> is NULL. No error returns occur for <<sprintf>>. For
+<<printf>> and <<fprintf>>, <<errno>> may be set according to
+<<fputc>>. For <<asprintf>> and <<asnprintf>>, <<errno>> may be set
+to ENOMEM if allocation fails, and for <<snprintf>>, <<errno>> may be
+set to EOVERFLOW if <[size]> or the output length exceeds INT_MAX.
PORTABILITY
- The ANSI C standard specifies that implementations must
- support at least formatted output of up to 509 characters.
+ANSI C requires <<printf>>, <<fprintf>>, <<sprintf>>, and
+<<snprintf>>. <<asprintf>> and <<asnprintf>> are newlib extensions.
+
+The ANSI C standard specifies that implementations must support at
+least formatted output of up to 509 characters. This implementation
+has no inherent limit.
+
+Depending on how newlib was configured, not all format specifiers are
+supported.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
Index: libc/stdio/vasniprintf.c
===================================================================
RCS file: libc/stdio/vasniprintf.c
diff -N libc/stdio/vasniprintf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libc/stdio/vasniprintf.c 28 Apr 2007 13:40:20 -0000
@@ -0,0 +1,69 @@
+/* Copyright (C) 2007 Eric Blake
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+/* This code was derived from asprintf.c */
+/* doc in viprintf.c */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+char *
+_DEFUN(_vasniprintf_r, (ptr, buf, lenp, fmt, ap),
+ struct _reent *ptr _AND
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _AND
+ va_list ap)
+{
+ int ret;
+ FILE f;
+ size_t len = *lenp;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ ret = _vfiprintf_r (ptr, &f, fmt, ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN(vasniprintf, (buf, lenp, fmt, ap),
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _AND
+ va_list ap)
+{
+ return _vasniprintf_r (_REENT, buf, lenp, fmt, ap);
+}
+
+#endif /* ! _REENT_ONLY */
Index: libc/stdio/vasnprintf.c
===================================================================
RCS file: libc/stdio/vasnprintf.c
diff -N libc/stdio/vasnprintf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libc/stdio/vasnprintf.c 28 Apr 2007 13:40:20 -0000
@@ -0,0 +1,69 @@
+/* Copyright (C) 2007 Eric Blake
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+/* This code was derived from asprintf.c */
+/* doc in vfprintf.c */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+char *
+_DEFUN(_vasnprintf_r, (ptr, buf, lenp, fmt, ap),
+ struct _reent *ptr _AND
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _AND
+ va_list ap)
+{
+ int ret;
+ FILE f;
+ size_t len = *lenp;
+
+ if (buf && len)
+ {
+ /* mark an existing buffer, but allow allocation of larger string */
+ f._flags = __SWR | __SSTR | __SOPT;
+ }
+ else
+ {
+ /* mark a zero-length reallocatable buffer */
+ f._flags = __SWR | __SSTR | __SMBF;
+ len = 0;
+ }
+ f._bf._base = f._p = (unsigned char *) buf;
+ /* For now, inherit the 32-bit signed limit of FILE._bf._size.
+ FIXME - it would be nice to rewrite sys/reent.h to support size_t
+ for _size. */
+ if (len > INT_MAX)
+ {
+ ptr->_errno = EOVERFLOW;
+ return NULL;
+ }
+ f._bf._size = f._w = len;
+ f._file = -1; /* No file. */
+ ret = _vfprintf_r (ptr, &f, fmt, ap);
+ if (ret < 0)
+ return NULL;
+ *lenp = ret;
+ *f._p = '\0';
+ return (char *) f._bf._base;
+}
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN(vasnprintf, (buf, lenp, fmt, ap),
+ char *buf _AND
+ size_t *lenp _AND
+ const char *fmt _AND
+ va_list ap)
+{
+ return _vasnprintf_r (_REENT, buf, lenp, fmt, ap);
+}
+
+#endif /* ! _REENT_ONLY */
Index: libc/stdio/vdiprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vdiprintf.c,v
retrieving revision 1.1
diff -u -p -r1.1 vdiprintf.c
--- libc/stdio/vdiprintf.c 4 Apr 2007 18:32:49 -0000 1.1
+++ libc/stdio/vdiprintf.c 28 Apr 2007 13:40:20 -0000
@@ -2,6 +2,7 @@
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
+/* doc in diprintf.c */
#include <_ansi.h>
#include <reent.h>
@@ -18,13 +19,16 @@ _DEFUN(_vdiprintf_r, (ptr, fd, format, a
va_list ap)
{
char *p;
- int n;
+ char buf[512];
+ size_t n = sizeof buf;
_REENT_SMALL_CHECK_INIT (ptr);
- n = _vasiprintf_r (ptr, &p, format, ap);
- if (n == -1) return -1;
+ p = _vasniprintf_r (ptr, buf, &n, format, ap);
+ if (!p)
+ return -1;
n = _write_r (ptr, fd, p, n);
- _free_r (ptr, p);
+ if (p != buf)
+ _free_r (ptr, p);
return n;
}
Index: libc/stdio/vdprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vdprintf.c,v
retrieving revision 1.2
diff -u -p -r1.2 vdprintf.c
--- libc/stdio/vdprintf.c 4 Apr 2007 18:32:49 -0000 1.2
+++ libc/stdio/vdprintf.c 28 Apr 2007 13:40:20 -0000
@@ -2,6 +2,7 @@
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
+/* doc in dprintf.c */
#include <_ansi.h>
#include <reent.h>
@@ -18,14 +19,16 @@ _DEFUN(_vdprintf_r, (ptr, fd, format, ap
va_list ap)
{
char *p;
- int n;
+ char buf[512];
+ size_t n = sizeof buf;
_REENT_SMALL_CHECK_INIT (ptr);
- n = _vasprintf_r (ptr, &p, format, ap);
- if (n == -1)
+ p = _vasnprintf_r (ptr, buf, &n, format, ap);
+ if (!p)
return -1;
n = _write_r (ptr, fd, p, n);
- _free_r (ptr, p);
+ if (p != buf)
+ _free_r (ptr, p);
return n;
}
Index: libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v
retrieving revision 1.54
diff -u -p -r1.54 vfprintf.c
--- libc/stdio/vfprintf.c 25 Apr 2007 19:47:36 -0000 1.54
+++ libc/stdio/vfprintf.c 28 Apr 2007 13:40:20 -0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1990, 2006 The Regents of the University of California.
+ * Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -36,7 +36,7 @@
/*
FUNCTION
-<<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
+<<vprintf>>, <<vfprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, vasnprintf>>---format argument list
INDEX
vprintf
@@ -46,6 +46,10 @@ INDEX
vsprintf
INDEX
vsnprintf
+INDEX
+ vasprintf
+INDEX
+ vasnprintf
ANSI_SYNOPSIS
#include <stdio.h>
@@ -53,96 +57,46 @@ ANSI_SYNOPSIS
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 vasprintf(char **<[strp]>, 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 _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
+ 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 _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>, size_t <[size]>,
+ int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
const char *<[fmt]>, va_list <[list]>);
-
-TRAD_SYNOPSIS
- #include <stdio.h>
- #include <varargs.h>
- int vprintf( <[fmt]>, <[list]>)
- char *<[fmt]>;
- va_list <[list]>;
-
- int vfprintf(<[fp]>, <[fmt]>, <[list]>)
- FILE *<[fp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vasprintf(<[strp]>, <[fmt]>, <[list]>)
- char **<[strp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vsprintf(<[str]>, <[fmt]>, <[list]>)
- char *<[str]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
- char *<[str]>;
- size_t <[size]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- FILE *<[fp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vasprintf_r(<[reent]>, <[strp]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char **<[strp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[str]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vsnprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[str]>;
- size_t <[size]>;
- 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>> and <<vsnprintf>> are
-(respectively) variants of <<printf>>, <<fprintf>>, <<asprintf>>, <<sprintf>>,
-and <<snprintf>>. 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.
+<<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:
-<<vasprintf>>/<<vsprintf>> returns the number of bytes in the output string,
-save that the concluding <<NULL>> is not counted.
-<<vprintf>> and <<vfprintf>> return the number of characters transmitted.
-If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>> and
-<<vasprintf>> returns -1. No error returns occur for <<vsprintf>>.
+The return values are consistent with the corresponding functions.
PORTABILITY
-ANSI C requires all three functions.
+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>>.
@@ -1247,13 +1201,13 @@ number: if ((dprec = prec) >= 0)
if (_fpvalue == 0) {
/* kludge for __dtoa irregularity */
PRINT ("0", 1);
- if (expt < ndig || (flags & ALT) != 0) {
+ if (ndig || flags & ALT) {
PRINT (decimal_point, 1);
PAD (ndig - 1, zeroes);
}
} else if (expt <= 0) {
PRINT ("0", 1);
- if(expt || ndig || (flags & ALT)) {
+ if (expt || ndig || flags & ALT) {
PRINT (decimal_point, 1);
PAD (-expt, zeroes);
PRINT (cp, ndig);
@@ -1267,15 +1221,15 @@ number: if ((dprec = prec) >= 0)
PRINT (cp, expt);
cp += expt;
PRINT (".", 1);
- PRINT (cp, ndig-expt);
+ PRINT (cp, ndig - expt);
}
} else { /* 'e' or 'E' */
if (ndig > 1 || flags & ALT) {
ox[0] = *cp++;
ox[1] = '.';
PRINT (ox, 2);
- if (_fpvalue) {
- PRINT (cp, ndig-1);
+ if (_fpvalue) {
+ PRINT (cp, ndig - 1);
} else /* 0.[0..] */
/* __dtoa irregularity */
PAD (ndig - 1, zeroes);
Index: libc/stdio/viprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/viprintf.c,v
retrieving revision 1.3
diff -u -p -r1.3 viprintf.c
--- libc/stdio/viprintf.c 28 Oct 2005 21:38:59 -0000 1.3
+++ libc/stdio/viprintf.c 28 Apr 2007 13:40:20 -0000
@@ -17,7 +17,7 @@
/*
FUNCTION
-<<viprintf>>, <<vfiprintf>>, <<vsiprintf>>---format argument list
+<<viprintf>>, <<vfiprintf>>, <<vsiprintf>>, <<vsniprintf>>, <<vasiprintf>>, <<vasniprintf>>---format argument list (integer only)
INDEX
viprintf
@@ -27,6 +27,10 @@ INDEX
vsiprintf
INDEX
vsniprintf
+INDEX
+ vasiprintf
+INDEX
+ vasniprintf
ANSI_SYNOPSIS
#include <stdio.h>
@@ -34,96 +38,45 @@ ANSI_SYNOPSIS
int viprintf(const char *<[fmt]>, va_list <[list]>);
int vfiprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
int vsiprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
- int vasiprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
int vsniprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
va_list <[list]>);
+ int vasiprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
+ char *vasniprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
+ va_list <[list]>);
int _viprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
va_list <[list]>);
int _vfiprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
const char *<[fmt]>, va_list <[list]>);
- int _vasiprintf_r(struct _reent *<[reent]>, char **<[str]>,
- const char *<[fmt]>, va_list <[list]>);
int _vsiprintf_r(struct _reent *<[reent]>, char *<[str]>,
const char *<[fmt]>, va_list <[list]>);
- int _vsniprintf_r(struct _reent *<[reent]>, char *<[str]>, size_t <[size]>,
- const char *<[fmt]>, va_list <[list]>);
-
-TRAD_SYNOPSIS
- #include <stdio.h>
- #include <varargs.h>
- int viprintf( <[fmt]>, <[list]>)
- char *<[fmt]>;
- va_list <[list]>;
-
- int vfiprintf(<[fp]>, <[fmt]>, <[list]>)
- FILE *<[fp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vasiprintf(<[strp]>, <[fmt]>, <[list]>)
- char **<[strp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vsiprintf(<[str]>, <[fmt]>, <[list]>)
- char *<[str]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int vsniprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
- char *<[str]>;
- size_t <[size]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _viprintf_r(<[reent]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vfiprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- FILE *<[fp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vasiprintf_r(<[reent]>, <[strp]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char **<[strp]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vsiprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[str]>;
- char *<[fmt]>;
- va_list <[list]>;
-
- int _vsniprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>)
- struct _reent *<[reent]>;
- char *<[str]>;
- size_t <[size]>;
- char *<[fmt]>;
- va_list <[list]>;
+ int _vsniprintf_r(struct _reent *<[reent]>, char *<[str]>,
+ size_t <[size]>, const char *<[fmt]>,
+ va_list <[list]>);
+ int _vasiprintf_r(struct _reent *<[reent]>, char **<[str]>,
+ const char *<[fmt]>, va_list <[list]>);
+ char *_vasniprintf_r(struct _reent *<[reent]>, char *<[str]>,
+ size_t *<[size]>, const char *<[fmt]>,
+ va_list <[list]>);
DESCRIPTION
-<<viprintf>>, <<vfiprintf>>, <<vasiprintf>>, <<vsiprintf>> and
-<<vsniprintf>> are (respectively) variants of <<iprintf>>, <<fiprintf>>,
-<<asiprintf>>, <<siprintf>>, and <<sniprintf>>. They differ only in
-restricting the caller to use non-floating-point format specifiers.
+<<viprintf>>, <<vfiprintf>>, <<vasiprintf>>, <<vsiprintf>>,
+<<vsniprintf>>, and <<vasniprintf>> are (respectively) variants of
+<<iprintf>>, <<fiprintf>>, <<asiprintf>>, <<siprintf>>, <<sniprintf>>,
+and <<asniprintf>>. 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>>.
+
+<<_viprintf_r>>, <<_vfiprintf_r>>, <<_vasiprintf_r>>,
+<<_vsiprintf_r>>, <<_vsniprintf_r>>, and <<_vasniprintf_r>> are
+reentrant versions of the above.
RETURNS
The return values are consistent with the corresponding functions:
-<<vasiprintf>>/<<vsiprintf>> returns the number of bytes in the output string,
-save that the concluding <<NULL>> is not counted.
-<<viprintf>> and <<vfiprintf>> return the number of characters transmitted.
-If an error occurs, <<viprintf>> and <<vfiprintf>> return <<EOF>> and
-<<vasiprintf>> returns -1. No error returns occur for <<vsiprintf>>.
PORTABILITY
-<<viprintf>>, <<vfiprintf>>, <<vasiprintf>>, <<vsiprintf>> and <<vsniprintf>>
-are newlib extensions.
+All of these functions are newlib extensions.
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
Index: libc/stdio/vsiprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vsiprintf.c,v
retrieving revision 1.2
diff -u -p -r1.2 vsiprintf.c
--- libc/stdio/vsiprintf.c 4 Apr 2007 18:32:49 -0000 1.2
+++ libc/stdio/vsiprintf.c 28 Apr 2007 13:40:20 -0000
@@ -14,7 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-/* doc in vfiprintf.c */
+/* doc in viprintf.c */
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "%W% (Berkeley) %G%";
Index: libc/stdio/vsniprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vsniprintf.c,v
retrieving revision 1.3
diff -u -p -r1.3 vsniprintf.c
--- libc/stdio/vsniprintf.c 4 Apr 2007 18:32:49 -0000 1.3
+++ libc/stdio/vsniprintf.c 28 Apr 2007 13:40:20 -0000
@@ -14,46 +14,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-
-/*
-FUNCTION
-<<vsniprintf>>---write formatted output (integer only)
-
-INDEX
- vsniprintf
-
-ANSI_SYNOPSIS
- #include <stdio.h>
-
- int vsniprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
-
-TRAD_SYNOPSIS
- #include <stdio.h>
-
- int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
- char *<[str]>;
- size_t <[size]>;
- char *<[fmt]>;
- va_list <[list]>;
-
-DESCRIPTION
-<<vsniprintf>> is a restricted version of <<vsnprintf>>: it has the same
-arguments and behavior, save that it cannot perform any floating-point
-formatting: the <<f>>, <<g>>, <<G>>, <<e>>, and <<F>> type specifiers
-are not recognized.
-
-RETURNS
- <<vsniprintf>> returns the number of bytes in the output string,
- save that the concluding <<NULL>> is not counted.
- <<vsniprintf>> returns when the end of the format string is
- encountered.
-
-PORTABILITY
-<<vsniprintf>> is not required by ANSI C.
-
-Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
-<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
-*/
+/* doc in viprintf.c */
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "%W% (Berkeley) %G%";