diff options
-rw-r--r-- | include/stdio.h | 6 | ||||
-rw-r--r-- | lib/libc/shlib_version | 2 | ||||
-rw-r--r-- | lib/libc/stdio/asprintf.c | 83 | ||||
-rw-r--r-- | lib/libc/stdio/fvwrite.c | 18 | ||||
-rw-r--r-- | lib/libc/stdio/printf.3 | 107 | ||||
-rw-r--r-- | lib/libc/stdio/vasprintf.c | 67 |
6 files changed, 238 insertions, 45 deletions
diff --git a/include/stdio.h b/include/stdio.h index d5152a67704..a31fa0610c8 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: stdio.h,v 1.7 1996/10/28 06:51:05 tholo Exp $ */ +/* $OpenBSD: stdio.h,v 1.8 1997/11/29 19:54:51 millert Exp $ */ /* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ */ /*- @@ -162,6 +162,7 @@ __END_DECLS #define __SNPT 0x0800 /* do not do fseek() optimisation */ #define __SOFF 0x1000 /* set iff _offset is in fact correct */ #define __SMOD 0x2000 /* true => fgetln modified _p text */ +#define __SALC 0x4000 /* allocate string space dynamically */ /* * The following three definitions are for ANSI C, which took them @@ -281,6 +282,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 *)); @@ -292,6 +294,8 @@ int setlinebuf __P((FILE *)); char *tempnam __P((const char *, const char *)); int snprintf __P((char *, size_t, const char *, ...)) __attribute__((format (printf, 3, 4))); +int vasprintf __P((char **, const char *, _BSD_VA_LIST_)) + __attribute__((format (printf, 2, 0))); int vsnprintf __P((char *, size_t, const char *, _BSD_VA_LIST_)) __attribute__((format (printf, 3, 0))); int vscanf __P((const char *, _BSD_VA_LIST_)) diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 51c2640f411..16555489150 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,2 +1,2 @@ major=17 -minor=4 +minor=5 diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c new file mode 100644 index 00000000000..1e5f00fa1ab --- /dev/null +++ b/lib/libc/stdio/asprintf.c @@ -0,0 +1,83 @@ +/* $OpenBSD: asprintf.c,v 1.1 1997/11/29 19:54:48 millert Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Todd C. Miller. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 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_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: asprintf.c,v 1.1 1997/11/29 19:54:48 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +#if __STDC__ +asprintf(char **str, char const *fmt, ...) +#else +asprintf(str, fmt, va_alist) + char **str; + const char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + f._flags = __SWR | __SSTR | __SALC; + f._bf._base = f._p = (unsigned char *)malloc(128); + if (f._bf._base == NULL) { + *str = NULL; + errno = ENOMEM; + return (-1); + } + f._bf._size = f._w = 127; /* Leave room for the NULL */ + ret = vfprintf(&f, fmt, ap); + *f._p = '\0'; + va_end(ap); + f._bf._base = realloc(f._bf._base, f._bf._size + 1); + if (f._bf._base == NULL) { + errno = ENOMEM; + ret = -1; + } + *str = f._bf._base; + return (ret); +} diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c index 259152be86f..c01968b72f8 100644 --- a/lib/libc/stdio/fvwrite.c +++ b/lib/libc/stdio/fvwrite.c @@ -35,10 +35,11 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: fvwrite.c,v 1.4 1996/10/26 08:16:07 tholo Exp $"; +static char rcsid[] = "$OpenBSD: fvwrite.c,v 1.5 1997/11/29 19:54:48 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <errno.h> #include "local.h" @@ -109,6 +110,21 @@ __sfvwrite(fp, uio) */ do { GETIOV(;); + if ((fp->_flags & (__SALC | __SSTR)) == + (__SALC | __SSTR) && fp->_w < len) { + size_t blen = fp->_p - fp->_bf._base; + + /* + * Alloc an extra 128 bytes (+ 1 for NULL) + * so we don't call realloc(3) so often. + */ + fp->_w = len + 128; + fp->_bf._size = blen + len + 128; + /* XXX - check return val */ + fp->_bf._base = + realloc(fp->_bf._base, fp->_bf._size + 1); + fp->_p = fp->_bf._base + blen; + } w = fp->_w; if (fp->_flags & __SSTR) { if (len < w) diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3 index 7786746a339..f43672a901e 100644 --- a/lib/libc/stdio/printf.3 +++ b/lib/libc/stdio/printf.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: printf.3,v 1.4 1997/06/30 03:22:08 millert Exp $ +.\" $OpenBSD: printf.3,v 1.5 1997/11/29 19:54:49 millert Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -35,6 +35,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" +.\" @(#)printf.3 8.1 (Berkeley) 6/4/93 +.\" .Dd June 4, 1993 .Dt PRINTF 3 .Os @@ -43,10 +45,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,19 +62,19 @@ .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" .Ft int .Fn vfprintf "FILE *stream" "const char *format" "va_list ap" .Ft int -.Fn vsprintf "char *str" "char *format" "va_list ap" +.Fn vsprintf "char *str" "const 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 +98,50 @@ 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 ; +.Fn asprintf +and +.Fn vasprintf +write to a dynamically allocated string that is stored in +.Fa ret . +.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 +.Fn Snprintf +and +.Fn vsnprintf +will return -1 if the +.Fa size +parameter is 0. +.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 +156,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 @@ -180,7 +190,6 @@ Arguments are numbered starting at .Cm 1 . If unaccessed arguments in the format string are interspersed with ones that are accessed the results will be indeterminate. - .It Zero or more of the following flags: .Bl -hyphen @@ -189,7 +198,7 @@ A .Cm # character specifying that the value should be converted to an ``alternate form''. -For +For .Cm c , .Cm d , .Cm i , @@ -199,7 +208,7 @@ For and .Cm u , conversions, this option has no effect. -For +For .Cm o conversions, the precision of the number is increased to force the first character of the output string to a zero (except if a zero value is printed @@ -239,7 +248,7 @@ For all conversions except .Cm n , the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion -.Pf ( Mc d , +.Pf ( Cm d , .Cm i , .Cm o , .Cm u , @@ -615,6 +624,14 @@ 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 first appeared in +.Bx Open +2.3. .Sh BUGS The conversion formats .Cm \&%D , @@ -649,6 +666,12 @@ callers must be careful not to overflow the actual space; this is often impossible to assure. For safety, programmers should use the .Fn snprintf -interface instead. -Unfortunately, this interface is not available on older -systems. +and +.Fn vasprintf +family of interfaces instead. +Unfortunately, the +.Fn snprintf +interface is not available on older +systems and the +.Fn vasprintf +interface is not portable. diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c new file mode 100644 index 00000000000..e11f33b7dff --- /dev/null +++ b/lib/libc/stdio/vasprintf.c @@ -0,0 +1,67 @@ +/* $OpenBSD: vasprintf.c,v 1.1 1997/11/29 19:54:47 millert Exp $ */ + +/* + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Todd C. Miller. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 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_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: vasprintf.c,v 1.1 1997/11/29 19:54:47 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +int +vasprintf(str, fmt, ap) + char **str; + const char *fmt; + _BSD_VA_LIST_ ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR | __SALC; + f._bf._base = f._p = (unsigned char *)malloc(128); + if (f._bf._base == NULL) { + *str = NULL; + errno = ENOMEM; + return (-1); + } + f._bf._size = f._w = 127; /* Leave room for the NULL */ + ret = vfprintf(&f, fmt, ap); + *f._p = '\0'; + f._bf._base = realloc(f._bf._base, f._bf._size + 1); + if (f._bf._base == NULL) { + errno = ENOMEM; + ret = -1; + } + *str = f._bf._base; + return (ret); +} |