| /* 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 <iosfwd> | 
 | #include <memory> | 
 | #include <string> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include <cm/optional> | 
 |  | 
 | #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<cmListFileArgument> args) | 
 |     : Impl{ std::make_shared<Implementation>(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<cmListFileArgument> const& Arguments() const noexcept | 
 |   { | 
 |     return this->Impl->Arguments; | 
 |   } | 
 |  | 
 | private: | 
 |   struct Implementation | 
 |   { | 
 |     Implementation(std::string name, long line, long lineEnd, | 
 |                    std::vector<cmListFileArgument> 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<cmListFileArgument> Arguments; | 
 |   }; | 
 |  | 
 |   std::shared_ptr<Implementation const> Impl; | 
 | }; | 
 |  | 
 | class cmListFileContext | 
 | { | 
 | public: | 
 |   std::string Name; | 
 |   std::string FilePath; | 
 |   long Line = 0; | 
 |   static long const DeferPlaceholderLine = -1; | 
 |   cm::optional<std::string> 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<std::string> 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<cmListFileContext, cmListFileBacktrace> | 
 | { | 
 |   using cmConstStack::cmConstStack; | 
 |   friend class cmConstStack<cmListFileContext, cmListFileBacktrace>; | 
 | }; | 
 | #ifndef cmListFileCache_cxx | 
 | extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>; | 
 | #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 <typename T> | 
 | 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<T> const& l, BT<T> const& r) | 
 |   { | 
 |     return l.Value == r.Value; | 
 |   } | 
 |   friend bool operator<(BT<T> const& l, BT<T> const& r) | 
 |   { | 
 |     return l.Value < r.Value; | 
 |   } | 
 |   friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; } | 
 |   friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; } | 
 | }; | 
 |  | 
 | std::ostream& operator<<(std::ostream& os, BT<std::string> 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 <typename T> | 
 | 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<cmListFileBacktrace> Backtraces; | 
 |   friend bool operator==(BTs<T> const& l, BTs<T> const& r) | 
 |   { | 
 |     return l.Value == r.Value; | 
 |   } | 
 |   friend bool operator<(BTs<T> const& l, BTs<T> const& r) | 
 |   { | 
 |     return l.Value < r.Value; | 
 |   } | 
 |   friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; } | 
 |   friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; } | 
 | }; | 
 |  | 
 | std::vector<BT<std::string>> 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<cmListFileFunction> Functions; | 
 | }; |