#include "cmd.h" namespace parser { static void command_line_to_arguments(const char* cmdl, std::vector& 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::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& routine, const char* cmd, quit_cmd(*handle)(cmd_line*, void*), void* param) { std::vector::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::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; }