diff --git a/include/fxos/semantics.h b/include/fxos/semantics.h index 1f7090c..631da14 100644 --- a/include/fxos/semantics.h +++ b/include/fxos/semantics.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace FxOS { diff --git a/shell/i.cpp b/shell/i.cpp index 28954de..87f29e8 100644 --- a/shell/i.cpp +++ b/shell/i.cpp @@ -246,17 +246,113 @@ void _isc(Session &session, std::string vspace_name, bool sort, // is //--- -static void parse_is(Session &, Parser &parser) +struct _is_args { + std::string vspace_name; + std::optional symbol; +}; + +static struct _is_args parse_is(Session &session, Parser &parser) +{ + _is_args args; + + parser.option("vspace", + [&args](std::string const &value) { args.vspace_name = value; }); + + parser.accept_options(); + + FxOS::Symbol s; + + if(!parser.at_end()) { + if(parser.lookahead().type == T::SYSCALL) { + s.type = FxOS::Symbol::Syscall; + s.value = parser.expect(T::SYSCALL).value.NUM; + } + else { + s.type = FxOS::Symbol::Address; + s.value = parser.expr(session.current_space); + } + args.symbol = s; + } + else { + args.symbol = {}; + } + + + 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); + } + } + parser.end(); + return args; } -void _is(Session &session) +void _is(Session &session, std::string vspace_name, + std::optional symbol) { - if(!session.current_space) + VirtualSpace *space = session.current_space; + if(!space) { + FxOS_log(ERR, "no virtual space selected"); return; + } - for(auto const &s: session.current_space->symbols.symbols) { + if(!vspace_name.empty()) + space = session.get_space(vspace_name); + + if(!space) { + FxOS_log(ERR, "virtual space '%s' does not exist", vspace_name); + return; + } + + std::vector symbols; + + if(!symbol.has_value()) + symbols = space->symbols.symbols; + else { + FxOS::Symbol s = symbol.value(); + + std::optional name = space->symbols.query(s.type, s.value); + + if(name.has_value()) + s.name = name.value(); + else if(s.type == FxOS::Symbol::Address) { + if(vspace_name.empty()) + FxOS_log(ERR, + "no symbol exists for address 0x%08x in current virtual space", + s.value); + else + FxOS_log(ERR, + "no symbol exists for syscall 0x%08x in virtual space '%s'", + s.value, vspace_name); + + return; + } + else if(s.type == FxOS::Symbol::Syscall) { + if(vspace_name.empty()) + FxOS_log(ERR, + "no symbol exists for syscall %%%04x in current virtual space", + s.value); + else + FxOS_log(ERR, + "no symbol exists for syscall %%%04x in virtual space '%s'", + s.value, vspace_name); + + return; + } + + symbols = {s}; + } + + for(auto const &s: symbols) { if(s.type == FxOS::Symbol::Syscall && s.value < 0x1000) { fmt::print(theme(10), " %{:03x}", s.value); } @@ -311,11 +407,13 @@ sort=true is specified, they are instead sorted by address. static ShellCommand _is_cmd( "is", [](Session &s, Parser &p) { - parse_is(s, p); - _is(s); + auto args = parse_is(s, p); + _is(s, args.vspace_name, args.symbol); }, [](Session &s, Parser &p) { parse_is(s, p); }, "Info Symbols", R"( -is +is [vspace=] [] -Lists all symbols in the current virtual space. +Lists symbols in the specified virtual space (defaults to the current +one). By default, all symbols are listed, but if an address or syscall is +provided, the symbol associated with it will be printed instead. )");