mirror of http://192.168.1.51:8099/gb/code_util
309 lines
6.2 KiB
C++
309 lines
6.2 KiB
C++
#include "cmd.h"
|
|
|
|
|
|
|
|
|
|
namespace parser
|
|
{
|
|
static void command_line_to_arguments(const char* cmdl, std::vector<std::string>& args)
|
|
{
|
|
while(*cmdl)
|
|
{
|
|
const char* h = cmdl;
|
|
while(*h == ' ' || *h == '\t')
|
|
h++;
|
|
if(*h == 0)
|
|
break;
|
|
|
|
cmdl = h;
|
|
if(*h == '\"')
|
|
{
|
|
cmdl++;
|
|
h++;
|
|
while(*h)
|
|
{
|
|
if(*h == '\"')
|
|
break;
|
|
if(*h == '\\')
|
|
h++;
|
|
h++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(*h)
|
|
{
|
|
if(*h == ' ' || *h == '\t')
|
|
break;
|
|
h++;
|
|
}
|
|
}
|
|
if(h > cmdl)
|
|
args.push_back(std::string(cmdl, h - cmdl));
|
|
else if(*h == '\"')
|
|
args.push_back("");
|
|
|
|
if(*h == 0)
|
|
break;
|
|
|
|
cmdl = h + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
cmd_line::cmd_line()
|
|
{}
|
|
cmd_line::~cmd_line()
|
|
{}
|
|
|
|
cmd_line* cmd_line::from_console(const char* tips)
|
|
{
|
|
std::string in("");
|
|
char ch = 0;
|
|
|
|
if(!tips || *tips == 0)
|
|
tips = "input";
|
|
|
|
printf("%s%s>%s", CONSOLE_COLOR_FRONT_PURPLE, tips, CONSOLE_COLOR_NONE);
|
|
while((ch = getchar()) != '\n')
|
|
in.append(1, ch);
|
|
|
|
return cmd_line::from_command_line(in.c_str());
|
|
}
|
|
cmd_line* cmd_line::from_command_line(const char* cmdl)
|
|
{
|
|
cmd_line* cmd = new cmd_line();
|
|
|
|
cmd->cmd_line_ = cmdl;
|
|
parser::command_line_to_arguments(cmdl, cmd->arguments_);
|
|
|
|
return cmd;
|
|
}
|
|
|
|
size_t cmd_line::count(void)
|
|
{
|
|
return arguments_.size();
|
|
}
|
|
const char* cmd_line::parameter(int ind)
|
|
{
|
|
if(ind >= 0 && ind < arguments_.size())
|
|
return arguments_[ind].c_str();
|
|
else
|
|
return nullptr;
|
|
}
|
|
const char* cmd_line::parameter(const char* key)
|
|
{
|
|
for(int i = 0; i < (int)arguments_.size() - 1; ++i)
|
|
{
|
|
if(arguments_[i] == key)
|
|
return arguments_[i + 1].c_str();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
void cmd_line::remove(int ind)
|
|
{
|
|
if(ind >= 0 && ind < arguments_.size())
|
|
arguments_.erase(arguments_.begin() + ind);
|
|
}
|
|
void cmd_line::remove(const char* key)
|
|
{
|
|
for(int i = 0; i < (int)arguments_.size() - 1; ++i)
|
|
{
|
|
if(arguments_[i] == key)
|
|
{
|
|
arguments_.erase(arguments_.begin() + i);
|
|
arguments_.erase(arguments_.begin() + i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
std::string cmd_line::to_command_line(void)
|
|
{
|
|
std::string cmdl("");
|
|
|
|
for(auto& v: arguments_)
|
|
{
|
|
if(v.find(" ") != std::string::npos ||
|
|
v.find("\t") != std::string::npos)
|
|
{
|
|
cmdl += "\"" + v + "\"";
|
|
}
|
|
else
|
|
cmdl += v;
|
|
cmdl += " ";
|
|
}
|
|
|
|
return std::move(cmdl);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
std::vector<console_dispatcher::CMDROUT> console_dispatcher::super_cmd_routine_;
|
|
static std::string format_64_addr(uint64_t addr)
|
|
{
|
|
char buf[40] = {0};
|
|
uint32_t *ptr = (uint32_t*)&addr;
|
|
|
|
sprintf(buf, "%08X%08X", ptr[1], ptr[0]);
|
|
|
|
return buf;
|
|
}
|
|
|
|
console_dispatcher::console_dispatcher() : un_handle_(&console_dispatcher::unhandled), un_handle_param_(nullptr)
|
|
{}
|
|
console_dispatcher::~console_dispatcher()
|
|
{}
|
|
|
|
quit_cmd console_dispatcher::unhandled(cmd_line* cmd, void* param)
|
|
{
|
|
return QUIT_CMD_NONE;
|
|
}
|
|
void console_dispatcher::add_command(std::vector<CMDROUT>& routine, const char* cmd, quit_cmd(*handle)(cmd_line*, void*), void* param)
|
|
{
|
|
std::vector<console_dispatcher::CMDROUT>::iterator it = std::find(routine.begin(), routine.end(), cmd);
|
|
if(it == routine.end())
|
|
{
|
|
console_dispatcher::CMDROUT cr;
|
|
cr.cmd = cmd;
|
|
cr.param = param;
|
|
cr.routine = handle;
|
|
|
|
routine.push_back(std::move(cr));
|
|
}
|
|
else
|
|
{
|
|
it->param = param;
|
|
it->routine = handle;
|
|
}
|
|
}
|
|
|
|
quit_cmd console_dispatcher::dispatch_command(cmd_line* cmd)
|
|
{
|
|
if(*cmd->parameter(0) == 0)
|
|
return QUIT_CMD_NONE;
|
|
|
|
std::vector<console_dispatcher::CMDROUT>::iterator it = std::find(console_dispatcher::super_cmd_routine_.begin(),
|
|
console_dispatcher::super_cmd_routine_.end(),
|
|
cmd->parameter(0));
|
|
if(console_dispatcher::super_cmd_routine_.end() == it)
|
|
it = std::find(cmd_routine_.begin(), cmd_routine_.end(), cmd->parameter(0));
|
|
|
|
if(it == cmd_routine_.end())
|
|
return un_handle_(cmd, un_handle_param_);
|
|
|
|
cmd->remove(0);
|
|
|
|
return it->routine(cmd, it->param);
|
|
}
|
|
|
|
void console_dispatcher::add_supper_command_routine(const char* cmd, quit_cmd(*handle)(cmd_line*, void*), void* param)
|
|
{
|
|
console_dispatcher::add_command(console_dispatcher::super_cmd_routine_, cmd, handle, param);
|
|
}
|
|
void console_dispatcher::print_sector(uint8_t* data, size_t bytes, uint64_t addr)
|
|
{
|
|
std::string space("");
|
|
|
|
if(addr & 0x0f)
|
|
{
|
|
int l = addr & 0x0f;
|
|
|
|
space.append((16 - l) * 3, ' ');
|
|
if(l >= 8)
|
|
space.append(1, ' ');
|
|
addr >>= 4;
|
|
addr <<= 4;
|
|
printf("0x%s %s", format_64_addr(addr).c_str(), space.c_str());
|
|
space = "";
|
|
for(int i = 0; i < 16 - l && i < bytes; ++i)
|
|
{
|
|
printf("%02X ", *data);
|
|
if(*data >= ' ' && *data < 0x7f)
|
|
space.append(1, *data);
|
|
else
|
|
space += ".";
|
|
data++;
|
|
}
|
|
printf(" %s\n", space.c_str());
|
|
|
|
if(bytes <= 16 - l)
|
|
return;
|
|
bytes -= 16 - l;
|
|
addr += 0x10;
|
|
}
|
|
|
|
for(size_t i = 0; i < bytes; ++i)
|
|
{
|
|
if((i % 16) == 0)
|
|
{
|
|
if(space.length())
|
|
printf(" %s\n", space.c_str());
|
|
space = "";
|
|
printf("0x%s", format_64_addr(addr + i).c_str());
|
|
}
|
|
if((i % 8) == 0)
|
|
printf(" ");
|
|
|
|
printf("%02X ", *data);
|
|
if(*data >= ' ' && *data < 0x7f)
|
|
space.append(1, *data);
|
|
else
|
|
space += ".";
|
|
data++;
|
|
}
|
|
|
|
if(space.length())
|
|
{
|
|
if(space.length() < 16)
|
|
{
|
|
std::string fill("");
|
|
|
|
fill.append((16 - space.length()) * 3, ' ');
|
|
if(space.length() < 8)
|
|
fill.append(1, ' ');
|
|
printf("%s", fill.c_str());
|
|
}
|
|
printf("%s\n", space.c_str());
|
|
}
|
|
}
|
|
|
|
void console_dispatcher::add_command_routine(const char* cmd, quit_cmd(*handle)(cmd_line*, void*), void* param)
|
|
{
|
|
console_dispatcher::add_command(cmd_routine_, cmd, handle, param);
|
|
}
|
|
void console_dispatcher::set_unhandled_routine(quit_cmd(*handle)(cmd_line*, void*), void* param)
|
|
{
|
|
un_handle_ = handle ? handle : &console_dispatcher::unhandled;
|
|
un_handle_param_ = param;
|
|
}
|
|
quit_cmd console_dispatcher::run(const char* tips, const char* cmdl)
|
|
{
|
|
cmd_line* cmd = nullptr;
|
|
quit_cmd quit = QUIT_CMD_NONE;
|
|
|
|
if(cmdl && *cmdl)
|
|
{
|
|
cmd = cmd_line::from_command_line(cmdl);
|
|
quit = dispatch_command(cmd);
|
|
cmd->release();
|
|
}
|
|
while(quit == QUIT_CMD_NONE && (cmd = cmd_line::from_console(tips)))
|
|
{
|
|
if(cmd->count())
|
|
quit = dispatch_command(cmd);
|
|
cmd->release();
|
|
}
|
|
|
|
return quit;
|
|
}
|
|
|