/****************************************************************************** * 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); }