1
0
mirror of synced 2025-01-30 19:43:43 +01:00

pattern: Fixed pragma once memory corruption

This commit is contained in:
WerWolv 2022-02-06 15:28:20 +01:00
parent c1b4c4e42a
commit 99f8efac9a
2 changed files with 32 additions and 14 deletions

View File

@ -22,10 +22,15 @@ namespace hex::pl {
std::optional<std::string> preprocess(const std::string &code, bool initialRun = true); std::optional<std::string> preprocess(const std::string &code, bool initialRun = true);
void addPragmaHandler(const std::string &pragmaType, const std::function<bool(const std::string &)> &function); void addPragmaHandler(const std::string &pragmaType, const std::function<bool(const std::string &)> &function);
void removePragmaHandler(const std::string &pragmaType);
void addDefaultPragmaHandlers(); void addDefaultPragmaHandlers();
const std::optional<PatternLanguageError> &getError() { return this->m_error; } const std::optional<PatternLanguageError> &getError() { return this->m_error; }
bool shouldOnlyIncludeOnce() {
return this->m_onlyIncludeOnce;
}
private: private:
[[noreturn]] static void throwPreprocessorError(const std::string &error, u32 lineNumber) { [[noreturn]] static void throwPreprocessorError(const std::string &error, u32 lineNumber) {
throw PatternLanguageError(lineNumber, "Preprocessor: " + error); throw PatternLanguageError(lineNumber, "Preprocessor: " + error);
@ -39,6 +44,8 @@ namespace hex::pl {
std::set<fs::path> m_onceIncludedFiles; std::set<fs::path> m_onceIncludedFiles;
std::optional<PatternLanguageError> m_error; std::optional<PatternLanguageError> m_error;
bool m_onlyIncludeOnce = false;
}; };
} }

View File

@ -79,18 +79,19 @@ namespace hex::pl {
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; Preprocessor preprocessor;
this->addPragmaHandler("once", [&, includePath, this](const std::string &value) { preprocessor.addDefaultPragmaHandlers();
auto [iter, added] = this->m_onceIncludedFiles.insert(includePath); preprocessor.m_defines = this->m_defines;
if (!added) shouldInclude = false; preprocessor.m_onceIncludedFiles = this->m_onceIncludedFiles;
return value.empty();
}); auto preprocessedInclude = preprocessor.preprocess(file.readString(), true);
auto preprocessedInclude = this->preprocess(file.readString(), false);
if (!preprocessedInclude.has_value()) if (!preprocessedInclude.has_value())
throw this->m_error; throw *preprocessor.m_error;
if (shouldInclude) { if (preprocessor.shouldOnlyIncludeOnce()) {
auto [iter, added] = this->m_onceIncludedFiles.insert(includePath);
if (added) {
auto content = preprocessedInclude.value(); auto content = preprocessedInclude.value();
std::replace(content.begin(), content.end(), '\n', ' '); std::replace(content.begin(), content.end(), '\n', ' ');
@ -98,6 +99,10 @@ namespace hex::pl {
output += content; output += content;
} }
}
this->m_defines = preprocessor.m_defines;
this->m_onceIncludedFiles = preprocessor.m_onceIncludedFiles;
} else if (code.substr(offset, 6) == "define") { } else if (code.substr(offset, 6) == "define") {
offset += 6; offset += 6;
@ -234,6 +239,10 @@ namespace hex::pl {
this->m_pragmaHandlers[pragmaType] = function; this->m_pragmaHandlers[pragmaType] = function;
} }
void Preprocessor::removePragmaHandler(const std::string &pragmaType) {
this->m_pragmaHandlers.erase(pragmaType);
}
void Preprocessor::addDefaultPragmaHandlers() { void Preprocessor::addDefaultPragmaHandlers() {
this->addPragmaHandler("MIME", [](const std::string &value) { this->addPragmaHandler("MIME", [](const std::string &value) {
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');
@ -241,7 +250,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) { this->addPragmaHandler("once", [this](const std::string &value) {
this->m_onlyIncludeOnce = true;
return value.empty(); return value.empty();
}); });
} }