From 90463a4a6ceb190d17b70a22a83d2d799e38ace9 Mon Sep 17 00:00:00 2001 From: chaoticgd <43898262+chaoticgd@users.noreply.github.com> Date: Sun, 1 Sep 2024 19:13:14 +0100 Subject: [PATCH] Debugger: Bring back the expression parser --- pcsx2-qt/Debugger/BreakpointDialog.cpp | 26 ++-- pcsx2-qt/Debugger/DisassemblyWidget.cpp | 11 +- pcsx2-qt/Debugger/MemoryViewWidget.cpp | 11 +- pcsx2-qt/Debugger/SymbolTree/SymbolTreeNode.h | 1 + .../Debugger/SymbolTree/SymbolTreeWidgets.cpp | 25 +++- .../Debugger/SymbolTree/SymbolTreeWidgets.h | 4 +- pcsx2/DebugTools/DebugInterface.cpp | 120 +++++++++++++----- pcsx2/DebugTools/DebugInterface.h | 1 + pcsx2/DebugTools/ExpressionParser.cpp | 63 ++++++--- pcsx2/DebugTools/ExpressionParser.h | 2 +- 10 files changed, 183 insertions(+), 81 deletions(-) diff --git a/pcsx2-qt/Debugger/BreakpointDialog.cpp b/pcsx2-qt/Debugger/BreakpointDialog.cpp index 285bde5be7..1d5c511094 100644 --- a/pcsx2-qt/Debugger/BreakpointDialog.cpp +++ b/pcsx2-qt/Debugger/BreakpointDialog.cpp @@ -93,10 +93,9 @@ void BreakpointDialog::accept() PostfixExpression expr; u64 address; - if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit().constData(), expr) || - !m_cpu->parseExpression(expr, address)) + if (!m_cpu->evaluateExpression(m_ui.txtAddress->text().toStdString().c_str(), address)) { - QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text())); + QMessageBox::warning(this, tr("Invalid Address"), getExpressionError()); return; } @@ -109,9 +108,9 @@ void BreakpointDialog::accept() bp->hasCond = true; bp->cond.debug = m_cpu; - if (!m_cpu->initExpression(m_ui.txtCondition->text().toLocal8Bit().constData(), expr)) + if (!m_cpu->initExpression(m_ui.txtCondition->text().toStdString().c_str(), expr)) { - QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(getExpressionError())); + QMessageBox::warning(this, tr("Invalid Condition"), getExpressionError()); return; } @@ -121,21 +120,17 @@ void BreakpointDialog::accept() } if (auto* mc = std::get_if(&m_bp_mc)) { - PostfixExpression expr; - u64 startAddress; - if (!m_cpu->initExpression(m_ui.txtAddress->text().toLocal8Bit().constData(), expr) || - !m_cpu->parseExpression(expr, startAddress)) + if (!m_cpu->evaluateExpression(m_ui.txtAddress->text().toStdString().c_str(), startAddress)) { - QMessageBox::warning(this, tr("Error"), tr("Invalid address \"%1\"").arg(m_ui.txtAddress->text())); + QMessageBox::warning(this, tr("Invalid Address"), getExpressionError()); return; } u64 size; - if (!m_cpu->initExpression(m_ui.txtSize->text().toLocal8Bit(), expr) || - !m_cpu->parseExpression(expr, size) || !size) + if (!m_cpu->evaluateExpression(m_ui.txtSize->text().toStdString().c_str(), size) || !size) { - QMessageBox::warning(this, tr("Error"), tr("Invalid size \"%1\"").arg(m_ui.txtSize->text())); + QMessageBox::warning(this, tr("Invalid Size"), getExpressionError()); return; } @@ -147,9 +142,10 @@ void BreakpointDialog::accept() mc->hasCond = true; mc->cond.debug = m_cpu; - if (!m_cpu->initExpression(m_ui.txtCondition->text().toLocal8Bit().constData(), expr)) + PostfixExpression expr; + if (!m_cpu->initExpression(m_ui.txtCondition->text().toStdString().c_str(), expr)) { - QMessageBox::warning(this, tr("Error"), tr("Invalid condition \"%1\"").arg(getExpressionError())); + QMessageBox::warning(this, tr("Invalid Condition"), getExpressionError()); return; } diff --git a/pcsx2-qt/Debugger/DisassemblyWidget.cpp b/pcsx2-qt/Debugger/DisassemblyWidget.cpp index b9e41af245..4f75ad08a0 100644 --- a/pcsx2-qt/Debugger/DisassemblyWidget.cpp +++ b/pcsx2-qt/Debugger/DisassemblyWidget.cpp @@ -163,21 +163,20 @@ void DisassemblyWidget::contextFollowBranch() void DisassemblyWidget::contextGoToAddress() { bool ok; - const QString targetString = QInputDialog::getText(this, tr("Go to address"), "", + const QString targetString = QInputDialog::getText(this, tr("Go To In Disassembly"), "", QLineEdit::Normal, "", &ok); if (!ok) return; - const u32 targetAddress = targetString.toUInt(&ok, 16) & ~3; - - if (!ok) + u64 address = 0; + if (!m_cpu->evaluateExpression(targetString.toStdString().c_str(), address)) { - QMessageBox::warning(this, tr("Go to address error"), tr("Invalid address")); + QMessageBox::warning(this, tr("Cannot Go To"), getExpressionError()); return; } - gotoAddressAndSetFocus(targetAddress); + gotoAddressAndSetFocus(static_cast(address) & ~3); } void DisassemblyWidget::contextAddFunction() diff --git a/pcsx2-qt/Debugger/MemoryViewWidget.cpp b/pcsx2-qt/Debugger/MemoryViewWidget.cpp index f675b6bf4d..f635dbc632 100644 --- a/pcsx2-qt/Debugger/MemoryViewWidget.cpp +++ b/pcsx2-qt/Debugger/MemoryViewWidget.cpp @@ -592,21 +592,20 @@ void MemoryViewWidget::contextPaste() void MemoryViewWidget::contextGoToAddress() { bool ok; - QString targetString = QInputDialog::getText(this, tr("Go to address"), "", + QString targetString = QInputDialog::getText(this, tr("Go To In Memory View"), "", QLineEdit::Normal, "", &ok); if (!ok) return; - const u32 targetAddress = targetString.toUInt(&ok, 16); - - if (!ok) + u64 address = 0; + if (!m_cpu->evaluateExpression(targetString.toStdString().c_str(), address)) { - QMessageBox::warning(this, "Go to address error", "Invalid address"); + QMessageBox::warning(this, tr("Cannot Go To"), getExpressionError()); return; } - gotoAddress(targetAddress); + gotoAddress(static_cast(address)); } void MemoryViewWidget::mouseDoubleClickEvent(QMouseEvent* event) diff --git a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeNode.h b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeNode.h index 53071914fd..1671cb7f98 100644 --- a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeNode.h +++ b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeNode.h @@ -25,6 +25,7 @@ public: Tag tag = OBJECT; ccc::MultiSymbolHandle symbol; QString name; + QString mangled_name; SymbolTreeLocation location; bool is_location_editable = false; std::optional size; diff --git a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.cpp b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.cpp index d920b9861a..647ebe8dfc 100644 --- a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.cpp +++ b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.cpp @@ -362,6 +362,13 @@ void SymbolTreeWidget::setupMenu() connect(copy_name, &QAction::triggered, this, &SymbolTreeWidget::onCopyName); m_context_menu->addAction(copy_name); + if (m_flags & ALLOW_MANGLED_NAME_ACTIONS) + { + QAction* copy_mangled_name = new QAction(tr("Copy Mangled Name"), this); + connect(copy_mangled_name, &QAction::triggered, this, &SymbolTreeWidget::onCopyMangledName); + m_context_menu->addAction(copy_mangled_name); + } + QAction* copy_location = new QAction(tr("Copy Location"), this); connect(copy_location, &QAction::triggered, this, &SymbolTreeWidget::onCopyLocation); m_context_menu->addAction(copy_location); @@ -484,6 +491,18 @@ void SymbolTreeWidget::onCopyName() QApplication::clipboard()->setText(node->name); } +void SymbolTreeWidget::onCopyMangledName() +{ + SymbolTreeNode* node = currentNode(); + if (!node) + return; + + if (!node->mangled_name.isEmpty()) + QApplication::clipboard()->setText(node->mangled_name); + else + QApplication::clipboard()->setText(node->name); +} + void SymbolTreeWidget::onCopyLocation() { SymbolTreeNode* node = currentNode(); @@ -611,7 +630,7 @@ SymbolTreeNode* SymbolTreeWidget::currentNode() // ***************************************************************************** FunctionTreeWidget::FunctionTreeWidget(DebugInterface& cpu, QWidget* parent) - : SymbolTreeWidget(ALLOW_GROUPING, 4, cpu, parent) + : SymbolTreeWidget(ALLOW_GROUPING | ALLOW_MANGLED_NAME_ACTIONS, 4, cpu, parent) { } @@ -652,6 +671,7 @@ std::unique_ptr FunctionTreeWidget::buildNode( std::unique_ptr node = std::make_unique(); node->name = std::move(work.name); + node->mangled_name = QString::fromStdString(function.mangled_name()); node->location = SymbolTreeLocation(SymbolTreeLocation::MEMORY, function.address().value); node->size = function.size(); node->symbol = ccc::MultiSymbolHandle(function); @@ -694,7 +714,7 @@ void FunctionTreeWidget::onNewButtonPressed() // ***************************************************************************** GlobalVariableTreeWidget::GlobalVariableTreeWidget(DebugInterface& cpu, QWidget* parent) - : SymbolTreeWidget(ALLOW_GROUPING | ALLOW_SORTING_BY_IF_TYPE_IS_KNOWN | ALLOW_TYPE_ACTIONS, 1, cpu, parent) + : SymbolTreeWidget(ALLOW_GROUPING | ALLOW_SORTING_BY_IF_TYPE_IS_KNOWN | ALLOW_TYPE_ACTIONS | ALLOW_MANGLED_NAME_ACTIONS, 1, cpu, parent) { } @@ -777,6 +797,7 @@ std::unique_ptr GlobalVariableTreeWidget::buildNode( { const ccc::GlobalVariable& global_variable = static_cast(*work.symbol); + node->mangled_name = QString::fromStdString(global_variable.mangled_name()); if (global_variable.type()) node->type = ccc::NodeHandle(global_variable, global_variable.type()); node->location = SymbolTreeLocation(SymbolTreeLocation::MEMORY, global_variable.address().value); diff --git a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.h b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.h index 6c0747c15b..ca5c3c01fa 100644 --- a/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.h +++ b/pcsx2-qt/Debugger/SymbolTree/SymbolTreeWidgets.h @@ -84,6 +84,7 @@ protected: void onDeleteButtonPressed(); void onCopyName(); + void onCopyMangledName(); void onCopyLocation(); void onRenameSymbol(); void onGoToInDisassembly(); @@ -117,7 +118,8 @@ protected: NO_SYMBOL_TREE_FLAGS = 0, ALLOW_GROUPING = 1 << 0, ALLOW_SORTING_BY_IF_TYPE_IS_KNOWN = 1 << 1, - ALLOW_TYPE_ACTIONS = 1 << 2 + ALLOW_TYPE_ACTIONS = 1 << 2, + ALLOW_MANGLED_NAME_ACTIONS = 1 << 3 }; u32 m_flags; diff --git a/pcsx2/DebugTools/DebugInterface.cpp b/pcsx2/DebugTools/DebugInterface.cpp index f3087cf7a8..05ff1bef41 100644 --- a/pcsx2/DebugTools/DebugInterface.cpp +++ b/pcsx2/DebugTools/DebugInterface.cpp @@ -10,17 +10,13 @@ #include "GS.h" // Required for gsNonMirroredRead() #include "Counters.h" +#include "Host.h" #include "R3000A.h" #include "IopMem.h" #include "VMManager.h" #include "common/StringUtil.h" -#ifdef __clang__ -// TODO: The sprintf() usage here needs to be rewritten... -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif - R5900DebugInterface r5900Debug; R3000DebugInterface r3000Debug; @@ -45,8 +41,20 @@ enum ReferenceIndexType class MipsExpressionFunctions : public IExpressionFunctions { public: - explicit MipsExpressionFunctions(DebugInterface* cpu) - : cpu(cpu){}; + explicit MipsExpressionFunctions(DebugInterface* cpu, bool enumerateSymbols) + : m_cpu(cpu) + { + if (!enumerateSymbols) + return; + + m_cpu->GetSymbolGuardian().Read([&](const ccc::SymbolDatabase& database) { + for (const ccc::Function& function : database.functions) + m_mangled_function_names_to_handles.emplace(function.mangled_name(), function.handle()); + + for (const ccc::GlobalVariable& global : database.global_variables) + m_mangled_global_names_to_handles.emplace(global.mangled_name(), global.handle()); + }); + } virtual bool parseReference(char* str, u64& referenceIndex) { @@ -54,7 +62,7 @@ public: { char reg[8]; std::snprintf(reg, std::size(reg), "r%d", i); - if (StringUtil::Strcasecmp(str, reg) == 0 || StringUtil::Strcasecmp(str, cpu->getRegisterName(0, i)) == 0) + if (StringUtil::Strcasecmp(str, reg) == 0 || StringUtil::Strcasecmp(str, m_cpu->getRegisterName(0, i)) == 0) { referenceIndex = i; return true; @@ -108,27 +116,62 @@ public: virtual bool parseSymbol(char* str, u64& symbolValue) { - SymbolInfo symbol = cpu->GetSymbolGuardian().SymbolWithName(std::string(str)); - if (!symbol.address.valid()) - return false; + bool success = false; + m_cpu->GetSymbolGuardian().Read([&](const ccc::SymbolDatabase& database) { + std::string name = str; - symbolValue = symbol.address.value; - return true; + // Check for mangled function names. + auto function_iterator = m_mangled_function_names_to_handles.find(name); + if (function_iterator != m_mangled_function_names_to_handles.end()) + { + const ccc::Function* function = database.functions.symbol_from_handle(function_iterator->second); + if (function && function->address().valid()) + { + symbolValue = function->address().value; + success = true; + return; + } + } + + // Check for mangled global variable names. + auto global_iterator = m_mangled_global_names_to_handles.find(name); + if (global_iterator != m_mangled_global_names_to_handles.end()) + { + const ccc::GlobalVariable* global = database.global_variables.symbol_from_handle(global_iterator->second); + if (global && global->address().valid()) + { + symbolValue = global->address().value; + success = true; + return; + } + } + + // Check for regular unmangled names. + const ccc::Symbol* symbol = database.symbol_with_name(name); + if (symbol && symbol->address().valid()) + { + symbolValue = symbol->address().value; + success = true; + return; + } + }); + + return success; } virtual u64 getReferenceValue(u64 referenceIndex) { if (referenceIndex < 32) - return cpu->getRegister(0, referenceIndex)._u64[0]; + return m_cpu->getRegister(0, referenceIndex)._u64[0]; if (referenceIndex == REF_INDEX_PC) - return cpu->getPC(); + return m_cpu->getPC(); if (referenceIndex == REF_INDEX_HI) - return cpu->getHI()._u64[0]; + return m_cpu->getHI()._u64[0]; if (referenceIndex == REF_INDEX_LO) - return cpu->getLO()._u64[0]; + return m_cpu->getLO()._u64[0]; if (referenceIndex & REF_INDEX_IS_OPSL) { - const u32 OP = memRead32(cpu->getPC()); + const u32 OP = memRead32(m_cpu->getPC()); const R5900::OPCODE& opcode = R5900::GetInstruction(OP); if (opcode.flags & IS_MEMORY) { @@ -154,7 +197,7 @@ public: } if (referenceIndex & REF_INDEX_FPU) { - return cpu->getRegister(EECAT_FPR, referenceIndex & 0x1F)._u64[0]; + return m_cpu->getRegister(EECAT_FPR, referenceIndex & 0x1F)._u64[0]; } return -1; } @@ -168,7 +211,7 @@ public: return EXPR_TYPE_UINT; } - virtual bool getMemoryValue(u32 address, int size, u64& dest, char* error) + virtual bool getMemoryValue(u32 address, int size, u64& dest, std::string& error) { switch (size) { @@ -178,37 +221,40 @@ public: case 8: break; default: - sprintf(error, "Invalid memory access size %d", size); + error = StringUtil::StdStringFromFormat( + TRANSLATE("ExpressionParser", "Invalid memory access size %d."), size); return false; } if (address % size) { - sprintf(error, "Invalid memory access (unaligned)"); + error = TRANSLATE("ExpressionParser", "Invalid memory access (unaligned)."); return false; } switch (size) { case 1: - dest = cpu->read8(address); + dest = m_cpu->read8(address); break; case 2: - dest = cpu->read16(address); + dest = m_cpu->read16(address); break; case 4: - dest = cpu->read32(address); + dest = m_cpu->read32(address); break; case 8: - dest = cpu->read64(address); + dest = m_cpu->read64(address); break; } return true; } -private: - DebugInterface* cpu; +protected: + DebugInterface* m_cpu; + std::map m_mangled_function_names_to_handles; + std::map m_mangled_global_names_to_handles; }; // @@ -308,19 +354,31 @@ std::optional DebugInterface::getStackFrameSize(const ccc::Function& functi return static_cast(stack_frame_size); } +bool DebugInterface::evaluateExpression(const char* expression, u64& dest) +{ + PostfixExpression postfix; + + if (!initExpression(expression, postfix)) + return false; + + if (!parseExpression(postfix, dest)) + return false; + + return true; +} + bool DebugInterface::initExpression(const char* exp, PostfixExpression& dest) { - MipsExpressionFunctions funcs(this); + MipsExpressionFunctions funcs(this, true); return initPostfixExpression(exp, &funcs, dest); } bool DebugInterface::parseExpression(PostfixExpression& exp, u64& dest) { - MipsExpressionFunctions funcs(this); + MipsExpressionFunctions funcs(this, false); return parsePostfixExpression(exp, &funcs, dest); } - // // R5900DebugInterface // diff --git a/pcsx2/DebugTools/DebugInterface.h b/pcsx2/DebugTools/DebugInterface.h index f628222007..bc50014d2d 100644 --- a/pcsx2/DebugTools/DebugInterface.h +++ b/pcsx2/DebugTools/DebugInterface.h @@ -79,6 +79,7 @@ public: [[nodiscard]] virtual SymbolGuardian& GetSymbolGuardian() const = 0; [[nodiscard]] virtual std::vector> GetThreadList() const = 0; + bool evaluateExpression(const char* expression, u64& dest); bool initExpression(const char* exp, PostfixExpression& dest); bool parseExpression(PostfixExpression& exp, u64& dest); bool isAlive(); diff --git a/pcsx2/DebugTools/ExpressionParser.cpp b/pcsx2/DebugTools/ExpressionParser.cpp index a55160f5be..7fc0a8866b 100644 --- a/pcsx2/DebugTools/ExpressionParser.cpp +++ b/pcsx2/DebugTools/ExpressionParser.cpp @@ -3,6 +3,9 @@ #include "ExpressionParser.h" +#include "Host.h" +#include "common/StringUtil.h" + #include #include #include @@ -18,7 +21,7 @@ typedef enum { typedef enum { EXCOMM_CONST, EXCOMM_CONST_FLOAT, EXCOMM_REF, EXCOMM_OP } ExpressionCommand; -static char expressionError[256]; +static std::string expressionError; typedef struct { char Name[4]; @@ -85,8 +88,6 @@ bool parseNumber(char* str, int defaultrad, int len, u64& result) str+=2; len-=2; } else { - if (!(str[0] >= '0' && str[0] <= '9')) return false; - if (tolower(str[len-1]) == 'b' && defaultrad != 16) { r = 2; @@ -210,7 +211,7 @@ bool isAlphaNum(char c) bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest) { - expressionError[0] = 0; + expressionError.clear(); int infixPos = 0; int infixLen = (int)strlen(infix); @@ -232,19 +233,26 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf if (first >= '0' && first <= '9') { - while (isAlphaNum(infix[infixPos])) + while (isAlphaNum(infix[infixPos]) && subPos < static_cast(sizeof(subStr)) - 1) { subStr[subPos++] = infix[infixPos++]; } subStr[subPos] = 0; + if(subPos == sizeof(subStr) - 1) + { + expressionError = TRANSLATE("ExpressionParser", "Token too long."); + return false; + } + u64 value; bool isFloat = false; if (parseFloat(subStr,subPos,value)) isFloat = true; else if (!parseNumber(subStr,16,subPos,value)) { - std::snprintf(expressionError, std::size(expressionError),"Invalid number \"%s\"",subStr); + expressionError = StringUtil::StdStringFromFormat( + TRANSLATE("ExpressionParser", "Invalid number \"%s\"."), subStr); return false; } @@ -252,12 +260,18 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf lastOpcode = EXOP_NUMBER; } else if ((first >= 'a' && first <= 'z') || first == '@') { - while (isAlphaNum(infix[infixPos])) + while (isAlphaNum(infix[infixPos]) && subPos < static_cast(sizeof(subStr)) - 1) { subStr[subPos++] = infix[infixPos++]; } subStr[subPos] = 0; + if(subPos == sizeof(subStr) - 1) + { + expressionError = TRANSLATE("ExpressionParser", "Token too long."); + return false; + } + u64 value; if (funcs->parseReference(subStr,value)) { @@ -273,14 +287,23 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf continue; } - std::snprintf(expressionError, std::size(expressionError),"Invalid symbol \"%s\"",subStr); + if(parseNumber(subStr,16,subPos,value)) + { + dest.push_back(ExpressionPair(EXCOMM_CONST,value)); + lastOpcode = EXOP_NUMBER; + continue; + } + + expressionError = StringUtil::StdStringFromFormat( + TRANSLATE("ExpressionParser", "Invalid symbol \"%s\"."), subStr); return false; } else { int len; ExpressionOpcodeType type = getExpressionOpcode(&infix[infixPos],len,lastOpcode); if (type == EXOP_NONE) { - std::snprintf(expressionError, std::size(expressionError),"Invalid operator at \"%s\"",&infix[infixPos]); + expressionError = StringUtil::StdStringFromFormat( + TRANSLATE("ExpressionParser", "Invalid operator at \"%s\"."), &infix[infixPos]); return false; } @@ -295,7 +318,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf { if (opcodeStack.empty()) { - std::snprintf(expressionError, std::size(expressionError),"Closing parenthesis without opening one"); + expressionError = TRANSLATE("ExpressionParser", "Closing parenthesis without opening one."); return false; } ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; @@ -309,7 +332,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf { if (opcodeStack.empty()) { - std::snprintf(expressionError, std::size(expressionError),"Closing bracket without opening one"); + expressionError = TRANSLATE("ExpressionParser", "Closing bracket without opening one."); return false; } ExpressionOpcodeType t = opcodeStack[opcodeStack.size()-1]; @@ -362,7 +385,7 @@ bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, Postf if (t == EXOP_BRACKETL) // opening bracket without closing one { - std::snprintf(expressionError, std::size(expressionError),"Parenthesis not closed"); + expressionError = TRANSLATE("ExpressionParser", "Parenthesis not closed."); return false; } dest.push_back(ExpressionPair(EXCOMM_OP,t)); @@ -421,7 +444,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, opcode = exp[num++].second; if (valueStack.size() < ExpressionOpcodes[opcode].args) { - std::snprintf(expressionError, std::size(expressionError),"Not enough arguments"); + expressionError = TRANSLATE("ExpressionParser", "Not enough arguments."); return false; } for (int l = 0; l < ExpressionOpcodes[opcode].args; l++) @@ -436,7 +459,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_MEMSIZE: // must be followed by EXOP_MEM if (exp[num++].second != EXOP_MEM) { - std::snprintf(expressionError, std::size(expressionError),"Invalid memsize operator"); + expressionError = TRANSLATE("ExpressionParser", "Invalid memsize operator."); return false; } @@ -480,7 +503,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_DIV: // a/b if (arg[0] == 0) { - std::snprintf(expressionError, std::size(expressionError),"Division by zero"); + expressionError = TRANSLATE("ExpressionParser", "Division by zero."); return false; } if (useFloat) @@ -491,7 +514,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_MOD: // a%b if (arg[0] == 0) { - std::snprintf(expressionError, std::size(expressionError),"Modulo by zero"); + expressionError = TRANSLATE("ExpressionParser", "Modulo by zero."); return false; } valueStack.push_back(arg[1]%arg[0]); @@ -570,7 +593,7 @@ bool parsePostfixExpression(PostfixExpression& exp, IExpressionFunctions* funcs, case EXOP_TERTELSE: // exp ? exp : exp, else muss zuerst kommen! if (exp[num++].second != EXOP_TERTIF) { - std::snprintf(expressionError, std::size(expressionError),"Invalid tertiary operator"); + expressionError = TRANSLATE("ExpressionParser", "Invalid tertiary operator."); return false; } valueStack.push_back(arg[2]?arg[1]:arg[0]); @@ -594,6 +617,8 @@ bool parseExpression(char* exp, IExpressionFunctions* funcs, u64& dest) const char* getExpressionError() { - if (expressionError[0] == 0) strcpy(expressionError,"Invalid expression"); - return expressionError; + if (expressionError.empty()) + return TRANSLATE("ExpressionParser", "Invalid expression."); + + return expressionError.c_str(); } diff --git a/pcsx2/DebugTools/ExpressionParser.h b/pcsx2/DebugTools/ExpressionParser.h index b3a10c7b58..26bfa828e4 100644 --- a/pcsx2/DebugTools/ExpressionParser.h +++ b/pcsx2/DebugTools/ExpressionParser.h @@ -22,7 +22,7 @@ public: virtual bool parseSymbol(char* str, u64& symbolValue) = 0; virtual u64 getReferenceValue(u64 referenceIndex) = 0; virtual ExpressionType getReferenceType(u64 referenceIndex) = 0; - virtual bool getMemoryValue(u32 address, int size, u64& dest, char* error) = 0; + virtual bool getMemoryValue(u32 address, int size, u64& dest, std::string& error) = 0; }; bool initPostfixExpression(const char* infix, IExpressionFunctions* funcs, PostfixExpression& dest);