From 71eb0ab9f8e98df9bd021c1c49d7ec00a66492cb Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 6 Apr 2023 15:30:13 +0200 Subject: [PATCH] CMakePM: Add CMake source file parser Files taken from the CMake repository https://gitlab.kitware.com/cmake/cmake.git 624461526f4707a2406ebbd40245a605b6bd41fa (tag: v3.26.3) Change-Id: I9ef388908cd22eb2748b5c17d039848ee23585b9 Reviewed-by: hjk Reviewed-by: Eike Ziller --- README.md | 37 ++ .../overview/creator-acknowledgements.qdoc | 42 ++ .../3rdparty/cmake/Copyright.txt | 136 +++++ .../3rdparty/cmake/README.md | 4 + .../3rdparty/cmake/cmListFileCache.cxx | 508 ++++++++++++++++ .../3rdparty/cmake/cmListFileCache.h | 246 ++++++++ .../3rdparty/cmake/cmListFileLexer.h | 68 +++ .../3rdparty/cmake/cmListFileLexer.in.l | 560 ++++++++++++++++++ .../3rdparty/cmake/cmStandardLexer.h | 89 +++ 9 files changed, 1690 insertions(+) create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/Copyright.txt create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/README.md create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.cxx create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.h create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.h create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.in.l create mode 100644 src/plugins/cmakeprojectmanager/3rdparty/cmake/cmStandardLexer.h diff --git a/README.md b/README.md index 4a97db2efcc..410d8f03e8d 100644 --- a/README.md +++ b/README.md @@ -867,3 +867,40 @@ SQLite (https://www.sqlite.org) is in the Public Domain. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +### cmake + + The CMake project manager uses the CMake lexer code for parsing CMake files + + https://gitlab.kitware.com/cmake/cmake.git + + CMake - Cross Platform Makefile Generator + Copyright 2000-2023 Kitware, Inc. and Contributors + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Kitware, Inc. nor the names of Contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc index 820e97247d5..7f193d124dc 100644 --- a/doc/qtcreator/src/overview/creator-acknowledgements.qdoc +++ b/doc/qtcreator/src/overview/creator-acknowledgements.qdoc @@ -1059,5 +1059,47 @@ \include license-mit.qdocinc + \li \b cmake + + The CMake project manager uses the CMake lexer code for parsing CMake files. + + \list + \li \l https://gitlab.kitware.com/cmake/cmake.git + \endlist + + CMake - Cross Platform Makefile Generator + Copyright 2000-2023 Kitware, Inc. and Contributors + All rights reserved. + + \badcode + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Kitware, Inc. nor the names of Contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + \endcode + + \endlist */ diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/Copyright.txt b/src/plugins/cmakeprojectmanager/3rdparty/cmake/Copyright.txt new file mode 100644 index 00000000000..515e403a2d4 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/Copyright.txt @@ -0,0 +1,136 @@ +CMake - Cross Platform Makefile Generator +Copyright 2000-2023 Kitware, Inc. and Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Kitware, Inc. nor the names of Contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------ + +The following individuals and institutions are among the Contributors: + +* Aaron C. Meadows +* Adriaan de Groot +* Aleksey Avdeev +* Alexander Neundorf +* Alexander Smorkalov +* Alexey Sokolov +* Alex Merry +* Alex Turbov +* Andreas Pakulat +* Andreas Schneider +* André Rigland Brodtkorb +* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf +* Benjamin Eikel +* Bjoern Ricks +* Brad Hards +* Christopher Harvey +* Christoph Grüninger +* Clement Creusot +* Daniel Blezek +* Daniel Pfeifer +* Dawid Wróbel +* Enrico Scholz +* Eran Ifrah +* Esben Mose Hansen, Ange Optimization ApS +* Geoffrey Viola +* Google Inc +* Gregor Jasny +* Helio Chissini de Castro +* Ilya Lavrenov +* Insight Software Consortium +* Intel Corporation +* Jan Woetzel +* Jordan Williams +* Julien Schueller +* Kelly Thompson +* Konstantin Podsvirov +* Laurent Montel +* Mario Bensi +* Martin Gräßlin +* Mathieu Malaterre +* Matthaeus G. Chajdas +* Matthias Kretz +* Matthias Maennich +* Michael Hirsch, Ph.D. +* Michael Stürmer +* Miguel A. Figueroa-Villanueva +* Mike Durso +* Mike Jackson +* Mike McQuaid +* Nicolas Bock +* Nicolas Despres +* Nikita Krupen'ko +* NVIDIA Corporation +* OpenGamma Ltd. +* Patrick Stotko +* Per Øyvind Karlsen +* Peter Collingbourne +* Petr Gotthard +* Philip Lowman +* Philippe Proulx +* Raffi Enficiaud, Max Planck Society +* Raumfeld +* Roger Leigh +* Rolf Eike Beer +* Roman Donchenko +* Roman Kharitonov +* Ruslan Baratov +* Sebastian Holtermann +* Stephen Kelly +* Sylvain Joubert +* The Qt Company Ltd. +* Thomas Sondergaard +* Tobias Hunger +* Todd Gamblin +* Tristan Carel +* University of Dundee +* Vadim Zhukov +* Will Dicharry + +See version control history for details of individual contributions. + +The above copyright and license notice applies to distributions of +CMake in source and binary form. Third-party software packages supplied +with CMake under compatible licenses provide their own copyright notices +documented in corresponding subdirectories or source files. + +------------------------------------------------------------------------------ + +CMake was initially developed by Kitware with the following sponsorship: + + * National Library of Medicine at the National Institutes of Health + as part of the Insight Segmentation and Registration Toolkit (ITK). + + * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel + Visualization Initiative. + + * National Alliance for Medical Image Computing (NAMIC) is funded by the + National Institutes of Health through the NIH Roadmap for Medical Research, + Grant U54 EB005149. + + * Kitware, Inc. diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/README.md b/src/plugins/cmakeprojectmanager/3rdparty/cmake/README.md new file mode 100644 index 00000000000..92a4d869a66 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/README.md @@ -0,0 +1,4 @@ +Files taken from the CMake repository https://gitlab.kitware.com/cmake/cmake.git + +624461526f4707a2406ebbd40245a605b6bd41fa (tag: v3.26.3) + diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.cxx b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.cxx new file mode 100644 index 00000000000..6270c825f2b --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.cxx @@ -0,0 +1,508 @@ +/* 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 +#include +#include + +#ifdef _WIN32 +# include +#endif + +#include "cmListFileLexer.h" +#include "cmMessageType.h" +#include "cmMessenger.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +struct cmListFileParser +{ + cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, + cmMessenger* messenger); + ~cmListFileParser(); + cmListFileParser(const cmListFileParser&) = delete; + cmListFileParser& operator=(const cmListFileParser&) = delete; + void IssueFileOpenError(std::string const& text) const; + void IssueError(std::string const& text) const; + bool ParseFile(const char* filename); + bool ParseString(const char* str, const char* virtual_filename); + bool Parse(); + bool ParseFunction(const char* name, long line); + bool AddArgument(cmListFileLexer_Token* token, + cmListFileArgument::Delimiter delim); + cm::optional CheckNesting() const; + cmListFile* ListFile; + cmListFileBacktrace Backtrace; + cmMessenger* Messenger; + const char* FileName = nullptr; + cmListFileLexer* Lexer; + std::string FunctionName; + long FunctionLine; + long FunctionLineEnd; + std::vector FunctionArguments; + enum + { + SeparationOkay, + SeparationWarning, + SeparationError + } Separation; +}; + +cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt, + cmMessenger* messenger) + : ListFile(lf) + , Backtrace(std::move(lfbt)) + , Messenger(messenger) + , Lexer(cmListFileLexer_New()) +{ +} + +cmListFileParser::~cmListFileParser() +{ + cmListFileLexer_Delete(this->Lexer); +} + +void cmListFileParser::IssueFileOpenError(const std::string& text) const +{ + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, + this->Backtrace); +} + +void cmListFileParser::IssueError(const std::string& text) const +{ + cmListFileContext lfc; + lfc.FilePath = this->FileName; + lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer); + cmListFileBacktrace lfbt = this->Backtrace; + lfbt = lfbt.Push(lfc); + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt); + cmSystemTools::SetFatalErrorOccurred(); +} + +bool cmListFileParser::ParseFile(const char* filename) +{ + this->FileName = filename; + +#ifdef _WIN32 + std::string expandedFileName = cmsys::Encoding::ToNarrow( + cmSystemTools::ConvertToWindowsExtendedPath(filename)); + filename = expandedFileName.c_str(); +#endif + + // Open the file. + cmListFileLexer_BOM bom; + if (!cmListFileLexer_SetFileName(this->Lexer, filename, &bom)) { + this->IssueFileOpenError("cmListFileCache: error can not open file."); + return false; + } + + if (bom == cmListFileLexer_BOM_Broken) { + cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr); + this->IssueFileOpenError("Error while reading Byte-Order-Mark. " + "File not seekable?"); + return false; + } + + // Verify the Byte-Order-Mark, if any. + if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) { + cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr); + this->IssueFileOpenError( + "File starts with a Byte-Order-Mark that is not UTF-8."); + return false; + } + + return this->Parse(); +} + +bool cmListFileParser::ParseString(const char* str, + const char* virtual_filename) +{ + this->FileName = virtual_filename; + + if (!cmListFileLexer_SetString(this->Lexer, str)) { + this->IssueFileOpenError("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) { + 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; + } + } + + // Check if all functions are nested properly. + if (auto badNesting = this->CheckNesting()) { + this->Messenger->IssueMessage( + MessageType::FATAL_ERROR, + "Flow control statements are not properly nested.", + this->Backtrace.Push(*badNesting)); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + + return true; +} + +bool cmListFile::ParseFile(const char* filename, cmMessenger* messenger, + cmListFileBacktrace const& lfbt) +{ + if (!cmSystemTools::FileExists(filename) || + cmSystemTools::FileIsDirectory(filename)) { + return false; + } + + bool parseError = false; + + { + cmListFileParser parser(this, lfbt, messenger); + parseError = !parser.ParseFile(filename); + } + + return !parseError; +} + +bool cmListFile::ParseString(const char* str, const char* virtual_filename, + cmMessenger* messenger, + const cmListFileBacktrace& lfbt) +{ + bool parseError = false; + + { + cmListFileParser parser(this, lfbt, messenger); + 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_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; + cmListFileContext lfc; + lfc.FilePath = this->FileName; + lfc.Line = line; + cmListFileBacktrace lfbt = this->Backtrace; + lfbt = lfbt.Push(lfc); + error << "Parse error. Function missing ending \")\". " + << "End of file reached."; + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, error.str(), lfbt); + return false; +} + +bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, + cmListFileArgument::Delimiter delim) +{ + this->FunctionArguments.emplace_back(token->text, delim, token->line); + if (this->Separation == SeparationOkay) { + return true; + } + bool isError = (this->Separation == SeparationError || + delim == cmListFileArgument::Bracket); + std::ostringstream m; + cmListFileContext lfc; + lfc.FilePath = this->FileName; + lfc.Line = token->line; + cmListFileBacktrace lfbt = this->Backtrace; + lfbt = lfbt.Push(lfc); + + 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) { + this->Messenger->IssueMessage(MessageType::FATAL_ERROR, m.str(), lfbt); + return false; + } + this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, m.str(), lfbt); + return true; +} + +namespace { +enum class NestingStateEnum +{ + If, + Else, + While, + Foreach, + Function, + Macro, + Block +}; + +struct NestingState +{ + NestingStateEnum State; + cmListFileContext Context; +}; + +bool TopIs(std::vector& stack, NestingStateEnum state) +{ + return !stack.empty() && stack.back().State == state; +} +} + +cm::optional cmListFileParser::CheckNesting() const +{ + std::vector stack; + + for (auto const& func : this->ListFile->Functions) { + auto const& name = func.LowerCaseName(); + if (name == "if") { + stack.push_back({ + NestingStateEnum::If, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "elseif") { + if (!TopIs(stack, NestingStateEnum::If)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.back() = { + NestingStateEnum::If, + cmListFileContext::FromListFileFunction(func, this->FileName), + }; + } else if (name == "else") { + if (!TopIs(stack, NestingStateEnum::If)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.back() = { + NestingStateEnum::Else, + cmListFileContext::FromListFileFunction(func, this->FileName), + }; + } else if (name == "endif") { + if (!TopIs(stack, NestingStateEnum::If) && + !TopIs(stack, NestingStateEnum::Else)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } else if (name == "while") { + stack.push_back({ + NestingStateEnum::While, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endwhile") { + if (!TopIs(stack, NestingStateEnum::While)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } else if (name == "foreach") { + stack.push_back({ + NestingStateEnum::Foreach, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endforeach") { + if (!TopIs(stack, NestingStateEnum::Foreach)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } else if (name == "function") { + stack.push_back({ + NestingStateEnum::Function, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endfunction") { + if (!TopIs(stack, NestingStateEnum::Function)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } else if (name == "macro") { + stack.push_back({ + NestingStateEnum::Macro, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endmacro") { + if (!TopIs(stack, NestingStateEnum::Macro)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } else if (name == "block") { + stack.push_back({ + NestingStateEnum::Block, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endblock") { + if (!TopIs(stack, NestingStateEnum::Block)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); + } + } + + if (!stack.empty()) { + return stack.back().Context; + } + + return cm::nullopt; +} + +#include "cmConstStack.tcc" +template class cmConstStack; + +std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) +{ + os << lfc.FilePath; + if (lfc.Line > 0) { + os << ":" << lfc.Line; + if (!lfc.Name.empty()) { + os << " (" << lfc.Name << ")"; + } + } else if (lfc.Line == cmListFileContext::DeferPlaceholderLine) { + os << ":DEFERRED"; + } + return os; +} + +bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + if (lhs.Line != rhs.Line) { + return lhs.Line < rhs.Line; + } + return lhs.FilePath < rhs.FilePath; +} + +bool operator==(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + return lhs.Line == rhs.Line && lhs.FilePath == rhs.FilePath; +} + +bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + return !(lhs == rhs); +} + +std::ostream& operator<<(std::ostream& os, BT const& s) +{ + return os << s.Value; +} + +std::vector> cmExpandListWithBacktrace( + std::string const& list, cmListFileBacktrace const& bt, bool emptyArgs) +{ + std::vector> result; + std::vector tmp = cmExpandedList(list, emptyArgs); + result.reserve(tmp.size()); + for (std::string& i : tmp) { + result.emplace_back(std::move(i), bt); + } + return result; +} diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.h b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.h new file mode 100644 index 00000000000..05539892c93 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileCache.h @@ -0,0 +1,246 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include +#include +#include +#include + +#include + +#include "cmConstStack.h" +#include "cmSystemTools.h" + +/** \class cmListFileCache + * \brief A class to cache list file contents. + * + * cmListFileCache is a class used to cache the contents of parsed + * cmake list files. + */ + +class cmMessenger; + +struct cmListFileArgument +{ + enum Delimiter + { + Unquoted, + Quoted, + Bracket + }; + cmListFileArgument() = default; + cmListFileArgument(std::string v, Delimiter d, long line) + : Value(std::move(v)) + , Delim(d) + , Line(line) + { + } + bool operator==(const cmListFileArgument& r) const + { + return (this->Value == r.Value) && (this->Delim == r.Delim); + } + bool operator!=(const cmListFileArgument& r) const { return !(*this == r); } + std::string Value; + Delimiter Delim = Unquoted; + long Line = 0; +}; + +class cmListFileFunction +{ +public: + cmListFileFunction(std::string name, long line, long lineEnd, + std::vector args) + : Impl{ std::make_shared(std::move(name), line, lineEnd, + std::move(args)) } + { + } + + std::string const& OriginalName() const noexcept + { + return this->Impl->OriginalName; + } + + std::string const& LowerCaseName() const noexcept + { + return this->Impl->LowerCaseName; + } + + long Line() const noexcept { return this->Impl->Line; } + long LineEnd() const noexcept { return this->Impl->LineEnd; } + + std::vector const& Arguments() const noexcept + { + return this->Impl->Arguments; + } + +private: + struct Implementation + { + Implementation(std::string name, long line, long lineEnd, + std::vector args) + : OriginalName{ std::move(name) } + , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) } + , Line{ line } + , LineEnd{ lineEnd } + , Arguments{ std::move(args) } + { + } + + std::string OriginalName; + std::string LowerCaseName; + long Line = 0; + long LineEnd = 0; + std::vector Arguments; + }; + + std::shared_ptr Impl; +}; + +class cmListFileContext +{ +public: + std::string Name; + std::string FilePath; + long Line = 0; + static long const DeferPlaceholderLine = -1; + cm::optional DeferId; + + cmListFileContext() = default; + // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it + // as being able to throw an exception. Suppress the warning as there doesn't + // seem to be any way for this to happen given the member types. + // NOLINTNEXTLINE(bugprone-exception-escape) + cmListFileContext(cmListFileContext&& /*other*/) noexcept = default; + cmListFileContext(const cmListFileContext& /*other*/) = default; + cmListFileContext& operator=(const cmListFileContext& /*other*/) = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept = + default; +#else + // The move assignment operators for several STL classes did not become + // noexcept until C++17, which causes some tools to warn about this move + // assignment operator throwing an exception when it shouldn't. + cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept = + delete; +#endif + + cmListFileContext(std::string name, std::string filePath, long line) + : Name(std::move(name)) + , FilePath(std::move(filePath)) + , Line(line) + { + } + + static cmListFileContext FromListFilePath(std::string const& filePath) + { + // We are entering a file-level scope but have not yet reached + // any specific line or command invocation within it. This context + // is useful to print when it is at the top but otherwise can be + // skipped during call stack printing. + cmListFileContext lfc; + lfc.FilePath = filePath; + return lfc; + } + + static cmListFileContext FromListFileFunction( + cmListFileFunction const& lff, std::string const& fileName, + cm::optional deferId = {}) + { + cmListFileContext lfc; + lfc.FilePath = fileName; + lfc.Line = lff.Line(); + lfc.Name = lff.OriginalName(); + lfc.DeferId = std::move(deferId); + return lfc; + } +}; + +std::ostream& operator<<(std::ostream&, cmListFileContext const&); +bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs); +bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); +bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); + +// Represent a backtrace (call stack) with efficient value semantics. +class cmListFileBacktrace + : public cmConstStack +{ + using cmConstStack::cmConstStack; + friend class cmConstStack; +}; +#ifndef cmListFileCache_cxx +extern template class cmConstStack; +#endif + +// Wrap type T as a value with a backtrace. For purposes of +// ordering and equality comparison, only the original value is +// used. The backtrace is considered incidental. +template +class BT +{ +public: + BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace()) + : Value(std::move(v)) + , Backtrace(std::move(bt)) + { + } + T Value; + cmListFileBacktrace Backtrace; + friend bool operator==(BT const& l, BT const& r) + { + return l.Value == r.Value; + } + friend bool operator<(BT const& l, BT const& r) + { + return l.Value < r.Value; + } + friend bool operator==(BT const& l, T const& r) { return l.Value == r; } + friend bool operator==(T const& l, BT const& r) { return l == r.Value; } +}; + +std::ostream& operator<<(std::ostream& os, BT const& s); + +// Wrap type T as a value with potentially multiple backtraces. For purposes +// of ordering and equality comparison, only the original value is used. The +// backtrace is considered incidental. +template +class BTs +{ +public: + BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace()) + : Value(std::move(v)) + { + this->Backtraces.emplace_back(std::move(bt)); + } + T Value; + std::vector Backtraces; + friend bool operator==(BTs const& l, BTs const& r) + { + return l.Value == r.Value; + } + friend bool operator<(BTs const& l, BTs const& r) + { + return l.Value < r.Value; + } + friend bool operator==(BTs const& l, T const& r) { return l.Value == r; } + friend bool operator==(T const& l, BTs const& r) { return l == r.Value; } +}; + +std::vector> cmExpandListWithBacktrace( + std::string const& list, + cmListFileBacktrace const& bt = cmListFileBacktrace(), + bool emptyArgs = false); + +struct cmListFile +{ + bool ParseFile(const char* path, cmMessenger* messenger, + cmListFileBacktrace const& lfbt); + + bool ParseString(const char* str, const char* virtual_filename, + cmMessenger* messenger, cmListFileBacktrace const& lfbt); + + std::vector Functions; +}; diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.h b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.h new file mode 100644 index 00000000000..3c89f63416a --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.h @@ -0,0 +1,68 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOLINTNEXTLINE(modernize-use-using) */ +typedef enum cmListFileLexer_Type_e +{ + cmListFileLexer_Token_None, + cmListFileLexer_Token_Space, + cmListFileLexer_Token_Newline, + cmListFileLexer_Token_Identifier, + cmListFileLexer_Token_ParenLeft, + cmListFileLexer_Token_ParenRight, + cmListFileLexer_Token_ArgumentUnquoted, + cmListFileLexer_Token_ArgumentQuoted, + cmListFileLexer_Token_ArgumentBracket, + cmListFileLexer_Token_CommentBracket, + cmListFileLexer_Token_BadCharacter, + cmListFileLexer_Token_BadBracket, + cmListFileLexer_Token_BadString +} cmListFileLexer_Type; + +/* NOLINTNEXTLINE(modernize-use-using) */ +typedef struct cmListFileLexer_Token_s cmListFileLexer_Token; +struct cmListFileLexer_Token_s +{ + cmListFileLexer_Type type; + char* text; + int length; + int line; + int column; +}; + +enum cmListFileLexer_BOM_e +{ + cmListFileLexer_BOM_None, + cmListFileLexer_BOM_Broken, + cmListFileLexer_BOM_UTF8, + cmListFileLexer_BOM_UTF16BE, + cmListFileLexer_BOM_UTF16LE, + cmListFileLexer_BOM_UTF32BE, + cmListFileLexer_BOM_UTF32LE +}; + +/* NOLINTNEXTLINE(modernize-use-using) */ +typedef enum cmListFileLexer_BOM_e cmListFileLexer_BOM; + +/* NOLINTNEXTLINE(modernize-use-using) */ +typedef struct cmListFileLexer_s cmListFileLexer; + +cmListFileLexer* cmListFileLexer_New(void); +int cmListFileLexer_SetFileName(cmListFileLexer*, const char*, + cmListFileLexer_BOM* bom); +int cmListFileLexer_SetString(cmListFileLexer*, const char*); +cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer*); +long cmListFileLexer_GetCurrentLine(cmListFileLexer*); +long cmListFileLexer_GetCurrentColumn(cmListFileLexer*); +const char* cmListFileLexer_GetTypeAsString(cmListFileLexer*, + cmListFileLexer_Type); +void cmListFileLexer_Delete(cmListFileLexer*); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.in.l b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.in.l new file mode 100644 index 00000000000..94cf8a59430 --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmListFileLexer.in.l @@ -0,0 +1,560 @@ +%{ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +/* + +This file must be translated to C and modified to build everywhere. + +Run flex >= 2.6 like this: + + flex --nounistd -DFLEXINT_H --noline -ocmListFileLexer.c cmListFileLexer.in.l + +Modify cmListFileLexer.c: + - remove trailing whitespace: sed -i 's/\s*$//' cmListFileLexer.c + - remove blank lines at end of file: sed -i '${/^$/d;}' cmListFileLexer.c + - #include "cmStandardLexer.h" at the top: sed -i '1i#include "cmStandardLexer.h"' cmListFileLexer.c + +*/ + +/* IWYU pragma: no_forward_declare yyguts_t */ + +#ifdef _WIN32 +#include "cmsys/Encoding.h" +#endif + +/* Setup the proper cmListFileLexer_yylex declaration. */ +#define YY_EXTRA_TYPE cmListFileLexer* +#define YY_DECL int cmListFileLexer_yylex (yyscan_t yyscanner, cmListFileLexer* lexer) + +#include "cmListFileLexer.h" + +/*--------------------------------------------------------------------------*/ +struct cmListFileLexer_s +{ + cmListFileLexer_Token token; + int bracket; + int comment; + int line; + int column; + int size; + FILE* file; + size_t cr; + char* string_buffer; + char* string_position; + int string_left; + yyscan_t scanner; +}; + +static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text, + int length); +static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text, + int length); +static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer, + size_t bufferSize); +static void cmListFileLexerInit(cmListFileLexer* lexer); +static void cmListFileLexerDestroy(cmListFileLexer* lexer); + +/* Replace the lexer input function. */ +#undef YY_INPUT +#define YY_INPUT(buf, result, max_size) \ + do { result = cmListFileLexerInput(cmListFileLexer_yyget_extra(yyscanner), buf, max_size); } while (0) + +/*--------------------------------------------------------------------------*/ +%} + +%option prefix="cmListFileLexer_yy" + +%option reentrant +%option yylineno +%option noyywrap +%pointer +%x STRING +%x BRACKET +%x BRACKETEND +%x COMMENT + +MAKEVAR \$\([A-Za-z0-9_]*\) +UNQUOTED ([^ \0\t\r\n\(\)#\\\"[=]|\\[^\0\n]) +LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t[=])*\" + +%% + +\n { + lexer->token.type = cmListFileLexer_Token_Newline; + cmListFileLexerSetToken(lexer, yytext, yyleng); + ++lexer->line; + lexer->column = 1; + BEGIN(INITIAL); + return 1; +} + +#?\[=*\[\n? { + const char* bracket = yytext; + lexer->comment = yytext[0] == '#'; + if (lexer->comment) { + lexer->token.type = cmListFileLexer_Token_CommentBracket; + bracket += 1; + } else { + lexer->token.type = cmListFileLexer_Token_ArgumentBracket; + } + cmListFileLexerSetToken(lexer, "", 0); + lexer->bracket = strchr(bracket+1, '[') - bracket; + if (yytext[yyleng-1] == '\n') { + ++lexer->line; + lexer->column = 1; + } else { + lexer->column += yyleng; + } + BEGIN(BRACKET); +} + +# { + lexer->column += yyleng; + BEGIN(COMMENT); +} + +[^\0\n]* { + lexer->column += yyleng; +} + +\( { + lexer->token.type = cmListFileLexer_Token_ParenLeft; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +\) { + lexer->token.type = cmListFileLexer_Token_ParenRight; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +[A-Za-z_][A-Za-z0-9_]* { + lexer->token.type = cmListFileLexer_Token_Identifier; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +\]=* { + /* Handle ]]====]=======]*/ + cmListFileLexerAppend(lexer, yytext, yyleng); + lexer->column += yyleng; + if (yyleng == lexer->bracket) { + BEGIN(BRACKETEND); + } +} + +\] { + lexer->column += yyleng; + /* Erase the partial bracket from the token. */ + lexer->token.length -= lexer->bracket; + lexer->token.text[lexer->token.length] = 0; + BEGIN(INITIAL); + return 1; +} + +([^]\0\n])+ { + cmListFileLexerAppend(lexer, yytext, yyleng); + lexer->column += yyleng; +} + +\n { + cmListFileLexerAppend(lexer, yytext, yyleng); + ++lexer->line; + lexer->column = 1; + BEGIN(BRACKET); +} + +[^\0\n] { + cmListFileLexerAppend(lexer, yytext, yyleng); + lexer->column += yyleng; + BEGIN(BRACKET); +} + +<> { + lexer->token.type = cmListFileLexer_Token_BadBracket; + BEGIN(INITIAL); + return 1; +} + +({UNQUOTED}|=|\[=*{UNQUOTED})({UNQUOTED}|[[=])* { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +({MAKEVAR}|{UNQUOTED}|=|\[=*{LEGACY})({LEGACY}|[[=])* { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +\[ { + lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +\" { + lexer->token.type = cmListFileLexer_Token_ArgumentQuoted; + cmListFileLexerSetToken(lexer, "", 0); + lexer->column += yyleng; + BEGIN(STRING); +} + +([^\\\0\n\"]|\\[^\0\n])+ { + cmListFileLexerAppend(lexer, yytext, yyleng); + lexer->column += yyleng; +} + +\\\n { + /* Continuation: text is not part of string */ + ++lexer->line; + lexer->column = 1; +} + +\n { + cmListFileLexerAppend(lexer, yytext, yyleng); + ++lexer->line; + lexer->column = 1; +} + +\" { + lexer->column += yyleng; + BEGIN(INITIAL); + return 1; +} + +[^\0\n] { + cmListFileLexerAppend(lexer, yytext, yyleng); + lexer->column += yyleng; +} + +<> { + lexer->token.type = cmListFileLexer_Token_BadString; + BEGIN(INITIAL); + return 1; +} + +[ \t\r]+ { + lexer->token.type = cmListFileLexer_Token_Space; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +. { + lexer->token.type = cmListFileLexer_Token_BadCharacter; + cmListFileLexerSetToken(lexer, yytext, yyleng); + lexer->column += yyleng; + return 1; +} + +<> { + lexer->token.type = cmListFileLexer_Token_None; + cmListFileLexerSetToken(lexer, 0, 0); + return 0; +} + +%% + +/*--------------------------------------------------------------------------*/ +static void cmListFileLexerSetToken(cmListFileLexer* lexer, const char* text, + int length) +{ + /* Set the token line and column number. */ + lexer->token.line = lexer->line; + lexer->token.column = lexer->column; + + /* Use the same buffer if possible. */ + if (lexer->token.text) { + if (text && length < lexer->size) { + strcpy(lexer->token.text, text); + lexer->token.length = length; + return; + } + free(lexer->token.text); + lexer->token.text = 0; + lexer->size = 0; + } + + /* Need to extend the buffer. */ + if (text) { + lexer->token.text = strdup(text); + lexer->token.length = length; + lexer->size = length + 1; + } else { + lexer->token.length = 0; + } +} + +/*--------------------------------------------------------------------------*/ +static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text, + int length) +{ + char* temp; + int newSize; + + /* If the appended text will fit in the buffer, do not reallocate. */ + newSize = lexer->token.length + length + 1; + if (lexer->token.text && newSize <= lexer->size) { + strcpy(lexer->token.text + lexer->token.length, text); + lexer->token.length += length; + return; + } + + /* We need to extend the buffer. */ + temp = malloc(newSize); + if (lexer->token.text) { + memcpy(temp, lexer->token.text, lexer->token.length); + free(lexer->token.text); + } + memcpy(temp + lexer->token.length, text, length); + temp[lexer->token.length + length] = 0; + lexer->token.text = temp; + lexer->token.length += length; + lexer->size = newSize; +} + +/*--------------------------------------------------------------------------*/ +static int cmListFileLexerInput(cmListFileLexer* lexer, char* buffer, + size_t bufferSize) +{ + if (lexer) { + if (lexer->file) { + /* Convert CRLF -> LF explicitly. The C FILE "t"ext mode + does not convert newlines on all platforms. Move any + trailing CR to the start of the buffer for the next read. */ + size_t cr = lexer->cr; + size_t n; + buffer[0] = '\r'; + n = fread(buffer + cr, 1, bufferSize - cr, lexer->file); + if (n) { + char* o = buffer; + const char* i = buffer; + const char* e; + n += cr; + cr = (buffer[n - 1] == '\r') ? 1 : 0; + e = buffer + n - cr; + while (i != e) { + if (i[0] == '\r' && i[1] == '\n') { + ++i; + } + *o++ = *i++; + } + n = o - buffer; + } else { + n = cr; + cr = 0; + } + lexer->cr = cr; + return n; + } else if (lexer->string_left) { + int length = lexer->string_left; + if ((int)bufferSize < length) { + length = (int)bufferSize; + } + memcpy(buffer, lexer->string_position, length); + lexer->string_position += length; + lexer->string_left -= length; + return length; + } + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +static void cmListFileLexerInit(cmListFileLexer* lexer) +{ + if (lexer->file || lexer->string_buffer) { + cmListFileLexer_yylex_init(&lexer->scanner); + cmListFileLexer_yyset_extra(lexer, lexer->scanner); + } +} + +/*--------------------------------------------------------------------------*/ +static void cmListFileLexerDestroy(cmListFileLexer* lexer) +{ + cmListFileLexerSetToken(lexer, 0, 0); + if (lexer->file || lexer->string_buffer) { + cmListFileLexer_yylex_destroy(lexer->scanner); + if (lexer->file) { + fclose(lexer->file); + lexer->file = 0; + } + if (lexer->string_buffer) { + free(lexer->string_buffer); + lexer->string_buffer = 0; + lexer->string_left = 0; + lexer->string_position = 0; + } + } +} + +/*--------------------------------------------------------------------------*/ +cmListFileLexer* cmListFileLexer_New(void) +{ + cmListFileLexer* lexer = (cmListFileLexer*)malloc(sizeof(cmListFileLexer)); + if (!lexer) { + return 0; + } + memset(lexer, 0, sizeof(*lexer)); + lexer->line = 1; + lexer->column = 1; + return lexer; +} + +/*--------------------------------------------------------------------------*/ +void cmListFileLexer_Delete(cmListFileLexer* lexer) +{ + cmListFileLexer_SetFileName(lexer, 0, 0); + free(lexer); +} + +/*--------------------------------------------------------------------------*/ +static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f) +{ + unsigned char b[2]; + if (fread(b, 1, 2, f) == 2) { + if (b[0] == 0xEF && b[1] == 0xBB) { + if (fread(b, 1, 1, f) == 1 && b[0] == 0xBF) { + return cmListFileLexer_BOM_UTF8; + } + } else if (b[0] == 0xFE && b[1] == 0xFF) { + /* UTF-16 BE */ + return cmListFileLexer_BOM_UTF16BE; + } else if (b[0] == 0 && b[1] == 0) { + if (fread(b, 1, 2, f) == 2 && b[0] == 0xFE && b[1] == 0xFF) { + return cmListFileLexer_BOM_UTF32BE; + } + } else if (b[0] == 0xFF && b[1] == 0xFE) { + fpos_t p; + fgetpos(f, &p); + if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) { + return cmListFileLexer_BOM_UTF32LE; + } + if (fsetpos(f, &p) != 0) { + return cmListFileLexer_BOM_Broken; + } + return cmListFileLexer_BOM_UTF16LE; + } + } + if (fseek(f, 0, SEEK_SET) != 0) { + return cmListFileLexer_BOM_Broken; + } + return cmListFileLexer_BOM_None; +} + +/*--------------------------------------------------------------------------*/ +int cmListFileLexer_SetFileName(cmListFileLexer* lexer, const char* name, + cmListFileLexer_BOM* bom) +{ + int result = 1; + cmListFileLexerDestroy(lexer); + if (name) { +#ifdef _WIN32 + wchar_t* wname = cmsysEncoding_DupToWide(name); + lexer->file = _wfopen(wname, L"rb"); + free(wname); +#else + lexer->file = fopen(name, "rb"); +#endif + if (lexer->file) { + if (bom) { + *bom = cmListFileLexer_ReadBOM(lexer->file); + } + } else { + result = 0; + } + } + cmListFileLexerInit(lexer); + return result; +} + +/*--------------------------------------------------------------------------*/ +int cmListFileLexer_SetString(cmListFileLexer* lexer, const char* text) +{ + int result = 1; + cmListFileLexerDestroy(lexer); + if (text) { + int length = (int)strlen(text); + lexer->string_buffer = (char*)malloc(length + 1); + if (lexer->string_buffer) { + strcpy(lexer->string_buffer, text); + lexer->string_position = lexer->string_buffer; + lexer->string_left = length; + } else { + result = 0; + } + } + cmListFileLexerInit(lexer); + return result; +} + +/*--------------------------------------------------------------------------*/ +cmListFileLexer_Token* cmListFileLexer_Scan(cmListFileLexer* lexer) +{ + if (!lexer->file && !lexer->string_buffer) { + return 0; + } + if (cmListFileLexer_yylex(lexer->scanner, lexer)) { + return &lexer->token; + } else { + cmListFileLexer_SetFileName(lexer, 0, 0); + return 0; + } +} + +/*--------------------------------------------------------------------------*/ +long cmListFileLexer_GetCurrentLine(cmListFileLexer* lexer) +{ + return lexer->line; +} + +/*--------------------------------------------------------------------------*/ +long cmListFileLexer_GetCurrentColumn(cmListFileLexer* lexer) +{ + return lexer->column; +} + +/*--------------------------------------------------------------------------*/ +const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer, + cmListFileLexer_Type type) +{ + (void)lexer; + switch (type) { + case cmListFileLexer_Token_None: + return "nothing"; + case cmListFileLexer_Token_Space: + return "space"; + case cmListFileLexer_Token_Newline: + return "newline"; + case cmListFileLexer_Token_Identifier: + return "identifier"; + case cmListFileLexer_Token_ParenLeft: + return "left paren"; + case cmListFileLexer_Token_ParenRight: + return "right paren"; + case cmListFileLexer_Token_ArgumentUnquoted: + return "unquoted argument"; + case cmListFileLexer_Token_ArgumentQuoted: + return "quoted argument"; + case cmListFileLexer_Token_ArgumentBracket: + return "bracket argument"; + case cmListFileLexer_Token_CommentBracket: + return "bracket comment"; + case cmListFileLexer_Token_BadCharacter: + return "bad character"; + case cmListFileLexer_Token_BadBracket: + return "unterminated bracket"; + case cmListFileLexer_Token_BadString: + return "unterminated string"; + } + return "unknown token"; +} diff --git a/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmStandardLexer.h b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmStandardLexer.h new file mode 100644 index 00000000000..27225280d6f --- /dev/null +++ b/src/plugins/cmakeprojectmanager/3rdparty/cmake/cmStandardLexer.h @@ -0,0 +1,89 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#if defined(__linux) +/* Needed for glibc < 2.12 */ +// NOLINTNEXTLINE(bugprone-reserved-identifier) +# define _XOPEN_SOURCE 600 +#endif +#if !defined(_POSIX_C_SOURCE) && !defined(_WIN32) && !defined(__sun) && \ + !defined(__OpenBSD__) +/* POSIX APIs are needed */ +// NOLINTNEXTLINE(bugprone-reserved-identifier) +# define _POSIX_C_SOURCE 200809L +#endif +#if defined(__sun) && defined(__GNUC__) && !defined(__cplusplus) +/* C sources: for fileno and strdup */ +// NOLINTNEXTLINE(bugprone-reserved-identifier) +# define _XOPEN_SOURCE 600 +#endif +#if defined(__FreeBSD__) || defined(__NetBSD__) +/* For isascii */ +// NOLINTNEXTLINE(bugprone-reserved-identifier) +# define _XOPEN_SOURCE 700 +#endif + +#include "cmsys/Configure.h" // IWYU pragma: keep + +/* Disable some warnings. */ +#if defined(_MSC_VER) +# pragma warning(disable : 4018) +# pragma warning(disable : 4127) +# pragma warning(disable : 4131) +# pragma warning(disable : 4244) +# pragma warning(disable : 4251) +# pragma warning(disable : 4267) +# pragma warning(disable : 4305) +# pragma warning(disable : 4309) +# pragma warning(disable : 4706) +# pragma warning(disable : 4786) +#endif + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Wsign-compare" +# endif +# if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 403 +# pragma GCC diagnostic ignored "-Wsign-conversion" +# endif +#endif + +#if defined(__LCC__) +# pragma diag_suppress 1873 /* comparison between signed and unsigned */ +#endif + +#if defined(__NVCOMPILER) +# pragma diag_suppress 111 /* statement is unreachable */ +# pragma diag_suppress 550 /* variable set but never used */ +#endif + +/* Make sure isatty is available. */ +#if defined(_WIN32) && !defined(__CYGWIN__) +# include +# if defined(_MSC_VER) +# define isatty _isatty +# endif +#else +# include // IWYU pragma: export +#endif + +/* Make sure malloc and free are available on QNX. */ +#ifdef __QNX__ +# include +#endif + +/* Disable features we do not need. */ +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_INPUT 1 +#define YY_NO_UNPUT 1 +#define ECHO + +#include +typedef KWIML_INT_int8_t flex_int8_t; +typedef KWIML_INT_uint8_t flex_uint8_t; +typedef KWIML_INT_int16_t flex_int16_t; +typedef KWIML_INT_uint16_t flex_uint16_t; +typedef KWIML_INT_int32_t flex_int32_t; +typedef KWIML_INT_uint32_t flex_uint32_t;