diff options
Diffstat (limited to 'roms/SLOF/lib/libc/stdio/vsnprintf.c')
-rw-r--r-- | roms/SLOF/lib/libc/stdio/vsnprintf.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/roms/SLOF/lib/libc/stdio/vsnprintf.c b/roms/SLOF/lib/libc/stdio/vsnprintf.c new file mode 100644 index 000000000..12f304398 --- /dev/null +++ b/roms/SLOF/lib/libc/stdio/vsnprintf.c @@ -0,0 +1,299 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include <stdbool.h> +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "ctype.h" + +static const unsigned long long convert[] = { + 0x0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF, + 0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL +}; + +static int +print_str_fill(char **buffer, size_t bufsize, char *sizec, + const char *str, char c) +{ + unsigned i, sizei, len; + char *bstart = *buffer; + + sizei = strtoul(sizec, NULL, 10); + len = strlen(str); + if (sizei > len) { + for (i = 0; + (i < (sizei - len)) && ((size_t)(*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *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)) && ((size_t)(*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) { + value /= base; + i++; + } + 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, 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)) && ((size_t)(*buffer - bstart) < bufsize); + i++) { + **buffer = c; + *buffer += 1; + } + } + + return 0; +} + + +static int +print_format(char **buffer, size_t bufsize, const char *format, void *var) +{ + 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 = *buffer; + + form++; + if(*form == '0' || *form == '.') { + sign = '0'; + form++; + } + + while ((*form != '\0') && ((size_t)(*buffer - start) < bufsize)) { + switch(*form) { + case 'u': + case 'd': + case 'i': + sizec[i] = '\0'; + value = (unsigned long) var; + signBit = 0x1ULL << (length_mod * 8 - 1); + if ((*form != 'u') && (signBit & value)) { + **buffer = '-'; + *buffer += 1; + value = (-(unsigned long)value) & convert[length_mod]; + } + 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; + /* fallthrough */ + case 'x': + sizec[i] = '\0'; + value = (unsigned long) var & convert[length_mod]; + 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, 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, 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, bufsize - (*buffer - start), + sizec, 1, 10, ' ', 0); + **buffer = (unsigned long) var; + *buffer += 1; + break; + case 's': + sizec[i] = '\0'; + print_str_fill(buffer, + bufsize - (*buffer - start), sizec, + (char *) var, ' '); + + print_str(buffer, bufsize - (*buffer - start), + (char *) var); + break; + case 'l': + form++; + if(*form == 'l') { + length_mod = sizeof(long long int); + } else { + form--; + length_mod = sizeof(long int); + } + break; + case 'h': + form++; + if(*form == 'h') { + length_mod = sizeof(signed char); + } else { + form--; + length_mod = sizeof(short int); + } + break; + case 'z': + length_mod = sizeof(size_t); + break; + default: + if(*form >= '0' && *form <= '9') + sizec[i++] = *form; + } + form++; + } + + + return (long int) (*buffer - start); +} + + +/* + * The vsnprintf function prints a formated strings into a buffer. + * BUG: buffer size checking does not fully work yet + */ +int +vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg) +{ + char *ptr, *bstart; + + 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' && (size_t)(buffer - bstart) < bufsize) + { + if(*ptr == '%') { + char formstr[20]; + int i=0; + + do { + formstr[i] = *ptr; + ptr++; + i++; + } while(!(*ptr == 'd' || *ptr == 'i' || *ptr == 'u' || *ptr == 'x' || *ptr == 'X' + || *ptr == 'p' || *ptr == 'c' || *ptr == 's' || *ptr == '%' + || *ptr == 'O' || *ptr == 'o' )); + formstr[i++] = *ptr; + formstr[i] = '\0'; + if(*ptr == '%') { + *buffer++ = '%'; + } else { + print_format(&buffer, + bufsize - (buffer - bstart), + formstr, va_arg(arg, void *)); + } + ptr++; + } else { + + *buffer = *ptr; + + buffer++; + ptr++; + } + } + + *buffer = '\0'; + + return (buffer - bstart); +} |