These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / SLOF / lib / libc / stdio / vsnprintf.c
index e78fb3d..21dd04d 100644 (file)
  *     IBM Corporation - initial implementation
  *****************************************************************************/
 
+#include <stdbool.h>
 #include "stdio.h"
 #include "stdlib.h"
 #include "string.h"
+#include "ctype.h"
 
-const static unsigned long long convert[] = {
+static const unsigned long long convert[] = {
        0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
 };
 
-
-
 static int
-print_itoa(char **buffer,unsigned long value, unsigned short int base)
+print_str_fill(char **buffer, size_t bufsize, char *sizec,
+                                       const char *str, char c)
 {
-       const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-       static char sign = 0;
-
-       if(base <= 2 || base > 16)
-               return 0;
-
-       if(value < 0) {
-               sign = 1;
-               value *= -1;
-       }
+       int i, sizei, len;
+       char *bstart = *buffer;
 
-       if(value < base) {
-               if(sign) {
-                       **buffer = '-';
+       sizei = strtoul(sizec, NULL, 10);
+       len = strlen(str);
+       if (sizei > len) {
+               for (i = 0;
+                       (i < (sizei - len)) && ((*buffer - bstart) < bufsize);
+                                                                       i++) {
+                       **buffer = c;
                        *buffer += 1;
-                       sign = 0;
                }
-               **buffer = zeichen[value];
-               *buffer += 1;
-       } else {
-               print_itoa(buffer, value / base, base);
-               **buffer = zeichen[(value % base)];
-               *buffer += 1;
        }
-
        return 1;
 }
 
+static int
+print_str(char **buffer, size_t bufsize, const char *str)
+{
+       char *bstart = *buffer;
+       size_t i;
+
+       for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) {
+               **buffer = str[i];
+               *buffer += 1;
+       }
+       return 1;
+}
 
 static unsigned int
 print_intlen(unsigned long value, unsigned short int base)
 {
        int i = 0;
 
-       while(value > 0) {
+       while (value > 0) {
                value /= base;
                i++;
        }
-       if(i == 0) i = 1;
+       if (i == 0)
+               i = 1;
        return i;
 }
 
+static int
+print_itoa(char **buffer, size_t bufsize, unsigned long value,
+                                       unsigned short base, bool upper)
+{
+       const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+       char c;
+       size_t i, len;
+
+       if(base <= 2 || base > 16)
+               return 0;
+
+       len = i = print_intlen(value, base);
+
+       /* Don't print to buffer if bufsize is not enough. */
+       if (len > bufsize)
+               return 0;
+
+       do {
+               c = zeichen[value % base];
+               if (upper)
+                       c = toupper(c);
+
+               (*buffer)[--i] = c;
+               value /= base;
+       } while(value);
+
+       *buffer += len;
+
+       return 1;
+}
+
+
 
 static int
-print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen)
+print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size,
+                               unsigned short int base, char c, int optlen)
 {
        int i, sizei, len;
+       char *bstart = *buffer;
 
        sizei = strtoul(sizec, NULL, 10);
        len = print_intlen(size, base) + optlen;
-       if(sizei > len) {
-               for(i = 0; i < (sizei - len); i++) {
+       if (sizei > len) {
+               for (i = 0;
+                       (i < (sizei - len)) && ((*buffer - bstart) < bufsize);
+                                                                       i++) {
                        **buffer = c;
                        *buffer += 1;
                }
@@ -86,17 +124,18 @@ print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int ba
 
 
 static int
-print_format(char **buffer, const char *format, void *var)
+print_format(char **buffer, size_t bufsize, const char *format, void *var)
 {
-       unsigned long start;
-       unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int);
+       char *start;
+       unsigned int i = 0, length_mod = sizeof(int);
        unsigned long value = 0;
        unsigned long signBit;
        char *form, sizec[32];
        char sign = ' ';
+       bool upper = false;
 
        form  = (char *) format;
-       start = (unsigned long) *buffer;
+       start = *buffer;
 
        form++;
        if(*form == '0' || *form == '.') {
@@ -104,7 +143,7 @@ print_format(char **buffer, const char *format, void *var)
                form++;
        }
 
-       while(*form != '\0') {
+       while ((*form != '\0') && ((*buffer - start) < bufsize)) {
                switch(*form) {
                        case 'u':
                        case 'd':
@@ -112,57 +151,59 @@ print_format(char **buffer, const char *format, void *var)
                                sizec[i] = '\0';
                                value = (unsigned long) var;
                                signBit = 0x1ULL << (length_mod * 8 - 1);
-                               if (signBit & value) {
+                               if ((*form != 'u') && (signBit & value)) {
                                        **buffer = '-';
                                        *buffer += 1;
                                        value = (-(unsigned long)value) & convert[length_mod];
                                }
-                               print_fill(buffer, sizec, value, 10, sign, 0);
-                               print_itoa(buffer, value, 10);
+                               print_fill(buffer, bufsize - (*buffer - start),
+                                               sizec, value, 10, sign, 0);
+                               print_itoa(buffer, bufsize - (*buffer - start),
+                                                       value, 10, upper);
                                break;
                        case 'X':
+                               upper = true;
                        case 'x':
                                sizec[i] = '\0';
                                value = (unsigned long) var & convert[length_mod];
-                               print_fill(buffer, sizec, value, 16, sign, 0);
-                               print_itoa(buffer, value, 16);
+                               print_fill(buffer, bufsize - (*buffer - start),
+                                               sizec, value, 16, sign, 0);
+                               print_itoa(buffer, bufsize - (*buffer - start),
+                                                       value, 16, upper);
                                break;
                        case 'O':
                        case 'o':
                                sizec[i] = '\0';
                                value = (long int) var & convert[length_mod];
-                               print_fill(buffer, sizec, value, 8, sign, 0);
-                               print_itoa(buffer, value, 8);
+                               print_fill(buffer, bufsize - (*buffer - start),
+                                               sizec, value, 8, sign, 0);
+                               print_itoa(buffer, bufsize - (*buffer - start),
+                                                       value, 8, upper);
                                break;
                        case 'p':
                                sizec[i] = '\0';
-                               print_fill(buffer, sizec, (unsigned long) var, 16, ' ', 2);
-                               **buffer = '0';
-                               *buffer += 1;   
-                               **buffer = 'x';
-                               *buffer += 1;
-                               print_itoa(buffer,(unsigned long) var, 16);
+                               print_fill(buffer, bufsize - (*buffer - start),
+                                       sizec, (unsigned long) var, 16, ' ', 2);
+                               print_str(buffer, bufsize - (*buffer - start),
+                                                                       "0x");
+                               print_itoa(buffer, bufsize - (*buffer - start),
+                                               (unsigned long) var, 16, upper);
                                break;
                        case 'c':
                                sizec[i] = '\0';
-                               print_fill(buffer, sizec, 1, 10, ' ', 0);
+                               print_fill(buffer, bufsize - (*buffer - start),
+                                                       sizec, 1, 10, ' ', 0);
                                **buffer = (unsigned long) var;
                                *buffer += 1;
                                break;
                        case 's':
                                sizec[i] = '\0';
-                               sizei = strtoul(sizec, NULL, 10);
-                               len = strlen((char *) var);
-                               if(sizei > len) {
-                                       for(i = 0; i < (sizei - len); i++) {
-                                               **buffer = ' ';
-                                               *buffer += 1;
-                                       }
-                               }
-                               for(i = 0; i < strlen((char *) var); i++) {
-                                       **buffer = ((char *) var)[i];
-                                       *buffer += 1;
-                               }
+                               print_str_fill(buffer,
+                                       bufsize - (*buffer - start), sizec,
+                                                       (char *) var, ' ');
+
+                               print_str(buffer, bufsize - (*buffer - start),
+                                                               (char *) var);
                                break;
                        case 'l':
                                form++;
@@ -182,6 +223,9 @@ print_format(char **buffer, const char *format, void *var)
                                        length_mod = sizeof(short int);
                                }
                                break;
+                       case 'z':
+                               length_mod = sizeof(size_t);
+                               break;
                        default:
                                if(*form >= '0' && *form <= '9')
                                        sizec[i++] = *form;
@@ -206,6 +250,16 @@ vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
        bstart = buffer;
        ptr = (char *) format;
 
+       /*
+        * Return from here if size passed is zero, otherwise we would
+        * overrun buffer while setting NULL character at the end.
+        */
+       if (!buffer || !bufsize)
+               return 0;
+
+       /* Leave one space for NULL character */
+       bufsize--;
+
        while(*ptr != '\0' && (buffer - bstart) < bufsize)
        {
                if(*ptr == '%') {
@@ -224,7 +278,9 @@ vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
                        if(*ptr == '%') {
                                *buffer++ = '%';
                        } else {
-                               print_format(&buffer, formstr, va_arg(arg, void *));
+                               print_format(&buffer,
+                                       bufsize - (buffer - bstart),
+                                       formstr, va_arg(arg, void *));
                        }
                        ptr++;
                } else {