base: new interface for textual output

Issue #1942
This commit is contained in:
Norman Feske
2016-05-03 16:31:17 +02:00
parent 3bceefc9cf
commit 1f395ae780
22 changed files with 693 additions and 95 deletions

View File

@ -17,9 +17,13 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/console.h>
#include <base/stdint.h>
/* base-internal includes */
#include <base/internal/output.h>
using namespace Genode;
@ -138,93 +142,6 @@ class Format_command
};
/**
* Convert digit to ASCII value
*/
static char ascii(int digit, int uppercase = 0)
{
if (digit > 9)
return digit + (uppercase ? 'A' : 'a') - 10;
return digit + '0';
}
/**
* Output signed value with the specified base
*/
template <typename T>
void Console::_out_signed(T value, unsigned base)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
/* set flag if value is negative */
int neg = value < 0 ? 1 : 0;
/* get absolute value */
value = value < 0 ? -value : value;
int i = 0;
/* handle zero as special case */
if (value == 0)
buf[i++] = ascii(0);
/* fill buffer starting with the least significant digits */
else
for (; value > 0; value /= base)
buf[i++] = ascii(value % base);
/* add sign to buffer for negative values */
if (neg)
_out_char('-');
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
/**
* Output unsigned value with the specified base and padding
*/
template <typename T>
void Console::_out_unsigned(T value, unsigned base, int pad)
{
/**
* for base 8, the number of digits is the number of value bytes times 3
* at a max, because 0xff is 0o377 and accumulating this implies a
* strictly decreasing factor
*/
char buf[sizeof(value)*3];
int i = 0;
/* handle zero as special case */
if (value == 0) {
buf[i++] = ascii(0);
pad--;
}
/* fill buffer starting with the least significant digits */
for (; value > 0; value /= base, pad--)
buf[i++] = ascii(value % base);
/* add padding zeros */
for (; pad-- > 0; )
_out_char(ascii(0));
/* output buffer in reverse order */
for (; i--; )
_out_char(buf[i]);
}
void Console::_out_string(const char *str)
{
if (!str)
@ -292,15 +209,18 @@ void Console::vprintf(const char *format, va_list list)
case Format_command::INT:
if (cmd.length == Format_command::LONG_LONG)
_out_signed<long long>(numeric_arg, cmd.base);
out_signed<long long>(numeric_arg, cmd.base,
[&] (char c) { _out_char(c); });
else
_out_signed<long>(numeric_arg, cmd.base);
out_signed<long>(numeric_arg, cmd.base,
[&] (char c) { _out_char(c); });
break;
case Format_command::UINT:
if (cmd.length == Format_command::LONG_LONG) {
_out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding);
out_unsigned<unsigned long long>(numeric_arg, cmd.base, cmd.padding,
[&] (char c) { _out_char(c); });
break;
}
@ -308,7 +228,8 @@ void Console::vprintf(const char *format, va_list list)
case Format_command::PTR:
_out_unsigned<unsigned long>(numeric_arg, cmd.base, cmd.padding);
out_unsigned<unsigned long>(numeric_arg, cmd.base, cmd.padding,
[&] (char c) { _out_char(c); });
break;
case Format_command::CHAR:

View File

@ -0,0 +1,51 @@
/*
* \brief Access to the component's LOG session
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <log_session/log_session.h>
/* base-internal includes */
#include <base/internal/globals.h>
#include <base/internal/output.h>
#include <base/internal/unmanaged_singleton.h>
using namespace Genode;
static Log *log_ptr;
Log &Log::log() { return *log_ptr; }
extern "C" int stdout_write(const char *s);
void Genode::init_log()
{
/* ignore subsequent calls */
if (log_ptr)
return;
struct Write_fn { void operator () (char const *s) { stdout_write(s); } };
typedef Buffered_output<Log_session::MAX_STRING_LEN, Write_fn>
Buffered_log_output;
static Buffered_log_output *buffered_log_output =
unmanaged_singleton<Buffered_log_output>(Write_fn());
log_ptr = unmanaged_singleton<Log>(*buffered_log_output);
}

View File

@ -0,0 +1,44 @@
/*
* \brief Access to the component's LOG session
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/log.h>
using namespace Genode;
void Log::_acquire(Type type)
{
_lock.lock();
/*
* Mark warnings and errors via distinct colors.
*/
switch (type) {
case LOG: break;
case WARNING: _output.out_string("\033[34mWarning: "); break;
case ERROR: _output.out_string("\033[31mError: "); break;
};
}
void Log::_release()
{
/*
* Reset color and add newline
*/
_output.out_string("\033[0m\n");
_lock.unlock();
}

View File

@ -0,0 +1,83 @@
/*
* \brief Textual output functions
* \author Norman Feske
* \date 2016-05-03
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/output.h>
/* base-internal includes */
#include <base/internal/output.h>
using namespace Genode;
/************
** Output **
************/
void Output::out_string(char const *str, size_t n)
{
if (!str)
return;
while (*str && n--) out_char(*str++);
}
/******************************
** Print function overloads **
******************************/
void Genode::print(Output &output, char const *str)
{
if (!str)
output.out_string("<null-string>");
else
while (*str) output.out_char(*str++);
}
void Genode::print(Output &output, void const *ptr)
{
print(output, Hex(reinterpret_cast<addr_t>(ptr)));
}
void Genode::print(Output &output, unsigned long value)
{
out_unsigned<unsigned long>(value, 10, 0, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, long value)
{
out_signed<long>(value, 10, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, long long value)
{
out_signed<long long>(value, 10, [&] (char c) { output.out_char(c); });
}
void Genode::print(Output &output, Hex const &value)
{
if (value.prefix == Hex::PREFIX)
output.out_string("0x");
size_t const pad_len = value.pad ? value.digits : 0;
out_unsigned<unsigned long>(value.value, 16, pad_len,
[&] (char c) { output.out_char(c); });
}

View File

@ -19,8 +19,12 @@
#include <base/printf.h>
#include <base/thread.h>
/* base-internal includes */
#include <base/internal/globals.h>
using namespace Genode;
addr_t init_main_thread_result;
extern void init_exception_handling();
@ -89,6 +93,7 @@ extern "C" void init_main_thread()
* destructor won't be registered for the atexit routine.
*/
(void*)env();
init_log();
/* initialize exception handling */
init_exception_handling();