Add customizable parsers per command
Jeffrey Pfau jeffrey@endrift.com
Tue, 02 Sep 2014 21:54:19 -0700
1 files changed,
91 insertions(+),
44 deletions(-)
jump to
M
src/debugger/cli-debugger.c
→
src/debugger/cli-debugger.c
@@ -17,7 +17,7 @@ DV_CHAR_TYPE
} type; union { int32_t intValue; - const char* charValue; + char* charValue; }; };@@ -25,7 +25,11 @@ static const char* ERROR_MISSING_ARGS = "Arguments missing";
static struct CLIDebugger* _activeDebugger; -typedef void (DebuggerCommand)(struct CLIDebugger*, struct DebugVector*); +typedef void (*DebuggerCommand)(struct CLIDebugger*, struct DebugVector*); +typedef struct DebugVector* (*DVParser)(struct CLIDebugger* debugger, const char* string, size_t length); + +static struct DebugVector* _DVParse(struct CLIDebugger* debugger, const char* string, size_t length); +static struct DebugVector* _DVStringParse(struct CLIDebugger* debugger, const char* string, size_t length); static void _breakInto(struct CLIDebugger*, struct DebugVector*); static void _continue(struct CLIDebugger*, struct DebugVector*);@@ -52,43 +56,44 @@ static void _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
static struct { const char* name; - DebuggerCommand* command; + DebuggerCommand command; + DVParser parser; const char* summary; } _debuggerCommands[] = { - { "b", _setBreakpoint, "Set a breakpoint" }, - { "break", _setBreakpoint, "Set a breakpoint" }, - { "c", _continue, "Continue execution" }, - { "continue", _continue, "Continue execution" }, - { "d", _clearBreakpoint, "Delete a breakpoint" }, - { "delete", _clearBreakpoint, "Delete a breakpoint" }, - { "dis", _disassemble, "Disassemble instructions" }, - { "dis/a", _disassembleArm, "Disassemble instructions as ARM" }, - { "dis/t", _disassembleThumb, "Disassemble instructions as Thumb" }, - { "disasm", _disassemble, "Disassemble instructions" }, - { "disasm/a", _disassembleArm, "Disassemble instructions as ARM" }, - { "disasm/t", _disassembleThumb, "Disassemble instructions as Thumb" }, - { "h", _printHelp, "Print help" }, - { "help", _printHelp, "Print help" }, - { "i", _printStatus, "Print the current status" }, - { "info", _printStatus, "Print the current status" }, - { "n", _next, "Execute next instruction" }, - { "next", _next, "Execute next instruction" }, - { "p", _print, "Print a value" }, - { "p/t", _printBin, "Print a value as binary" }, - { "p/x", _printHex, "Print a value as hexadecimal" }, - { "print", _print, "Print a value" }, - { "print/t", _printBin, "Print a value as binary" }, - { "print/x", _printHex, "Print a value as hexadecimal" }, - { "q", _quit, "Quit the emulator" }, - { "quit", _quit, "Quit the emulator" }, - { "rb", _readByte, "Read a byte from a specified offset" }, - { "rh", _readHalfword, "Read a halfword from a specified offset" }, - { "rw", _readWord, "Read a word from a specified offset" }, - { "status", _printStatus, "Print the current status" }, - { "w", _setWatchpoint, "Set a watchpoint" }, - { "watch", _setWatchpoint, "Set a watchpoint" }, - { "x", _breakInto, "Break into attached debugger (for developers)" }, - { 0, 0, 0 } + { "b", _setBreakpoint, _DVParse, "Set a breakpoint" }, + { "break", _setBreakpoint, _DVParse, "Set a breakpoint" }, + { "c", _continue, 0, "Continue execution" }, + { "continue", _continue, 0, "Continue execution" }, + { "d", _clearBreakpoint, _DVParse, "Delete a breakpoint" }, + { "delete", _clearBreakpoint, _DVParse, "Delete a breakpoint" }, + { "dis", _disassemble, _DVParse, "Disassemble instructions" }, + { "dis/a", _disassembleArm, _DVParse, "Disassemble instructions as ARM" }, + { "dis/t", _disassembleThumb, _DVParse, "Disassemble instructions as Thumb" }, + { "disasm", _disassemble, _DVParse, "Disassemble instructions" }, + { "disasm/a", _disassembleArm, _DVParse, "Disassemble instructions as ARM" }, + { "disasm/t", _disassembleThumb, _DVParse, "Disassemble instructions as Thumb" }, + { "h", _printHelp, _DVStringParse, "Print help" }, + { "help", _printHelp, _DVStringParse, "Print help" }, + { "i", _printStatus, 0, "Print the current status" }, + { "info", _printStatus, 0, "Print the current status" }, + { "n", _next, 0, "Execute next instruction" }, + { "next", _next, 0, "Execute next instruction" }, + { "p", _print, _DVParse, "Print a value" }, + { "p/t", _printBin, _DVParse, "Print a value as binary" }, + { "p/x", _printHex, _DVParse, "Print a value as hexadecimal" }, + { "print", _print, _DVParse, "Print a value" }, + { "print/t", _printBin, _DVParse, "Print a value as binary" }, + { "print/x", _printHex, _DVParse, "Print a value as hexadecimal" }, + { "q", _quit, 0, "Quit the emulator" }, + { "quit", _quit, 0, "Quit the emulator" }, + { "rb", _readByte, _DVParse, "Read a byte from a specified offset" }, + { "rh", _readHalfword, _DVParse, "Read a halfword from a specified offset" }, + { "rw", _readWord, _DVParse, "Read a word from a specified offset" }, + { "status", _printStatus, 0, "Print the current status" }, + { "w", _setWatchpoint, _DVParse, "Set a watchpoint" }, + { "watch", _setWatchpoint, _DVParse, "Set a watchpoint" }, + { "x", _breakInto, 0, "Break into attached debugger (for developers)" }, + { 0, 0, 0, 0 } }; static inline void _printPSR(union PSR psr) {@@ -219,7 +224,7 @@ } else {
int i; for (i = 0; _debuggerCommands[i].name; ++i) { if (strcmp(_debuggerCommands[i].name, dv->charValue) == 0) { - printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); + printf(" %s\n", _debuggerCommands[i].summary); } } }@@ -441,10 +446,44 @@ }
return dv; } +static struct DebugVector* _DVStringParse(struct CLIDebugger* debugger, const char* string, size_t length) { + if (!string || length < 1) { + return 0; + } + + struct DebugVector dvTemp = { .type = DV_CHAR_TYPE }; + + size_t adjusted; + const char* next = strchr(string, ' '); + if (next) { + adjusted = next - string; + } else { + adjusted = length; + } + dvTemp.charValue = malloc(adjusted); + strncpy(dvTemp.charValue, string, adjusted); + + length -= adjusted; + string += adjusted; + + struct DebugVector* dv = malloc(sizeof(struct DebugVector)); + *dv = dvTemp; + if (string[0] == ' ') { + dv->next = _DVStringParse(debugger, string + 1, length - 1); + if (dv->next && dv->next->type == DV_ERROR_TYPE) { + dv->type = DV_ERROR_TYPE; + } + } + return dv; +} + static void _DVFree(struct DebugVector* dv) { struct DebugVector* next; while (dv) { next = dv->next; + if (dv->type == DV_CHAR_TYPE) { + free(dv->charValue); + } free(dv); dv = next; }@@ -456,12 +495,6 @@ size_t cmdLength;
struct DebugVector* dv = 0; if (firstSpace) { cmdLength = firstSpace - line; - dv = _DVParse(debugger, firstSpace + 1, count - cmdLength - 1); - if (dv && dv->type == DV_ERROR_TYPE) { - printf("Parse error\n"); - _DVFree(dv); - return false; - } } else { cmdLength = count; }@@ -473,6 +506,20 @@ if (strlen(name) != cmdLength) {
continue; } if (strncasecmp(name, line, cmdLength) == 0) { + if (_debuggerCommands[i].parser) { + if (firstSpace) { + dv = _debuggerCommands[i].parser(debugger, firstSpace + 1, count - cmdLength - 1); + if (dv && dv->type == DV_ERROR_TYPE) { + printf("Parse error\n"); + _DVFree(dv); + return false; + } + } else { + printf("Wrong number of arguments"); + } + } else if (firstSpace) { + printf("Wrong number of arguments"); + } _debuggerCommands[i].command(debugger, dv); _DVFree(dv); return true;