forked from Lephenixnoir/fxos
137 lines
3.5 KiB
C++
137 lines
3.5 KiB
C++
#include "shell.h"
|
|
#include "parser.h"
|
|
#include "commands.h"
|
|
|
|
#include <fmt/core.h>
|
|
#include <optional>
|
|
|
|
//---
|
|
// e
|
|
//---
|
|
|
|
static std::vector<long> parse_e(Session &session, Parser &parser)
|
|
{
|
|
std::vector<long> values;
|
|
|
|
while(!parser.at_end()) {
|
|
values.push_back(parser.expr(session.current_space));
|
|
}
|
|
|
|
parser.end();
|
|
return values;
|
|
}
|
|
|
|
void _e(Session &session, std::vector<long> const &values)
|
|
{
|
|
for(long value: values) {
|
|
/* Hexa format */
|
|
int length = (labs(value) <= (1ll << 32) ? 8 : 16) + 2 + (value < 0);
|
|
std::string format = fmt::format("{{:#0{}x}}", length);
|
|
fmt::print(format, value);
|
|
|
|
long a = abs(value);
|
|
if(a <= 100 || a % 100 <= 1 || a % 100 >= 99)
|
|
fmt::print(" = {}", a);
|
|
|
|
VirtualSpace *space = session.current_space;
|
|
|
|
if(space) {
|
|
std::optional<std::string> opt;
|
|
|
|
/* Promote to syscall ID */
|
|
OS *os = space->os_analysis();
|
|
int syscall_id;
|
|
|
|
if(os && (syscall_id = os->find_syscall(value)) != -1) {
|
|
fmt::print(" = %{:03x}", syscall_id);
|
|
opt = space->symbols.query(Symbol::Syscall, syscall_id);
|
|
if(opt)
|
|
fmt::print(" = {}", *opt);
|
|
}
|
|
|
|
opt = space->symbols.query(Symbol::Address, value);
|
|
if(opt)
|
|
fmt::print(" = {}", *opt);
|
|
}
|
|
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
|
|
//---
|
|
// ev
|
|
//---
|
|
|
|
struct _ev_args
|
|
{
|
|
std::string space_name;
|
|
std::vector<long> values;
|
|
};
|
|
|
|
static _ev_args parse_ev(Session &session, Parser &parser)
|
|
{
|
|
_ev_args args {};
|
|
args.space_name = parser.symbol("vspace_name");
|
|
|
|
VirtualSpace *space = session.get_space(args.space_name);
|
|
if(space) {
|
|
while(!parser.at_end()) {
|
|
args.values.push_back(parser.expr(space));
|
|
}
|
|
}
|
|
// TODO: Error message when session specified in _ev does not exist
|
|
|
|
parser.end();
|
|
return args;
|
|
}
|
|
|
|
void _ev(Session &, std::string, std::vector<long> const &values)
|
|
{
|
|
for(long value: values) {
|
|
/* Hexa format */
|
|
int length = (labs(value) <= (1ll << 32) ? 8 : 16) + 2 + (value < 0);
|
|
std::string format = fmt::format("{{:#0{}x}}", length);
|
|
fmt::print(format, value);
|
|
|
|
long a = abs(value);
|
|
if(a <= 100 || a % 100 <= 1 || a % 100 >= 99)
|
|
fmt::print(" = {}", a);
|
|
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
|
|
static ShellCommand _e_cmd(
|
|
"e", [](Session &s, Parser &p) { _e(s, parse_e(s, p)); },
|
|
[](Session &s, Parser &p) { parse_e(s, p); }, "Evaluate expression", R"(
|
|
e [<expression>...]
|
|
|
|
Evaluates the specified expressions. The expressions may include syscall
|
|
references (%0ab), named symbols (TRA), the current cursor ($), and
|
|
arithmetic expressions.
|
|
|
|
The parser doesn't accept arithmetic expressions directly on the command-line;
|
|
they must be placed within parentheses.
|
|
|
|
The resulting values undergo a simple analysis which recovers symbol names and
|
|
syscall addresses.
|
|
|
|
e TRA ($+2)
|
|
Evaluate the address of the TRA register, and the address of the next
|
|
instruction.
|
|
)");
|
|
|
|
static ShellCommand _ev_cmd(
|
|
"ev",
|
|
[](Session &s, Parser &p) {
|
|
auto const &args = parse_ev(s, p);
|
|
_ev(s, args.space_name, args.values);
|
|
},
|
|
[](Session &s, Parser &p) { parse_ev(s, p); },
|
|
"Evaluate expression in Virtual space", R"(
|
|
ev <virtual_space> [<expression>...]
|
|
|
|
Same as e, but resolves symbols within the named virtual space rather than the
|
|
current one. See e? for more information.
|
|
)");
|