/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Core/FormatEntity.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- FormatEntity.h ------------------------------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLDB_CORE_FORMATENTITY_H |
10 | | #define LLDB_CORE_FORMATENTITY_H |
11 | | |
12 | | #include "lldb/lldb-enumerations.h" |
13 | | #include "lldb/lldb-types.h" |
14 | | #include <algorithm> |
15 | | #include <cstddef> |
16 | | #include <cstdint> |
17 | | |
18 | | #include <string> |
19 | | #include <vector> |
20 | | |
21 | | namespace lldb_private { |
22 | | class Address; |
23 | | class CompletionRequest; |
24 | | class ExecutionContext; |
25 | | class FileSpec; |
26 | | class Status; |
27 | | class Stream; |
28 | | class StringList; |
29 | | class SymbolContext; |
30 | | class ValueObject; |
31 | | } |
32 | | |
33 | | namespace llvm { |
34 | | class StringRef; |
35 | | } |
36 | | |
37 | | namespace lldb_private { |
38 | | class FormatEntity { |
39 | | public: |
40 | | struct Entry { |
41 | | enum class Type { |
42 | | Invalid, |
43 | | ParentNumber, |
44 | | ParentString, |
45 | | EscapeCode, |
46 | | Root, |
47 | | String, |
48 | | Scope, |
49 | | Variable, |
50 | | VariableSynthetic, |
51 | | ScriptVariable, |
52 | | ScriptVariableSynthetic, |
53 | | AddressLoad, |
54 | | AddressFile, |
55 | | AddressLoadOrFile, |
56 | | ProcessID, |
57 | | ProcessFile, |
58 | | ScriptProcess, |
59 | | ThreadID, |
60 | | ThreadProtocolID, |
61 | | ThreadIndexID, |
62 | | ThreadName, |
63 | | ThreadQueue, |
64 | | ThreadStopReason, |
65 | | ThreadStopReasonRaw, |
66 | | ThreadReturnValue, |
67 | | ThreadCompletedExpression, |
68 | | ScriptThread, |
69 | | ThreadInfo, |
70 | | TargetArch, |
71 | | ScriptTarget, |
72 | | ModuleFile, |
73 | | File, |
74 | | Lang, |
75 | | FrameIndex, |
76 | | FrameNoDebug, |
77 | | FrameRegisterPC, |
78 | | FrameRegisterSP, |
79 | | FrameRegisterFP, |
80 | | FrameRegisterFlags, |
81 | | FrameRegisterByName, |
82 | | FrameIsArtificial, |
83 | | ScriptFrame, |
84 | | FunctionID, |
85 | | FunctionDidChange, |
86 | | FunctionInitialFunction, |
87 | | FunctionName, |
88 | | FunctionNameWithArgs, |
89 | | FunctionNameNoArgs, |
90 | | FunctionMangledName, |
91 | | FunctionAddrOffset, |
92 | | FunctionAddrOffsetConcrete, |
93 | | FunctionLineOffset, |
94 | | FunctionPCOffset, |
95 | | FunctionInitial, |
96 | | FunctionChanged, |
97 | | FunctionIsOptimized, |
98 | | LineEntryFile, |
99 | | LineEntryLineNumber, |
100 | | LineEntryColumn, |
101 | | LineEntryStartAddress, |
102 | | LineEntryEndAddress, |
103 | | CurrentPCArrow |
104 | | }; |
105 | | |
106 | | struct Definition { |
107 | | /// The name/string placeholder that corresponds to this definition. |
108 | | const char *name; |
109 | | /// Insert this exact string into the output |
110 | | const char *string = nullptr; |
111 | | /// Entry::Type corresponding to this definition. |
112 | | const Entry::Type type; |
113 | | /// Data that is returned as the value of the format string. |
114 | | const uint64_t data = 0; |
115 | | /// The number of children of this node in the tree of format strings. |
116 | | const uint32_t num_children = 0; |
117 | | /// An array of "num_children" Definition entries. |
118 | | const Definition *children = nullptr; |
119 | | /// Whether the separator is kept during parsing or not. It's used |
120 | | /// for entries with parameters. |
121 | | const bool keep_separator = false; |
122 | | |
123 | | constexpr Definition(const char *name, const FormatEntity::Entry::Type t) |
124 | | : name(name), type(t) {} |
125 | | |
126 | | constexpr Definition(const char *name, const char *string) |
127 | | : name(name), string(string), type(Entry::Type::EscapeCode) {} |
128 | | |
129 | | constexpr Definition(const char *name, const FormatEntity::Entry::Type t, |
130 | | const uint64_t data) |
131 | | : name(name), type(t), data(data) {} |
132 | | |
133 | | constexpr Definition(const char *name, const FormatEntity::Entry::Type t, |
134 | | const uint64_t num_children, |
135 | | const Definition *children, |
136 | | const bool keep_separator = false) |
137 | | : name(name), type(t), num_children(num_children), children(children), |
138 | | keep_separator(keep_separator) {} |
139 | | }; |
140 | | |
141 | | template <size_t N> |
142 | | static constexpr Definition |
143 | | DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t, |
144 | | const Definition (&children)[N], |
145 | 0 | bool keep_separator = false) { |
146 | 0 | return Definition(name, t, N, children, keep_separator); |
147 | 0 | } Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<1ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [1ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<3ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [3ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<8ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [8ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<2ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [2ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<12ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [12ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<5ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [5ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<7ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [7ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<10ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [10ul], bool) Unexecuted instantiation: lldb_private::FormatEntity::Entry::Definition lldb_private::FormatEntity::Entry::DefinitionWithChildren<16ul>(char const*, lldb_private::FormatEntity::Entry::Type, lldb_private::FormatEntity::Entry::Definition const (&) [16ul], bool) |
148 | | |
149 | | Entry(Type t = Type::Invalid, const char *s = nullptr, |
150 | | const char *f = nullptr) |
151 | 2.94M | : string(s ? s0 : ""), printf_format(f ? f0 : ""), type(t) {} |
152 | | |
153 | | Entry(llvm::StringRef s); |
154 | | Entry(char ch); |
155 | | |
156 | | void AppendChar(char ch); |
157 | | |
158 | | void AppendText(const llvm::StringRef &s); |
159 | | |
160 | | void AppendText(const char *cstr); |
161 | | |
162 | 874k | void AppendEntry(const Entry &&entry) { children.push_back(entry); } |
163 | | |
164 | 85.4k | void Clear() { |
165 | 85.4k | string.clear(); |
166 | 85.4k | printf_format.clear(); |
167 | 85.4k | children.clear(); |
168 | 85.4k | type = Type::Invalid; |
169 | 85.4k | fmt = lldb::eFormatDefault; |
170 | 85.4k | number = 0; |
171 | 85.4k | deref = false; |
172 | 85.4k | } |
173 | | |
174 | | static const char *TypeToCString(Type t); |
175 | | |
176 | | void Dump(Stream &s, int depth = 0) const; |
177 | | |
178 | 0 | bool operator==(const Entry &rhs) const { |
179 | 0 | if (string != rhs.string) |
180 | 0 | return false; |
181 | 0 | if (printf_format != rhs.printf_format) |
182 | 0 | return false; |
183 | 0 | const size_t n = children.size(); |
184 | 0 | const size_t m = rhs.children.size(); |
185 | 0 | for (size_t i = 0; i < std::min<size_t>(n, m); ++i) { |
186 | 0 | if (!(children[i] == rhs.children[i])) |
187 | 0 | return false; |
188 | 0 | } |
189 | 0 | if (children != rhs.children) |
190 | 0 | return false; |
191 | 0 | if (type != rhs.type) |
192 | 0 | return false; |
193 | 0 | if (fmt != rhs.fmt) |
194 | 0 | return false; |
195 | 0 | if (deref != rhs.deref) |
196 | 0 | return false; |
197 | 0 | return true; |
198 | 0 | } |
199 | | |
200 | | std::string string; |
201 | | std::string printf_format; |
202 | | std::vector<Entry> children; |
203 | | Type type; |
204 | | lldb::Format fmt = lldb::eFormatDefault; |
205 | | lldb::addr_t number = 0; |
206 | | bool deref = false; |
207 | | }; |
208 | | |
209 | | static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, |
210 | | const ExecutionContext *exe_ctx, const Address *addr, |
211 | | ValueObject *valobj, bool function_changed, |
212 | | bool initial_function); |
213 | | |
214 | | static bool FormatStringRef(const llvm::StringRef &format, Stream &s, |
215 | | const SymbolContext *sc, |
216 | | const ExecutionContext *exe_ctx, |
217 | | const Address *addr, ValueObject *valobj, |
218 | | bool function_changed, bool initial_function); |
219 | | |
220 | | static bool FormatCString(const char *format, Stream &s, |
221 | | const SymbolContext *sc, |
222 | | const ExecutionContext *exe_ctx, |
223 | | const Address *addr, ValueObject *valobj, |
224 | | bool function_changed, bool initial_function); |
225 | | |
226 | | static Status Parse(const llvm::StringRef &format, Entry &entry); |
227 | | |
228 | | static Status ExtractVariableInfo(llvm::StringRef &format_str, |
229 | | llvm::StringRef &variable_name, |
230 | | llvm::StringRef &variable_format); |
231 | | |
232 | | static void AutoComplete(lldb_private::CompletionRequest &request); |
233 | | |
234 | | // Format the current elements into the stream \a s. |
235 | | // |
236 | | // The root element will be stripped off and the format str passed in will be |
237 | | // either an empty string (print a description of this object), or contain a |
238 | | // `.`-separated series like a domain name that identifies further |
239 | | // sub-elements to display. |
240 | | static bool FormatFileSpec(const FileSpec &file, Stream &s, |
241 | | llvm::StringRef elements, |
242 | | llvm::StringRef element_format); |
243 | | |
244 | | /// For each variable in 'args' this function writes the variable |
245 | | /// name and it's pretty-printed value representation to 'out_stream' |
246 | | /// in following format: |
247 | | /// |
248 | | /// \verbatim |
249 | | /// name_1=repr_1, name_2=repr_2 ... |
250 | | /// \endverbatim |
251 | | static void PrettyPrintFunctionArguments(Stream &out_stream, |
252 | | VariableList const &args, |
253 | | ExecutionContextScope *exe_scope); |
254 | | |
255 | | protected: |
256 | | static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, |
257 | | uint32_t depth); |
258 | | }; |
259 | | } // namespace lldb_private |
260 | | |
261 | | #endif // LLDB_CORE_FORMATENTITY_H |