diff options
-rw-r--r-- | src/include/ctype.h | 67 | ||||
-rw-r--r-- | src/include/kernel/console.H | 49 | ||||
-rw-r--r-- | src/include/stdio.h | 4 | ||||
-rw-r--r-- | src/include/util/functor.H | 122 | ||||
-rw-r--r-- | src/include/util/sprintf.H | 326 | ||||
-rw-r--r-- | src/kernel/console.C | 49 | ||||
-rw-r--r-- | src/lib/ctype.C | 46 | ||||
-rw-r--r-- | src/lib/makefile | 2 | ||||
-rw-r--r-- | src/lib/sprintf.C | 538 | ||||
-rw-r--r-- | src/lib/stdio.C | 48 | ||||
-rw-r--r-- | src/makefile | 2 |
11 files changed, 748 insertions, 505 deletions
diff --git a/src/include/ctype.h b/src/include/ctype.h index 6970da734..641745bd2 100644 --- a/src/include/ctype.h +++ b/src/include/ctype.h @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -38,6 +38,71 @@ extern "C" */ int toupper(int) __attribute__((const)); +/** + * @brief Determine if character is a digit (0-9). + * + * @param[in] Input character. + * @return int - 0 if not a digit, non-zero if is a digit. + */ +int isdigit(int) __attribute__((const)); + +/** + * @brief Determine if character is a lower-case character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int islower(int) __attribute__((const)); + +/** + * @brief Determine if character is a upper-case character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int islower(int) __attribute__((const)); + +/** + * @brief Determine if character is a alphabetic character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int isalpha(int) __attribute__((const)); + +/** + * @brief Determine if character is a alpha-numeric character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int isalnum(int) __attribute__((const)); + +/** + * @brief Determine if character is a punctuation character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int ispunct(int) __attribute__((const)); + +/** + * @brief Determine if character is a space character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int isspace(int) __attribute__((const)); + +/** + * @brief Determine if character is a printable character. + * + * @param[in] Input character. + * @return int - 0 if not, non-zero if so. + */ +int isprint(int) __attribute__((const)); + + #ifdef __cplusplus }; #endif diff --git a/src/include/kernel/console.H b/src/include/kernel/console.H index 850fac46c..74ab75408 100644 --- a/src/include/kernel/console.H +++ b/src/include/kernel/console.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/kernel/console.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/kernel/console.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2010,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __KERNEL_CONSOLE_H #define __KERNEL_CONSOLE_H @@ -27,6 +27,8 @@ #include <string.h> #include <builtins.h> +#include <util/sprintf.H> + #ifdef HOSTBOOT_DEBUG #define printkd(format...) printk(format) #else @@ -35,10 +37,11 @@ void printk(const char*, ...) FORMAT_PRINTF; -class Console +class Console : public Util::ConsoleBufferInterface { public: int putc(int); + size_t operator()(int c) { return putc(c); }; enum { BUFFER_SIZE = 1024 * 16 }; diff --git a/src/include/stdio.h b/src/include/stdio.h index 0e066af3b..c6d42b145 100644 --- a/src/include/stdio.h +++ b/src/include/stdio.h @@ -24,6 +24,7 @@ #define __STDIO_H #include <stdarg.h> +#include <stdint.h> #ifdef __cplusplus extern "C" @@ -31,8 +32,9 @@ extern "C" #endif int sprintf(char *str, const char * format, ...); +int snprintf(char *str, size_t size, const char * format, ...); int vsprintf(char *str, const char * format, va_list); - +int vsnprintf(char *str, size_t size, const char * format, va_list); #ifdef __cplusplus } diff --git a/src/include/util/functor.H b/src/include/util/functor.H deleted file mode 100644 index b5bf1f9de..000000000 --- a/src/include/util/functor.H +++ /dev/null @@ -1,122 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/functor.H $ */ -/* */ -/* IBM CONFIDENTIAL */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2011,2013 */ -/* */ -/* p1 */ -/* */ -/* Object Code Only (OCO) source materials */ -/* Licensed Internal Code Source Materials */ -/* IBM HostBoot Licensed Internal Code */ -/* */ -/* The source code for this program is not published or otherwise */ -/* divested of its trade secrets, irrespective of what has been */ -/* deposited with the U.S. Copyright Office. */ -/* */ -/* Origin: 30 */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef __UTIL_FUNCTOR_H -#define __UTIL_FUNCTOR_H - -#include <builtins.h> - -namespace Util -{ - template <typename _ARG, typename _RESULT> - class unary_functor - { - public: - typedef _ARG argument_type; - typedef _RESULT result_type; - - public: - virtual ~unary_functor() {}; - virtual result_type operator()(argument_type) = 0; - }; - - template <typename _ARG1, typename _ARG2, typename _RESULT> - class binary_functor - { - public: - typedef _ARG1 first_argument_type; - typedef _ARG2 second_argument_type; - typedef _RESULT result_type; - - public: - virtual ~binary_functor() {}; - virtual result_type operator() - (first_argument_type, second_argument_type) = 0; - }; - - // Function pointer wrappers for functors. - - template <typename _ARG, typename _RESULT> - class ptr_to_unary_function : public unary_functor<_ARG, _RESULT> - { - public: - typedef _RESULT(*function_type)(_ARG); - - private: - function_type function; - - public: - ptr_to_unary_function(function_type f) : function(f) {}; - - - _RESULT operator()(_ARG t) - { - return function(t); - } - }; - - template <typename _ARG, typename _RESULT> - ALWAYS_INLINE inline - ptr_to_unary_function<_ARG, _RESULT> ptr_fun(_RESULT (*f)(_ARG)) - { - return ptr_to_unary_function<_ARG,_RESULT>(f); - } - -#define PTR_FUN1_T(ARG_T, RESULT_T) \ - ptr_to_unary_function<_ARG, _RESULT> - - - template <typename _ARG, typename _RESULT, typename _CLASS> - class mem_ptr_to_unary_function : public unary_functor<_ARG, _RESULT> - { - public: - typedef _CLASS member_type; - typedef _RESULT(member_type::*function_type)(_ARG); - - private: - member_type& object; - function_type function; - - public: - mem_ptr_to_unary_function(member_type& o, function_type f) - : object(o), function(f) {}; - - _RESULT operator()(_ARG t) - { - return (object.*function)(t); - } - }; - - template <typename _ARG, typename _RESULT, typename _CLASS> - ALWAYS_INLINE inline - mem_ptr_to_unary_function<_ARG, _RESULT, _CLASS> - mem_ptr_fun(_CLASS& o, _RESULT (_CLASS::*f)(_ARG)) - { - return mem_ptr_to_unary_function<_ARG,_RESULT,_CLASS>(o, f); - } - -#define MEM_PTR_FUN1_T(CLASS_T, ARG_T, RESULT_T) \ - mem_ptr_to_unary_function<ARG_T, RESULT_T, CLASS_T> - -}; - -#endif diff --git a/src/include/util/sprintf.H b/src/include/util/sprintf.H index 1385e9b17..f03ea6228 100644 --- a/src/include/util/sprintf.H +++ b/src/include/util/sprintf.H @@ -25,332 +25,18 @@ #include <stdarg.h> #include <stdint.h> -#include <builtins.h> - -class Console; namespace Util { - - class ConsoleTraits + class ConsoleBufferInterface { - public: - enum trait { NONE, HEX, DEC, }; + public: + virtual ~ConsoleBufferInterface() {}; + virtual size_t operator() (int) = 0; }; - template <typename _T, ConsoleTraits::trait _S = ConsoleTraits::NONE> - class ConsoleDisplay - { - public: - template <typename _F> - ALWAYS_INLINE - static size_t display(_F& c, _T value) { return 0; }; - }; - - template <ConsoleTraits::trait _S> - class ConsoleDisplay<char*, _S> - { - public: - template <typename _F> - ALWAYS_INLINE - static size_t display(_F& c, char* value) - { - size_t count = 0; - while(*value != '\0') - { - c(*value); - value++; - count++; - } - return count; - } - }; - - template <> - class ConsoleDisplay<char, ConsoleTraits::NONE> - { - public: - template <typename _F> - ALWAYS_INLINE - static size_t display(_F& c, char value) - { - c(value); - return 1; - } - }; - - template <typename _T> - class ConsoleDisplay<_T, ConsoleTraits::DEC> - { - public: - template <typename _F> - ALWAYS_INLINE - static size_t display(_F& c, _T value) - { - size_t count = 0; - if (value == 0) - { - c('0'); count++; - } - else if (value < 0) - { - c('-'); count++; - value *= -1; - count += subdisplay(c, value); - } - else - count += subdisplay(c, value); - return count; - } - - template <typename _F> - static size_t subdisplay(_F& c, _T value) - { - size_t count = 0; - if (value != 0) - { - count += subdisplay(c, value / 10); - c('0' + (value % 10)); - count++; - } - return count; - } - }; - - template<typename _T> - class ConsoleDisplay<_T, ConsoleTraits::HEX> - { - public: - template <typename _F> - ALWAYS_INLINE - static size_t display(_F& c, _T value) - { - size_t count = 0; - if (value == 0) - { - c('0'); count++; - } - else - { - count += subdisplay(c, value); - } - return count; - } - - template <typename _F> - static size_t subdisplay(_F& c, _T value) - { - size_t count = 0; - if (value != 0) - { - count += subdisplay(c, value / 16); - char nibble = value % 16; - if (nibble >= 0x0a) - c('A' + (nibble - 0x0a)); - else - c('0' + nibble); - count++; - } - return count; - } - }; - - template<typename _F> - size_t vasprintf(_F output_func, const char* fmt_str, va_list& args) - { - size_t count = 0; - - bool format = false; - int size = 0; - - while('\0' != *fmt_str) - { - if (('%' == *fmt_str) || (format)) - switch (*fmt_str) - { - case '%': - { - if (format) - { - count += - ConsoleDisplay<char>::display(output_func, - '%'); - format = false; - } - else - { - format = true; - size = 2; - } - break; - } - case 'c': - { - format = false; - count += ConsoleDisplay<char> - ::display(output_func, (char)va_arg(args,int)); - break; - } - case 'h': - { - size--; - break; - } - case 'l': - { - size++; - break; - } - case 'z': // size_t or ssize_t - { - size = 4; - break; - } - case 'd': // decimal - { - format = false; - switch(size) - { - case 0: - count += ConsoleDisplay<char, - ConsoleTraits::DEC> - ::display(output_func, - (char)va_arg(args,int)); - break; - - case 1: - count += ConsoleDisplay<short, - ConsoleTraits::DEC> - ::display(output_func, - (short)va_arg(args,int)); - break; - - case 2: - count += ConsoleDisplay<int, - ConsoleTraits::DEC> - ::display(output_func, - va_arg(args,int)); - break; - - case 3: - case 4: - count += ConsoleDisplay<long, - ConsoleTraits::DEC> - ::display(output_func, - va_arg(args,long)); - break; - } - break; - } - case 'u': // unsigned decimal - { - format = false; - switch(size) - { - case 0: - count += ConsoleDisplay<unsigned char, - ConsoleTraits::DEC> - ::display(output_func, - (unsigned char) - va_arg(args,unsigned int)); - break; - - case 1: - count += ConsoleDisplay<unsigned short, - ConsoleTraits::DEC> - ::display(output_func, - (unsigned short) - va_arg(args,unsigned int)); - break; - - case 2: - count += ConsoleDisplay<unsigned int, - ConsoleTraits::DEC> - ::display(output_func, - va_arg(args,unsigned int)); - break; - - case 3: - case 4: - count += ConsoleDisplay<unsigned long, - ConsoleTraits::DEC> - ::display(output_func, - va_arg(args,unsigned long)); - break; - } - break; - } - case 'x': // unsigned hex - case 'X': - { - format = false; - switch(size) - { - case 0: - count += ConsoleDisplay<unsigned char, - ConsoleTraits::HEX> - ::display(output_func, - (unsigned char) - va_arg(args,unsigned int)); - break; - - case 1: - count += ConsoleDisplay<unsigned short, - ConsoleTraits::HEX> - ::display(output_func, - (unsigned short) - va_arg(args,unsigned int)); - break; - - case 2: - count += ConsoleDisplay<unsigned int, - ConsoleTraits::HEX> - ::display(output_func, - va_arg(args,unsigned int)); - break; - - case 3: - case 4: - count += ConsoleDisplay<unsigned long, - ConsoleTraits::HEX> - ::display(output_func, - va_arg(args,unsigned long)); - break; - } - break; - } - case 's': // string - { - format = false; - count += ConsoleDisplay<char*> - ::display(output_func, - (char*) va_arg(args,void*)); - break; - } - case 'p': // pointer - { - format = false; - count += ConsoleDisplay<char> - ::display(output_func, - '0'); - count += ConsoleDisplay<char> - ::display(output_func, - 'x'); - count += ConsoleDisplay<unsigned long, - ConsoleTraits::HEX> - ::display(output_func, - va_arg(args,unsigned long)); - break; - } - } - else - count += ConsoleDisplay<char>::display(output_func, *fmt_str); - - fmt_str++; - } - - return count; - } + size_t vasprintf(ConsoleBufferInterface& output_func, + const char* fmt_str, va_list& args); }; diff --git a/src/kernel/console.C b/src/kernel/console.C index 892295ac5..eaab1de28 100644 --- a/src/kernel/console.C +++ b/src/kernel/console.C @@ -1,29 +1,28 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/kernel/console.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/kernel/console.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2010,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #include <util/singleton.H> #include <kernel/console.H> #include <util/sprintf.H> -#include <util/functor.H> #include <stdarg.h> char kernel_printk_buffer[Console::BUFFER_SIZE]; @@ -48,15 +47,13 @@ int Console::putc(int c) void printk(const char* str, ...) { - using Util::mem_ptr_fun; using Util::vasprintf; va_list args; va_start(args, str); Console& console = Singleton<Console>::instance(); - vasprintf(mem_ptr_fun(console, &Console::putc), - str, args); + vasprintf(console, str, args); va_end(args); } diff --git a/src/lib/ctype.C b/src/lib/ctype.C index 8ae144a5d..e937102bf 100644 --- a/src/lib/ctype.C +++ b/src/lib/ctype.C @@ -31,3 +31,49 @@ int toupper(int ch) return ch; } +int isdigit(int c) +{ + return ((c >= '0') && (c <= '9')); +} + +int islower(int c) +{ + return ((c >= 'a') && (c <= 'z')); +} + +int isupper(int c) +{ + return ((c >= 'A') && (c <= 'Z')); +} + +int isalpha(int c) +{ + return islower(c) || isupper(c); +} + +int isalnum(int c) +{ + return isdigit(c) || isalpha(c); +} + +int ispunct(int c) +{ + // Look at an ASCII table... + return ((c >= '!') && (c <= '/')) || + ((c >= ':') && (c <= '@')) || + ((c >= '[') && (c <= '`')) || + ((c >= '{') && (c <= '~')); +} + +int isspace(int c) +{ + // There are other space characters, like tabs, but I don't think we + // need to support them. + return (c == ' '); +} + +int isprint(int c) +{ + return isalnum(c) || ispunct(c) || isspace(c); +} + diff --git a/src/lib/makefile b/src/lib/makefile index b8cf9a6b3..e8b648c6c 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -22,7 +22,7 @@ # IBM_PROLOG_END_TAG ROOTPATH = ../.. -OBJS = string.o string_ext.o stdlib.o ctype.o assert.o stdio.o math.o +OBJS = string.o string_ext.o stdlib.o ctype.o assert.o stdio.o math.o sprintf.o OBJS += syscall_stub.o syscall_task.o syscall_msg.o OBJS += syscall_mmio.o syscall_time.o sync.o syscall_misc.o OBJS += syscall_mm.o splaytree.o cxxtest_data.o diff --git a/src/lib/sprintf.C b/src/lib/sprintf.C new file mode 100644 index 000000000..9443c705e --- /dev/null +++ b/src/lib/sprintf.C @@ -0,0 +1,538 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/lib/sprintf.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <util/sprintf.H> +#include <builtins.h> +#include <string.h> +#include <ctype.h> + +namespace Util +{ + +struct format_options +{ + enum + { + ALT_FORM = 0x1, + ZERO_PAD = 0x2, + LEFT_ALIGN = 0x4, + EMPTY_SIGN = 0x8, + PLUS_SIGN = 0x10 + }; + + int flags; + + size_t field_width; + size_t precision; + + enum lengths + { + LEN_INT, + LEN_CHAR, + LEN_SHORT, + LEN_LONG, + LEN_LONGLONG, + LEN_SIZET, + LEN_PTRDIFF, + }; + + lengths length; + + bool upper; + + enum types + { + TYPE_PERCENT, + TYPE_SIGNED_DECIMAL, + TYPE_DECIMAL, + TYPE_OCTAL, + TYPE_HEX, + TYPE_BINARY, + TYPE_CHAR, + TYPE_STRING, + TYPE_PTR, + }; + + types type; +}; + +void parse_format_options(format_options& opt, const char*& fmt) +{ + opt = format_options(); + ++fmt; // increment past first %. + + if (('\0' == *fmt) || ('%' == *fmt)) + { + opt.type = opt.TYPE_PERCENT; + return; + } + + // Look for 'flag' type options. + bool should_continue = true; + while(should_continue) + { + switch(*fmt) + { + case '#': + opt.flags |= opt.ALT_FORM; + ++fmt; + break; + + case '0': + opt.flags |= opt.ZERO_PAD; + ++fmt; + break; + + case '-': + opt.flags |= opt.LEFT_ALIGN; + ++fmt; + break; + + case ' ': + opt.flags |= opt.EMPTY_SIGN; + ++fmt; + break; + + case '+': + opt.flags |= opt.PLUS_SIGN; + ++fmt; + break; + + default: + should_continue = false; + break; + } + } + + // Look for field width options. + should_continue = true; + while (should_continue) + { + if(isdigit(*fmt)) + { + opt.field_width *= 10; + opt.field_width += (*fmt) - '0'; + ++fmt; + } + else + { + should_continue = false; + } + } + + // Look for precision options. + if ('.' == *fmt) + { + ++fmt; + should_continue = true; + while (should_continue) + { + if(isdigit(*fmt)) + { + opt.precision *= 10; + opt.precision += (*fmt) - '0'; + ++fmt; + } + else + { + should_continue = false; + } + } + } + + // Look for length modifiers. + should_continue = true; + while (should_continue) + { + switch (*fmt) + { + case 'h': + if ((opt.length == opt.LEN_SHORT) || + (opt.length == opt.LEN_CHAR)) + { + opt.length = opt.LEN_CHAR; + } + else + { + opt.length = opt.LEN_SHORT; + } + ++fmt; + break; + + case 'l': + if ((opt.length == opt.LEN_LONG) || + (opt.length == opt.LEN_LONGLONG)) + { + opt.length = opt.LEN_LONGLONG; + } + else + { + opt.length = opt.LEN_LONG; + } + ++fmt; + break; + + case 'z': + opt.length = opt.LEN_SIZET; + ++fmt; + break; + + case 't': + opt.length = opt.LEN_PTRDIFF; + ++fmt; + break; + + default: + should_continue = false; + break; + } + } + + // Look for the type specifier + switch (*fmt) + { + case 'd': + case 'i': + opt.type = opt.TYPE_SIGNED_DECIMAL; + break; + + case 'o': + opt.type = opt.TYPE_OCTAL; + break; + + case 'u': + opt.type = opt.TYPE_DECIMAL; + break; + + case 'x': + opt.type = opt.TYPE_HEX; + break; + + case 'X': + opt.type = opt.TYPE_HEX; + opt.upper = true; + break; + + case 'b': + opt.type = opt.TYPE_BINARY; + break; + + case 'B': + opt.type = opt.TYPE_BINARY; + opt.upper = true; + break; + + case 'c': + opt.type = opt.TYPE_CHAR; + break; + + case 's': + opt.type = opt.TYPE_STRING; + break; + + case 'p': + opt.type = opt.TYPE_PTR; + break; + + default: + opt.type = opt.TYPE_PERCENT; + } + if ('\0' != *fmt) + { + ++fmt; + } + +} + +size_t display_pre_header(ConsoleBufferInterface& func, + const format_options& f, size_t size) +{ + size_t count = 0; + if (!(f.flags & format_options::LEFT_ALIGN) && + f.field_width) + { + for (size_t i = size; i < f.field_width; i++) + { + func(' '); + ++count; + } + } + return count; +} + +size_t display_post_header(ConsoleBufferInterface& func, + const format_options& f, size_t size) +{ + size_t count = 0; + if ((f.flags & format_options::LEFT_ALIGN) && + f.field_width) + { + for (size_t i = size; i < f.field_width; i++) + { + func(' '); + ++count; + } + } + return count; +} + +size_t display_string(ConsoleBufferInterface& func, + const format_options& f, const char* string) +{ + size_t count = 0; + size_t len = strlen(string); + + count += display_pre_header(func, f, len); + for(size_t i = 0; i < len; i++) + { + func(string[i]); + ++count; + } + count += display_post_header(func, f, len); + + return count; +} + +size_t display_number(ConsoleBufferInterface& func, + const format_options& f, uint64_t number) +{ + static const char* digits = "0123456789abcdef"; + size_t count = 0; + + char output[64]; + size_t len = 0; + + // Determine sign of number. + char sign = '\0'; + if (f.type == format_options::TYPE_SIGNED_DECIMAL) + { + if (0 > (int64_t) number) + { + sign = '-'; + number = -1 * (int64_t) number; + } + else if (f.flags & format_options::PLUS_SIGN) + { + sign = '+'; + } + else if (f.flags & format_options::EMPTY_SIGN) + { + sign = ' '; + } + } + + // Determine base. + uint64_t base = 0; + switch (f.type) + { + case format_options::TYPE_BINARY: + base = 2; + break; + + case format_options::TYPE_OCTAL: + base = 8; + break; + + case format_options::TYPE_HEX: + case format_options::TYPE_PTR: + base = 16; + break; + + case format_options::TYPE_SIGNED_DECIMAL: + case format_options::TYPE_DECIMAL: + default: + base = 10; + break; + } + + // Determine alt-form header state. + size_t special_len = 0; + char special[2]; + + if ((f.flags & format_options::ALT_FORM) || + (f.type == format_options::TYPE_PTR)) + { + switch (f.type) + { + case format_options::TYPE_BINARY: + special[0] = '0'; + special[1] = 'b'; + special_len = 2; + break; + + case format_options::TYPE_HEX: + case format_options::TYPE_PTR: + special[0] = '0'; + special[1] = 'x'; + special_len = 2; + break; + + case format_options::TYPE_OCTAL: + special[0] = '0'; + special_len = 1; + break; + + default: + break; + } + } + + // Convert number to ascii. + while(number) + { + output[len++] = digits[number % base]; + number /= base; + } + if (len == 0) + { + output[len++] = digits[0]; + } + + // Fix up zero pad. + while(len < f.precision) + { + output[len++] = digits[0]; + } + + // Output pre-header. + size_t total_len = len + (sign == '\0' ? 0 : 1) + special_len; + if (f.flags & format_options::ZERO_PAD) + { + while (total_len < f.field_width) + { + output[len++] = digits[0]; + ++total_len; + } + } + else + { + count += display_pre_header(func, f, total_len); + } + + // Output sign, special. + if (sign != '\0') + { + func(sign); + ++count; + } + if (special_len) + { + for (size_t i = 0; i < special_len; i++) + { + func(f.upper ? toupper(special[i]) : special[i]); + ++count; + } + } + + // Output number. + for (size_t i = 0; i < len; i++) + { + func(f.upper ? toupper(output[len - (i+1)]) : output[len - (i+1)]); + ++count; + } + + // Output post-header. + if (!(f.flags & format_options::ZERO_PAD)) + { + count += display_post_header(func, f, total_len); + } + + return count; +} + +size_t vasprintf(ConsoleBufferInterface& func, const char* fmt, va_list& args) +{ + int count = 0; + + while(*fmt) + { + if ('%' == *fmt) + { + format_options f; + parse_format_options(f, fmt); + + switch(f.type) + { + case format_options::TYPE_PERCENT: + func('%'); + ++count; + break; + + case format_options::TYPE_PTR: + display_number(func, f, (uint64_t) va_arg(args, void*)); + break; + + case format_options::TYPE_CHAR: + count += display_pre_header(func, f, 1); + func(va_arg(args,int)); + ++count; + count += display_post_header(func, f, 1); + break; + + case format_options::TYPE_STRING: + count += display_string(func, f, va_arg(args,const char*)); + break; + + // All the number cases. + default: + { + uint64_t number = 0; + switch (f.length) + { + case format_options::LEN_INT: + case format_options::LEN_CHAR: + case format_options::LEN_SHORT: + // All of these types are automatically + // promoted to 'unsigned int' when passed + // through va_arg lists. + number = (uint64_t) va_arg(args, unsigned int); + break; + + case format_options::LEN_LONG: + case format_options::LEN_LONGLONG: + // Hostboot doesn't use 'long long' but FSP + // code tends to use %llx for uint64_t. + number = (uint64_t) va_arg(args, unsigned long); + break; + + case format_options::LEN_SIZET: + number = (uint64_t) va_arg(args, size_t); + break; + + case format_options::LEN_PTRDIFF: + number = (uint64_t) va_arg(args, ptrdiff_t); + break; + } + count += display_number(func, f, number); + } + } + } + else // Stand-alone character. + { + func(*fmt++); + ++count; + } + } + return count; +} + +}; diff --git a/src/lib/stdio.C b/src/lib/stdio.C index 0bdb63873..6f139e228 100644 --- a/src/lib/stdio.C +++ b/src/lib/stdio.C @@ -23,9 +23,8 @@ #include <stdint.h> #include <stdio.h> #include <util/sprintf.H> -#include <util/functor.H> -class SprintfBuffer +class SprintfBuffer : public Util::ConsoleBufferInterface { public: int putc(int c) @@ -34,31 +33,52 @@ class SprintfBuffer { iv_pos--; } - else + else if (iv_pos < iv_size) { iv_buffer[iv_pos++] = c; } + else + { + iv_pos++; + } return c; } - explicit SprintfBuffer(char* buf) : iv_pos(0), iv_buffer(buf) {}; + explicit SprintfBuffer(char* buf, size_t size = UINT64_MAX) : + iv_pos(0), iv_size(size), iv_buffer(buf) {}; + + size_t operator()(int c) { return putc(c); } private: size_t iv_pos; + size_t iv_size; char * iv_buffer; }; int sprintf(char *str, const char * format, ...) { - using Util::mem_ptr_fun; using Util::vasprintf; va_list args; va_start(args, format); SprintfBuffer console(str); - size_t count = vasprintf(mem_ptr_fun(console, &SprintfBuffer::putc), - format, args); + size_t count = vasprintf(console, format, args); + + va_end(args); + console.putc('\0'); + return count; +} + +int snprintf(char *str, size_t size, const char * format, ...) +{ + using Util::vasprintf; + + va_list args; + va_start(args, format); + + SprintfBuffer console(str, size); + size_t count = vasprintf(console, format, args); va_end(args); console.putc('\0'); @@ -67,11 +87,19 @@ int sprintf(char *str, const char * format, ...) int vsprintf(char *str, const char * format, va_list args) { - using Util::mem_ptr_fun; + using Util::vasprintf; SprintfBuffer console(str); - size_t count = vasprintf(mem_ptr_fun(console, &SprintfBuffer::putc), - format, args); + size_t count = vasprintf(console, format, args); + + console.putc('\0'); + return count; +} + +int vsnprintf(char *str, size_t size, const char * format, va_list args) +{ + SprintfBuffer console(str, size); + size_t count = vasprintf(console, format, args); console.putc('\0'); return count; diff --git a/src/makefile b/src/makefile index 33dad720c..8067cd4e7 100644 --- a/src/makefile +++ b/src/makefile @@ -27,7 +27,7 @@ SUBDIRS = kernel.d lib.d libc++.d sys.d usr.d build.d runtime.d IMGS = hbicore hbicore_test hbirt hbirt_test BASE_OBJECTS = string.o string_ext.o ctype.o math.o builtins.o stdio.o \ - splaytree.o cxxtest_data.o + splaytree.o cxxtest_data.o sprintf.o ifdef HOSTBOOT_PROFILE BASE_OBJECTS += gcov.o |