From 5baa3110259662e514961c20517807f96a4f2e9d Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 22 Nov 2021 13:38:33 +0100 Subject: [PATCH] Make defines proxy recognize define values that are escaped over multiple lines --- .../Parsing/Impl/DefinesStreamProxy.cpp | 82 ++++++++++++++++--- src/Parser/Parsing/Impl/DefinesStreamProxy.h | 8 ++ 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index d8135161..adca5d70 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -116,10 +116,48 @@ void DefinesStreamProxy::Define::IdentifyParameters(const std::vector 0; linePos--) + { + const auto c = line.m_line[linePos - 1]; + if (c == '\\') + return static_cast(linePos) - 1; + + if (!isspace(c)) + return -1; + } + + return -1; +} + +void DefinesStreamProxy::ContinueDefine(const ParserLine& line) +{ + const auto lineEndEscapePos = GetLineEndEscapePos(line); + if (lineEndEscapePos < 0) + { + m_current_define_value << line.m_line << " "; + m_current_define.m_value = m_current_define_value.str(); + m_current_define.IdentifyParameters(m_current_define_parameters); + AddDefine(std::move(m_current_define)); + + m_in_define = false; + m_current_define = Define(); + m_current_define_value.str(std::string()); + m_current_define_parameters.clear(); + } + else + { + if (line.m_line.size() > static_cast(lineEndEscapePos)) + m_current_define_value << line.m_line.substr(0, static_cast(lineEndEscapePos)) << " "; + } +} + std::vector DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition) { if (line.m_line[parameterPosition] != '(') @@ -137,11 +175,11 @@ std::vector DefinesStreamProxy::MatchDefineParameters(const ParserL if (!ExtractIdentifier(line, parameterPosition)) throw ParsingException(CreatePos(line, parameterPosition), "Cannot extract name of parameter of define"); - if(!SkipWhitespace(line, parameterPosition)) - throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters"); - parameters.emplace_back(std::string(line.m_line, nameStartPos, parameterPosition - nameStartPos)); + if (!SkipWhitespace(line, parameterPosition)) + throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters"); + if (parameterPosition >= line.m_line.size()) throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters"); @@ -179,15 +217,29 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsi const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos); - const auto parameters = MatchDefineParameters(line, currentPos); + auto parameters = MatchDefineParameters(line, currentPos); - std::string value; - if (currentPos < line.m_line.size()) - value = line.m_line.substr(currentPos + 1); + const auto lineEndEscapePos = GetLineEndEscapePos(line); + if (lineEndEscapePos < 0) + { + std::string value; + if (currentPos < line.m_line.size()) + value = line.m_line.substr(currentPos + 1); - Define define(name, value); - define.IdentifyParameters(parameters); - AddDefine(std::move(define)); + Define define(name, value); + define.IdentifyParameters(parameters); + AddDefine(std::move(define)); + } + else + { + m_in_define = true; + m_current_define = Define(name, std::string()); + m_current_define_value.str(std::string()); + m_current_define_parameters = std::move(parameters); + + if (currentPos < line.m_line.size() && (currentPos + 1) > static_cast(lineEndEscapePos)) + m_current_define_value << line.m_line.substr(currentPos + 1, static_cast(lineEndEscapePos) - (currentPos + 1)) << " "; + } return true; } @@ -481,8 +533,12 @@ ParserLine DefinesStreamProxy::NextLine() { auto line = m_stream->NextLine(); - if (MatchDirectives(line) - || !m_modes.empty() && !m_modes.top()) + if (m_in_define) + { + ContinueDefine(line); + line.m_line.clear(); + } + else if (MatchDirectives(line) || !m_modes.empty() && !m_modes.top()) { line.m_line.clear(); } diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index df8cc835..a840e5bb 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -2,6 +2,7 @@ #include #include +#include #include "AbstractDirectiveStreamProxy.h" #include "Parsing/IParserLineStream.h" @@ -47,7 +48,14 @@ private: std::stack m_modes; unsigned m_ignore_depth; + bool m_in_define; + Define m_current_define; + std::ostringstream m_current_define_value; + std::vector m_current_define_parameters; + + static int GetLineEndEscapePos(const ParserLine& line); static std::vector MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); + void ContinueDefine(const ParserLine& line); _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);