mirror of https://github.com/mgba-emu/mgba.git
Basic tab-completion
This commit is contained in:
parent
01d8569262
commit
2ef64ede02
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue