code_util/cmd.cpp

309 lines
6.2 KiB
C++
Raw Permalink Normal View History

2023-02-24 09:24:48 +00:00
#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;
}