diff --git a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp index acd62f896..fef87853c 100644 --- a/plugins/libimhex/include/hex/pattern_language/ast_node.hpp +++ b/plugins/libimhex/include/hex/pattern_language/ast_node.hpp @@ -310,21 +310,21 @@ namespace hex::pl { PatternData *pattern; if (Token::isUnsigned(this->m_type)) - pattern = new PatternDataUnsigned(offset, size); + pattern = new PatternDataUnsigned(offset, size, evaluator); else if (Token::isSigned(this->m_type)) - pattern = new PatternDataSigned(offset, size); + pattern = new PatternDataSigned(offset, size, evaluator); else if (Token::isFloatingPoint(this->m_type)) - pattern = new PatternDataFloat(offset, size); + pattern = new PatternDataFloat(offset, size, evaluator); else if (this->m_type == Token::ValueType::Boolean) - pattern = new PatternDataBoolean(offset); + pattern = new PatternDataBoolean(offset, evaluator); else if (this->m_type == Token::ValueType::Character) - pattern = new PatternDataCharacter(offset); + pattern = new PatternDataCharacter(offset, evaluator); else if (this->m_type == Token::ValueType::Character16) - pattern = new PatternDataCharacter16(offset); + pattern = new PatternDataCharacter16(offset, evaluator); else if (this->m_type == Token::ValueType::Padding) - pattern = new PatternDataPadding(offset, 1); + pattern = new PatternDataPadding(offset, 1, evaluator); else if (this->m_type == Token::ValueType::String) - pattern = new PatternDataString(offset, 1); + pattern = new PatternDataString(offset, 1, evaluator); else if (this->m_type == Token::ValueType::Auto) return { nullptr }; else @@ -589,7 +589,6 @@ namespace hex::pl { if (function.parameterCount != 1) LogConsole::abortEvaluation("formatter function needs exactly one parameter", node); - pattern->setEvaluator(evaluator); pattern->setFormatterFunction(function); } else if (name == "transform" && requiresValue()) { auto functions = evaluator->getCustomFunctions(); @@ -600,7 +599,6 @@ namespace hex::pl { if (function.parameterCount != 1) LogConsole::abortEvaluation("transform function needs exactly one parameter", node); - pattern->setEvaluator(evaluator); pattern->setTransformFunction(function); } else if (name == "pointer_base" && requiresValue()) { auto functions = evaluator->getCustomFunctions(); @@ -816,13 +814,13 @@ namespace hex::pl { PatternData *outputPattern; if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataPadding(startOffset, 0); + outputPattern = new PatternDataPadding(startOffset, 0, evaluator); } else if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataString(startOffset, 0); + outputPattern = new PatternDataString(startOffset, 0, evaluator); } else if (dynamic_cast(templatePattern)) { - outputPattern = new PatternDataString16(startOffset, 0); + outputPattern = new PatternDataString16(startOffset, 0, evaluator); } else { - auto arrayPattern = new PatternDataStaticArray(startOffset, 0); + auto arrayPattern = new PatternDataStaticArray(startOffset, 0, evaluator); arrayPattern->setEntries(templatePattern->clone(), entryCount); outputPattern = arrayPattern; } @@ -839,10 +837,15 @@ namespace hex::pl { } PatternData* createDynamicArray(Evaluator *evaluator) const { - auto arrayPattern = new PatternDataDynamicArray(evaluator->dataOffset(), 0); + auto arrayPattern = new PatternDataDynamicArray(evaluator->dataOffset(), 0, evaluator); arrayPattern->setVariableName(this->m_name); std::vector entries; + auto arrayCleanup = SCOPE_GUARD { + for (auto entry : entries) + delete entry; + }; + size_t size = 0; u64 entryCount = 0; @@ -934,6 +937,8 @@ namespace hex::pl { arrayPattern->setEntries(entries); arrayPattern->setSize(size); + arrayCleanup.release(); + return arrayPattern; } }; @@ -986,7 +991,7 @@ namespace hex::pl { auto sizePattern = this->m_sizeType->createPatterns(evaluator).front(); ON_SCOPE_EXIT { delete sizePattern; }; - auto pattern = new PatternDataPointer(offset, sizePattern->getSize()); + auto pattern = new PatternDataPointer(offset, sizePattern->getSize(), evaluator); pattern->setVariableName(this->m_name); offset = evaluator->dataOffset(); @@ -1085,10 +1090,15 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataStruct(evaluator->dataOffset(), 0); + auto pattern = new PatternDataStruct(evaluator->dataOffset(), 0, evaluator); u64 startOffset = evaluator->dataOffset(); std::vector memberPatterns; + auto structCleanup = SCOPE_GUARD { + delete pattern; + for (auto member : memberPatterns) + delete member; + }; evaluator->pushScope(pattern, memberPatterns); @@ -1116,6 +1126,8 @@ namespace hex::pl { pattern->setMembers(memberPatterns); pattern->setSize(evaluator->dataOffset() - startOffset); + structCleanup.release(); + return { pattern }; } @@ -1149,12 +1161,18 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataUnion(evaluator->dataOffset(), 0); + auto pattern = new PatternDataUnion(evaluator->dataOffset(), 0, evaluator); size_t size = 0; std::vector memberPatterns; u64 startOffset = evaluator->dataOffset(); + auto unionCleanup = SCOPE_GUARD { + delete pattern; + for (auto member : memberPatterns) + delete member; + }; + evaluator->pushScope(pattern, memberPatterns); for (auto member : this->m_members) { for (auto &memberPattern : member->createPatterns(evaluator)) { @@ -1169,6 +1187,8 @@ namespace hex::pl { pattern->setMembers(memberPatterns); pattern->setSize(size); + unionCleanup.release(); + return { pattern }; } @@ -1200,7 +1220,9 @@ namespace hex::pl { } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataEnum(evaluator->dataOffset(), 0); + auto pattern = new PatternDataEnum(evaluator->dataOffset(), 0, evaluator); + auto enumCleanup = SCOPE_GUARD { delete pattern; }; + std::vector> enumEntries; for (const auto &[name, value] : this->m_entries) { @@ -1217,6 +1239,8 @@ namespace hex::pl { pattern->setSize(underlying->getSize()); pattern->setEndian(underlying->getEndian()); + enumCleanup.release(); + return { pattern }; } @@ -1252,10 +1276,17 @@ namespace hex::pl { void addEntry(const std::string &name, ASTNode* size) { this->m_entries.emplace_back(name, size); } [[nodiscard]] std::vector createPatterns(Evaluator *evaluator) const override { - auto pattern = new PatternDataBitfield(evaluator->dataOffset(), 0); + auto pattern = new PatternDataBitfield(evaluator->dataOffset(), 0, evaluator); size_t bitOffset = 0; std::vector fields; + + auto bitfieldCleanup = SCOPE_GUARD { + delete pattern; + for (auto field : fields) + delete field; + }; + evaluator->pushScope(pattern, fields); for (auto [name, bitSizeNode] : this->m_entries) { auto literal = bitSizeNode->evaluate(evaluator); @@ -1267,7 +1298,7 @@ namespace hex::pl { [](auto &&offset) -> u8 { return static_cast(offset); } }, dynamic_cast(literal)->getValue()); - auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize); + auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize, evaluator); field->setVariableName(name); bitOffset += bitSize; @@ -1280,6 +1311,8 @@ namespace hex::pl { evaluator->dataOffset() += pattern->getSize(); + bitfieldCleanup.release(); + return { pattern }; } @@ -1915,7 +1948,12 @@ namespace hex::pl { std::vector variables; ctx->pushScope(nullptr, variables); - ON_SCOPE_EXIT { ctx->popScope(); }; + ON_SCOPE_EXIT { + for (auto variable : variables) + delete variable; + + ctx->popScope(); + }; u32 paramIndex = 0; for (const auto &[name, type] : this->m_params) { diff --git a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp index b7ab3ce21..3ceb007e8 100644 --- a/plugins/libimhex/include/hex/pattern_language/evaluator.hpp +++ b/plugins/libimhex/include/hex/pattern_language/evaluator.hpp @@ -15,6 +15,7 @@ namespace hex::prv { class Provider; } namespace hex::pl { class PatternData; + class PatternCreationLimiter; class ASTNode; class Evaluator { @@ -87,6 +88,20 @@ namespace hex::pl { return this->m_arrayLimit; } + void setPatternLimit(u32 limit) { + this->m_patternLimit = limit; + } + + [[nodiscard]] + u32 getPatternLimit() { + return this->m_patternLimit; + } + + [[nodiscard]] + u32 getPatternCount() { + return this->m_currPatternCount; + } + u64& dataOffset() { return this->m_currOffset; } bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) { @@ -106,9 +121,13 @@ namespace hex::pl { } void createVariable(const std::string &name, ASTNode *type, const std::optional &value = std::nullopt); - void setVariable(const std::string &name, const Token::Literal& value); + private: + + void patternCreated(); + void patternDestroyed(); + private: u64 m_currOffset; prv::Provider *m_provider = nullptr; @@ -117,11 +136,16 @@ namespace hex::pl { std::endian m_defaultEndian = std::endian::native; u32 m_evalDepth; u32 m_arrayLimit; + u32 m_patternLimit; + + u32 m_currPatternCount; std::vector m_scopes; std::map m_customFunctions; std::vector m_customFunctionDefinitions; std::vector m_stack; + + friend class PatternCreationLimiter; }; } \ No newline at end of file diff --git a/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp b/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp index fdcc8b0c7..49a87f1de 100644 --- a/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp +++ b/plugins/libimhex/include/hex/pattern_language/pattern_data.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include #include #include @@ -51,10 +53,29 @@ namespace hex::pl { bool m_inlined = false; }; - class PatternData { + class PatternCreationLimiter { public: - PatternData(u64 offset, size_t size, u32 color = 0) - : m_offset(offset), m_size(size), m_color(color), m_parent(nullptr) { + explicit PatternCreationLimiter(Evaluator *evaluator) : m_evaluator(evaluator) { + this->m_evaluator->patternCreated(); + } + + PatternCreationLimiter(const PatternCreationLimiter &other) { + this->m_evaluator = other.m_evaluator; + this->m_evaluator->patternCreated(); + } + + ~PatternCreationLimiter() { + this->m_evaluator->patternDestroyed(); + } + + private: + Evaluator *m_evaluator; + }; + + class PatternData : public PatternCreationLimiter { + public: + PatternData(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternCreationLimiter(evaluator), m_offset(offset), m_size(size), m_color(color), m_parent(nullptr), m_evaluator(evaluator) { constexpr u32 Palette[] = { 0x70b4771f, 0x700e7fff, 0x702ca02c, 0x702827d6, 0x70bd6794, 0x704b568c, 0x70c277e3, 0x707f7f7f, 0x7022bdbc, 0x70cfbe17 }; if (color != 0) @@ -100,7 +121,6 @@ namespace hex::pl { void setDisplayName(const std::string &name) { this->m_displayName = name; } [[nodiscard]] Evaluator* getEvaluator() const { return this->m_evaluator; } - void setEvaluator(Evaluator *evaluator) { this->m_evaluator = evaluator; } [[nodiscard]] const auto& getTransformFunction() const { return this->m_transformFunction; } void setTransformFunction(const ContentRegistry::PatternLanguageFunctions::Function &function) { this->m_transformFunction = function; } @@ -295,7 +315,7 @@ namespace hex::pl { class PatternDataPadding : public PatternData { public: - PatternDataPadding(u64 offset, size_t size) : PatternData(offset, size, 0xFF000000) { } + PatternDataPadding(u64 offset, size_t size, Evaluator *evaluator) : PatternData(offset, size, evaluator, 0xFF000000) { } PatternData* clone() override { return new PatternDataPadding(*this); @@ -313,8 +333,8 @@ namespace hex::pl { class PatternDataPointer : public PatternData { public: - PatternDataPointer(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color), m_pointedAt(nullptr) { + PatternDataPointer(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color), m_pointedAt(nullptr) { } PatternDataPointer(const PatternDataPointer &other) : PatternData(other) { @@ -415,8 +435,8 @@ namespace hex::pl { class PatternDataUnsigned : public PatternData { public: - PatternDataUnsigned(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataUnsigned(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternData* clone() override { return new PatternDataUnsigned(*this); @@ -446,8 +466,8 @@ namespace hex::pl { class PatternDataSigned : public PatternData { public: - PatternDataSigned(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataSigned(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternData* clone() override { return new PatternDataSigned(*this); @@ -478,8 +498,8 @@ namespace hex::pl { class PatternDataFloat : public PatternData { public: - PatternDataFloat(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataFloat(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternData* clone() override { return new PatternDataFloat(*this); @@ -514,8 +534,8 @@ namespace hex::pl { class PatternDataBoolean : public PatternData { public: - explicit PatternDataBoolean(u64 offset, u32 color = 0) - : PatternData(offset, 1, color) { } + explicit PatternDataBoolean(u64 offset, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, 1, evaluator, color) { } PatternData* clone() override { return new PatternDataBoolean(*this); @@ -542,8 +562,8 @@ namespace hex::pl { class PatternDataCharacter : public PatternData { public: - explicit PatternDataCharacter(u64 offset, u32 color = 0) - : PatternData(offset, 1, color) { } + explicit PatternDataCharacter(u64 offset, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, 1, evaluator, color) { } PatternData* clone() override { return new PatternDataCharacter(*this); @@ -565,8 +585,8 @@ namespace hex::pl { class PatternDataCharacter16 : public PatternData { public: - explicit PatternDataCharacter16(u64 offset, u32 color = 0) - : PatternData(offset, 2, color) { } + explicit PatternDataCharacter16(u64 offset, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, 2, evaluator, color) { } PatternData* clone() override { return new PatternDataCharacter16(*this); @@ -590,8 +610,8 @@ namespace hex::pl { class PatternDataString : public PatternData { public: - PatternDataString(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataString(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternData* clone() override { return new PatternDataString(*this); @@ -613,8 +633,8 @@ namespace hex::pl { class PatternDataString16 : public PatternData { public: - PatternDataString16(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { } + PatternDataString16(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternData* clone() override { return new PatternDataString16(*this); @@ -641,8 +661,8 @@ namespace hex::pl { class PatternDataDynamicArray : public PatternData, public Inlinable { public: - PatternDataDynamicArray(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataDynamicArray(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternDataDynamicArray(const PatternDataDynamicArray &other) : PatternData(other) { @@ -773,8 +793,8 @@ namespace hex::pl { class PatternDataStaticArray : public PatternData, public Inlinable { public: - PatternDataStaticArray(u64 offset, size_t size, u32 color = 0) - : PatternData(offset, size, color) { + PatternDataStaticArray(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } PatternDataStaticArray(const PatternDataStaticArray &other) : PatternData(other) { @@ -910,7 +930,8 @@ namespace hex::pl { class PatternDataStruct : public PatternData, public Inlinable { public: - PatternDataStruct(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color){ + PatternDataStruct(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color){ } PatternDataStruct(const PatternDataStruct &other) : PatternData(other) { @@ -1045,7 +1066,8 @@ namespace hex::pl { class PatternDataUnion : public PatternData, public Inlinable { public: - PatternDataUnion(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) { + PatternDataUnion(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } @@ -1181,7 +1203,8 @@ namespace hex::pl { class PatternDataEnum : public PatternData { public: - PatternDataEnum(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) { + PatternDataEnum(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } @@ -1274,8 +1297,8 @@ namespace hex::pl { class PatternDataBitfieldField : public PatternData { public: - PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, u32 color = 0) - : m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, color) { + PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, Evaluator *evaluator, u32 color = 0) + : m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, evaluator, color) { } @@ -1343,7 +1366,8 @@ namespace hex::pl { class PatternDataBitfield : public PatternData, public Inlinable { public: - PatternDataBitfield(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) { + PatternDataBitfield(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0) + : PatternData(offset, size, evaluator, color) { } diff --git a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp index 15044671b..7494a7474 100644 --- a/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp +++ b/plugins/libimhex/include/hex/pattern_language/pattern_language.hpp @@ -34,6 +34,9 @@ namespace hex::pl { const std::vector>& getConsoleLog(); const std::optional>& getError(); + u32 getCreatedPatternCount(); + u32 getMaximumPatternCount(); + private: Preprocessor *m_preprocessor; Lexer *m_lexer; @@ -45,8 +48,6 @@ namespace hex::pl { prv::Provider *m_provider = nullptr; std::endian m_defaultEndian = std::endian::native; - u32 m_evalDepth; - u32 m_arrayLimit; std::optional> m_currError; }; diff --git a/plugins/libimhex/source/pattern_language/evaluator.cpp b/plugins/libimhex/source/pattern_language/evaluator.cpp index 7310c05c7..baae5bf2d 100644 --- a/plugins/libimhex/source/pattern_language/evaluator.cpp +++ b/plugins/libimhex/source/pattern_language/evaluator.cpp @@ -21,19 +21,21 @@ namespace hex::pl { LogConsole::abortEvaluation("cannot determine type of auto variable", type); if (std::get_if(&*value) != nullptr) - pattern = new PatternDataUnsigned(0, sizeof(u128)); + pattern = new PatternDataUnsigned(0, sizeof(u128), this); else if (std::get_if(&*value) != nullptr) - pattern = new PatternDataSigned(0, sizeof(s128)); + pattern = new PatternDataSigned(0, sizeof(s128), this); else if (std::get_if(&*value) != nullptr) - pattern = new PatternDataFloat(0, sizeof(double)); + pattern = new PatternDataFloat(0, sizeof(double), this); else if (std::get_if(&*value) != nullptr) - pattern = new PatternDataBoolean(0); + pattern = new PatternDataBoolean(0, this); else if (std::get_if(&*value) != nullptr) - pattern = new PatternDataCharacter(0); + pattern = new PatternDataCharacter(0, this); else if (std::get_if(&*value) != nullptr) pattern = std::get(*value)->clone(); else if (std::get_if(&*value) != nullptr) - pattern = new PatternDataString(0, 1); + pattern = new PatternDataString(0, 1, this); + else + __builtin_unreachable(); } pattern->setVariableName(name); @@ -106,6 +108,7 @@ namespace hex::pl { this->m_scopes.clear(); this->dataOffset() = 0x00; + this->m_currPatternCount = 0; for (auto &func : this->m_customFunctionDefinitions) delete func; @@ -139,10 +142,22 @@ namespace hex::pl { delete pattern; patterns.clear(); + this->m_currPatternCount = 0; + return std::nullopt; } return patterns; } + void Evaluator::patternCreated() { + if (this->m_currPatternCount > this->m_patternLimit) + LogConsole::abortEvaluation(hex::format("exceeded maximum number of patterns: {}", this->m_patternLimit)); + this->m_currPatternCount++; + } + + void Evaluator::patternDestroyed() { + this->m_currPatternCount--; + } + } \ No newline at end of file diff --git a/plugins/libimhex/source/pattern_language/pattern_language.cpp b/plugins/libimhex/source/pattern_language/pattern_language.cpp index bb80ae6a7..7ea323601 100644 --- a/plugins/libimhex/source/pattern_language/pattern_language.cpp +++ b/plugins/libimhex/source/pattern_language/pattern_language.cpp @@ -43,21 +43,31 @@ namespace hex::pl { if (limit <= 0) return false; - this->m_evalDepth = limit; + this->m_evaluator->setEvaluationDepth(limit); return true; }); - this->m_preprocessor->addPragmaHandler("array_limit", [this](std::string value) { + this->m_preprocessor->addPragmaHandler("array_limit", [this](const std::string &value) { auto limit = strtol(value.c_str(), nullptr, 0); if (limit <= 0) return false; - this->m_arrayLimit = limit; + this->m_evaluator->setArrayLimit(limit); return true; }); - this->m_preprocessor->addPragmaHandler("base_address", [](std::string value) { + this->m_preprocessor->addPragmaHandler("pattern_limit", [this](const std::string &value) { + auto limit = strtol(value.c_str(), nullptr, 0); + + if (limit <= 0) + return false; + + this->m_evaluator->setPatternLimit(limit); + return true; + }); + + this->m_preprocessor->addPragmaHandler("base_address", [](const std::string &value) { auto baseAddress = strtoull(value.c_str(), nullptr, 0); ImHexApi::Provider::get()->setBaseAddress(baseAddress); @@ -79,8 +89,10 @@ namespace hex::pl { this->m_currError.reset(); this->m_evaluator->getConsole().clear(); this->m_evaluator->setProvider(provider); - this->m_evalDepth = 32; - this->m_arrayLimit = 0x1000; + this->m_evaluator->setDefaultEndian(std::endian::native); + this->m_evaluator->setEvaluationDepth(32); + this->m_evaluator->setArrayLimit(0x1000); + this->m_evaluator->setPatternLimit(0x2000); for (auto &node : this->m_currAST) delete node; @@ -92,10 +104,6 @@ namespace hex::pl { return { }; } - this->m_evaluator->setDefaultEndian(this->m_defaultEndian); - this->m_evaluator->setEvaluationDepth(this->m_evalDepth); - this->m_evaluator->setArrayLimit(this->m_arrayLimit); - auto tokens = this->m_lexer->lex(preprocessedCode.value()); if (!tokens.has_value()) { this->m_currError = this->m_lexer->getError(); @@ -134,4 +142,12 @@ namespace hex::pl { return this->m_currError; } + u32 PatternLanguage::getCreatedPatternCount() { + return this->m_evaluator->getPatternCount(); + } + + u32 PatternLanguage::getMaximumPatternCount() { + return this->m_evaluator->getPatternLimit(); + } + } \ No newline at end of file diff --git a/source/views/view_pattern_editor.cpp b/source/views/view_pattern_editor.cpp index 2608679bb..1badd1fb8 100644 --- a/source/views/view_pattern_editor.cpp +++ b/source/views/view_pattern_editor.cpp @@ -259,12 +259,23 @@ namespace hex { ImGui::SameLine(); if (this->m_evaluatorRunning) ImGui::TextSpinner("hex.view.pattern.evaluating"_lang); - else + else { if (ImGui::Checkbox("hex.view.pattern.auto"_lang, &this->m_runAutomatically)) { if (this->m_runAutomatically) this->m_hasUnevaluatedChanges = true; } + ImGui::SameLine(); + ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); + ImGui::SameLine(); + + ImGui::TextUnformatted(hex::format("{} / {}", + this->m_patternLanguageRuntime->getCreatedPatternCount(), + this->m_patternLanguageRuntime->getMaximumPatternCount() + ).c_str() + ); + } + if (this->m_textEditor.IsTextChanged()) { ProjectFile::markDirty();