From c692006b9d272cebfa35c023335cd0bce2021854 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 29 Dec 2017 00:02:20 -0500 Subject: [PATCH] Debugger: Expose parser evaluation --- include/mgba/internal/debugger/parser.h | 5 +- src/debugger/cli-debugger.c | 83 +----------------------- src/debugger/parser.c | 85 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 82 deletions(-) diff --git a/include/mgba/internal/debugger/parser.h b/include/mgba/internal/debugger/parser.h index b111849fc..eecf7e80d 100644 --- a/include/mgba/internal/debugger/parser.h +++ b/include/mgba/internal/debugger/parser.h @@ -10,8 +10,6 @@ CXX_GUARD_START -#include - enum Operation { OP_ASSIGN, OP_ADD, @@ -62,6 +60,9 @@ void parseLexedExpression(struct ParseTree* tree, struct LexVector* lv); void lexFree(struct LexVector* lv); void parseFree(struct ParseTree* tree); +struct mDebugger; +bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment); + CXX_GUARD_END #endif diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index b85308692..28887a1f2 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -538,85 +538,6 @@ static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv debugger->system->printStatus(debugger->system); } -static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) { - switch (operation) { - case OP_ASSIGN: - current = next; - break; - case OP_ADD: - current += next; - break; - case OP_SUBTRACT: - current -= next; - break; - case OP_MULTIPLY: - current *= next; - break; - case OP_DIVIDE: - if (next != 0) { - current /= next; - } else { - dv->type = CLIDV_ERROR_TYPE; - return 0; - } - break; - case OP_AND: - current &= next; - break; - case OP_OR: - current |= next; - break; - case OP_XOR: - current ^= next; - break; - case OP_LESS: - current = current < next; - break; - case OP_GREATER: - current = current > next; - break; - case OP_EQUAL: - current = current == next; - break; - case OP_LE: - current = current <= next; - break; - case OP_GE: - current = current >= next; - break; - } - return current; -} - -static void _evaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) { - int32_t lhs, rhs; - switch (tree->token.type) { - case TOKEN_UINT_TYPE: - dv->intValue = tree->token.uintValue; - break; - case TOKEN_SEGMENT_TYPE: - _evaluateParseTree(debugger, tree->lhs, dv); - dv->segmentValue = dv->intValue; - _evaluateParseTree(debugger, tree->rhs, dv); - break; - case TOKEN_OPERATOR_TYPE: - _evaluateParseTree(debugger, tree->lhs, dv); - lhs = dv->intValue; - _evaluateParseTree(debugger, tree->rhs, dv); - rhs = dv->intValue; - dv->intValue = _performOperation(tree->token.operatorValue, lhs, rhs, dv); - break; - case TOKEN_IDENTIFIER_TYPE: - if (mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, &dv->intValue, &dv->segmentValue)) { - break; - } - // Fall through - case TOKEN_ERROR_TYPE: - default: - dv->type = CLIDV_ERROR_TYPE; - } -} - struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length) { if (!string || length < 1) { return 0; @@ -636,7 +557,9 @@ struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* stri if (tree.token.type == TOKEN_ERROR_TYPE) { dvTemp.type = CLIDV_ERROR_TYPE; } else { - _evaluateParseTree(&debugger->d, &tree, &dvTemp); + if (!mDebuggerEvaluateParseTree(&debugger->d, &tree, &dvTemp.intValue, &dvTemp.segmentValue)) { + dvTemp.type = CLIDV_ERROR_TYPE; + } } parseFree(tree.lhs); diff --git a/src/debugger/parser.c b/src/debugger/parser.c index ff9e28cdf..9c53cc9f3 100644 --- a/src/debugger/parser.c +++ b/src/debugger/parser.c @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include enum LexState { @@ -509,3 +510,87 @@ void parseFree(struct ParseTree* tree) { } free(tree); } + +static bool _performOperation(enum Operation operation, int32_t current, int32_t next, int32_t* value) { + switch (operation) { + case OP_ASSIGN: + current = next; + break; + case OP_ADD: + current += next; + break; + case OP_SUBTRACT: + current -= next; + break; + case OP_MULTIPLY: + current *= next; + break; + case OP_DIVIDE: + if (next != 0) { + current /= next; + } else { + return false; + } + break; + case OP_AND: + current &= next; + break; + case OP_OR: + current |= next; + break; + case OP_XOR: + current ^= next; + break; + case OP_LESS: + current = current < next; + break; + case OP_GREATER: + current = current > next; + break; + case OP_EQUAL: + current = current == next; + break; + case OP_LE: + current = current <= next; + break; + case OP_GE: + current = current >= next; + break; + } + *value = current; + return true; +} + +bool mDebuggerEvaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, int32_t* value, int* segment) { + if (!value) { + return false; + } + int32_t lhs, rhs; + switch (tree->token.type) { + case TOKEN_UINT_TYPE: + if (segment) { + *segment = -1; + } + *value = tree->token.uintValue; + return true; + case TOKEN_SEGMENT_TYPE: + if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, value, segment)) { + return false; + } + return mDebuggerEvaluateParseTree(debugger, tree->lhs, segment, NULL); + case TOKEN_OPERATOR_TYPE: + if (!mDebuggerEvaluateParseTree(debugger, tree->lhs, &lhs, segment)) { + return false; + } + if (!mDebuggerEvaluateParseTree(debugger, tree->rhs, &rhs, segment)) { + return false; + } + return _performOperation(tree->token.operatorValue, lhs, rhs, value); + case TOKEN_IDENTIFIER_TYPE: + return mDebuggerLookupIdentifier(debugger, tree->token.identifierValue, value, segment); + case TOKEN_ERROR_TYPE: + default: + break; + } + return false; +}