Begin command line parsing

This commit is contained in:
Jeffrey Pfau 2013-04-13 01:23:41 -07:00
parent 10884de57a
commit f715534083

View File

@ -10,16 +10,32 @@
#include <unistd.h>
#include "linenoise.h"
typedef void (DebuggerComamnd)(struct ARMDebugger*);
struct DebugVector {
struct DebugVector* next;
enum DVType {
ERROR_TYPE,
INT_TYPE,
CHAR_TYPE
} type;
union {
int32_t intValue;
const char* charValue;
};
};
static void _breakInto(struct ARMDebugger*);
static void _printStatus(struct ARMDebugger*);
static void _quit(struct ARMDebugger*);
typedef void (DebuggerComamnd)(struct ARMDebugger*, struct DebugVector*);
static void _breakInto(struct ARMDebugger*, struct DebugVector*);
static void _print(struct ARMDebugger*, struct DebugVector*);
static void _printStatus(struct ARMDebugger*, struct DebugVector*);
static void _quit(struct ARMDebugger*, struct DebugVector*);
struct {
const char* name;
DebuggerComamnd* command;
} debuggerCommands[] = {
{ "p", _print },
{ "print", _print },
{ "i", _printStatus },
{ "info", _printStatus },
{ "q", _quit },
@ -45,13 +61,22 @@ static void _handleDeath(int sig) {
printf("No debugger attached!\n");
}
static void _breakInto(struct ARMDebugger* debugger) {
static void _breakInto(struct ARMDebugger* debugger, struct DebugVector* dv) {
(void)(debugger);
(void)(dv);
sig_t oldSignal = signal(SIGTRAP, _handleDeath);
kill(getpid(), SIGTRAP);
signal(SIGTRAP, oldSignal);
}
static void _print(struct ARMDebugger* debugger, struct DebugVector* dv) {
(void)(debugger);
for ( ; dv; dv = dv->next) {
printf(" %u", dv->intValue);
}
printf("\n");
}
static inline void _printLine(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
// TODO: write a disassembler
if (mode == MODE_ARM) {
@ -63,7 +88,8 @@ static inline void _printLine(struct ARMDebugger* debugger, uint32_t address, en
}
}
static void _printStatus(struct ARMDebugger* debugger) {
static void _printStatus(struct ARMDebugger* debugger, struct DebugVector* dv) {
(void)(dv);
int r;
for (r = 0; r < 4; ++r) {
printf("%08X %08X %08X %08X\n",
@ -83,15 +109,260 @@ static void _printStatus(struct ARMDebugger* debugger) {
_printLine(debugger, debugger->cpu->gprs[ARM_PC] - instructionLength, mode);
}
static void _quit(struct ARMDebugger* debugger) {
static void _quit(struct ARMDebugger* debugger, struct DebugVector* dv) {
(void)(dv);
debugger->state = DEBUGGER_EXITING;
}
enum _DVParseState {
PARSE_ERROR = -1,
PARSE_ROOT = 0,
PARSE_EXPECT_REGISTER,
PARSE_EXPECT_REGISTER_2,
PARSE_EXPECT_LR,
PARSE_EXPECT_PC,
PARSE_EXPECT_SP,
PARSE_EXPECT_DECIMAL,
PARSE_EXPECT_HEX,
PARSE_EXPECT_PREFIX,
PARSE_EXPECT_SUFFIX,
};
static struct DebugVector* _DVParse(struct ARMDebugger* debugger, const char* string) {
if (!string || !string[0]) {
return 0;
}
enum _DVParseState state = PARSE_ROOT;
struct DebugVector dvTemp = { .type = INT_TYPE };
uint32_t current = 0;
while (string[0] && string[0] != ' ' && state != PARSE_ERROR) {
char token = string[0];
++string;
switch (state) {
case PARSE_ROOT:
switch (token) {
case 'r':
state = PARSE_EXPECT_REGISTER;
break;
case 'p':
state = PARSE_EXPECT_PC;
break;
case 's':
state = PARSE_EXPECT_SP;
break;
case 'l':
state = PARSE_EXPECT_LR;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
state = PARSE_EXPECT_DECIMAL;
current = token - '0';
break;
case '0':
state = PARSE_EXPECT_PREFIX;
break;
case '$':
state = PARSE_EXPECT_HEX;
current = 0;
break;
default:
state = PARSE_ERROR;
break;
};
break;
case PARSE_EXPECT_LR:
switch (token) {
case 'r':
current = debugger->cpu->gprs[ARM_LR];
state = PARSE_EXPECT_SUFFIX;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_PC:
switch (token) {
case 'c':
current = debugger->cpu->gprs[ARM_PC];
state = PARSE_EXPECT_SUFFIX;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_SP:
switch (token) {
case 'p':
current = debugger->cpu->gprs[ARM_SP];
state = PARSE_EXPECT_SUFFIX;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_REGISTER:
switch (token) {
case '0':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
current = debugger->cpu->gprs[token - '0'];
state = PARSE_EXPECT_SUFFIX;
break;
case '1':
state = PARSE_EXPECT_REGISTER_2;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_REGISTER_2:
switch (token) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
current = debugger->cpu->gprs[token - '0' + 10];
state = PARSE_EXPECT_SUFFIX;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_DECIMAL:
switch (token) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// TODO: handle overflow
current *= 10;
current += token - '0';
break;
default:
state = PARSE_ERROR;
}
break;
case PARSE_EXPECT_HEX:
switch (token) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// TODO: handle overflow
current *= 16;
current += token - '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
// TODO: handle overflow
current *= 16;
current += token - 'A' + 10;
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
// TODO: handle overflow
current *= 16;
current += token - 'a' + 10;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_PREFIX:
switch (token) {
case 'X':
case 'x':
current = 0;
state = PARSE_EXPECT_HEX;
break;
default:
state = PARSE_ERROR;
break;
}
break;
case PARSE_EXPECT_SUFFIX:
// TODO
state = PARSE_ERROR;
break;
case PARSE_ERROR:
// This shouldn't be reached
break;
}
}
struct DebugVector* dv = malloc(sizeof(struct DebugVector));
if (state == PARSE_ERROR) {
dv->type = ERROR_TYPE;
dv->next = 0;
} else {
dvTemp.intValue = current;
*dv = dvTemp;
if (string[0] == ' ') {
dv->next = _DVParse(debugger, string + 1);
}
}
return dv;
}
static void _DVFree(struct DebugVector* dv) {
struct DebugVector* next;
while (dv) {
next = dv->next;
free(dv);
dv = next;
}
}
static void _parse(struct ARMDebugger* debugger, const char* line) {
char* firstSpace = strchr(line, ' ');
size_t cmdLength;
struct DebugVector* dv = 0;
if (firstSpace) {
cmdLength = line - firstSpace;
cmdLength = firstSpace - line;
dv = _DVParse(debugger, firstSpace + 1);
} else {
cmdLength = strlen(line);
}
@ -103,12 +374,15 @@ static void _parse(struct ARMDebugger* debugger, const char* line) {
continue;
}
if (strncasecmp(name, line, cmdLength) == 0) {
debuggerCommands[i].command(debugger);
debuggerCommands[i].command(debugger, dv);
_DVFree(dv);
linenoiseHistoryAdd(line);
return;
}
}
_DVFree(dv);
ARMRun(debugger->cpu);
_printStatus(debugger);
_printStatus(debugger, 0);
}
void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
@ -117,7 +391,7 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
void ARMDebuggerEnter(struct ARMDebugger* debugger) {
char* line;
_printStatus(debugger);
_printStatus(debugger, 0);
while ((line = linenoise("> "))) {
_parse(debugger, line);
free(line);