summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2013-09-23 14:55:10 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-10-07 10:02:28 -0500
commitb8d7070d329b3a6577ae6c11ae7b1afb27db7a22 (patch)
tree0e93546356b039af78869b5edc86d8d4d1ff08a9 /src/lib
parent4dc8e90ef55cb15b6a36a8d27ae43a6b2261521b (diff)
downloadtalos-hostboot-b8d7070d329b3a6577ae6c11ae7b1afb27db7a22.tar.gz
talos-hostboot-b8d7070d329b3a6577ae6c11ae7b1afb27db7a22.zip
Make sprintf-class functions comply with standard.
Change-Id: I6a04179bb2c339668450bcbcf608ebef477c5bfe Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6399 Tested-by: Jenkins Server Reviewed-by: Brian H. Horton <brianh@linux.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/lib')
-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
4 files changed, 623 insertions, 11 deletions
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;
OpenPOWER on IntegriCloud