1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmListFileCache_h
#define cmListFileCache_h
#include "cmConfigure.h" // IWYU pragma: keep
#include <cstddef>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "cmStateSnapshot.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 cmCommandContext
{
struct cmCommandName
{
std::string Lower;
std::string Original;
cmCommandName() = default;
cmCommandName(std::string const& name) { *this = name; }
cmCommandName& operator=(std::string const& name);
} Name;
long Line = 0;
cmCommandContext() = default;
cmCommandContext(const char* name, int line)
: Name(name)
, Line(line)
{
}
};
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 cmListFileContext
{
public:
std::string Name;
std::string FilePath;
long Line = 0;
static cmListFileContext FromCommandContext(cmCommandContext const& lfcc,
std::string const& fileName)
{
cmListFileContext lfc;
lfc.FilePath = fileName;
lfc.Line = lfcc.Line;
lfc.Name = lfcc.Name.Original;
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);
struct cmListFileFunction : public cmCommandContext
{
std::vector<cmListFileArgument> Arguments;
};
// Represent a backtrace (call stack). Provide value semantics
// but use efficient reference-counting underneath to avoid copies.
class cmListFileBacktrace
{
public:
// Default-constructed backtrace may not be used until after
// set via assignment from a backtrace constructed with a
// valid snapshot.
cmListFileBacktrace() = default;
// Construct an empty backtrace whose bottom sits in the directory
// indicated by the given valid snapshot.
cmListFileBacktrace(cmStateSnapshot const& snapshot);
cmStateSnapshot GetBottom() const;
// Get a backtrace with the given file scope added to the top.
// May not be called until after construction with a valid snapshot.
cmListFileBacktrace Push(std::string const& file) const;
// Get a backtrace with the given call context added to the top.
// May not be called until after construction with a valid snapshot.
cmListFileBacktrace Push(cmListFileContext const& lfc) const;
// Get a backtrace with the top level removed.
// May not be called until after a matching Push.
cmListFileBacktrace Pop() const;
// Get the context at the top of the backtrace.
// This may be called only if Empty() would return false.
cmListFileContext const& Top() const;
// Print the top of the backtrace.
void PrintTitle(std::ostream& out) const;
// Print the call stack below the top of the backtrace.
void PrintCallStack(std::ostream& out) const;
// Get the number of 'frames' in this backtrace
size_t Depth() const;
// Return true if this backtrace is empty.
bool Empty() const;
private:
struct Entry;
std::shared_ptr<Entry const> TopEntry;
cmListFileBacktrace(std::shared_ptr<Entry const> parent,
cmListFileContext const& lfc);
cmListFileBacktrace(std::shared_ptr<Entry const> top);
};
// 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);
std::vector<BT<std::string>> ExpandListWithBacktrace(
std::string const& list,
cmListFileBacktrace const& bt = cmListFileBacktrace());
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;
};
#endif
|