pattern: Added #pragma once to prevent multi-includes of files
This commit is contained in:
parent
7321d205fe
commit
af57b39d8f
@ -9,6 +9,8 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <hex/helpers/paths.hpp>
|
||||||
|
|
||||||
namespace hex::pl {
|
namespace hex::pl {
|
||||||
|
|
||||||
class Preprocessor {
|
class Preprocessor {
|
||||||
@ -34,6 +36,8 @@ namespace hex::pl {
|
|||||||
std::set<std::tuple<std::string, std::string, u32>> m_defines;
|
std::set<std::tuple<std::string, std::string, u32>> m_defines;
|
||||||
std::set<std::tuple<std::string, std::string, u32>> m_pragmas;
|
std::set<std::tuple<std::string, std::string, u32>> m_pragmas;
|
||||||
|
|
||||||
|
std::set<fs::path> m_onceIncludedFiles;
|
||||||
|
|
||||||
std::pair<u32, std::string> m_error;
|
std::pair<u32, std::string> m_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ namespace hex::pl {
|
|||||||
this->m_validator = new Validator();
|
this->m_validator = new Validator();
|
||||||
this->m_evaluator = new Evaluator();
|
this->m_evaluator = new Evaluator();
|
||||||
|
|
||||||
|
this->m_preprocessor->addDefaultPragmaHandlers();
|
||||||
|
|
||||||
this->m_preprocessor->addPragmaHandler("endian", [this](std::string value) {
|
this->m_preprocessor->addPragmaHandler("endian", [this](std::string value) {
|
||||||
if (value == "big") {
|
if (value == "big") {
|
||||||
this->m_evaluator->setDefaultEndian(std::endian::big);
|
this->m_evaluator->setDefaultEndian(std::endian::big);
|
||||||
@ -83,8 +85,6 @@ namespace hex::pl {
|
|||||||
ImHexApi::Provider::get()->setBaseAddress(baseAddress);
|
ImHexApi::Provider::get()->setBaseAddress(baseAddress);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this->m_preprocessor->addDefaultPragmaHandlers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternLanguage::~PatternLanguage() {
|
PatternLanguage::~PatternLanguage() {
|
||||||
|
@ -62,11 +62,11 @@ namespace hex::pl {
|
|||||||
}
|
}
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
std::string includePath = includeFile;
|
fs::path includePath = includeFile;
|
||||||
|
|
||||||
if (includeFile[0] != '/') {
|
if (includeFile[0] != '/') {
|
||||||
for (const auto &dir : hex::getPath(ImHexPath::PatternsInclude)) {
|
for (const auto &dir : hex::getPath(ImHexPath::PatternsInclude)) {
|
||||||
std::string tempPath = hex::format("{0}/{1}", dir.string().c_str(), includeFile.c_str());
|
fs::path tempPath = dir / includePath;
|
||||||
if (fs::exists(tempPath)) {
|
if (fs::exists(tempPath)) {
|
||||||
includePath = tempPath;
|
includePath = tempPath;
|
||||||
break;
|
break;
|
||||||
@ -78,16 +78,25 @@ namespace hex::pl {
|
|||||||
if (!file.isValid())
|
if (!file.isValid())
|
||||||
throwPreprocessorError(hex::format("{0}: No such file or directory", includeFile.c_str()), lineNumber);
|
throwPreprocessorError(hex::format("{0}: No such file or directory", includeFile.c_str()), lineNumber);
|
||||||
|
|
||||||
|
bool shouldInclude = true;
|
||||||
|
this->addPragmaHandler("once", [&, includePath, this](const std::string &value) {
|
||||||
|
auto [iter, added] = this->m_onceIncludedFiles.insert(includePath);
|
||||||
|
if (!added) shouldInclude = false;
|
||||||
|
return value.empty();
|
||||||
|
});
|
||||||
|
|
||||||
auto preprocessedInclude = this->preprocess(file.readString(), false);
|
auto preprocessedInclude = this->preprocess(file.readString(), false);
|
||||||
if (!preprocessedInclude.has_value())
|
if (!preprocessedInclude.has_value())
|
||||||
throw this->m_error;
|
throw this->m_error;
|
||||||
|
|
||||||
auto content = preprocessedInclude.value();
|
if (shouldInclude) {
|
||||||
|
auto content = preprocessedInclude.value();
|
||||||
|
|
||||||
std::replace(content.begin(), content.end(), '\n', ' ');
|
std::replace(content.begin(), content.end(), '\n', ' ');
|
||||||
std::replace(content.begin(), content.end(), '\r', ' ');
|
std::replace(content.begin(), content.end(), '\r', ' ');
|
||||||
|
|
||||||
output += content;
|
output += content;
|
||||||
|
}
|
||||||
} else if (code.substr(offset, 6) == "define") {
|
} else if (code.substr(offset, 6) == "define") {
|
||||||
offset += 6;
|
offset += 6;
|
||||||
|
|
||||||
@ -126,14 +135,18 @@ namespace hex::pl {
|
|||||||
} else if (code.substr(offset, 6) == "pragma") {
|
} else if (code.substr(offset, 6) == "pragma") {
|
||||||
offset += 6;
|
offset += 6;
|
||||||
|
|
||||||
while (std::isblank(code[offset]))
|
while (std::isblank(code[offset])) {
|
||||||
offset += 1;
|
offset += 1;
|
||||||
|
|
||||||
|
if (code[offset] == '\n' || code[offset] == '\r')
|
||||||
|
throwPreprocessorError("no instruction given in #pragma directive", lineNumber);
|
||||||
|
}
|
||||||
|
|
||||||
std::string pragmaKey;
|
std::string pragmaKey;
|
||||||
while (!std::isblank(code[offset])) {
|
while (!std::isblank(code[offset]) && code[offset] != '\n' && code[offset] != '\r') {
|
||||||
pragmaKey += code[offset];
|
pragmaKey += code[offset];
|
||||||
|
|
||||||
if (offset >= code.length() || code[offset] == '\n' || code[offset] == '\r')
|
if (offset >= code.length())
|
||||||
throwPreprocessorError("no instruction given in #pragma directive", lineNumber);
|
throwPreprocessorError("no instruction given in #pragma directive", lineNumber);
|
||||||
|
|
||||||
offset += 1;
|
offset += 1;
|
||||||
@ -151,9 +164,6 @@ namespace hex::pl {
|
|||||||
offset += 1;
|
offset += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pragmaValue.empty())
|
|
||||||
throwPreprocessorError("missing value in #pragma directive", lineNumber);
|
|
||||||
|
|
||||||
this->m_pragmas.emplace(pragmaKey, pragmaValue, lineNumber);
|
this->m_pragmas.emplace(pragmaKey, pragmaValue, lineNumber);
|
||||||
} else
|
} else
|
||||||
throwPreprocessorError("unknown preprocessor directive", lineNumber);
|
throwPreprocessorError("unknown preprocessor directive", lineNumber);
|
||||||
@ -219,8 +229,7 @@ namespace hex::pl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Preprocessor::addPragmaHandler(const std::string &pragmaType, const std::function<bool(const std::string &)> &function) {
|
void Preprocessor::addPragmaHandler(const std::string &pragmaType, const std::function<bool(const std::string &)> &function) {
|
||||||
if (!this->m_pragmaHandlers.contains(pragmaType))
|
this->m_pragmaHandlers[pragmaType] = function;
|
||||||
this->m_pragmaHandlers.emplace(pragmaType, function);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Preprocessor::addDefaultPragmaHandlers() {
|
void Preprocessor::addDefaultPragmaHandlers() {
|
||||||
@ -230,6 +239,9 @@ namespace hex::pl {
|
|||||||
this->addPragmaHandler("endian", [](const std::string &value) {
|
this->addPragmaHandler("endian", [](const std::string &value) {
|
||||||
return value == "big" || value == "little" || value == "native";
|
return value == "big" || value == "little" || value == "native";
|
||||||
});
|
});
|
||||||
|
this->addPragmaHandler("once", [](const std::string &value) {
|
||||||
|
return value.empty();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -105,6 +105,7 @@ namespace hex::plugin::builtin {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
pl::Preprocessor preprocessor;
|
pl::Preprocessor preprocessor;
|
||||||
|
preprocessor.addDefaultPragmaHandlers();
|
||||||
|
|
||||||
if (!ImHexApi::Provider::isValid())
|
if (!ImHexApi::Provider::isValid())
|
||||||
return;
|
return;
|
||||||
@ -119,7 +120,6 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
||||||
});
|
});
|
||||||
preprocessor.addDefaultPragmaHandlers();
|
|
||||||
|
|
||||||
this->m_possiblePatternFiles.clear();
|
this->m_possiblePatternFiles.clear();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user