diff --git a/plugins/libimhex/include/hex/helpers/utils.hpp b/plugins/libimhex/include/hex/helpers/utils.hpp index 5e6082073..0846f74ca 100644 --- a/plugins/libimhex/include/hex/helpers/utils.hpp +++ b/plugins/libimhex/include/hex/helpers/utils.hpp @@ -158,6 +158,21 @@ namespace hex { return T(1) << bit_width(T(x - 1)); } + inline std::vector splitString(std::string_view string, std::string_view delimiter) { + size_t start = 0, end; + std::string token; + std::vector res; + + while ((end = string.find (delimiter, start)) != std::string::npos) { + token = string.substr(start, end - start); + start = end + delimiter.length(); + res.push_back(token); + } + + res.push_back(std::string(string.substr(start))); + return res; + } + inline std::string toEngineeringString(double value) { constexpr std::array prefixes = { "a", "f", "p", "n", "u", "m", "", "k", "M", "G", "T", "P", "E" }; diff --git a/plugins/libimhex/include/hex/lang/evaluator.hpp b/plugins/libimhex/include/hex/lang/evaluator.hpp index 863ac8092..be800b1da 100644 --- a/plugins/libimhex/include/hex/lang/evaluator.hpp +++ b/plugins/libimhex/include/hex/lang/evaluator.hpp @@ -69,6 +69,7 @@ namespace hex::lang { ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node); ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node); + PatternData* patternFromName(const std::vector &name); PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node); void evaluateMember(ASTNode *node, std::vector &currMembers, bool increaseOffset); PatternData* evaluateStruct(ASTNodeStruct *node); diff --git a/plugins/libimhex/source/lang/builtin_functions.cpp b/plugins/libimhex/source/lang/builtin_functions.cpp index 06bc4f9b0..5775702f6 100644 --- a/plugins/libimhex/source/lang/builtin_functions.cpp +++ b/plugins/libimhex/source/lang/builtin_functions.cpp @@ -138,6 +138,33 @@ namespace hex::lang { return nullptr; }); + + ContentRegistry::PatternLanguageFunctions::add("addressof", 1, [this](auto params) -> ASTNode* { + auto name = asType(params[0])->getString(); + + std::vector path = splitString(name, "."); + auto pattern = this->patternFromName(path); + + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() }); + }); + + ContentRegistry::PatternLanguageFunctions::add("sizeof", 1, [this](auto params) -> ASTNode* { + auto name = asType(params[0])->getString(); + + std::vector path = splitString(name, "."); + auto pattern = this->patternFromName(path); + + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getSize() }); + }); + + ContentRegistry::PatternLanguageFunctions::add("nextAfter", 1, [this](auto params) -> ASTNode* { + auto name = asType(params[0])->getString(); + + std::vector path = splitString(name, "."); + auto pattern = this->patternFromName(path); + + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() + pattern->getSize() }); + }); } } \ No newline at end of file diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index 01157bcd6..66a2aa4ae 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -36,10 +36,7 @@ namespace hex::lang { throwEvaluateError("failed to find identifier"); } - ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) { - if (this->m_currMembers.empty() && this->m_globalMembers.empty()) - throwEvaluateError("no variables available"); - + PatternData* Evaluator::patternFromName(const std::vector &path) { std::vector currMembers; if (!this->m_currMembers.empty()) @@ -48,8 +45,8 @@ namespace hex::lang { std::copy(this->m_globalMembers.begin(), this->m_globalMembers.end(), std::back_inserter(currMembers)); PatternData *currPattern = nullptr; - for (u32 i = 0; i < node->getPath().size(); i++) { - const auto &identifier = node->getPath()[i]; + for (u32 i = 0; i < path.size(); i++) { + const auto &identifier = path[i]; if (auto structPattern = dynamic_cast(currPattern); structPattern != nullptr) currMembers = structPattern->getMembers(); @@ -76,6 +73,18 @@ namespace hex::lang { if (auto pointerPattern = dynamic_cast(currPattern); pointerPattern != nullptr) currPattern = pointerPattern->getPointedAtPattern(); + return currPattern; + } + + ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) { + if (this->m_currMembers.empty() && this->m_globalMembers.empty()) + throwEvaluateError("no variables available"); + + if (node->getPath().size() == 1 && node->getPath()[0] == "$") + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset }); + + auto currPattern = this->patternFromName(node->getPath()); + if (auto unsignedPattern = dynamic_cast(currPattern); unsignedPattern != nullptr) { u8 value[unsignedPattern->getSize()]; this->m_provider->read(unsignedPattern->getOffset(), value, unsignedPattern->getSize());