blob: e78fb3d8e384bf0ffd5630c49e7b3faa084eb089 [file] [log] [blame]
/******************************************************************************
* 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 "stdio.h"
#include "stdlib.h"
#include "string.h"
const static 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)
{
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;
}
if(value < base) {
if(sign) {
**buffer = '-';
*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 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_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen)
{
int i, sizei, len;
sizei = strtoul(sizec, NULL, 10);
len = print_intlen(size, base) + optlen;
if(sizei > len) {
for(i = 0; i < (sizei - len); i++) {
**buffer = c;
*buffer += 1;
}
}
return 0;
}
static int
print_format(char **buffer, const char *format, void *var)
{
unsigned long start;
unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int);
unsigned long value = 0;
unsigned long signBit;
char *form, sizec[32];
char sign = ' ';
form = (char *) format;
start = (unsigned long) *buffer;
form++;
if(*form == '0' || *form == '.') {
sign = '0';
form++;
}
while(*form != '\0') {
switch(*form) {
case 'u':
case 'd':
case 'i':
sizec[i] = '\0';
value = (unsigned long) var;
signBit = 0x1ULL << (length_mod * 8 - 1);
if (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);
break;
case 'X':
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);
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);
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);
break;
case 'c':
sizec[i] = '\0';
print_fill(buffer, 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;
}
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;
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;
while(*ptr != '\0' && (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, formstr, va_arg(arg, void *));
}
ptr++;
} else {
*buffer = *ptr;
buffer++;
ptr++;
}
}
*buffer = '\0';
return (buffer - bstart);
}