X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX1/ZMoJZV0fZFpIJxGm0lp8expoiDi6qqRRh8Dnufe LjMqRVYo/RDpAL From: Juan Manuel Guerrero To: djgpp-workers AT delorie DOT com Subject: Implementation of [v]as[n]printf() family of functions. Date: Sun, 6 Apr 2008 23:47:40 +0200 User-Agent: KMail/1.9.5 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200804062347.42980.juan.guerrero@gmx.de> X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com Suggestions, comments, objections are welcome. 2008-04-06 Juan Manuell Guerrero * include/stdio.h: Declarartions for asprintf, asnprintf, vasprintf and vasnprintf added. * src/libc/compat/stdio/asprintf.c: BSD/GNU compatibility function. * src/libc/compat/stdio/asprintf.txh: Info about asprintf. * src/libc/compat/stdio/asnprntf.c: BSD/GNU compatibility function. * src/libc/compat/stdio/asnprntf.txh: Info about asprintf. * src/libc/compat/stdio/vasnprtf.c: BSD/GNU compatibility function. * src/libc/compat/stdio/vasnprtf.txh: Info about vasprintf. * src/libc/compat/stdio/vasprntf.c: BSD/GNU compatibility function. * src/libc/compat/stdio/vasprntf.txh: Info about vasprintf. * src/docs/kb/wc204.txi: Info about asprintf, asnprintf, vasprintf and vasnprintf added. diff -aprNU3 djgpp.orig/include/stdio.h djgpp/include/stdio.h --- djgpp.orig/include/stdio.h 2007-12-11 07:48:42 +0000 +++ djgpp/include/stdio.h 2008-04-06 23:35:36 +0000 @@ -164,6 +164,10 @@ int putw(int _v, FILE *_f); void setbuffer(FILE *_f, void *_buf, int _size); void setlinebuf(FILE *_f); int _rename(const char *_old, const char *_new); /* Simple (no directory) */ +int asprintf(char **_sp, const char *_format, ...) __attribute__((format (__printf__, 2, 3))); +int asnprintf(char **_sp, size_t _n, const char *_format, ...) __attribute__((format (__printf__, 3, 4))); +int vasprintf(char **_sp, const char *_format, va_list _ap) __attribute__((format (__printf__, 2, 0))); +int vasnprintf(char **_sp, size_t _n, const char *_format, va_list _ap) __attribute__((format (__printf__, 3, 0))); #ifndef _OFF_T __DJ_off_t diff -aprNU3 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi --- djgpp.orig/src/docs/kb/wc204.txi 2008-04-06 21:07:16 +0000 +++ djgpp/src/docs/kb/wc204.txi 2008-04-06 23:33:42 +0000 @@ -1102,3 +1102,11 @@ formats for @code{"%x"} and @code{"%X"} The C99 macro @code{signbit} and the supporting functions @code{__signbitf}, @code{__signbitd} and @code{__signbitld} were added. + +@findex asnprintf AT r{, added to the library} +@findex asprintf AT r{, added to the library} +@findex vasnprintf AT r{, added to the library} +@findex vasprintf AT r{, added to the library} +New BSD/GNU compatibility functions @code{asnprintf}, @code{asprintf}, +@code{vasnprintf} and @code{vasprintf} added. + diff -aprNU3 djgpp.orig/src/libc/compat/stdio/asnprntf.c djgpp/src/libc/compat/stdio/asnprntf.c --- djgpp.orig/src/libc/compat/stdio/asnprntf.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/asnprntf.c 2008-04-06 23:35:36 +0000 @@ -0,0 +1,16 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +asnprintf(char **strp, size_t n, const char *fmt, ...) +{ + va_list args; + int len; + + va_start(args, fmt); + len = vasnprintf(strp, n, fmt, args); + va_end(args); + + return len; +} diff -aprNU3 djgpp.orig/src/libc/compat/stdio/asnprntf.txh djgpp/src/libc/compat/stdio/asnprntf.txh --- djgpp.orig/src/libc/compat/stdio/asnprntf.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/asnprntf.txh 2008-04-06 23:35:36 +0000 @@ -0,0 +1,57 @@ +@node asnprintf, stdio +@findex asnprintf +@subheading Syntax + +@example +#include + +int asnprintf(char **@var{bufferp}, size_t @var{n}, const char *@var{format}, @dots{}); +@end example + +@subheading Description + +Sends formatted output from the arguments (@dots{}) including +the terminating null byte to the allocated buffer and returns +a pointer to it via the first parameter *@var{bufferp}. This +memory must be returned to the heap with @code{free} (@pxref{free}). +This function will write @var{n} - 1 characters. The @var{n}th character +is used for the terminating nul. If @var{n} is zero, @var{buffer} is not +touched. This function is analog of @code{snprintf()} (@pxref{snprintf}). + +@subheading Return Value + +The number of characters that would have been written (excluding the trailing +nul) is returned; otherwise EOF is returned to flag encoding or buffer space +errors. + +The maximum accepted value of @var{n} is @code{INT_MAX}. @code{INT_MAX} is +defined in @code{}. EOF is returned and @code{errno} is set to +@code{EFBIG}, if @var{n} is greater than this limit. + +@subheading Portability + +@port-note ansi The buffer size limit is imposed by DJGPP. Other systems may not have this limitation. + +@portability !ansi, !posix + +@subheading Example + +@example +char *strbuf; /* Pointer to the allocated buffer by asnprintf. */ +int strlng; +long double pi = 3.1415926535897932384626433832795L; + +strlng = asnprintf(&strbuf, 100, "Pi = %.15Lf\n", pi); + +if (EOF == strlng) + printf("error: asnprintf failed.\n"); +else +@{ + /* + * Your code using the allocated buffer by asnprintf. + */ + do_something(strbuf, strlng); + + free(strbuf); /* Release the memory allocated by asnprintf. */ +@} +@end example diff -aprNU3 djgpp.orig/src/libc/compat/stdio/asprintf.c djgpp/src/libc/compat/stdio/asprintf.c --- djgpp.orig/src/libc/compat/stdio/asprintf.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/asprintf.c 2008-04-06 23:35:36 +0000 @@ -0,0 +1,16 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +int +asprintf(char **strp, const char *fmt, ...) +{ + va_list args; + int len; + + va_start(args, fmt); + len = vasprintf(strp, fmt, args); + va_end(args); + + return len; +} diff -aprNU3 djgpp.orig/src/libc/compat/stdio/asprintf.txh djgpp/src/libc/compat/stdio/asprintf.txh --- djgpp.orig/src/libc/compat/stdio/asprintf.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/asprintf.txh 2008-04-06 23:35:36 +0000 @@ -0,0 +1,51 @@ +@node asprintf, stdio +@findex asprintf +@subheading Syntax + +@example +#include + +int asprintf(char **@var{bufferp}, const char *@var{format}, @dots{}); +@end example + +@subheading Description + +Sends formatted output from the arguments (@dots{}) including +the terminating null byte to the allocated buffer and returns +a pointer to it via the first parameter *@var{bufferp}. This +memory must be returned to the heap with @code{free} (@pxref{free}). +This function is analog of @code{sprintf()} (@pxref{sprintf}). + +@subheading Return Value + +The number of characters that would have been written (excluding +the terminating null byte) is returned; otherwise EOF is returned +to flag encoding or buffer space errors and the pointer +*@var{bufferp} is set to @code{NULL}. + + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +char *strbuf; /* Pointer to the allocated buffer by asprintf. */ +int strlng; +long double pi = 3.1415926535897932384626433832795L; + +strlng = asprintf(&strbuf, "Pi = %.15Lf\n", pi); + +if (EOF == strlng) + printf("error: asprintf failed.\n"); +else +@{ + /* + * Your code using the allocated buffer by asprintf. + */ + do_something(strbuf, strlng); + + free(strbuf); /* Release the memory allocated by asprintf. */ +@} +@end example diff -aprNU3 djgpp.orig/src/libc/compat/stdio/makefile djgpp/src/libc/compat/stdio/makefile --- djgpp.orig/src/libc/compat/stdio/makefile 2007-12-11 07:48:42 +0000 +++ djgpp/src/libc/compat/stdio/makefile 2008-04-06 23:35:36 +0000 @@ -2,6 +2,8 @@ # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details TOP=../.. +SRC += asnprntf.c +SRC += asprintf.c SRC += fseeko.c SRC += fseeko64.c SRC += ftello.c @@ -9,8 +11,10 @@ SRC += ftello64.c SRC += mkstemp.c SRC += mktemp.c SRC += tempnam.c -SRC += vscanf.c +SRC += vasnprtf.c +SRC += vasprntf.c SRC += vfscanf.S +SRC += vscanf.c SRC += vsscanf.c include $(TOP)/../makefile.inc diff -aprNU3 djgpp.orig/src/libc/compat/stdio/vasnprtf.c djgpp/src/libc/compat/stdio/vasnprtf.c --- djgpp.orig/src/libc/compat/stdio/vasnprtf.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/vasnprtf.c 2008-04-06 23:35:36 +0000 @@ -0,0 +1,56 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include +#include +#include +#include + +int +vasnprintf(char **strp, size_t n, const char *fmt, va_list argsp) +{ + FILE _strbuf; + int len; + + + /* _cnt is an int in the FILE structure. To prevent wrap-around, + * we limit n to between 0 and INT_MAX inclusively. */ + if (n > INT_MAX) + { + errno = EFBIG; + return EOF; + } + + /* Just query how much space is needed. */ + memset(&_strbuf, 0, sizeof(_strbuf)); + __stropenw(&_strbuf, NULL, 0); + len = _doprnt(fmt, argsp, &_strbuf); + + *strp = NULL; + if (n > 0) + { + if (len != EOF) + { + len++; + if ((size_t)len > n) + len = n; + *strp = malloc(len); + if (*strp) + { + __stropenw(&_strbuf, *strp, len - 1); + len = _doprnt(fmt, argsp, &_strbuf); + __strclosew(&_strbuf); + if (len == EOF) + { + free(*strp); + *strp = NULL; + } + } + } + else + len = EOF; + } + + return len; +} diff -aprNU3 djgpp.orig/src/libc/compat/stdio/vasnprtf.txh djgpp/src/libc/compat/stdio/vasnprtf.txh --- djgpp.orig/src/libc/compat/stdio/vasnprtf.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/vasnprtf.txh 2008-04-06 23:35:36 +0000 @@ -0,0 +1,60 @@ +@node vasnprintf, stdio +@findex vasnprintf +@subheading Syntax + +@example +#include +#include + +int vasnprintf(char **@var{buffer}, size_t @var{n}, const char *@var{format}, + va_list @var{ap}); +@end example + +@subheading Description + +Sends formatted output from the arguments in (@var{ap}) including +the terminating null byte to the allocated buffer and returns +a pointer to it via the first parameter *@var{bufferp}. This +memory must be returned to the heap with @code{free} (@pxref{free}). +This function will write @var{n} - 1 characters. The @var{n}th character +is used for the terminating nul. If @var{n} is zero, @var{buffer} is not +touched. This function is analog of @code{vsnprintf()} (@pxref{vsnprintf}). + +@subheading Return Value + +The number of characters that would have been written (excluding the trailing +nul) is returned; otherwise EOF is returned to flag encoding or buffer space +errors. + +The maximum accepted value of @var{n} is @code{INT_MAX}. @code{INT_MAX} is +defined in @code{}. EOF is returned and @code{errno} is set to +@code{EFBIG}, if @var{n} is greater than this limit. + +@subheading Portability + +@port-note ansi The buffer size limit is imposed by DJGPP. Other systems may not have this limitation. + +@portability !ansi, !posix + +@subheading Example + +@example +char *strbuf; /* Pointer to the allocated buffer by vasnprintf. */ +int strlng; + +strlng = vasnprintf(&strbuf, 1000, "arg[0] = %s\n" + "arg[1] = %s\n" + "arg[2] = %s\n", arg_list); + +if (EOF == strlng) + printf("error: vasnprintf failed.\n"); +else +@{ + /* + * Your code using the allocated buffer by vasnprintf. + */ + do_something(strbuf, strlng); + + free(strbuf); /* Release the memory allocated by vasnprintf. */ +@} +@end example diff -aprNU3 djgpp.orig/src/libc/compat/stdio/vasprntf.c djgpp/src/libc/compat/stdio/vasprntf.c --- djgpp.orig/src/libc/compat/stdio/vasprntf.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/vasprntf.c 2008-04-06 23:35:36 +0000 @@ -0,0 +1,39 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ +#include +#include +#include +#include + +int +vasprintf(char **strp, const char *fmt, va_list argsp) +{ + FILE _strbuf; + int len; + + + /* Just query how much space is needed. */ + memset(&_strbuf, 0, sizeof(_strbuf)); + __stropenw(&_strbuf, NULL, 0); + len = _doprnt(fmt, argsp, &_strbuf); + + *strp = NULL; + if (len != EOF) + { + *strp = malloc(len + 1); + if (*strp) + { + __stropenw(&_strbuf, *strp, len); + len = _doprnt(fmt, argsp, &_strbuf); + __strclosew(&_strbuf); + if (len == EOF) + { + free(*strp); + *strp = NULL; + } + } + else + len = EOF; + } + + return len; +} diff -aprNU3 djgpp.orig/src/libc/compat/stdio/vasprntf.txh djgpp/src/libc/compat/stdio/vasprntf.txh --- djgpp.orig/src/libc/compat/stdio/vasprntf.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/compat/stdio/vasprntf.txh 2008-04-06 23:35:36 +0000 @@ -0,0 +1,54 @@ +@node vasprintf, stdio +@findex vasprintf +@subheading Syntax + +@example +#include +#include + +int vasprintf(char **@var{bufferp}, const char *@var{format}, + va_list @var{ap}); +@end example + +@subheading Description + +Sends formatted output from the arguments in (@var{ap}) including +the terminating null byte to the allocated buffer and returns +a pointer to it via the first parameter *@var{bufferp}. This +memory must be returned to the heap with @code{free} (@pxref{free}). +This function is analog of @code{vsprintf()} (@pxref{vsprintf}). + +@subheading Return Value + +The number of characters that would have been written (excluding +the terminating null byte) is returned; otherwise EOF is returned +to flag encoding or buffer space errors and the pointer +*@var{bufferp} is set to @code{NULL}. + + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example +char *strbuf; /* Pointer to the allocated buffer by vasprintf. */ +int strlng; + +strlng = vasprintf(&strbuf, "arg[0] = %s\n" + "arg[1] = %s\n" + "arg[2] = %s\n", arg_list); + +if (EOF == strlng) + printf("error: vasprintf failed.\n"); +else +@{ + /* + * Your code using the allocated buffer by vasprintf. + */ + do_something(strbuf, strlng); + + free(strbuf); /* Release the memory allocated by vasprintf. */ +@} +@end example