[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.