fxos/shell/h.cpp

92 lines
2.2 KiB
C++

#include "shell.h"
#include "parser.h"
#include "commands.h"
#include "theme.h"
#include <fmt/core.h>
using Selections = std::vector<std::pair<uint32_t, int>>;
static bool is_selected(uint32_t address, Selections const &sel)
{
for(auto &p: sel) {
if(address >= p.first && address < p.first + p.second)
return true;
}
return false;
}
void _h_hexdump(Session &session, Range r, Selections sel)
{
if(!session.current_space)
return;
VirtualSpace &v = *session.current_space;
uint32_t start = r.start & ~0xf;
uint32_t end = (r.end + 15) & ~0xf;
for(uint32_t pos = start; pos != end; pos += 16) {
fmt::print(theme(3), " 0x{:08x} ", pos);
/* Hexdump */
for(int offset = 0; offset < 16; offset++) {
if(!(offset % 4))
fmt::print(" ");
uint32_t addr = pos + offset;
if(addr < r.start || addr >= r.end) {
fmt::print(" ");
}
else if(is_selected(addr, sel)) {
fmt::print(theme(13), "{:02x}", v.read_u8(addr).value);
}
else {
fmt::print("{:02x}", v.read_u8(addr).value);
}
}
/* ASCII */
fmt::print(" ");
for(int offset = 0; offset < 16; offset++) {
if(!(offset % 4))
fmt::print(" ");
uint32_t addr = pos + offset;
if(addr < r.start || addr >= r.end) {
fmt::print(" ");
}
else {
int c = v.read_u8(addr);
fmt::print(theme(11), "{:c}", isprint(c) ? c : '.');
}
}
fmt::print("\n");
}
}
//---
// h
//---
static Range parse_h(Session &session, Parser &parser)
{
Range r = parser.range(session.current_space, 0, 128);
parser.end();
return r;
}
void _h(Session &session, Range r)
{
_h_hexdump(session, r, {});
}
static ShellCommand _h_cmd(
"h", [](Session &s, Parser &p) { _h(s, parse_h(s, p)); },
[](Session &s, Parser &p) { parse_h(s, p); }, "Hexdump", R"(
h (<address>|<range>)
Dumps the specified range into hexadecimal and ASCII representations. When an
address is specified, defaults to a length of 128.
)");