fxos/shell/v.cpp

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); });
}