mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-29 15:44:02 +00:00
base: remove format strings from API
This patch ultimatedly removes format strings from Genode's base API. Users of the former base/snprintf.h and base/console.h headers may use the free-standing 'format' library hosted in the ports repository. Fixes #2064 Fixes #3869
This commit is contained in:
parent
e9b249b709
commit
d727d18871
@ -9,7 +9,6 @@ SRC_CC += bootstrap/thread.cc
|
||||
SRC_CC += hw/capability.cc
|
||||
SRC_CC += lib/base/allocator_avl.cc
|
||||
SRC_CC += lib/base/avl_tree.cc
|
||||
SRC_CC += lib/base/console.cc
|
||||
SRC_CC += lib/base/elf_binary.cc
|
||||
SRC_CC += lib/base/heap.cc
|
||||
SRC_CC += lib/base/registry.cc
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <base/env.h>
|
||||
#include <base/capability.h>
|
||||
#include <base/log.h>
|
||||
#include <base/snprintf.h> /* deprecated */
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -47,13 +46,6 @@ class Genode::Connection_base : Noncopyable, Interface
|
||||
_id_space_element(_parent_client, _env.id_space())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Legacy constructor
|
||||
*
|
||||
* \noapi
|
||||
*/
|
||||
Connection_base();
|
||||
|
||||
void upgrade(Session::Resources resources)
|
||||
{
|
||||
String<80> const args("ram_quota=", resources.ram_quota, ", "
|
||||
@ -110,29 +102,6 @@ class Genode::Connection : public Connection_base
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Buffer for storing the session arguments passed to the
|
||||
* 'session' method that is called before the 'Connection' is
|
||||
* constructed.
|
||||
*/
|
||||
|
||||
enum { FORMAT_STRING_SIZE = Parent::Session_args::MAX_SIZE };
|
||||
|
||||
char _session_args[FORMAT_STRING_SIZE];
|
||||
|
||||
Affinity _affinity_arg { };
|
||||
|
||||
void _session(Parent &,
|
||||
Affinity const &affinity,
|
||||
const char *format_args, va_list list)
|
||||
{
|
||||
String_console sc(_session_args, FORMAT_STRING_SIZE);
|
||||
sc.vprintf(format_args, list);
|
||||
va_end(list);
|
||||
|
||||
_affinity_arg = affinity;
|
||||
}
|
||||
|
||||
using Client_id = Parent::Client::Id;
|
||||
|
||||
static Capability<SESSION_TYPE> _request(Env &env,
|
||||
@ -163,32 +132,10 @@ class Genode::Connection : public Connection_base
|
||||
}
|
||||
}
|
||||
|
||||
Capability<SESSION_TYPE> _request_cap()
|
||||
{
|
||||
try {
|
||||
return _env.session<SESSION_TYPE>(_id_space_element.id(),
|
||||
_session_args, _affinity_arg); }
|
||||
catch (...) {
|
||||
error(SESSION_TYPE::service_name(), "-session creation failed "
|
||||
"(", Cstring(_session_args), ")");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Capability<SESSION_TYPE> _cap = _request_cap();
|
||||
Capability<SESSION_TYPE> _cap;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
Connection(Env &env, Capability<SESSION_TYPE>)
|
||||
:
|
||||
Connection_base(env), _cap(_request_cap())
|
||||
{ }
|
||||
|
||||
Connection(Env &env,
|
||||
Session_label const &label,
|
||||
Ram_quota const &ram_quota,
|
||||
@ -217,36 +164,6 @@ class Genode::Connection : public Connection_base
|
||||
* Return session capability
|
||||
*/
|
||||
Capability<SESSION_TYPE> cap() const { return _cap; }
|
||||
|
||||
/**
|
||||
* Issue session request to the parent
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
Capability<SESSION_TYPE> session(Parent &parent, const char *format_args, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format_args);
|
||||
|
||||
_session(parent, Affinity(), format_args, list);
|
||||
return Capability<SESSION_TYPE>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue session request to the parent
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
Capability<SESSION_TYPE> session(Parent &parent,
|
||||
Affinity const &affinity,
|
||||
char const *format_args, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format_args);
|
||||
|
||||
_session(parent, affinity, format_args, list);
|
||||
return Capability<SESSION_TYPE>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__CONNECTION_H_ */
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* \brief Simple console for debug output
|
||||
* \author Norman Feske
|
||||
* \date 2006-04-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__CONSOLE_H_
|
||||
#define _INCLUDE__BASE__CONSOLE_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace Genode { class Console; }
|
||||
|
||||
|
||||
class Genode::Console
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Console() {}
|
||||
|
||||
/**
|
||||
* Print format string
|
||||
*/
|
||||
void printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
void vprintf(const char *format, va_list) __attribute__((format(printf, 2, 0)));
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Back end used for the output of a single character
|
||||
*/
|
||||
virtual void _out_char(char c) = 0;
|
||||
|
||||
/**
|
||||
* Back end for the output of a null-terminated string
|
||||
*
|
||||
* The default implementation uses _out_char. This method may
|
||||
* be overridden by the backend for improving efficiency.
|
||||
*
|
||||
* This method is virtual to enable the use an optimized
|
||||
* string-output operation on some target platforms, e.g.,
|
||||
* a kernel debugger that offers a string-output syscall. The
|
||||
* default implementation calls '_out_char' for each character.
|
||||
*/
|
||||
virtual void _out_string(const char *str);
|
||||
|
||||
private:
|
||||
|
||||
template <typename T> void _out_unsigned(T value, unsigned base = 10, int pad = 0);
|
||||
template <typename T> void _out_signed(T value, unsigned base = 10);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__CONSOLE_H_ */
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* \brief Facility to write format string into character buffer
|
||||
* \author Norman Feske
|
||||
* \date 2006-07-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__SNPRINTF_H_
|
||||
#define _INCLUDE__BASE__SNPRINTF_H_
|
||||
|
||||
#include <base/console.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class String_console;
|
||||
|
||||
/**
|
||||
* Print format string into character buffer
|
||||
*
|
||||
* \param dst destination buffer
|
||||
* \param dst_len size of 'dst' in bytes
|
||||
* \param format format string followed by the list of arguments
|
||||
*
|
||||
* \return number of characters written to destination buffer
|
||||
*/
|
||||
inline size_t snprintf(char *dst, size_t dst_size, const char *format, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
}
|
||||
|
||||
|
||||
class Genode::String_console : public Console
|
||||
{
|
||||
private:
|
||||
|
||||
char *_dst;
|
||||
size_t _dst_len;
|
||||
size_t _w_offset { 0 };
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
String_console &operator = (String_console const &);
|
||||
String_console(String_console const &);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param dst destination character buffer
|
||||
* \param dst_len size of 'dst'
|
||||
*/
|
||||
String_console(char *dst, size_t dst_len)
|
||||
: _dst(dst), _dst_len(dst_len)
|
||||
{ _dst[0] = 0; }
|
||||
|
||||
/**
|
||||
* Return number of characters in destination buffer
|
||||
*/
|
||||
size_t len() { return _w_offset; }
|
||||
|
||||
|
||||
/***********************
|
||||
** Console interface **
|
||||
***********************/
|
||||
|
||||
void _out_char(char c) override
|
||||
{
|
||||
/* ensure to leave space for null-termination */
|
||||
if (_w_offset + 2 > _dst_len)
|
||||
return;
|
||||
|
||||
_dst[_w_offset++] = c;
|
||||
_dst[_w_offset] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline Genode::size_t Genode::snprintf(char *dst, size_t dst_len, const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
|
||||
String_console sc(dst, dst_len);
|
||||
sc.vprintf(format, list);
|
||||
|
||||
va_end(list);
|
||||
return sc.len();
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__SNPRINTF_H_ */
|
@ -9,7 +9,6 @@ SRC_CC += slab.cc
|
||||
SRC_CC += allocator_avl.cc
|
||||
SRC_CC += heap.cc sliced_heap.cc
|
||||
SRC_CC += registry.cc
|
||||
SRC_CC += console.cc
|
||||
SRC_CC += output.cc
|
||||
SRC_CC += child.cc
|
||||
SRC_CC += child_process.cc
|
||||
|
@ -124,8 +124,6 @@ _ZN6Genode14Signal_contextD2Ev T
|
||||
_ZN6Genode14cache_coherentEmm T
|
||||
_ZN6Genode14env_deprecatedEv T
|
||||
_ZN6Genode14ipc_reply_waitERKNS_17Native_capabilityENS_18Rpc_exception_codeERNS_11Msgbuf_baseES5_ T
|
||||
_ZN6Genode15Connection_baseC1Ev T
|
||||
_ZN6Genode15Connection_baseC2Ev T
|
||||
_ZN6Genode15Signal_receiver12local_submitENS_6Signal4DataE T
|
||||
_ZN6Genode15Signal_receiver14pending_signalEv T
|
||||
_ZN6Genode15Signal_receiver15wait_for_signalEv T
|
||||
@ -293,12 +291,6 @@ _ZN6Genode6ThreadC2EmPKcmNS0_4TypeEPNS_11Cpu_sessionENS_8Affinity8LocationE T
|
||||
_ZN6Genode6ThreadD0Ev T
|
||||
_ZN6Genode6ThreadD1Ev T
|
||||
_ZN6Genode6ThreadD2Ev T
|
||||
_ZN6Genode7Console11_out_stringEPKc T
|
||||
_ZN6Genode7Console6printfEPKcz T
|
||||
_ZN6Genode7Console7vprintfEPKcP13__va_list_tag T
|
||||
_ZN6Genode7Console7vprintfEPKcPc T
|
||||
_ZN6Genode7Console7vprintfEPKcPv T
|
||||
_ZN6Genode7Console7vprintfEPKcSt9__va_list T
|
||||
_ZN6Genode7Timeout14_alarm_discardEv T
|
||||
_ZN6Genode7Timeout17schedule_one_shotENS_12MicrosecondsERNS_15Timeout_handlerE T
|
||||
_ZN6Genode7Timeout17schedule_periodicENS_12MicrosecondsERNS_15Timeout_handlerE T
|
||||
@ -390,10 +382,10 @@ _ZTVN6Genode5ChildE D 440
|
||||
_ZTVN6Genode6OutputE D 48
|
||||
_ZTVN6Genode6ThreadE D 48
|
||||
_ZTVN6Genode7ConsoleE D 48
|
||||
_ZThn236_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T
|
||||
_ZThn236_N5Timer10Connection9curr_timeEv T
|
||||
_ZThn288_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T
|
||||
_ZThn288_N5Timer10Connection9curr_timeEv T
|
||||
_ZThn104_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T
|
||||
_ZThn104_N5Timer10Connection9curr_timeEv T
|
||||
_ZThn52_N5Timer10Connection11set_timeoutEN6Genode12MicrosecondsERNS1_15Timeout_handlerE T
|
||||
_ZThn52_N5Timer10Connection9curr_timeEv T
|
||||
_ZThn8_N6Genode17Timeout_scheduler14handle_timeoutENS_8DurationE T
|
||||
_ZThn8_N6Genode17Timeout_schedulerD0Ev T
|
||||
_ZThn8_N6Genode17Timeout_schedulerD1Ev T
|
||||
|
@ -1,261 +0,0 @@
|
||||
/*
|
||||
* \brief Output of format strings
|
||||
* \author Norman Feske
|
||||
* \date 2006-04-07
|
||||
*
|
||||
* NOTE: Support for long long ints is not required by Core.
|
||||
* Hence, this functionality and further features such
|
||||
* as floating point numbers should better be placed
|
||||
* in another 'rich_conole' lib outside of the Genode's
|
||||
* base repository.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/console.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/output.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Format string command representation
|
||||
*/
|
||||
class Format_command
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type { INT, UINT, STRING, CHAR, PTR, PERCENT, INVALID };
|
||||
enum Length { DEFAULT, LONG, SIZE_T, LONG_LONG };
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Read decimal value from string
|
||||
*/
|
||||
int decode_decimal(const char *str, int *consumed)
|
||||
{
|
||||
int res = 0;
|
||||
while (1) {
|
||||
char c = str[*consumed];
|
||||
|
||||
if (!c || c < '0' || c > '0' + 9)
|
||||
return res;
|
||||
|
||||
res = (res * 10) + c - '0';
|
||||
(*consumed)++;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Type type = INVALID; /* format argument type */
|
||||
Length length = DEFAULT; /* format argument length */
|
||||
int padding = 0; /* min number of characters to print */
|
||||
int base = 10; /* base of numeric arguments */
|
||||
bool zeropad = false; /* pad with zero instead of space */
|
||||
bool uppercase = false; /* use upper case for hex numbers */
|
||||
int consumed = 0; /* nb of consumed format string chars */
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param format begin of command in format string
|
||||
*/
|
||||
explicit Format_command(const char *format)
|
||||
{
|
||||
/* check for command begin and eat the character */
|
||||
if (format[consumed] != '%') return;
|
||||
if (!format[++consumed]) return;
|
||||
|
||||
/* heading zero indicates zero-padding */
|
||||
zeropad = (format[consumed] == '0');
|
||||
|
||||
/* read decimal padding value */
|
||||
padding = decode_decimal(format, &consumed);
|
||||
if (!format[consumed]) return;
|
||||
|
||||
/* decode length */
|
||||
switch (format[consumed]) {
|
||||
|
||||
case 'l':
|
||||
{
|
||||
/* long long ints are marked by a subsequenting 'l' character */
|
||||
bool is_long_long = (format[consumed + 1] == 'l');
|
||||
|
||||
length = is_long_long ? LONG_LONG : LONG;
|
||||
consumed += is_long_long ? 2 : 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z':
|
||||
|
||||
length = SIZE_T;
|
||||
consumed++;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
|
||||
length = LONG;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (!format[consumed]) return;
|
||||
|
||||
/* decode type */
|
||||
switch (format[consumed]) {
|
||||
|
||||
case 'd':
|
||||
case 'i': type = INT; base = 10; break;
|
||||
case 'o': type = UINT; base = 8; break;
|
||||
case 'u': type = UINT; base = 10; break;
|
||||
case 'x': type = UINT; base = 16; break;
|
||||
case 'X': type = UINT; base = 16; uppercase = 1; break;
|
||||
case 'p': type = PTR; base = 16; break;
|
||||
case 'c': type = CHAR; break;
|
||||
case 's': type = STRING; break;
|
||||
case '%': type = PERCENT; break;
|
||||
|
||||
case 0: return;
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* eat type character */
|
||||
consumed++;
|
||||
}
|
||||
|
||||
int numeric()
|
||||
{
|
||||
return (type == INT || type == UINT || type == PTR);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Console::_out_string(const char *str)
|
||||
{
|
||||
if (!str)
|
||||
_out_string("<NULL>");
|
||||
else
|
||||
while (*str) _out_char(*str++);
|
||||
}
|
||||
|
||||
|
||||
void Console::printf(const char *format, ...)
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
vprintf(format, list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
|
||||
void Console::vprintf(const char *format, va_list list)
|
||||
{
|
||||
|
||||
while (*format) {
|
||||
|
||||
/* eat and output plain characters */
|
||||
if (*format != '%') {
|
||||
_out_char(*format++);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse format argument descriptor */
|
||||
Format_command cmd(format);
|
||||
|
||||
/* read numeric argument from va_list */
|
||||
long long numeric_arg = 0;
|
||||
if (cmd.numeric()) {
|
||||
switch (cmd.length) {
|
||||
|
||||
case Format_command::LONG_LONG:
|
||||
|
||||
numeric_arg = va_arg(list, long long);
|
||||
break;
|
||||
|
||||
case Format_command::LONG:
|
||||
|
||||
numeric_arg = (cmd.type == Format_command::UINT) ?
|
||||
(long long)va_arg(list, unsigned long) : va_arg(list, long);
|
||||
break;
|
||||
|
||||
case Format_command::SIZE_T:
|
||||
|
||||
numeric_arg = va_arg(list, size_t);
|
||||
break;
|
||||
|
||||
case Format_command::DEFAULT:
|
||||
|
||||
numeric_arg = (cmd.type == Format_command::UINT) ?
|
||||
(long long)va_arg(list, unsigned int) : va_arg(list, int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* call type-specific output routines */
|
||||
switch (cmd.type) {
|
||||
|
||||
case Format_command::INT:
|
||||
|
||||
if (cmd.length == Format_command::LONG_LONG)
|
||||
out_signed<long long>(numeric_arg, cmd.base,
|
||||
[&] (char c) { _out_char(c); });
|
||||
else
|
||||
out_signed<long>((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,
|
||||
[&] (char c) { _out_char(c); });
|
||||
break;
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
|
||||
case Format_command::PTR:
|
||||
|
||||
out_unsigned<unsigned long>((long)numeric_arg, cmd.base, cmd.padding,
|
||||
[&] (char c) { _out_char(c); });
|
||||
break;
|
||||
|
||||
case Format_command::CHAR:
|
||||
|
||||
_out_char((char)va_arg(list, int));
|
||||
break;
|
||||
|
||||
case Format_command::STRING:
|
||||
|
||||
_out_string(va_arg(list, const char *));
|
||||
break;
|
||||
|
||||
case Format_command::PERCENT:
|
||||
|
||||
_out_char('%');
|
||||
break;
|
||||
|
||||
case Format_command::INVALID:
|
||||
|
||||
_out_string("<warning: unsupported format string argument>");
|
||||
/* consume the argument of the unsupported command */
|
||||
va_arg(list, long);
|
||||
break;
|
||||
}
|
||||
|
||||
/* proceed with format string after command */
|
||||
format += cmd.consumed;
|
||||
}
|
||||
}
|
@ -38,13 +38,3 @@ Id_space<Parent::Client> &Genode::env_session_id_space()
|
||||
|
||||
return id_space;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* \deprecated
|
||||
*/
|
||||
Connection_base::Connection_base()
|
||||
:
|
||||
_env(internal_env()),
|
||||
_id_space_element(_parent_client, _env.id_space())
|
||||
{ }
|
||||
|
@ -41,8 +41,8 @@
|
||||
[init -> test-ldso] *
|
||||
[init -> test-ldso] Catch exceptions in program*
|
||||
[init -> test-ldso] ---------------------------*
|
||||
[init -> test-ldso] *Error: ROM-session creation failed (ram_quota=*, cap_quota=*, label="unknown_rom")*
|
||||
[init -> test-ldso] *Error: Could not open ROM session for "unknown_rom"*
|
||||
[init -> test-ldso] *Error: ROM-session creation failed*label="unknown_rom"*
|
||||
[init -> test-ldso] *Error: could not open ROM session for "unknown_rom"*
|
||||
[init -> test-ldso] exception in remote procedure call: caught*
|
||||
[init -> test-ldso] exception in program: caught*
|
||||
[init -> test-ldso] exception in shared lib: caught*
|
||||
|
@ -26,7 +26,7 @@
|
||||
[init -> test-report_rom] Reporter: start reporting (while the ROM client still listens)
|
||||
[init -> test-report_rom] ROM client: wait for update notification
|
||||
[init -> test-report_rom] ROM client: try to open the same report again
|
||||
[init -> test-report_rom] *Error: Report-session creation failed (label="brightness", ram_quota=14336, cap_quota=3, buffer_size=4096)*
|
||||
[init -> test-report_rom] *Error: Report-session creation failed*label="brightness"*
|
||||
[init -> test-report_rom] ROM client: caught Service_denied - OK
|
||||
[init -> test-report_rom] --- test-report_rom finished ---
|
||||
[init] child "test-report_rom" exited with exit value 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user