From 4b9aff5b29ef39dff2c3c697dde72d11568ae9a1 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Mon, 4 Oct 2021 20:26:34 +0200 Subject: [PATCH] patterns: Allow str to be used in function bodies --- .../source/content/pl_builtin_functions.cpp | 2 +- .../include/hex/pattern_language/ast_node.hpp | 44 +++++++++++++++++-- .../include/hex/pattern_language/token.hpp | 1 + .../source/pattern_language/evaluator.cpp | 16 +++---- .../source/pattern_language/parser.cpp | 4 +- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/plugins/builtin/source/content/pl_builtin_functions.cpp b/plugins/builtin/source/content/pl_builtin_functions.cpp index 346e72760..e320e6afc 100644 --- a/plugins/builtin/source/content/pl_builtin_functions.cpp +++ b/plugins/builtin/source/content/pl_builtin_functions.cpp @@ -192,7 +192,7 @@ namespace hex::plugin::builtin { auto string = Token::literalToString(params[0], false); auto index = Token::literalToSigned(params[1]); - if (std::abs(index) >= string.length()) + if (std::abs(index) > string.length()) LogConsole::abortEvaluation("character index out of range"); if (index >= 0) diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index a89aad372..71e5cb3ce 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -176,6 +176,22 @@ namespace hex::pl { LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); } }, + [this](std::string left, char right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Plus: + return new ASTNodeLiteral(left + right); + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + } + }, + [this](char left, std::string right) -> ASTNode* { + switch (this->getOperator()) { + case Token::Operator::Plus: + return new ASTNodeLiteral(left + right); + default: + LogConsole::abortEvaluation("invalid operand used in mathematical expression", this); + } + }, [this](auto &&left, auto &&right) -> ASTNode* { switch (this->getOperator()) { case Token::Operator::Plus: @@ -1359,8 +1375,8 @@ namespace hex::pl { auto &literal = evaluator->getStack()[pattern->getOffset()]; std::visit(overloaded { - [&](std::string &assignmentValue) { }, - [&](auto &&assignmentValue) { std::memcpy(&value, &assignmentValue, pattern->getSize()); } + [&](std::string &assignmentValue) { }, + [&](auto &&assignmentValue) { std::memcpy(&value, &assignmentValue, pattern->getSize()); } }, literal); } else @@ -1369,6 +1385,21 @@ namespace hex::pl { value = hex::changeEndianess(value, pattern->getSize(), pattern->getEndian()); }; + auto readString = [&evaluator](std::string &value, PatternData *pattern) { + if (pattern->isLocal()) { + auto &literal = evaluator->getStack()[pattern->getOffset()]; + + std::visit(overloaded { + [&](std::string &assignmentValue) { value = assignmentValue; }, + [&](auto &&assignmentValue) { } + }, literal); + } + else { + value.resize(pattern->getSize()); + evaluator->getProvider()->read(pattern->getOffset(), value.data(), value.size()); + } + }; + Token::Literal literal; if (dynamic_cast(pattern) || dynamic_cast(pattern)) { u128 value = 0; @@ -1407,7 +1438,14 @@ namespace hex::pl { auto &literal = evaluator->getStack()[pattern->getOffset()]; std::visit(overloaded { - [&](std::string &assignmentValue) { value = assignmentValue; }, + [&](char assignmentValue) { if (assignmentValue != 0x00) value = std::string({ assignmentValue }); }, + [&](std::string assignmentValue) { value = assignmentValue; }, + [&, this](PatternData * const &assignmentValue) { + if (!dynamic_cast(assignmentValue) && !dynamic_cast(assignmentValue)) + LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); + + readString(value, assignmentValue); + }, [&, this](auto &&assignmentValue) { LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); } }, literal); } diff --git a/plugins/libimhex/include/hex/pattern_language/token.hpp b/plugins/libimhex/include/hex/pattern_language/token.hpp index fa8b7bd7b..80181aa58 100644 --- a/plugins/libimhex/include/hex/pattern_language/token.hpp +++ b/plugins/libimhex/include/hex/pattern_language/token.hpp @@ -220,6 +220,7 @@ namespace hex::pl { case ValueType::Character: return "char"; case ValueType::Character16: return "char16"; case ValueType::Padding: return "padding"; + case ValueType::String: return "str"; default: return "< ??? >"; } } diff --git a/plugins/libimhex/source/pattern_language/evaluator.cpp b/plugins/libimhex/source/pattern_language/evaluator.cpp index baae5bf2d..8adb12fb4 100644 --- a/plugins/libimhex/source/pattern_language/evaluator.cpp +++ b/plugins/libimhex/source/pattern_language/evaluator.cpp @@ -20,19 +20,19 @@ namespace hex::pl { if (!value.has_value()) LogConsole::abortEvaluation("cannot determine type of auto variable", type); - if (std::get_if(&*value) != nullptr) + if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataUnsigned(0, sizeof(u128), this); - else if (std::get_if(&*value) != nullptr) + else if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataSigned(0, sizeof(s128), this); - else if (std::get_if(&*value) != nullptr) + else if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataFloat(0, sizeof(double), this); - else if (std::get_if(&*value) != nullptr) + else if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataBoolean(0, this); - else if (std::get_if(&*value) != nullptr) + else if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataCharacter(0, this); - else if (std::get_if(&*value) != nullptr) - pattern = std::get(*value)->clone(); - else if (std::get_if(&*value) != nullptr) + else if (std::get_if(&value.value()) != nullptr) + pattern = std::get(value.value())->clone(); + else if (std::get_if(&value.value()) != nullptr) pattern = new PatternDataString(0, 1, this); else __builtin_unreachable(); diff --git a/plugins/libimhex/source/pattern_language/parser.cpp b/plugins/libimhex/source/pattern_language/parser.cpp index eff67fa41..b99d61db0 100644 --- a/plugins/libimhex/source/pattern_language/parser.cpp +++ b/plugins/libimhex/source/pattern_language/parser.cpp @@ -494,10 +494,10 @@ namespace hex::pl { statement = parseFunctionCall(); } else - statement = parseMemberVariable(parseType()); + statement = parseMemberVariable(parseType(true)); } else if (peek(KEYWORD_BE) || peek(KEYWORD_LE) || peek(VALUETYPE_ANY)) { - auto type = parseType(); + auto type = parseType(true); if (MATCHES(sequence(IDENTIFIER))) statement = parseMemberVariable(type);