ysyx-workbench/npc/utils/sdb/include/sdb.hpp
2024-07-09 20:42:01 +08:00

99 lines
2.6 KiB
C++

#ifndef _SDB_SDB_HEADER_FILE_
#define _SDB_SDB_HEADER_FILE_
#include <components.hpp>
#include <console.hpp>
#include <memory>
#include <stdexcept>
#include <string>
#include <trm_interface.hpp>
#include <types.h>
namespace cr = CppReadline;
using ret = cr::Console::ReturnCode;
namespace SDB {
enum SDBStatus {
SDB_SUCCESS,
SDB_EBREAK = 2,
SDB_WRONG_ARGUMENT,
SDB_DIFFTEST_FAILED
};
class SDBHandlers;
struct Handler {
const std::vector<const char *> names;
// cr::Console::CommandFunction f;
std::function<int(SDBHandlers *, const cr::Console::Arguments &)> f;
};
class SDBHandlers {
private:
const TrmInterface &funcs;
std::vector<Handler> all_handlers = {
Handler{{"c", "continue"}, &SDBHandlers::cmd_continue},
Handler{{"si", "step-instruction"}, &SDBHandlers::cmd_step},
Handler{{"info-r"}, &SDBHandlers::cmd_info_registers},
Handler{{"p", "print"}, &SDBHandlers::cmd_print},
Handler{{"disas", "disassemble"}, &SDBHandlers::cmd_disassemble},
};
int cmd_continue(const cr::Console::Arguments &input);
int cmd_step(const std::vector<std::string> &input);
int cmd_info_registers(const std::vector<std::string> &input);
int cmd_print(const std::vector<std::string> &input);
int cmd_disassemble(const std::vector<std::string> &input);
int exec_catch(uint64_t);
public:
SDBHandlers(const TrmInterface &funcs) : funcs(funcs){};
void register_handlers(cr::Console *c);
};
class SDB {
private:
std::unique_ptr<CppReadline::Console> c;
const TrmInterface &funcs;
SDBHandlers handlers;
public:
SDB(const TrmInterface &funcs,
std::string const &greeting = "\033[1;34m(npc)\033[0m ")
: handlers(SDBHandlers{funcs}), funcs(funcs) {
c = std::make_unique<CppReadline::Console>(greeting);
handlers.register_handlers(c.get());
};
int main_loop() {
int ret_code;
funcs.init(0);
std::vector<std::string> step_commands{"c", "continue", "si",
"step-instruction"};
do {
ret_code = c->readLine();
// We can also change the prompt based on last return value:
if (ret_code == SDB_SUCCESS || ret_code == SDB_EBREAK)
c->setGreeting("\033[1;34m(npc)\033[0m ");
else
c->setGreeting("\033[1;31m(npc)\033[0m ");
switch (ret_code) {
case SDB_EBREAK: {
std::cout << "\033[1;31m=== ebreak ===\033[0m" << std::endl;
c->removeCommands(step_commands);
break;
}
case SDB_WRONG_ARGUMENT: {
std::cout << "Wrong argument(s) is given to command handler\n";
break;
}
}
} while (ret_code != ret::Quit);
return 0;
}
};
} // namespace SDB
#endif