Fix macro parameters not being able to be specified over multiple lines when defining

This commit is contained in:
Jan 2023-12-12 00:37:20 +01:00
parent b7022291a8
commit 74154653aa
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
2 changed files with 75 additions and 43 deletions

View File

@ -123,7 +123,8 @@ DefinesStreamProxy::DefinesStreamProxy(IParserLineStream* stream, const bool ski
: m_stream(stream), : m_stream(stream),
m_skip_directive_lines(skipDirectiveLines), m_skip_directive_lines(skipDirectiveLines),
m_ignore_depth(0), 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; return -1;
} }
void DefinesStreamProxy::ContinueDefine(const ParserLine& line) void DefinesStreamProxy::ContinueDefine(const ParserLine& line, const unsigned currentPos)
{ {
const auto lineEndEscapePos = GetLineEndEscapePos(line); const auto lineEndEscapePos = GetLineEndEscapePos(line);
if (lineEndEscapePos < 0) 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.m_value = m_current_define_value.str();
m_current_define.IdentifyParameters(m_current_define_parameters); m_current_define.IdentifyParameters(m_current_define_parameters);
AddDefine(std::move(m_current_define)); AddDefine(std::move(m_current_define));
@ -159,49 +164,58 @@ void DefinesStreamProxy::ContinueDefine(const ParserLine& line)
} }
else else
{ {
if (line.m_line.size() > static_cast<unsigned>(lineEndEscapePos)) if (line.m_line.size() > static_cast<unsigned>(lineEndEscapePos) && currentPos < static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(0, static_cast<unsigned>(lineEndEscapePos)); m_current_define_value << line.m_line.substr(currentPos, static_cast<unsigned>(lineEndEscapePos) - currentPos);
} }
} }
std::vector<std::string> DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition) void DefinesStreamProxy::ContinueParameters(const ParserLine& line, unsigned& currentPos)
{ {
if (line.m_line[parameterPosition] != '(') const auto lineEndEscapePos = GetLineEndEscapePos(line);
return std::vector<std::string>();
parameterPosition++;
std::vector<std::string> parameters;
while (true) while (true)
{ {
if (!SkipWhitespace(line, parameterPosition) || parameterPosition >= line.m_line.size()) if (!SkipWhitespace(line, currentPos))
throw ParsingException(CreatePos(line, parameterPosition), "Invalid define parameter list"); throw ParsingException(CreatePos(line, currentPos), "Invalid define parameter list");
const auto nameStartPos = parameterPosition; if (lineEndEscapePos >= 0 && currentPos >= static_cast<unsigned>(lineEndEscapePos))
if (!ExtractIdentifier(line, parameterPosition)) return;
throw ParsingException(CreatePos(line, parameterPosition), "Cannot extract name of parameter of define");
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)) if ((m_parameter_state == ParameterState::AFTER_OPEN || m_parameter_state == ParameterState::AFTER_PARAM) && line.m_line[currentPos] == ')')
throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters");
if (parameterPosition >= line.m_line.size())
throw ParsingException(CreatePos(line, parameterPosition), "Unclosed define parameters");
if (line.m_line[parameterPosition] == ')')
{ {
parameterPosition++; currentPos++;
break; m_parameter_state = ParameterState::NOT_IN_PARAMETERS;
return;
} }
if (line.m_line[parameterPosition] != ',') if (m_parameter_state == ParameterState::AFTER_PARAM && line.m_line[currentPos] == ',')
throw ParsingException(CreatePos(line, parameterPosition), "Unknown symbol in define parameter list"); {
currentPos++;
m_parameter_state = ParameterState::AFTER_COMMA;
continue;
}
parameterPosition++; const auto nameStartPos = currentPos;
if (!ExtractIdentifier(line, currentPos))
throw ParsingException(CreatePos(line, currentPos), "Cannot extract name of parameter of define");
m_current_define_parameters.emplace_back(line.m_line, nameStartPos, currentPos - nameStartPos);
m_parameter_state = ParameterState::AFTER_PARAM;
} }
}
return parameters; void DefinesStreamProxy::MatchDefineParameters(const ParserLine& line, unsigned& currentPos)
{
m_current_define_parameters = std::vector<std::string>();
if (line.m_line[currentPos] != '(')
return;
m_parameter_state = ParameterState::AFTER_OPEN;
currentPos++;
ContinueParameters(line, currentPos);
} }
bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) 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); 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); const auto lineEndEscapePos = GetLineEndEscapePos(line);
if (lineEndEscapePos < 0) if (lineEndEscapePos < 0)
{ {
std::string value; std::string value;
if (currentPos < line.m_line.size()) if (currentPos < line.m_line.size())
value = line.m_line.substr(currentPos + 1); value = line.m_line.substr(currentPos);
Define define(name, value); Define define(name, value);
define.IdentifyParameters(parameters); define.IdentifyParameters(m_current_define_parameters);
AddDefine(std::move(define)); AddDefine(std::move(define));
} }
else else
@ -241,10 +256,9 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsi
m_in_define = true; m_in_define = true;
m_current_define = Define(name, std::string()); m_current_define = Define(name, std::string());
m_current_define_value.str(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<unsigned>(lineEndEscapePos)) if (currentPos < line.m_line.size() && (currentPos) < static_cast<unsigned>(lineEndEscapePos))
m_current_define_value << line.m_line.substr(currentPos + 1, static_cast<unsigned>(lineEndEscapePos) - (currentPos + 1)); m_current_define_value << line.m_line.substr(currentPos, static_cast<unsigned>(lineEndEscapePos) - (currentPos));
} }
return true; return true;
@ -451,7 +465,7 @@ bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsig
return true; return true;
} }
bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) bool DefinesStreamProxy::MatchDirectives(ParserLine& line)
{ {
unsigned directiveStartPos; unsigned directiveStartPos;
unsigned directiveEndPos; unsigned directiveEndPos;
@ -709,7 +723,15 @@ ParserLine DefinesStreamProxy::NextLine()
{ {
if (m_in_define) 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) if (!m_skip_directive_lines)
{ {
line.m_line = std::string(); line.m_line = std::string();

View File

@ -47,13 +47,21 @@ public:
}; };
private: private:
enum class BlockMode enum class BlockMode : uint8_t
{ {
NOT_IN_BLOCK, NOT_IN_BLOCK,
IN_BLOCK, IN_BLOCK,
BLOCK_BLOCKED BLOCK_BLOCKED
}; };
enum class ParameterState : uint8_t
{
NOT_IN_PARAMETERS,
AFTER_OPEN,
AFTER_PARAM,
AFTER_COMMA
};
IParserLineStream* const m_stream; IParserLineStream* const m_stream;
const bool m_skip_directive_lines; const bool m_skip_directive_lines;
std::map<std::string, Define> m_defines; std::map<std::string, Define> m_defines;
@ -61,13 +69,15 @@ private:
unsigned m_ignore_depth; unsigned m_ignore_depth;
bool m_in_define; bool m_in_define;
ParameterState m_parameter_state;
Define m_current_define; Define m_current_define;
std::ostringstream m_current_define_value; std::ostringstream m_current_define_value;
std::vector<std::string> m_current_define_parameters; std::vector<std::string> m_current_define_parameters;
static int GetLineEndEscapePos(const ParserLine& line); static int GetLineEndEscapePos(const ParserLine& line);
static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); void MatchDefineParameters(const ParserLine& line, unsigned& currentPos);
void ContinueDefine(const ParserLine& line); 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 MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchUndefDirective(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); _NODISCARD bool MatchIfDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
@ -75,7 +85,7 @@ private:
_NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchElseDirective(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 MatchEndifDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition);
_NODISCARD bool MatchDirectives(const ParserLine& line); _NODISCARD bool MatchDirectives(ParserLine& line);
static void static void
ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues); ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues);