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