Basic tab-completion

This commit is contained in:
Jeffrey Pfau 2013-10-10 01:05:25 -07:00
parent 01d8569262
commit 2ef64ede02
1 changed files with 44 additions and 12 deletions

View File

@ -45,10 +45,10 @@ static void _setWatchpoint(struct ARMDebugger*, struct DebugVector*);
static void _breakIntoDefault(int signal); static void _breakIntoDefault(int signal);
struct { static struct {
const char* name; const char* name;
DebuggerComamnd* command; DebuggerComamnd* command;
} debuggerCommands[] = { } _debuggerCommands[] = {
{ "b", _setBreakpoint }, { "b", _setBreakpoint },
{ "break", _setBreakpoint }, { "break", _setBreakpoint },
{ "c", _continue }, { "c", _continue },
@ -56,9 +56,10 @@ struct {
{ "i", _printStatus }, { "i", _printStatus },
{ "info", _printStatus }, { "info", _printStatus },
{ "n", _next }, { "n", _next },
{ "next", _next },
{ "p", _print }, { "p", _print },
{ "print", _print },
{ "p/x", _printHex }, { "p/x", _printHex },
{ "print", _print },
{ "print/x", _printHex }, { "print/x", _printHex },
{ "q", _quit }, { "q", _quit },
{ "quit", _quit }, { "quit", _quit },
@ -66,9 +67,9 @@ struct {
{ "rh", _readHalfword }, { "rh", _readHalfword },
{ "rw", _readWord }, { "rw", _readWord },
{ "status", _printStatus }, { "status", _printStatus },
{ "x", _breakInto },
{ "w", _setWatchpoint }, { "w", _setWatchpoint },
{ "watch", _setWatchpoint }, { "watch", _setWatchpoint },
{ "x", _breakInto },
{ 0, 0 } { 0, 0 }
}; };
@ -254,8 +255,8 @@ enum _DVParseState {
PARSE_EXPECT_SUFFIX, PARSE_EXPECT_SUFFIX,
}; };
static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string) { static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string, size_t length) {
if (!string || !string[0] || string[0] == '\n') { if (!string || length < 1) {
return 0; return 0;
} }
@ -263,9 +264,10 @@ static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* st
struct DebugVector dvTemp = { .type = INT_TYPE }; struct DebugVector dvTemp = { .type = INT_TYPE };
uint32_t current = 0; uint32_t current = 0;
while (string[0] && string[0] != ' ' && string[0] != '\n' && state != PARSE_ERROR) { while (length > 0 && string[0] && string[0] != ' ' && state != PARSE_ERROR) {
char token = string[0]; char token = string[0];
++string; ++string;
--length;
switch (state) { switch (state) {
case PARSE_ROOT: case PARSE_ROOT:
switch (token) { switch (token) {
@ -467,7 +469,7 @@ static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* st
dvTemp.intValue = current; dvTemp.intValue = current;
*dv = dvTemp; *dv = dvTemp;
if (string[0] == ' ') { if (string[0] == ' ') {
dv->next = _DVParse(debugger, string + 1); dv->next = _DVParse(debugger, string + 1, length - 1);
} }
} }
return dv; return dv;
@ -483,12 +485,12 @@ static void _DVFree(struct DebugVector* dv) {
} }
static int _parse(struct ARMDebugger* debugger, const char* line, size_t count) { static int _parse(struct ARMDebugger* debugger, const char* line, size_t count) {
char* firstSpace = strchr(line, ' '); const char* firstSpace = strchr(line, ' ');
size_t cmdLength; size_t cmdLength;
struct DebugVector* dv = 0; struct DebugVector* dv = 0;
if (firstSpace) { if (firstSpace) {
cmdLength = firstSpace - line; cmdLength = firstSpace - line;
dv = _DVParse(debugger, firstSpace + 1); dv = _DVParse(debugger, firstSpace + 1, count - cmdLength - 1);
if (dv && dv->type == ERROR_TYPE) { if (dv && dv->type == ERROR_TYPE) {
printf("Parse error\n"); printf("Parse error\n");
_DVFree(dv); _DVFree(dv);
@ -500,12 +502,12 @@ static int _parse(struct ARMDebugger* debugger, const char* line, size_t count)
int i; int i;
const char* name; const char* name;
for (i = 0; (name = debuggerCommands[i].name); ++i) { for (i = 0; (name = _debuggerCommands[i].name); ++i) {
if (strlen(name) != cmdLength) { if (strlen(name) != cmdLength) {
continue; continue;
} }
if (strncasecmp(name, line, cmdLength) == 0) { if (strncasecmp(name, line, cmdLength) == 0) {
debuggerCommands[i].command(debugger, dv); _debuggerCommands[i].command(debugger, dv);
_DVFree(dv); _DVFree(dv);
return 1; return 1;
} }
@ -543,6 +545,32 @@ static void _commandLine(struct ARMDebugger* debugger) {
} }
} }
static unsigned char _tabComplete(EditLine* elstate, int ch) {
(void)(ch);
const LineInfo* li = el_line(elstate);
const char* commandPtr;
int cmd = 0, len = 0;
const char* name = 0;
for (commandPtr = li->buffer; commandPtr <= li->cursor; ++commandPtr, ++len) {
for (; (name = _debuggerCommands[cmd].name); ++cmd) {
int cmp = strncasecmp(name, li->buffer, len);
if (cmp > 0) {
return CC_ERROR;
}
if (cmp == 0) {
break;
}
}
}
if (_debuggerCommands[cmd + 1].name && strncasecmp(_debuggerCommands[cmd + 1].name, li->buffer, len - 1) == 0) {
return CC_ERROR;
}
name += len - 1;
el_insertstr(elstate, name);
el_insertstr(elstate, " ");
return CC_REDISPLAY;
}
void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) { void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
debugger->cpu = cpu; debugger->cpu = cpu;
debugger->state = DEBUGGER_PAUSED; debugger->state = DEBUGGER_PAUSED;
@ -551,6 +579,10 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
debugger->elstate = el_init("gbac", stdin, stdout, stderr); debugger->elstate = el_init("gbac", stdin, stdout, stderr);
el_set(debugger->elstate, EL_PROMPT, _prompt); el_set(debugger->elstate, EL_PROMPT, _prompt);
el_set(debugger->elstate, EL_EDITOR, "emacs"); el_set(debugger->elstate, EL_EDITOR, "emacs");
el_set(debugger->elstate, EL_CLIENTDATA, debugger);
el_set(debugger->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete);
el_set(debugger->elstate, EL_BIND, "\t", "tab-complete", 0);
debugger->histate = history_init(); debugger->histate = history_init();
HistEvent ev; HistEvent ev;
history(debugger->histate, &ev, H_SETSIZE, 200); history(debugger->histate, &ev, H_SETSIZE, 200);