Compare commits

...

10 Commits

Author SHA1 Message Date
Lephenixnoir 0bdb98562d Merge pull request 'Move vspace to option in isc command, adding custom addresses as positional arguments' (#6) from Dr-Carlos/fxos:isc into master
Reviewed-on: https://gitea.planet-casio.com/Lephenixnoir/fxos/pulls/6
2022-04-20 10:17:16 +02:00
Dr-Carlos 3308f72773 _isc: sort specific addresses if required 2022-04-19 21:51:27 +09:30
Dr-Carlos 771b12eab8 _isc: resolve vspace when parsing and misc fixes 2022-04-19 21:21:21 +09:30
Dr-Carlos 08c000539c _isc: use os->syscall_at instead of remove_if 2022-04-19 07:32:09 +09:30
Dr-Carlos e037d5889c _isc: print instead of throwing error 2022-04-19 07:13:07 +09:30
Dr-Carlos 86300fc1c7 _isc: add positional arg to specify printed info 2022-04-19 07:13:07 +09:30
Dr-Carlos 631482e4f5 _isc: add vspace as an option and fix it 2022-04-19 07:13:07 +09:30
Lephenixnoir 0f5c1c2eba
shell: improve error behavior of parser and autocompletion
* Example on _e, but other commands are probably affected
* When completing, throw CompletionRequest("_error", <message>) to have
  a reasonable output and not mess up readline
* Avoid early returns (or if a command really cannot be completed,
  adjust the ShellCommand declaration to not run the command)
* Less CommandError in the parser, these would throw during
  autocompletion and annoy everyone
* Allow options with empty value so that we don't throw when
  autocompleting after typing eg. 'vspace='
2022-04-18 11:55:25 +01:00
Lephenixnoir e0783c2348
shell: exhaust parser after parsing error 2022-04-18 11:30:49 +01:00
Lephenixnoir 707c154f00 Merge pull request 'Throw error when e vspace does not exist' (#5) from Dr-Carlos/fxos:master into master
Reviewed-on: https://gitea.planet-casio.com/Lephenixnoir/fxos/pulls/5
2022-04-18 12:07:25 +02:00
7 changed files with 112 additions and 45 deletions

View File

@ -26,19 +26,21 @@ static _e_args parse_e(Session &session, Parser &parser)
parser.accept_options();
VirtualSpace *space;
if(!args.space_name.empty())
VirtualSpace *space = session.current_space;
if(!args.space_name.empty()) {
space = session.get_space(args.space_name);
else
space = session.current_space;
if(!space) {
std::string msg =
format("virtual space '%s' does not exist", args.space_name);
if(parser.completing())
throw Parser::CompletionRequest("_error", msg);
else
FxOS_log(ERR, "%s", msg);
}
}
if(space)
while(!parser.at_end())
args.values.push_back(parser.expr(space));
else
FxOS_log(ERR, "virtual space '%s' does not exist", args.space_name);
// TODO: Error message when session specified in _e does not exist
while(!parser.at_end())
args.values.push_back(parser.expr(space));
parser.end();
return args;

View File

@ -6,6 +6,7 @@
#include <algorithm>
#include <fmt/core.h>
#include <fxos/util/log.h>
//---
// ic
@ -135,21 +136,36 @@ void _io(Session &session, std::string name)
struct _isc_args
{
std::string vspace_name;
bool sort;
bool sort = false;
std::vector<uint32_t> addresses;
};
static struct _isc_args parse_isc(Session &, Parser &parser)
static struct _isc_args parse_isc(Session &session, Parser &parser)
{
struct _isc_args args
{
};
_isc_args args;
parser.option("sort",
[&args](std::string const &value) { args.sort = (value == "true"); });
parser.option("vspace",
[&args](std::string const &value) { args.vspace_name = value; });
parser.accept_options();
args.vspace_name = parser.at_end() ? "" : parser.symbol("vspace_name");
parser.accept_options();
VirtualSpace *space = session.current_space;
if(!args.vspace_name.empty()) {
space = session.get_space(args.vspace_name);
if(!space) {
std::string msg
= format("virtual space '%s' does not exist", args.vspace_name);
if(parser.completing())
throw Parser::CompletionRequest("_error", msg);
else
FxOS_log(ERR, "%s", msg);
}
}
while(!parser.at_end())
args.addresses.push_back(parser.expr(space));
parser.end();
return args;
@ -166,26 +182,54 @@ bool operator<(const SyscallInfo &left, const SyscallInfo &right)
return (left.address < right.address) || (left.id < right.id);
}
void _isc(Session &session, std::string vspace_name, bool sort)
void _isc(Session &session, std::string vspace_name, bool sort,
std::vector<uint32_t> addresses)
{
VirtualSpace *space = session.current_space;
if(vspace_name != "")
space = session.get_space(vspace_name);
if(!space)
if(!space) {
FxOS_log(ERR, "no virtual space selected");
return;
}
// TODO: is <vspace_name> doesn't work
if(!vspace_name.empty())
space = session.get_space(vspace_name);
if(!space) {
FxOS_log(ERR, "virtual space '%s' does not exist", vspace_name);
return;
}
OS *os = space->os_analysis();
if(!os)
throw CommandError("os analysis on '{}' failed", vspace_name);
if(!os) {
if(!vspace_name.empty())
FxOS_log(ERR, "OS analysis on '%s' failed", vspace_name);
else
FxOS_log(ERR, "OS analysis failed");
return;
}
if(!addresses.empty()) {
if(sort)
std::sort(&addresses[0], &addresses[addresses.size()]);
for(uint32_t address: addresses) {
int syscall = os->find_syscall(address);
if(syscall == -1)
continue;
fmt::print(theme(3), " 0x{:08x}", address);
fmt::print(theme(10), " %{:01x}", syscall);
fmt::print("\n");
}
return;
}
int total = os->syscall_count();
auto info = std::make_unique<SyscallInfo[]>(total);
for(int i = 0; i < total; i++) {
for(int i = 0; i < total; i++)
info[i] = (SyscallInfo) {.address = os->syscall(i), .id = i};
}
if(sort)
std::sort(&info[0], &info[total]);
@ -254,10 +298,10 @@ static ShellCommand _isc_cmd(
"isc",
[](Session &s, Parser &p) {
auto args = parse_isc(s, p);
_isc(s, args.vspace_name, args.sort);
_isc(s, args.vspace_name, args.sort, args.addresses);
},
[](Session &s, Parser &p) { parse_isc(s, p); }, "Info Syscalls", R"(
isc [sort=true] [<vspace_name>]
isc [sort=true] [vspace=<virtual_space>] [<address>...]
Prints the syscall table for the specified virtual space (defaults to the
current one). By default, syscalls are enumerated by syscall number. If

View File

@ -143,7 +143,7 @@ num_suffix [kMG]
num ({num_hex}|{num_dec}|{num_bin}){num_suffix}?
syscall [%][a-fA-F0-9]+
option [a-zA-Z]+=[^ ]+
option [a-zA-Z]+=[^ ]*
symbol [a-zA-Z_.][a-zA-Z0-9_.]*
space [ \t]+

View File

@ -12,7 +12,8 @@ static FxOS::Symbol parse_ms(Session &session, Parser &parser)
if(parser.lookahead().type == T::SYSCALL) {
s.type = FxOS::Symbol::Syscall;
s.value = parser.expect(T::SYSCALL).value.NUM;
} else {
}
else {
s.type = FxOS::Symbol::Address;
s.value = parser.expr(session.current_space);
}

View File

@ -129,6 +129,11 @@ char *autocomplete(char const *text, int state)
options = complete_region(text);
else if(r.category == "symbol" && r.space != nullptr)
options = complete_symbol(text, r.space);
else if(r.category == "_error") {
options.clear();
options.push_back("(ERROR) " + r.value);
options.push_back(".");
}
else
options.clear();
i = 0;

View File

@ -2,6 +2,7 @@
#include "errors.h"
#include <stdexcept>
#include <fmt/core.h>
#include <fxos/util/log.h>
//---
// Lexing tools
@ -99,10 +100,6 @@ Token Parser::lookahead() const
bool Parser::at_end() const
{
/* When parsing to complete we try to go infinitely far, so we ignore
T::END. We supply T::SEPARATOR to complete the compound commands */
if(m_complete)
return (m_la.type == T::SEPARATOR);
return (m_la.type == T::SEPARATOR || m_la.type == T::END);
}
@ -113,6 +110,17 @@ void Parser::end()
throw SyntaxError("expected end of command");
}
void Parser::exhaust()
{
while(!at_end())
feed();
}
bool Parser::completing() const
{
return m_complete;
}
void Parser::skip_separators()
{
while(m_la.type == T::SEPARATOR)
@ -282,11 +290,13 @@ void Parser::accept_options()
std::string name = opt.substr(0, opt.find('='));
if(!m_options.count(name)) {
throw CommandError("unrecognized option {}", name);
if(!m_complete)
FxOS_log(ERR, "unrecognized option %s", name);
}
else {
std::string value = opt.substr(opt.find('=') + 1);
m_options[name](value);
}
std::string value = opt.substr(opt.find('=') + 1);
m_options[name](value);
}
}
@ -314,13 +324,12 @@ long Parser::atom()
if(os && (int)opt->value < os->syscall_count())
val = os->syscall(opt->value);
}
else {
throw CommandError("symbol '{}' is undefined", t.value.STRING);
}
else if(!m_complete)
FxOS_log(ERR, "symbol '%s' is undefined", t.value.STRING);
}
else
throw CommandError(
"cannot query symbol '{}', no virtual space", t.value.STRING);
else if(!m_complete)
FxOS_log(ERR, "cannot query symbol '%s' (no virtual space)",
t.value.STRING);
return val;
}
else if(t.type == T::SYSCALL) {

View File

@ -115,6 +115,12 @@ public:
Token lookahead() const;
/* Require that command is finished */
void end();
/* Exhaust all input (usually after encountering an error) */
void exhaust();
/* Whether we are parsing for autocompletion. This is only available to
allow appropriate decisions about printing vs. ignoring error messages.
Do not change parsing rules based on this information! */
bool completing() const;
/* Expect a token of this type, or of any of the listed types */
Token expect(T type, bool ignore_spaces=true);