2021-09-08 15:18:24 +02:00
|
|
|
#include <hex/pattern_language/pattern_language.hpp>
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
#include <hex/helpers/file.hpp>
|
2021-01-22 18:01:39 +01:00
|
|
|
#include <hex/providers/provider.hpp>
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
#include <hex/pattern_language/preprocessor.hpp>
|
|
|
|
#include <hex/pattern_language/lexer.hpp>
|
|
|
|
#include <hex/pattern_language/parser.hpp>
|
|
|
|
#include <hex/pattern_language/validator.hpp>
|
|
|
|
#include <hex/pattern_language/evaluator.hpp>
|
2021-01-22 18:01:39 +01:00
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
namespace hex::pl {
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-06 20:35:38 +02:00
|
|
|
class PatternData;
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
PatternLanguage::PatternLanguage() {
|
2021-01-22 18:01:39 +01:00
|
|
|
this->m_preprocessor = new Preprocessor();
|
|
|
|
this->m_lexer = new Lexer();
|
|
|
|
this->m_parser = new Parser();
|
|
|
|
this->m_validator = new Validator();
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_evaluator = new Evaluator();
|
|
|
|
|
|
|
|
this->m_preprocessor->addPragmaHandler("endian", [this](std::string value) {
|
|
|
|
if (value == "big") {
|
|
|
|
this->m_defaultEndian = std::endian::big;
|
|
|
|
return true;
|
|
|
|
} else if (value == "little") {
|
|
|
|
this->m_defaultEndian = std::endian::little;
|
|
|
|
return true;
|
|
|
|
} else if (value == "native") {
|
|
|
|
this->m_defaultEndian = std::endian::native;
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
});
|
2021-03-07 13:20:33 +01:00
|
|
|
|
|
|
|
this->m_preprocessor->addPragmaHandler("eval_depth", [this](std::string value) {
|
|
|
|
auto limit = strtol(value.c_str(), nullptr, 0);
|
|
|
|
|
|
|
|
if (limit <= 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
this->m_recursionLimit = limit;
|
|
|
|
return true;
|
|
|
|
});
|
2021-04-13 21:49:31 +02:00
|
|
|
|
|
|
|
this->m_preprocessor->addPragmaHandler("base_address", [](std::string value) {
|
|
|
|
auto baseAddress = strtoull(value.c_str(), nullptr, 0);
|
|
|
|
|
|
|
|
SharedData::currentProvider->setBaseAddress(baseAddress);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_preprocessor->addDefaultPragmaHandlers();
|
2021-01-22 18:01:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PatternLanguage::~PatternLanguage() {
|
|
|
|
delete this->m_preprocessor;
|
|
|
|
delete this->m_lexer;
|
|
|
|
delete this->m_parser;
|
|
|
|
delete this->m_validator;
|
|
|
|
delete this->m_evaluator;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
std::optional<std::vector<PatternData*>> PatternLanguage::executeString(prv::Provider *provider, const std::string &string) {
|
2021-01-22 18:01:39 +01:00
|
|
|
this->m_currError.reset();
|
|
|
|
this->m_evaluator->getConsole().clear();
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_evaluator->setProvider(provider);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
auto preprocessedCode = this->m_preprocessor->preprocess(string);
|
2021-01-22 18:01:39 +01:00
|
|
|
if (!preprocessedCode.has_value()) {
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_currError = this->m_preprocessor->getError();
|
2021-01-22 18:01:39 +01:00
|
|
|
return { };
|
|
|
|
}
|
|
|
|
|
2021-03-07 13:20:33 +01:00
|
|
|
this->m_evaluator->setDefaultEndian(this->m_defaultEndian);
|
|
|
|
this->m_evaluator->setRecursionLimit(this->m_recursionLimit);
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
auto tokens = this->m_lexer->lex(preprocessedCode.value());
|
2021-01-22 18:01:39 +01:00
|
|
|
if (!tokens.has_value()) {
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_currError = this->m_lexer->getError();
|
2021-01-22 18:01:39 +01:00
|
|
|
return { };
|
|
|
|
}
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
auto ast = this->m_parser->parse(tokens.value());
|
2021-01-22 18:01:39 +01:00
|
|
|
if (!ast.has_value()) {
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_currError = this->m_parser->getError();
|
2021-01-22 18:01:39 +01:00
|
|
|
return { };
|
|
|
|
}
|
|
|
|
|
2021-03-31 22:54:43 +02:00
|
|
|
ON_SCOPE_EXIT {
|
|
|
|
for(auto &node : ast.value())
|
|
|
|
delete node;
|
|
|
|
};
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
auto validatorResult = this->m_validator->validate(ast.value());
|
2021-01-22 18:01:39 +01:00
|
|
|
if (!validatorResult) {
|
2021-01-23 14:00:09 +01:00
|
|
|
this->m_currError = this->m_validator->getError();
|
2021-01-22 18:01:39 +01:00
|
|
|
return { };
|
|
|
|
}
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
auto patternData = this->m_evaluator->evaluate(ast.value());
|
2021-01-22 18:01:39 +01:00
|
|
|
if (!patternData.has_value())
|
|
|
|
return { };
|
|
|
|
|
|
|
|
return patternData.value();
|
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
std::optional<std::vector<PatternData*>> PatternLanguage::executeFile(prv::Provider *provider, const std::string &path) {
|
|
|
|
File file(path, File::Mode::Read);
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
return this->executeString(provider, file.readString());
|
2021-01-22 18:01:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
const std::vector<std::pair<LogConsole::Level, std::string>>& PatternLanguage::getConsoleLog() {
|
2021-01-22 18:01:39 +01:00
|
|
|
return this->m_evaluator->getConsole().getLog();
|
|
|
|
}
|
|
|
|
|
2021-01-23 14:00:09 +01:00
|
|
|
const std::optional<std::pair<u32, std::string>>& PatternLanguage::getError() {
|
2021-01-22 18:01:39 +01:00
|
|
|
return this->m_currError;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|