diff --git a/shell/i.cpp b/shell/i.cpp index 28954de..d6d9c88 100644 --- a/shell/i.cpp +++ b/shell/i.cpp @@ -246,17 +246,125 @@ 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; + FxOS::Symbol 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); + } + } + else { + s.type = FxOS::Symbol::Address; + s.value = 0; + } + + args.symbol = s; + + + 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, FxOS::Symbol 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.type == FxOS::Symbol::Address && symbol.value == 0) + symbols = space->symbols.symbols; + else { + std::optional name + = space->symbols.query(symbol.type, symbol.value); + + if(name.has_value()) + symbol.name = name.value(); + else if(symbol.type == FxOS::Symbol::Address) { + if(vspace_name.empty()) + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for address 0x{:08x} in current virtual space\n", + symbol.value); + else + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for address 0x{:08x} in virtual space '{}'\n", + symbol.value, vspace_name); + + return; + } + else if(symbol.type == FxOS::Symbol::Syscall) { + if(vspace_name.empty()) { + if(symbol.value < 0x1000) + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for syscall %{:03x} in current virtual space\n", + symbol.value); + else + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for syscall %{:04x} in current virtual space\n", + symbol.value); + } + else { + if(symbol.value < 0x1000) + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for syscall %{:03x} in virtual space '{}'\n", + symbol.value, vspace_name); + else + fmt::print(stderr, + "\x1b[31;1merror:\x1b[0m no symbol exists for syscall %{:04x} in virtual space '{}'\n", + symbol.value, vspace_name); + } + + return; + } + + symbols = {symbol}; + } + + for(auto const &s: symbols) { if(s.type == FxOS::Symbol::Syscall && s.value < 0x1000) { fmt::print(theme(10), " %{:03x}", s.value); } @@ -311,11 +419,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. )");