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                            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 
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     void AppendEntry(const Entry &&entry) { children.push_back(entry); }
163 
164     void Clear() {
165       string.clear();
166       printf_format.clear();
167       children.clear();
168       type = Type::Invalid;
169       fmt = lldb::eFormatDefault;
170       number = 0;
171       deref = false;
172     }
173 
174     static const char *TypeToCString(Type t);
175 
176     void Dump(Stream &s, int depth = 0) const;
177 
178     bool operator==(const Entry &rhs) const {
179       if (string != rhs.string)
180         return false;
181       if (printf_format != rhs.printf_format)
182         return false;
183       const size_t n = children.size();
184       const size_t m = rhs.children.size();
185       for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
186         if (!(children[i] == rhs.children[i]))
187           return false;
188       }
189       if (children != rhs.children)
190         return false;
191       if (type != rhs.type)
192         return false;
193       if (fmt != rhs.fmt)
194         return false;
195       if (deref != rhs.deref)
196         return false;
197       return true;
198     }
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 protected:
245   static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
246                               uint32_t depth);
247 };
248 } // namespace lldb_private
249 
250 #endif // LLDB_CORE_FORMATENTITY_H
251