1 //===-- FormatEntity.h ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_FormatEntity_h_
11 #define liblldb_FormatEntity_h_
12 
13 #include "lldb/Utility/CompletionRequest.h"
14 #include "lldb/Utility/FileSpec.h"
15 #include "lldb/Utility/Status.h"
16 #include "lldb/lldb-enumerations.h"
17 #include "lldb/lldb-types.h"
18 #include <algorithm>
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #include <string>
23 #include <vector>
24 
25 namespace lldb_private {
26 class Address;
27 }
28 namespace lldb_private {
29 class ExecutionContext;
30 }
31 namespace lldb_private {
32 class Stream;
33 }
34 namespace lldb_private {
35 class StringList;
36 }
37 namespace lldb_private {
38 class SymbolContext;
39 }
40 namespace lldb_private {
41 class ValueObject;
42 }
43 namespace llvm {
44 class StringRef;
45 }
46 
47 namespace lldb_private {
48 class FormatEntity {
49 public:
50   struct Entry {
51     enum class Type {
52       Invalid,
53       ParentNumber,
54       ParentString,
55       InsertString,
56       Root,
57       String,
58       Scope,
59       Variable,
60       VariableSynthetic,
61       ScriptVariable,
62       ScriptVariableSynthetic,
63       AddressLoad,
64       AddressFile,
65       AddressLoadOrFile,
66       ProcessID,
67       ProcessFile,
68       ScriptProcess,
69       ThreadID,
70       ThreadProtocolID,
71       ThreadIndexID,
72       ThreadName,
73       ThreadQueue,
74       ThreadStopReason,
75       ThreadReturnValue,
76       ThreadCompletedExpression,
77       ScriptThread,
78       ThreadInfo,
79       TargetArch,
80       ScriptTarget,
81       ModuleFile,
82       File,
83       Lang,
84       FrameIndex,
85       FrameNoDebug,
86       FrameRegisterPC,
87       FrameRegisterSP,
88       FrameRegisterFP,
89       FrameRegisterFlags,
90       FrameRegisterByName,
91       FrameIsArtificial,
92       ScriptFrame,
93       FunctionID,
94       FunctionDidChange,
95       FunctionInitialFunction,
96       FunctionName,
97       FunctionNameWithArgs,
98       FunctionNameNoArgs,
99       FunctionAddrOffset,
100       FunctionAddrOffsetConcrete,
101       FunctionLineOffset,
102       FunctionPCOffset,
103       FunctionInitial,
104       FunctionChanged,
105       FunctionIsOptimized,
106       LineEntryFile,
107       LineEntryLineNumber,
108       LineEntryColumn,
109       LineEntryStartAddress,
110       LineEntryEndAddress,
111       CurrentPCArrow
112     };
113 
114     enum FormatType { None, UInt32, UInt64, CString };
115 
116     struct Definition {
117       const char *name;
118       const char *string; // Insert this exact string into the output
119       Entry::Type type;
120       FormatType format_type; // uint32_t, uint64_t, cstr, or anything that can
121                               // be formatted by printf or lldb::Format
122       uint64_t data;
123       uint32_t num_children;
124       Definition *children; // An array of "num_children" Definition entries,
125       bool keep_separator;
126     };
127 
128     Entry(Type t = Type::Invalid, const char *s = nullptr,
129           const char *f = nullptr)
130         : string(s ? s : ""), printf_format(f ? f : ""), children(),
131           definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0),
132           deref(false) {}
133 
134     Entry(llvm::StringRef s);
135     Entry(char ch);
136 
137     void AppendChar(char ch);
138 
139     void AppendText(const llvm::StringRef &s);
140 
141     void AppendText(const char *cstr);
142 
AppendEntryEntry143     void AppendEntry(const Entry &&entry) { children.push_back(entry); }
144 
ClearEntry145     void Clear() {
146       string.clear();
147       printf_format.clear();
148       children.clear();
149       definition = nullptr;
150       type = Type::Invalid;
151       fmt = lldb::eFormatDefault;
152       number = 0;
153       deref = false;
154     }
155 
156     static const char *TypeToCString(Type t);
157 
158     void Dump(Stream &s, int depth = 0) const;
159 
160     bool operator==(const Entry &rhs) const {
161       if (string != rhs.string)
162         return false;
163       if (printf_format != rhs.printf_format)
164         return false;
165       const size_t n = children.size();
166       const size_t m = rhs.children.size();
167       for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
168         if (!(children[i] == rhs.children[i]))
169           return false;
170       }
171       if (children != rhs.children)
172         return false;
173       if (definition != rhs.definition)
174         return false;
175       if (type != rhs.type)
176         return false;
177       if (fmt != rhs.fmt)
178         return false;
179       if (deref != rhs.deref)
180         return false;
181       return true;
182     }
183 
184     std::string string;
185     std::string printf_format;
186     std::vector<Entry> children;
187     Definition *definition;
188     Type type;
189     lldb::Format fmt;
190     lldb::addr_t number;
191     bool deref;
192   };
193 
194   static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,
195                      const ExecutionContext *exe_ctx, const Address *addr,
196                      ValueObject *valobj, bool function_changed,
197                      bool initial_function);
198 
199   static bool FormatStringRef(const llvm::StringRef &format, Stream &s,
200                               const SymbolContext *sc,
201                               const ExecutionContext *exe_ctx,
202                               const Address *addr, ValueObject *valobj,
203                               bool function_changed, bool initial_function);
204 
205   static bool FormatCString(const char *format, Stream &s,
206                             const SymbolContext *sc,
207                             const ExecutionContext *exe_ctx,
208                             const Address *addr, ValueObject *valobj,
209                             bool function_changed, bool initial_function);
210 
211   static Status Parse(const llvm::StringRef &format, Entry &entry);
212 
213   static Status ExtractVariableInfo(llvm::StringRef &format_str,
214                                     llvm::StringRef &variable_name,
215                                     llvm::StringRef &variable_format);
216 
217   static size_t AutoComplete(lldb_private::CompletionRequest &request);
218 
219   //----------------------------------------------------------------------
220   // Format the current elements into the stream \a s.
221   //
222   // The root element will be stripped off and the format str passed in will be
223   // either an empty string (print a description of this object), or contain a
224   // `.`-separated series like a domain name that identifies further
225   //  sub-elements to display.
226   //----------------------------------------------------------------------
227   static bool FormatFileSpec(const FileSpec &file, Stream &s,
228                              llvm::StringRef elements,
229                              llvm::StringRef element_format);
230 
231 protected:
232   static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
233                               uint32_t depth);
234 };
235 } // namespace lldb_private
236 
237 #endif // liblldb_FormatEntity_h_
238