fxos/shell/b.cpp

166 lines
4.5 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>
#include <fxos/util/log.h>
using namespace FxOS;
//---
// bs
//---
struct _bs_args
{
bool make_new = false;
bool rename = false;
bool remove = false;
std::string name;
};
static struct _bs_args parse_bs(Session &, Parser &parser)
{
struct _bs_args args;
parser.option("-n", [&args](Parser &) { args.make_new = true; });
parser.option("-r", [&args](Parser &) { args.rename = true; });
parser.option("--remove", [&args](Parser &) { args.remove = true; });
parser.accept_options();
if(args.make_new + args.rename + args.remove > 1)
throw CommandError("bs: can only specify one of -n, -r, --remove");
args.name = parser.symbol("binary_name");
parser.end();
return args;
}
void _bs(Session &session, struct _bs_args const &args)
{
/* Name checks */
Binary *b = session.project().getBinary(args.name);
if((args.make_new || args.rename) && b) {
FxOS_log(ERR, "There is already a binary “%s” in the project",
args.name.c_str());
return;
}
if((args.remove || (!args.make_new && !args.rename)) && !b) {
FxOS_log(ERR, "No binary “%s” in current project", args.name.c_str());
return;
}
if(args.rename && !session.currentBinary()) {
FxOS_log(ERR, "No current binary!");
return;
}
if(args.make_new) {
/* Create an empty binary and select it */
std::string name = session.project().createBinary(args.name);
fmt::print("Selecting new binary “{}”\n", name);
session.selectBinary(name);
}
else if(args.rename) {
fmt::print("Renaming binary “{}” into “{}”\n",
session.currentBinaryName(), args.name);
session.project().renameBinary(session.currentBinaryName(), args.name);
session.selectBinary(args.name);
}
else if(args.remove) {
Project &p = session.project();
fmt::print("Removing binary “{}”.\n", args.name);
p.removeBinary(args.name);
/* Select another binary if the current one is gone */
if(session.currentBinaryName() == args.name) {
auto const &binaries = p.binaries();
session.selectBinary(
binaries.size() ? binaries.begin()->first : "");
}
}
else {
session.selectBinary(args.name);
}
}
//---
// bm
//---
struct _bm_args
{
std::string path;
std::vector<MemoryRegion> regions;
};
static _bm_args parse_bm(Session &session, Parser &parser)
{
_bm_args args {};
args.path = parser.str();
/* TODO: bm: Allow specifying address without a size */
do
args.regions.push_back(parser.region(session.currentBinary()));
while(!parser.at_end());
parser.end();
return args;
}
void _bm(Session &session, std::string file, std::vector<MemoryRegion> regions)
{
Binary *b = session.currentBinary();
if(!b) {
FxOS_log(ERR, "No current binary");
return;
}
Buffer contents(file);
for(auto &r: regions)
b->vspace().bind_region(r, contents);
session.project().setDirty();
}
//---
// Command registration
//---
static ShellCommand _bs_cmd(
"bs", [](Session &s, Parser &p) { _bs(s, parse_bs(s, p)); },
[](Session &s, Parser &p) { parse_bs(s, p); },
"Binary Select, new, rename or remove", R"(
bs [-n | -r] <binary>
bs --remove <binary>
Selects the specified binary from the current project. With -n, creates a new
binary and selects it. With -r, renames the currently-selected binary.
With --remove, delete the specified binary from the project.
WARNING: There is no undo (yet). If you mistakenly remove a binary, do not save
the project. Backup the project folder and exit fxos without saving.
)");
static ShellCommand _bm_cmd(
"bm",
[](Session &s, Parser &p) {
auto const &args = parse_bm(s, p);
_bm(s, args.path, args.regions);
},
[](Session &s, Parser &p) { parse_bm(s, p); }, "Binary Map file", R"(
bm "<file>" <region>...
Maps the named file into all the specified regions of the current binary. If
the file is smaller than the region, it is zero-padded; if the region is
smaller, the extra data is ignored. The amount of data mapped is always exactly
the size of the requested region.
bm "/os/fx/3.10/3.10.bin" ROM ROM_P2
Maps a binary file 3.10.bin to ROM, through both P1 and P2.
)");