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);
struct {
static struct {
const char* name;
DebuggerComamnd* command;
} debuggerCommands[] = {
} _debuggerCommands[] = {
{ "b", _setBreakpoint },
{ "break", _setBreakpoint },
{ "c", _continue },
@ -56,9 +56,10 @@ struct {
{ "i", _printStatus },
{ "info", _printStatus },
{ "n", _next },
{ "next", _next },
{ "p", _print },
{ "print", _print },
{ "p/x", _printHex },
{ "print", _print },
{ "print/x", _printHex },
{ "q", _quit },
{ "quit", _quit },
@ -66,9 +67,9 @@ struct {
{ "rh", _readHalfword },
{ "rw", _readWord },
{ "status", _printStatus },
{ "x", _breakInto },
{ "w", _setWatchpoint },
{ "watch", _setWatchpoint },
{ "x", _breakInto },
{ 0, 0 }
};
@ -254,8 +255,8 @@ enum _DVParseState {
PARSE_EXPECT_SUFFIX,
};
static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string) {
if (!string || !string[0] || string[0] == '\n') {
static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string, size_t length) {
if (!string || length < 1) {
return 0;
}
@ -263,9 +264,10 @@ static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* st
struct DebugVector dvTemp = { .type = INT_TYPE };
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];
++string;
--length;
switch (state) {
case PARSE_ROOT:
switch (token) {
@ -467,7 +469,7 @@ static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* st
dvTemp.intValue = current;
*dv = dvTemp;
if (string[0] == ' ') {
dv->next = _DVParse(debugger, string + 1);
dv->next = _DVParse(debugger, string + 1, length - 1);
}
}
return dv;
@ -483,12 +485,12 @@ static void _DVFree(struct DebugVector* dv) {
}
static int _parse(struct ARMDebugger* debugger, const char* line, size_t count) {
char* firstSpace = strchr(line, ' ');
const char* firstSpace = strchr(line, ' ');
size_t cmdLength;
struct DebugVector* dv = 0;
if (firstSpace) {
cmdLength = firstSpace - line;
dv = _DVParse(debugger, firstSpace + 1);
dv = _DVParse(debugger, firstSpace + 1, count - cmdLength - 1);
if (dv && dv->type == ERROR_TYPE) {
printf("Parse error\n");
_DVFree(dv);
@ -500,12 +502,12 @@ static int _parse(struct ARMDebugger* debugger, const char* line, size_t count)
int i;
const char* name;
for (i = 0; (name = debuggerCommands[i].name); ++i) {
for (i = 0; (name = _debuggerCommands[i].name); ++i) {
if (strlen(name) != cmdLength) {
continue;
}
if (strncasecmp(name, line, cmdLength) == 0) {
debuggerCommands[i].command(debugger, dv);
_debuggerCommands[i].command(debugger, dv);
_DVFree(dv);
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) {
debugger->cpu = cpu;
debugger->state = DEBUGGER_PAUSED;
@ -551,6 +579,10 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
debugger->elstate = el_init("gbac", stdin, stdout, stderr);
el_set(debugger->elstate, EL_PROMPT, _prompt);
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();
HistEvent ev;
history(debugger->histate, &ev, H_SETSIZE, 200);