Files
qt-creator/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.cxx
hjk 7e919a07b6 CMake: Remove odd but unused assignment
Change-Id: I052baddc82b7bef24e656c35be1a4edd97a85007
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2023-04-20 13:09:53 +00:00

242 lines
7.6 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#define cmListFileCache_cxx
#include "cmListFileCache.h"
#include <memory>
#include <sstream>
#include <utility>
#include "cmListFileLexer.h"
struct cmListFileParser
{
cmListFileParser(cmListFile* lf, std::string &error);
~cmListFileParser();
cmListFileParser(const cmListFileParser&) = delete;
cmListFileParser& operator=(const cmListFileParser&) = delete;
void IssueError(std::string const& text) const;
bool ParseFile(const char* filename);
bool ParseString(const std::string &str, const std::string &virtual_filename);
bool Parse();
bool ParseFunction(const char* name, long line);
bool AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim);
cmListFile* ListFile;
cmListFileLexer* Lexer;
std::string FunctionName;
long FunctionLine;
long FunctionLineEnd;
std::vector<cmListFileArgument> FunctionArguments;
std::string &Error;
enum
{
SeparationOkay,
SeparationWarning,
SeparationError
} Separation;
};
cmListFileParser::cmListFileParser(cmListFile *lf, std::string &error)
: ListFile(lf)
, Lexer(cmListFileLexer_New())
, Error(error)
{
}
cmListFileParser::~cmListFileParser()
{
cmListFileLexer_Delete(this->Lexer);
}
void cmListFileParser::IssueError(const std::string& text) const
{
Error += text;
Error += "\n";
}
bool cmListFileParser::ParseString(const std::string &str,
const std::string &/*virtual_filename*/)
{
if (!cmListFileLexer_SetString(this->Lexer, str.c_str(), (int)str.size())) {
this->IssueError("cmListFileCache: cannot allocate buffer.");
return false;
}
return this->Parse();
}
bool cmListFileParser::Parse()
{
// Use a simple recursive-descent parser to process the token
// stream.
bool haveNewline = true;
while (cmListFileLexer_Token* token = cmListFileLexer_Scan(this->Lexer)) {
if (token->type == cmListFileLexer_Token_Space) {
} else if (token->type == cmListFileLexer_Token_Newline) {
haveNewline = true;
} else if (token->type == cmListFileLexer_Token_CommentBracket
|| token->type == cmListFileLexer_Token_CommentLine) {
haveNewline = false;
} else if (token->type == cmListFileLexer_Token_Identifier) {
if (haveNewline) {
haveNewline = false;
if (this->ParseFunction(token->text, token->line)) {
this->ListFile->Functions.emplace_back(
std::move(this->FunctionName), this->FunctionLine,
this->FunctionLineEnd, std::move(this->FunctionArguments));
} else {
return false;
}
} else {
std::ostringstream error;
error << "Parse error. Expected a newline, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
this->IssueError(error.str());
return false;
}
} else {
std::ostringstream error;
error << "Parse error. Expected a command name, got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
this->IssueError(error.str());
return false;
}
}
return true;
}
bool cmListFile::ParseString(const std::string &str, const std::string& virtual_filename, std::string &error)
{
bool parseError = false;
{
cmListFileParser parser(this, error);
parseError = !parser.ParseString(str, virtual_filename);
}
return !parseError;
}
bool cmListFileParser::ParseFunction(const char* name, long line)
{
// Ininitialize a new function call.
this->FunctionName = name;
this->FunctionLine = line;
// Command name has already been parsed. Read the left paren.
cmListFileLexer_Token* token;
while ((token = cmListFileLexer_Scan(this->Lexer)) &&
token->type == cmListFileLexer_Token_Space) {
}
if (!token) {
std::ostringstream error;
/* clang-format off */
error << "Unexpected end of file.\n"
<< "Parse error. Function missing opening \"(\".";
/* clang-format on */
this->IssueError(error.str());
return false;
}
if (token->type != cmListFileLexer_Token_ParenLeft) {
std::ostringstream error;
error << "Parse error. Expected \"(\", got "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
this->IssueError(error.str());
return false;
}
// Arguments.
unsigned long parenDepth = 0;
this->Separation = SeparationOkay;
while ((token = cmListFileLexer_Scan(this->Lexer))) {
if (token->type == cmListFileLexer_Token_Space ||
token->type == cmListFileLexer_Token_Newline) {
this->Separation = SeparationOkay;
continue;
}
if (token->type == cmListFileLexer_Token_ParenLeft) {
parenDepth++;
this->Separation = SeparationOkay;
if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
return false;
}
} else if (token->type == cmListFileLexer_Token_ParenRight) {
if (parenDepth == 0) {
this->FunctionLineEnd = token->line;
return true;
}
parenDepth--;
this->Separation = SeparationOkay;
if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
return false;
}
this->Separation = SeparationWarning;
} else if (token->type == cmListFileLexer_Token_Identifier ||
token->type == cmListFileLexer_Token_ArgumentUnquoted) {
if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
return false;
}
this->Separation = SeparationWarning;
} else if (token->type == cmListFileLexer_Token_ArgumentQuoted) {
if (!this->AddArgument(token, cmListFileArgument::Quoted)) {
return false;
}
this->Separation = SeparationWarning;
} else if (token->type == cmListFileLexer_Token_CommentLine) {
if (!this->AddArgument(token, cmListFileArgument::Comment)) {
return false;
}
this->Separation = SeparationWarning;
} else if (token->type == cmListFileLexer_Token_ArgumentBracket) {
if (!this->AddArgument(token, cmListFileArgument::Bracket)) {
return false;
}
this->Separation = SeparationError;
} else if (token->type == cmListFileLexer_Token_CommentBracket) {
this->Separation = SeparationError;
} else {
// Error.
std::ostringstream error;
error << "Parse error. Function missing ending \")\". "
<< "Instead found "
<< cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
this->IssueError(error.str());
return false;
}
}
std::ostringstream error;
error << "Parse error. Function missing ending \")\". "
<< "End of file reached.";
IssueError(error.str());
return false;
}
bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim)
{
this->FunctionArguments.emplace_back(token->text, delim, token->line, token->column);
if (this->Separation == SeparationOkay) {
return true;
}
bool isError = (this->Separation == SeparationError ||
delim == cmListFileArgument::Bracket);
std::ostringstream m;
m << "Syntax " << (isError ? "Error" : "Warning") << " in cmake code at "
<< "column " << token->column << "\n"
<< "Argument not separated from preceding token by whitespace.";
/* clang-format on */
if (isError) {
IssueError(m.str());
return false;
}
return true;
}