forked from Lephenixnoir/fxos
202 lines
4.3 KiB
C++
202 lines
4.3 KiB
C++
#include "shell.h"
|
|
#include "theme.h"
|
|
#include "parser.h"
|
|
#include "commands.h"
|
|
#include "errors.h"
|
|
|
|
#include <fmt/core.h>
|
|
#include <fmt/color.h>
|
|
|
|
#include <fxos/memory.h>
|
|
|
|
using namespace FxOS;
|
|
|
|
//---
|
|
// vl
|
|
//---
|
|
|
|
static std::vector<std::string> parse_vl(Session &, Parser &parser)
|
|
{
|
|
std::vector<std::string> spaces;
|
|
|
|
while(!parser.at_end())
|
|
spaces.push_back(parser.symbol("vspace_name"));
|
|
|
|
parser.end();
|
|
return spaces;
|
|
}
|
|
|
|
static void show_vspace(std::string name, VirtualSpace &s, Session &session)
|
|
{
|
|
bool is_current = (&s == session.current_space);
|
|
|
|
if(is_current) fmt::print("* ");
|
|
fmt::print(theme(11), "{}\n", name);
|
|
|
|
if(s.bindings().size() == 0) {
|
|
fmt::print(" (no bindings)\n");
|
|
return;
|
|
}
|
|
|
|
fmt::print(" Region Start End File\n");
|
|
for(auto &b: s.bindings()) {
|
|
MemoryRegion const *ref = MemoryRegion::region_for(b.region);
|
|
fmt::print(" {:<7s} 0x{:08x} .. 0x{:08x}", (ref ? ref->name : ""),
|
|
b.region.start, b.region.end);
|
|
if(b.buffer.path != "")
|
|
fmt::print(" {}", b.buffer.path);
|
|
fmt::print("\n");
|
|
}
|
|
}
|
|
|
|
void _vl(Session &session, std::vector<std::string> const &args)
|
|
{
|
|
if(!args.size()) {
|
|
for(auto &it: session.spaces)
|
|
show_vspace(it.first, it.second, session);
|
|
}
|
|
else for(auto &name: args) {
|
|
session.require_vspace(name);
|
|
show_vspace(name, session.spaces[name], session);
|
|
}
|
|
}
|
|
|
|
//---
|
|
// vs
|
|
//---
|
|
|
|
static std::string parse_vs(Session &, Parser &parser)
|
|
{
|
|
std::string name = parser.symbol("vspace_name");
|
|
parser.end();
|
|
return name;
|
|
}
|
|
|
|
void _vs(Session &session, std::string const &name)
|
|
{
|
|
session.require_vspace(name);
|
|
session.current_space = &session.spaces[name];
|
|
}
|
|
|
|
//---
|
|
// vc
|
|
//---
|
|
|
|
static std::string parse_vc(Session &, Parser &parser)
|
|
{
|
|
std::string name = "";
|
|
if(!parser.at_end()) name = parser.symbol();
|
|
parser.end();
|
|
return name;
|
|
}
|
|
|
|
static void _vc(Session &session, std::string name)
|
|
{
|
|
if(name == "") name = session.space_name("space", true);
|
|
else name = session.space_name(name, false);
|
|
|
|
/* Create an empty space and select it */
|
|
session.spaces.emplace(name, VirtualSpace {});
|
|
_vs(session, name);
|
|
_g(session, 0x80000000);
|
|
}
|
|
|
|
//---
|
|
// vct
|
|
//---
|
|
|
|
struct _vct_args {
|
|
std::string path;
|
|
std::string vspace_name;
|
|
};
|
|
|
|
static _vct_args parse_vct(Session &, Parser &parser)
|
|
{
|
|
_vct_args args;
|
|
args.path = parser.str();
|
|
if(!parser.at_end()) args.vspace_name = parser.symbol();
|
|
parser.end();
|
|
return args;
|
|
}
|
|
|
|
void _vct(Session &session, std::string filename, std::string name)
|
|
{
|
|
fs::path path = session.file(filename);
|
|
|
|
if(name == "")
|
|
name = session.space_name(path.filename(), false);
|
|
else if(session.spaces.count(name))
|
|
throw CommandError("virtual space '{}' already exists", name);
|
|
|
|
_vc(session, name);
|
|
_dot(session, { filename }, false);
|
|
}
|
|
|
|
//---
|
|
// vm
|
|
//---
|
|
|
|
struct _vm_args {
|
|
std::string path;
|
|
std::vector<MemoryRegion> regions;
|
|
};
|
|
|
|
static _vm_args parse_vm(Session &session, Parser &parser)
|
|
{
|
|
_vm_args args {};
|
|
args.path = parser.str();
|
|
|
|
/* TODO: vm: Allow specifying address without a size */
|
|
do args.regions.push_back(parser.region(session.current_space));
|
|
while(!parser.at_end());
|
|
|
|
parser.end();
|
|
return args;
|
|
}
|
|
|
|
void _vm(Session &session, std::string file, std::vector<MemoryRegion> regions)
|
|
{
|
|
session.require_vspace();
|
|
|
|
std::string path = session.file(file);
|
|
Buffer contents(path);
|
|
|
|
/* If no files are loaded yet, set the PC to the first loaded region */
|
|
if(!session.current_space->bindings().size())
|
|
session.pc = regions[0].start;
|
|
|
|
for(auto &r: regions)
|
|
session.current_space->bind_region(r, contents);
|
|
}
|
|
|
|
//---
|
|
// Command registration
|
|
//---
|
|
|
|
[[gnu::constructor]] static void _(void)
|
|
{
|
|
shell_register_command("vl",
|
|
[](Session &s, Parser &p) { _vl(s, parse_vl(s, p)); },
|
|
[](Session &s, Parser &p){ parse_vl(s, p); });
|
|
|
|
shell_register_command("vs",
|
|
[](Session &s, Parser &p) { _vs(s, parse_vs(s, p)); },
|
|
[](Session &s, Parser &p){ parse_vs(s, p); });
|
|
|
|
shell_register_command("vc",
|
|
[](Session &s, Parser &p) { _vc(s, parse_vc(s, p)); },
|
|
[](Session &s, Parser &p){ parse_vc(s, p); });
|
|
|
|
shell_register_command("vct",
|
|
[](Session &s, Parser &p) {
|
|
auto const &args = parse_vct(s, p);
|
|
_vct(s, args.path, args.vspace_name); },
|
|
[](Session &s, Parser &p){ parse_vct(s, p); });
|
|
|
|
shell_register_command("vm",
|
|
[](Session &s, Parser &p) {
|
|
auto const &args = parse_vm(s, p);
|
|
_vm(s, args.path, args.regions); },
|
|
[](Session &s, Parser &p){ parse_vm(s, p); });
|
|
}
|