[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v8 5/9] Add an implentation of asprintf() for xen
Also needed to fix vsnprintf() et al so it can be called with a NULL buf (and zero size, of course). Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> Cc: Ian Campbell <ian.campbell@xxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Cc: Jan Beulich <jbeulich@xxxxxxxx> Cc: Keir Fraser <keir@xxxxxxx> Cc: Tim Deegan <tim@xxxxxxx> --- xen/common/vsprintf.c | 115 ++++++++++++++++++++++++++++++++++------------ xen/include/xen/lib.h | 4 ++ xen/include/xen/stdarg.h | 1 + 3 files changed, 91 insertions(+), 29 deletions(-) diff --git a/xen/common/vsprintf.c b/xen/common/vsprintf.c index 8c43282..e68886a 100644 --- a/xen/common/vsprintf.c +++ b/xen/common/vsprintf.c @@ -192,45 +192,45 @@ static char *number( size -= precision; if (!(type&(ZEROPAD+LEFT))) { while(size-->0) { - if (buf <= end) + if (buf < end) *buf = ' '; ++buf; } } if (sign) { - if (buf <= end) + if (buf < end) *buf = sign; ++buf; } if (type & SPECIAL) { - if (buf <= end) + if (buf < end) *buf = '0'; ++buf; if (base == 16) { - if (buf <= end) + if (buf < end) *buf = digits[33]; ++buf; } } if (!(type & LEFT)) { while (size-- > 0) { - if (buf <= end) + if (buf < end) *buf = c; ++buf; } } while (i < precision--) { - if (buf <= end) + if (buf < end) *buf = '0'; ++buf; } while (i-- > 0) { - if (buf <= end) + if (buf < end) *buf = tmp[i]; ++buf; } while (size-- > 0) { - if (buf <= end) + if (buf < end) *buf = ' '; ++buf; } @@ -244,18 +244,18 @@ static char *string(char *str, char *end, const char *s, if (!(flags & LEFT)) { while (len < field_width--) { - if (str <= end) + if (str < end) *str = ' '; ++str; } } for (i = 0; i < len; ++i) { - if (str <= end) + if (str < end) *str = *s; ++str; ++s; } while (len < field_width--) { - if (str <= end) + if (str < end) *str = ' '; ++str; } @@ -294,7 +294,7 @@ static char *pointer(char *str, char *end, const char **fmt_ptr, { /* Print '+<offset>/<len>' */ str = number(str, end, sym_offset, 16, -1, -1, SPECIAL|SIGN|PLUS); - if ( str <= end ) + if ( str < end ) *str = '/'; ++str; str = number(str, end, sym_size, 16, -1, -1, SPECIAL); @@ -308,10 +308,10 @@ static char *pointer(char *str, char *end, const char **fmt_ptr, const struct vcpu *v = arg; ++*fmt_ptr; - if ( str <= end ) + if ( str < end ) *str = 'd'; str = number(str + 1, end, v->domain->domain_id, 10, -1, -1, 0); - if ( str <= end ) + if ( str < end ) *str = 'v'; return number(str + 1, end, v->vcpu_id, 10, -1, -1, 0); } @@ -365,16 +365,16 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) BUG_ON(((int)size < 0) || ((unsigned int)size != size)); str = buf; - end = buf + size - 1; + end = buf + size; - if (end < buf - 1) { + if (end < buf) { end = ((void *) -1); - size = end - buf + 1; + size = end - buf; } for (; *fmt ; ++fmt) { if (*fmt != '%') { - if (str <= end) + if (str < end) *str = *fmt; ++str; continue; @@ -440,17 +440,17 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) case 'c': if (!(flags & LEFT)) { while (--field_width > 0) { - if (str <= end) + if (str < end) *str = ' '; ++str; } } c = (unsigned char) va_arg(args, int); - if (str <= end) + if (str < end) *str = c; ++str; while (--field_width > 0) { - if (str <= end) + if (str < end) *str = ' '; ++str; } @@ -485,7 +485,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) continue; case '%': - if (str <= end) + if (str < end) *str = '%'; ++str; continue; @@ -508,11 +508,11 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) break; default: - if (str <= end) + if (str < end) *str = '%'; ++str; if (*fmt) { - if (str <= end) + if (str < end) *str = *fmt; ++str; } else { @@ -541,11 +541,14 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) str = number(str, end, num, base, field_width, precision, flags); } - if (str <= end) - *str = '\0'; - else if (size > 0) - /* don't write out a null byte if the buf size is zero */ - *end = '\0'; + + /* don't write out a null byte if the buf size is zero */ + if (size > 0) { + if (str < end) + *str = '\0'; + else + end[-1] = '\0'; + } /* the trailing null byte doesn't count towards the total * ++str; */ @@ -631,6 +634,60 @@ int scnprintf(char * buf, size_t size, const char *fmt, ...) } EXPORT_SYMBOL(scnprintf); +/** + * vasprintf - Format a string and allocate a buffer to place it in + * + * @bufp: Pointer to a pointer to receive the allocated buffer + * @fmt: The format string to use + * @args: Arguments for the format string + * + * -ENOMEM is returned on failure and @bufp is not touched. + * On success, 0 is returned. The buffer passed back is + * guaranteed to be null terminated. The memory is allocated + * from xenheap, so the buffer should be freed with xfree(). + */ +int vasprintf(char **bufp, const char *fmt, va_list args) +{ + va_list args_copy; + size_t size; + char *buf; + + va_copy(args_copy, args); + size = vsnprintf(NULL, 0, fmt, args_copy); + va_end(args_copy); + + buf = xmalloc_array(char, ++size); + if ( !buf ) + return -ENOMEM; + + (void) vsnprintf(buf, size, fmt, args); + + *bufp = buf; + return 0; +} + +/** + * asprintf - Format a string and place it in a buffer + * @bufp: Pointer to a pointer to receive the allocated buffer + * @fmt: The format string to use + * @...: Arguments for the format string + * + * -ENOMEM is returned on failure and @bufp is not touched. + * On success, 0 is returned. The buffer passed back is + * guaranteed to be null terminated. The memory is allocated + * from xenheap, so the buffer should be freed with xfree(). + */ +int asprintf(char **bufp, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vasprintf(bufp,fmt,args); + va_end(args); + return i; +} + /* * Local variables: * mode: C diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h index 1369b2b..e81b80e 100644 --- a/xen/include/xen/lib.h +++ b/xen/include/xen/lib.h @@ -104,6 +104,10 @@ extern int scnprintf(char * buf, size_t size, const char * fmt, ...) __attribute__ ((format (printf, 3, 4))); extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) __attribute__ ((format (printf, 3, 0))); +extern int asprintf(char ** bufp, const char * fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int vasprintf(char ** bufp, const char * fmt, va_list args) + __attribute__ ((format (printf, 2, 0))); long simple_strtol( const char *cp,const char **endp, unsigned int base); diff --git a/xen/include/xen/stdarg.h b/xen/include/xen/stdarg.h index 216fe6d..29249a1 100644 --- a/xen/include/xen/stdarg.h +++ b/xen/include/xen/stdarg.h @@ -2,6 +2,7 @@ #define __XEN_STDARG_H__ typedef __builtin_va_list va_list; +#define va_copy(dest, src) __builtin_va_copy((dest), (src)) #define va_start(ap, last) __builtin_va_start((ap), (last)) #define va_end(ap) __builtin_va_end(ap) #define va_arg __builtin_va_arg -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |