summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/stdio.h2
-rw-r--r--lib/libc/stdio/Makefile.inc10
-rw-r--r--lib/libc/stdio/asprintf.c59
-rw-r--r--lib/libc/stdio/printf.380
-rw-r--r--lib/libc/stdio/vasprintf.c108
5 files changed, 221 insertions, 38 deletions
diff --git a/include/stdio.h b/include/stdio.h
index e930010..9c4c37e 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -283,6 +283,7 @@ __END_DECLS
*/
#if !defined (_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
__BEGIN_DECLS
+int asprintf __P((char **, const char *, ...));
char *fgetln __P((FILE *, size_t *));
int fpurge __P((FILE *));
int getw __P((FILE *));
@@ -293,6 +294,7 @@ void setbuffer __P((FILE *, char *, int));
int setlinebuf __P((FILE *));
char *tempnam __P((const char *, const char *));
int snprintf __P((char *, size_t, const char *, ...));
+int vasprintf __P((char **, const char *, _BSD_VA_LIST_));
int vsnprintf __P((char *, size_t, const char *, _BSD_VA_LIST_));
int vscanf __P((const char *, _BSD_VA_LIST_));
int vsscanf __P((const char *, const char *, _BSD_VA_LIST_));
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index 5ca5016..b9c02a4 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -3,16 +3,16 @@
# stdio sources
.PATH: ${.CURDIR}/stdio
-SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \
- fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
+SRCS+= asprintf.c clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c \
+ fgetc.c fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
fprintf.c fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \
fseek.c fsetpos.c ftell.c funopen.c fvwrite.c fwalk.c fwrite.c \
getc.c getchar.c gets.c getw.c makebuf.c mktemp.c perror.c \
printf.c putc.c putchar.c puts.c putw.c refill.c remove.c rewind.c \
rget.c scanf.c setbuf.c setbuffer.c setvbuf.c snprintf.c sprintf.c \
- sscanf.c stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vfprintf.c \
- vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c \
- wbuf.c wsetup.c
+ sscanf.c stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vasprintf.c \
+ vfprintf.c vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \
+ vsscanf.c wbuf.c wsetup.c
MAN3+= stdio/fclose.3 stdio/ferror.3 stdio/fflush.3 stdio/fgetln.3 \
stdio/fgets.3 stdio/fopen.3 stdio/fputs.3 stdio/fread.3 stdio/fseek.3 \
diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c
new file mode 100644
index 0000000..9b4d05b
--- /dev/null
+++ b/lib/libc/stdio/asprintf.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1996 Peter Wemm <peter@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#if __STDC__
+int
+asprintf(char **str, char const *fmt, ...)
+#else
+int
+asprintf(str, fmt, va_alist)
+ char **str;
+ char *fmt;
+ va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ ret = vasprintf(str, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index 4238a90..e675b3e 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -43,10 +43,12 @@
.Nm fprintf ,
.Nm sprintf ,
.Nm snprintf ,
+.Nm asprintf ,
.Nm vprintf ,
.Nm vfprintf,
.Nm vsprintf ,
-.Nm vsnprintf
+.Nm vsnprintf ,
+.Nm vasprintf
.Nd formatted output conversion
.Sh SYNOPSIS
.Fd #include <stdio.h>
@@ -58,8 +60,8 @@
.Fn sprintf "char *str" "const char *format" ...
.Ft int
.Fn snprintf "char *str" "size_t size" "const char *format" ...
-.\" .Ft int
-.\" .Fn smprintf "const char *format" ...
+.Ft int
+.Fn asprintf "char **ret" "const char *format" ...
.Fd #include <stdarg.h>
.Ft int
.Fn vprintf "const char *format" "va_list ap"
@@ -69,8 +71,8 @@
.Fn vsprintf "char *str" "char *format" "va_list ap"
.Ft int
.Fn vsnprintf "char *str" "size_t size" "const char *format" "va_list ap"
-.\" .Ft int
-.\" .Fn vsmprintf "const char *format" "va_list ap"
+.Ft int
+.Fn vasprintf "char **ret" "const char *format" "va_list ap"
.Sh DESCRIPTION
The
.Fn printf
@@ -94,45 +96,47 @@ write output to the given output
and
.Fn vsnprintf
write to the character string
-.Fa str .
-.\" .IR str ;
-.\" and
-.\" .I smprintf
-.\" and
-.\" .I vsmprintf
-.\" dynamically allocate a new string with
-.\" .IR malloc .
+.Fa str ;
+and
+.Fn asprintf
+and
+.Fn vasprintf
+dynamically allocate a new string with
+.Xr malloc 3
+/
+.Xr realloc 3 .
+.Pp
These functions write the output under the control of a
.Fa format
string that specifies how subsequent arguments
(or arguments accessed via the variable-length argument facilities of
.Xr stdarg 3 )
are converted for output.
-.\" Except for
-.\" .I smprintf
-.\" and
-.\" .IR vsmprintf ,
-.\" all of these functions return
+.Pp
These functions return
the number of characters printed
(not including the trailing
.Ql \e0
used to end output to strings).
-.\" .I Smprintf
-.\" and
-.\" .I vsmprintf
-.\" return a pointer to a string of an appropriate length;
-.\" this pointer should be passed to
-.\" .I free
-.\" to release the associated storage
-.\" when it is no longer needed.
-.\" If sufficient space is not avaliable,
-.\" .I smprintf
-.\" and
-.\" .I vsmprintf
-.\" will return
-.\" .SM
-.\" .BR
+.Pp
+.Fn Asprintf
+and
+.Fn vasprintf
+return a pointer to a buffer sufficiently large to hold the
+string in the
+.Fa ret
+argument;
+This pointer should be passed to
+.Xr free 3
+to release the allocated storage when it is no longer needed.
+If sufficient space cannot be allocated,
+.Fn asprintf
+and
+.Fn vasprintf
+will return -1 and set
+.Fa ret
+to be a NULL pointer.
+.Pp
.Fn Snprintf
and
.Fn vsnprintf
@@ -147,6 +151,7 @@ if the return value is greater than or equal to the
.Fa size
argument, the string was too short
and some of the printed characters were discarded.
+.Pp
.Fn Sprintf
and
.Fn vsprintf
@@ -600,6 +605,15 @@ The functions
and
.Fn vsnprintf
are new to this release.
+.Pp
+The functions
+.Fn asprintf
+and
+.Fn vasprintf
+first appeared in the GNU C library. This implementation is thought
+to be compatable but is not derived from the GNU code. This implementation
+was written by Peter Wemm <peter@FreeBSD.org> and first appeared in
+FreeBSD-2.2.
.Sh BUGS
The conversion formats
.Cm \&%D ,
diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c
new file mode 100644
index 0000000..bec579a
--- /dev/null
+++ b/lib/libc/stdio/vasprintf.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1996 Peter Wemm <peter@freebsd.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_RCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_RCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#define CHUNK_SPARE 128 /* how much spare to allocate to avoid realloc calls */
+
+struct bufcookie {
+ char *base; /* start of buffer */
+ int size;
+ int left;
+};
+
+static int
+writehook(cookie, buf, len)
+ void *cookie;
+ char *buf;
+ int len;
+{
+ struct bufcookie *h = (struct bufcookie *)cookie;
+
+ if (len == 0)
+ return 0;
+
+ if (len > h->left) {
+ /* grow malloc region */
+ h->left = h->left + len + CHUNK_SPARE;
+ h->size = h->size + len + CHUNK_SPARE;
+ h->base = realloc(h->base, h->size);
+ if (h->base == NULL)
+ return (-1);
+ }
+ /* "write" it */
+ (void)memcpy(h->base + h->size - h->left, buf, len);
+ h->left -= len;
+ return (0);
+}
+
+
+int
+vasprintf(str, fmt, ap)
+ char **str;
+ const char *fmt;
+ va_list ap;
+{
+ int ret;
+ FILE *f;
+ struct bufcookie h;
+
+ h.base = malloc(CHUNK_SPARE);
+ if (h.base == NULL)
+ return (-1);
+ h.size = CHUNK_SPARE;
+ h.left = CHUNK_SPARE;
+
+ f = funopen(&h, NULL, writehook, NULL, NULL);
+ if (f == NULL) {
+ free(h.base);
+ return (-1);
+ }
+ ret = vfprintf(f, fmt, ap);
+ fclose(f);
+ if (ret < 0) {
+ free(h.base);
+ return (-1);
+ }
+ if (h.base == NULL) /* failed to realloc in writehook */
+ return (-1);
+
+ h.base[h.size - h.left] = '\0';
+ *str = realloc(h.base, h.size - h.left + 1);
+ if (*str == NULL) /* failed to realloc it to actual size */
+ return -1;
+ return (ret);
+}
OpenPOWER on IntegriCloud