asprintf: add "axprintf" functions that allocate extra storage

Add a set of variants on the asprintf functions, "axprintf", which
allocate extra storage for metadata at the head of the allocated
buffer.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2018-12-13 22:07:31 -08:00
parent e3b4332643
commit db72dc0684
2 changed files with 42 additions and 18 deletions

View file

@ -65,12 +65,18 @@ char * safe_alloc nasm_strcat(const char *one, const char *two);
char * safe_alloc end_with_null nasm_strcatn(const char *one, ...);
/*
* Variants on asprintf(). Note that unlike the standard version, we
* return the pointer rather than the length; if you want the length
* use %n.
* nasm_[v]asprintf() are variants of the semi-standard [v]asprintf()
* functions, except that we return the pointer instead of a count.
* Use %n if you need the count, too.
*
* nasm_[v]axprintf() are similar, but allocates a user-defined amount
* of storage before the string, and returns a pointer to the
* allocated buffer.
*/
char * safe_alloc nasm_asprintf(const char *fmt, ...);
char * safe_alloc printf_func(1, 2) nasm_asprintf(const char *fmt, ...);
char * safe_alloc nasm_vasprintf(const char *fmt, va_list ap);
void * safe_alloc printf_func(2, 3) nasm_axprintf(size_t extra, const char *fmt, ...);
void * safe_alloc nasm_vaxprintf(size_t extra, const char *fmt, va_list ap);
/* Assert the argument is a pointer without evaluating it */
#define nasm_assert_pointer(p) ((void)sizeof(*(p)))

View file

@ -35,26 +35,44 @@
#include "nasmlib.h"
#include "alloc.h"
char *nasm_vasprintf(const char *fmt, va_list ap)
/*
* nasm_[v]asprintf() are variants of the semi-standard [v]asprintf()
* functions, except that we return the pointer instead of a count.
* Use %n if you need the count, too.
*
* nasm_[v]axprintf() are similar, but allocates a user-defined amount
* of storage before the string, and returns a pointer to the
* allocated buffer.
*/
void *nasm_vaxprintf(size_t extra, const char *fmt, va_list ap)
{
#ifdef HAVE_VASPRINTF
char *strp;
int rv = vasprintf(&strp, fmt, ap);
if (rv < 0)
nasm_alloc_failed();
return strp;
#else
char *strp;
va_list xap;
int len;
size_t bytes;
va_copy(xap, ap);
len = vsnprintf(NULL, 0, fmt, xap);
bytes = vsnprintf(NULL, 0, fmt, xap) + 1;
va_end(xap);
strp = nasm_malloc(len+1);
vsnprintf(strp, len, fmt, ap);
strp = nasm_malloc(extra+bytes);
vsnprintf(strp+extra, bytes, fmt, ap);
return strp;
}
char *nasm_vasprintf(const char *fmt, va_list ap)
{
return nasm_vaxprintf(0, fmt, ap);
}
void *nasm_axprintf(size_t extra, const char *fmt, ...)
{
va_list ap;
void *strp;
va_start(ap, fmt);
strp = nasm_vaxprintf(extra, fmt, ap);
va_end(ap);
return strp;
#endif
}
char *nasm_asprintf(const char *fmt, ...)
@ -63,7 +81,7 @@ char *nasm_asprintf(const char *fmt, ...)
char *strp;
va_start(ap, fmt);
strp = nasm_vasprintf(fmt, ap);
strp = nasm_vaxprintf(0, fmt, ap);
va_end(ap);
return strp;