View
@@ -11,7 +11,7 @@
struct LexVector* lv = *state; \
lexFree(lv); \
LexVectorClear(lv); \
- size_t adjusted = lexExpression(lv, STR, strlen(STR)); \
+ size_t adjusted = lexExpression(lv, STR, strlen(STR), ""); \
assert_false(adjusted > strlen(STR))
M_TEST_SUITE_SETUP(Lexer) {
@@ -715,6 +715,68 @@ M_TEST_DEFINE(lexNestedParentheticalExpression) {
assert_int_equal(LexVectorGetPointer(lv, 8)->type, TOKEN_CLOSE_PAREN_TYPE);
}
+M_TEST_DEFINE(lexSpaceSimple) {
+ LEX(" 1 ");
+
+ assert_int_equal(LexVectorSize(lv), 1);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1);
+}
+
+M_TEST_DEFINE(lexSpaceIdentifier) {
+ LEX(" x ");
+
+ assert_int_equal(LexVectorSize(lv), 1);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_IDENTIFIER_TYPE);
+ assert_string_equal(LexVectorGetPointer(lv, 0)->identifierValue, "x");
+}
+
+M_TEST_DEFINE(lexSpaceOperator) {
+ LEX("1 + 2");
+
+ assert_int_equal(LexVectorSize(lv), 3);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->uintValue, 1);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_OPERATOR_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->operatorValue, OP_ADD);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->uintValue, 2);
+}
+
+M_TEST_DEFINE(lexSpaceParen) {
+ LEX(" ( 1 + 2 ) ");
+
+ assert_int_equal(LexVectorSize(lv), 5);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD);
+ assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 3)->uintValue, 2);
+ assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_CLOSE_PAREN_TYPE);
+}
+
+M_TEST_DEFINE(lexSpaceParens) {
+ LEX(" ( 1 + ( 2 + 3 ) ) ");
+
+ assert_int_equal(LexVectorSize(lv), 9);
+ assert_int_equal(LexVectorGetPointer(lv, 0)->type, TOKEN_OPEN_PAREN_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 1)->uintValue, 1);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->type, TOKEN_OPERATOR_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 2)->operatorValue, OP_ADD);
+ assert_int_equal(LexVectorGetPointer(lv, 3)->type, TOKEN_OPEN_PAREN_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 4)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 4)->uintValue, 2);
+ assert_int_equal(LexVectorGetPointer(lv, 5)->type, TOKEN_OPERATOR_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 5)->operatorValue, OP_ADD);
+ assert_int_equal(LexVectorGetPointer(lv, 6)->type, TOKEN_UINT_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 6)->uintValue, 3);
+ assert_int_equal(LexVectorGetPointer(lv, 7)->type, TOKEN_CLOSE_PAREN_TYPE);
+ assert_int_equal(LexVectorGetPointer(lv, 8)->type, TOKEN_CLOSE_PAREN_TYPE);
+}
+
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(Lexer,
cmocka_unit_test(lexEmpty),
cmocka_unit_test(lexInt),
@@ -785,4 +847,9 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(Lexer,
cmocka_unit_test(lexCloseParen),
cmocka_unit_test(lexIdentifierCloseParen),
cmocka_unit_test(lexParentheticalExpression),
- cmocka_unit_test(lexNestedParentheticalExpression))
+ cmocka_unit_test(lexNestedParentheticalExpression),
+ cmocka_unit_test(lexSpaceSimple),
+ cmocka_unit_test(lexSpaceIdentifier),
+ cmocka_unit_test(lexSpaceOperator),
+ cmocka_unit_test(lexSpaceParen),
+ cmocka_unit_test(lexSpaceParens))
View
@@ -16,7 +16,7 @@ struct LPTest {
struct LPTest* lp = *state; \
lexFree(&lp->lv); \
LexVectorClear(&lp->lv); \
- size_t adjusted = lexExpression(&lp->lv, STR, strlen(STR)); \
+ size_t adjusted = lexExpression(&lp->lv, STR, strlen(STR), ""); \
assert_false(adjusted > strlen(STR)); \
struct ParseTree* tree = &lp->tree; \
parseLexedExpression(tree, &lp->lv)
@@ -30,8 +30,7 @@ M_TEST_SUITE_SETUP(Parser) {
M_TEST_SUITE_TEARDOWN(Parser) {
struct LPTest* lp = *state;
- parseFree(lp->tree.lhs); \
- parseFree(lp->tree.rhs); \
+ parseFree(&lp->tree); \
lexFree(&lp->lv);
LexVectorDeinit(&lp->lv);
free(lp);
View
@@ -6,6 +6,7 @@
#include <mgba/internal/lr35902/debugger/debugger.h>
#include <mgba/core/core.h>
+#include <mgba/internal/debugger/parser.h>
#include <mgba/internal/lr35902/decoder.h>
#include <mgba/internal/lr35902/lr35902.h>
#include <mgba/internal/lr35902/debugger/memory-debugger.h>
@@ -23,6 +24,13 @@ static struct LR35902DebugBreakpoint* _lookupBreakpoint(struct LR35902DebugBreak
return 0;
}
+static void _destroyBreakpoint(struct LR35902DebugBreakpoint* breakpoint) {
+ if (breakpoint->condition) {
+ parseFree(breakpoint->condition);
+ free(breakpoint->condition);
+ }
+}
+
static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
struct LR35902DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->pc);
@@ -32,6 +40,13 @@ static void LR35902DebuggerCheckBreakpoints(struct mDebuggerPlatform* d) {
if (breakpoint->segment >= 0 && debugger->cpu->memory.currentSegment(debugger->cpu, breakpoint->address) != breakpoint->segment) {
return;
}
+ if (breakpoint->condition) {
+ int32_t value;
+ int segment;
+ if (!mDebuggerEvaluateParseTree(d->p, breakpoint->condition, &value, &segment) || !(value || segment >= 0)) {
+ return;
+ }
+ }
struct mDebuggerEntryInfo info = {
.address = breakpoint->address
};
@@ -44,6 +59,7 @@ static void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform);
static void LR35902DebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info);
static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
+static void LR35902DebuggerSetConditionalBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment, struct ParseTree* condition);
static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
static void LR35902DebuggerSetWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment, enum mWatchpointType type);
static void LR35902DebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address, int segment);
@@ -59,6 +75,7 @@ struct mDebuggerPlatform* LR35902DebuggerPlatformCreate(void) {
platform->init = LR35902DebuggerInit;
platform->deinit = LR35902DebuggerDeinit;
platform->setBreakpoint = LR35902DebuggerSetBreakpoint;
+ platform->setConditionalBreakpoint = LR35902DebuggerSetConditionalBreakpoint;
platform->clearBreakpoint = LR35902DebuggerClearBreakpoint;
platform->setWatchpoint = LR35902DebuggerSetWatchpoint;
platform->clearWatchpoint = LR35902DebuggerClearWatchpoint;
@@ -79,6 +96,10 @@ void LR35902DebuggerInit(void* cpu, struct mDebuggerPlatform* platform) {
void LR35902DebuggerDeinit(struct mDebuggerPlatform* platform) {
struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
+ size_t i;
+ for (i = 0; i < LR35902DebugBreakpointListSize(&debugger->breakpoints); ++i) {
+ _destroyBreakpoint(LR35902DebugBreakpointListGetPointer(&debugger->breakpoints, i));
+ }
LR35902DebugBreakpointListDeinit(&debugger->breakpoints);
LR35902DebugWatchpointListDeinit(&debugger->watchpoints);
}
@@ -100,6 +121,15 @@ static void LR35902DebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t a
struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints);
breakpoint->address = address;
breakpoint->segment = segment;
+ breakpoint->condition = NULL;
+}
+
+static void LR35902DebuggerSetConditionalBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment, struct ParseTree* condition) {
+ struct LR35902Debugger* debugger = (struct LR35902Debugger*) d;
+ struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListAppend(&debugger->breakpoints);
+ breakpoint->address = address;
+ breakpoint->segment = segment;
+ breakpoint->condition = condition;
}
static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address, int segment) {
@@ -109,6 +139,7 @@ static void LR35902DebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t
for (i = 0; i < LR35902DebugBreakpointListSize(breakpoints); ++i) {
struct LR35902DebugBreakpoint* breakpoint = LR35902DebugBreakpointListGetPointer(breakpoints, i);
if (breakpoint->address == address && breakpoint->segment == segment) {
+ _destroyBreakpoint(LR35902DebugBreakpointListGetPointer(breakpoints, i));
LR35902DebugBreakpointListShift(breakpoints, i, 1);
}
}