From 93aae116c55869281053b7ff7ba0b64c5ac09c37 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 12 Dec 2023 00:37:20 +0100 Subject: [PATCH] Fix macro parameters not being able to be specified over multiple lines when defining --- .../Parsing/Impl/DefinesStreamProxy.cpp | 98 ++++++++++++------- src/Parser/Parsing/Impl/DefinesStreamProxy.h | 18 +++- 2 files changed, 74 insertions(+), 42 deletions(-) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index b54a5330a..e723d8697 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -123,7 +123,8 @@ DefinesStreamProxy::DefinesStreamProxy(IParserLineStream* stream, const bool ski : m_stream(stream), m_skip_directive_lines(skipDirectiveLines), m_ignore_depth(0), - m_in_define(false) + m_in_define(false), + m_parameter_state(ParameterState::NOT_IN_PARAMETERS) { } @@ -142,12 +143,16 @@ int DefinesStreamProxy::GetLineEndEscapePos(const ParserLine& line) return -1; } -void DefinesStreamProxy::ContinueDefine(const ParserLine& line) +void DefinesStreamProxy::ContinueDefine(const ParserLine& line, const unsigned currentPos) { const auto lineEndEscapePos = GetLineEndEscapePos(line); if (lineEndEscapePos < 0) { - m_current_define_value << line.m_line; + if (currentPos <= 0) + m_current_define_value << line.m_line; + else + m_current_define_value << line.m_line.substr(currentPos); + m_current_define.m_value = m_current_define_value.str(); m_current_define.IdentifyParameters(m_current_define_parameters); AddDefine(std::move(m_current_define)); @@ -159,49 +164,58 @@ void DefinesStreamProxy::ContinueDefine(const ParserLine& line) } else { - if (line.m_line.size() > static_cast(lineEndEscapePos)) - m_current_define_value << line.m_line.substr(0, static_cast(lineEndEscapePos)); + if (line.m_line.size() > static_cast(lineEndEscapePos) && currentPos < static_cast(lineEndEscapePos)) + m_current_define_value << line.m_line.substr(currentPos, static_cast(lineEndEscapePos) - currentPos); } } -std::vector DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition) +void DefinesStreamProxy::ContinueParameters(const ParserLine& line, unsigned& currentPos) { - if (line.m_line[parameterPosition] != '(') - return std::vector(); - - parameterPosition++; - std::vector parameters; - + const auto lineEndEscapePos = GetLineEndEscapePos(line); while (true) { - if (!SkipWhitespace(line, parameterPosition) || parameterPosition >= line.m_line.size()) - throw ParsingException(CreatePos(line, parameterPosition), "Invalid define parameter list"); + if (!SkipWhitespace(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Invalid define parameter list"); - const auto nameStartPos = parameterPosition; - if (!ExtractIdentifier(line, parameterPosition)) - throw ParsingException(CreatePos(line, parameterPosition), "Cannot extract name of parameter of define"); + if (lineEndEscapePos >= 0 && currentPos >= static_cast(lineEndEscapePos)) + return; - parameters.emplace_back(std::string(line.m_line, nameStartPos, parameterPosition - nameStartPos)); + if (currentPos >= line.m_line.size()) + throw ParsingException(CreatePos(line, currentPos), "Invalid define parameter list"); - 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"); + if ((m_parameter_state == ParameterState::AFTER_OPEN || m_parameter_state == ParameterState::AFTER_PARAM) && line.m_line[currentPos] == ')') + { + currentPos++; + m_parameter_state = ParameterState::NOT_IN_PARAMETERS; + return; + } - if (line.m_line[parameterPosition] == ')') + if (m_parameter_state == ParameterState::AFTER_PARAM && line.m_line[currentPos] == ',') { - parameterPosition++; - break; + currentPos++; + m_parameter_state = ParameterState::AFTER_COMMA; + continue; } - if (line.m_line[parameterPosition] != ',') - throw ParsingException(CreatePos(line, parameterPosition), "Unknown symbol in define parameter list"); + const auto nameStartPos = currentPos; + if (!ExtractIdentifier(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot extract name of parameter of define"); - parameterPosition++; + m_current_define_parameters.emplace_back(line.m_line, nameStartPos, currentPos - nameStartPos); + m_parameter_state = ParameterState::AFTER_PARAM; } +} + +void DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& currentPos) +{ + m_current_define_parameters = std::vector(); + if (line.m_line[currentPos] != '(') + return; + + m_parameter_state = ParameterState::AFTER_OPEN; + currentPos++; - return parameters; + ContinueParameters(line, currentPos); } bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) @@ -223,17 +237,18 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsi const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos); - auto parameters = MatchDefineParameters(line, currentPos); + MatchDefineParameters(line, currentPos); + SkipWhitespace(line, currentPos); const auto lineEndEscapePos = GetLineEndEscapePos(line); if (lineEndEscapePos < 0) { std::string value; if (currentPos < line.m_line.size()) - value = line.m_line.substr(currentPos + 1); + value = line.m_line.substr(currentPos); Define define(name, value); - define.IdentifyParameters(parameters); + define.IdentifyParameters(m_current_define_parameters); AddDefine(std::move(define)); } else @@ -241,10 +256,9 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsi 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)); + if (currentPos < line.m_line.size() && (currentPos) < static_cast(lineEndEscapePos)) + m_current_define_value << line.m_line.substr(currentPos, static_cast(lineEndEscapePos) - (currentPos)); } return true; @@ -451,7 +465,7 @@ bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsig return true; } -bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) +bool DefinesStreamProxy::MatchDirectives(ParserLine& line) { unsigned directiveStartPos; unsigned directiveEndPos; @@ -709,7 +723,15 @@ ParserLine DefinesStreamProxy::NextLine() { if (m_in_define) { - ContinueDefine(line); + unsigned currentPos = 0u; + + if (m_parameter_state != ParameterState::NOT_IN_PARAMETERS) + { + ContinueParameters(line, currentPos); + SkipWhitespace(line, currentPos); + } + + ContinueDefine(line, currentPos); if (!m_skip_directive_lines) { line.m_line = std::string(); diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index 8b216981a..be61175c1 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -47,13 +47,21 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy }; private: - enum class BlockMode + enum class BlockMode : uint8_t { NOT_IN_BLOCK, IN_BLOCK, BLOCK_BLOCKED }; + enum class ParameterState : uint8_t + { + NOT_IN_PARAMETERS, + AFTER_OPEN, + AFTER_PARAM, + AFTER_COMMA + }; + IParserLineStream* const m_stream; const bool m_skip_directive_lines; std::map m_defines; @@ -61,13 +69,15 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy unsigned m_ignore_depth; bool m_in_define; + ParameterState m_parameter_state; 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); + void MatchDefineParameters(const ParserLine& line, unsigned& currentPos); + void ContinueDefine(const ParserLine& line, unsigned currentPos); + void ContinueParameters(const ParserLine& line, unsigned& currentPos); _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchIfDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); @@ -75,7 +85,7 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchElseDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchEndifDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); - _NODISCARD bool MatchDirectives(const ParserLine& line); + _NODISCARD bool MatchDirectives(ParserLine& line); static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector& parameterValues);