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 <stddef.h>
16#include <stdint.h>
17
18#include <string>
19#include <vector>
20
21namespace lldb_private {
22class Address;
23class CompletionRequest;
24class ExecutionContext;
25class FileSpec;
26class Status;
27class Stream;
28class StringList;
29class SymbolContext;
30class ValueObject;
31}
32
33namespace llvm {
34class StringRef;
35}
36
37namespace lldb_private {
38class FormatEntity {
39public:
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), string(nullptr), 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 bool keep_separator = false) {
146 return Definition(name, t, N, children, keep_separator);
147 }
148
149 Entry(Type t = Type::Invalid, const char *s = nullptr,
150 const char *f = nullptr)
151 : string(s ? s : ""), printf_format(f ? f : ""), children(), type(t),
152 fmt(lldb::eFormatDefault), number(0), deref(false) {}
153
154 Entry(llvm::StringRef s);
155 Entry(char ch);
156
157 void AppendChar(char ch);
158
159 void AppendText(const llvm::StringRef &s);
160
161 void AppendText(const char *cstr);
162
163 void AppendEntry(const Entry &&entry) { children.push_back(entry); }
164
165 void Clear() {
166 string.clear();
167 printf_format.clear();
168 children.clear();
169 type = Type::Invalid;
170 fmt = lldb::eFormatDefault;
171 number = 0;
172 deref = false;
173 }
174
175 static const char *TypeToCString(Type t);
176
177 void Dump(Stream &s, int depth = 0) const;
178
179 bool operator==(const Entry &rhs) const {
180 if (string != rhs.string)
181 return false;
182 if (printf_format != rhs.printf_format)
183 return false;
184 const size_t n = children.size();
185 const size_t m = rhs.children.size();
186 for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
187 if (!(children[i] == rhs.children[i]))
188 return false;
189 }
190 if (children != rhs.children)
191 return false;
192 if (type != rhs.type)
193 return false;
194 if (fmt != rhs.fmt)
195 return false;
196 if (deref != rhs.deref)
197 return false;
198 return true;
199 }
200
201 std::string string;
202 std::string printf_format;
203 std::vector<Entry> children;
204 Type type;
205 lldb::Format fmt;
206 lldb::addr_t number;
207 bool deref;
208 };
209
210 static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,
211 const ExecutionContext *exe_ctx, const Address *addr,
212 ValueObject *valobj, bool function_changed,
213 bool initial_function);
214
215 static bool FormatStringRef(const llvm::StringRef &format, Stream &s,
216 const SymbolContext *sc,
217 const ExecutionContext *exe_ctx,
218 const Address *addr, ValueObject *valobj,
219 bool function_changed, bool initial_function);
220
221 static bool FormatCString(const char *format, Stream &s,
222 const SymbolContext *sc,
223 const ExecutionContext *exe_ctx,
224 const Address *addr, ValueObject *valobj,
225 bool function_changed, bool initial_function);
226
227 static Status Parse(const llvm::StringRef &format, Entry &entry);
228
229 static Status ExtractVariableInfo(llvm::StringRef &format_str,
230 llvm::StringRef &variable_name,
231 llvm::StringRef &variable_format);
232
233 static void AutoComplete(lldb_private::CompletionRequest &request);
234
235 // Format the current elements into the stream \a s.
236 //
237 // The root element will be stripped off and the format str passed in will be
238 // either an empty string (print a description of this object), or contain a
239 // `.`-separated series like a domain name that identifies further
240 // sub-elements to display.
241 static bool FormatFileSpec(const FileSpec &file, Stream &s,
242 llvm::StringRef elements,
243 llvm::StringRef element_format);
244
245protected:
246 static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
247 uint32_t depth);
248};
249} // namespace lldb_private
250
251#endif // LLDB_CORE_FORMATENTITY_H
252