summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/ctype.h67
-rw-r--r--src/include/kernel/console.H49
-rw-r--r--src/include/stdio.h4
-rw-r--r--src/include/util/functor.H122
-rw-r--r--src/include/util/sprintf.H326
-rw-r--r--src/kernel/console.C49
-rw-r--r--src/lib/ctype.C46
-rw-r--r--src/lib/makefile2
-rw-r--r--src/lib/sprintf.C538
-rw-r--r--src/lib/stdio.C48
-rw-r--r--src/makefile2
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
OpenPOWER on IntegriCloud