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 
DefinitionEntry::Definition122     constexpr Definition(const char *name, const FormatEntity::Entry::Type t)
123         : name(name), type(t) {}
124 
DefinitionEntry::Definition125     constexpr Definition(const char *name, const char *string)
126         : name(name), string(string), type(Entry::Type::EscapeCode) {}
127 
DefinitionEntry::Definition128     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)
nameEntry::Definition136         : 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 
AppendEntryEntry161   void AppendEntry(const Entry &&entry) { children.push_back(entry); }
162 
ClearEntry163   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>(n, 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 ExtractVariableInfo(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