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 liblldb_FormatEntity_h_
10 #define liblldb_FormatEntity_h_
11 
12 #include "lldb/Utility/CompletionRequest.h"
13 #include "lldb/Utility/FileSpec.h"
14 #include "lldb/Utility/Status.h"
15 #include "lldb/lldb-enumerations.h"
16 #include "lldb/lldb-types.h"
17 #include <algorithm>
18 #include <stddef.h>
19 #include <stdint.h>
20 
21 #include <string>
22 #include <vector>
23 
24 namespace lldb_private {
25 class Address;
26 class ExecutionContext;
27 class Stream;
28 class StringList;
29 class SymbolContext;
30 class ValueObject;
31 }
32 namespace llvm {
33 class StringRef;
34 }
35 
36 namespace lldb_private {
37 class FormatEntity {
38 public:
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       ThreadReturnValue,
65       ThreadCompletedExpression,
66       ScriptThread,
67       ThreadInfo,
68       TargetArch,
69       ScriptTarget,
70       ModuleFile,
71       File,
72       Lang,
73       FrameIndex,
74       FrameNoDebug,
75       FrameRegisterPC,
76       FrameRegisterSP,
77       FrameRegisterFP,
78       FrameRegisterFlags,
79       FrameRegisterByName,
80       FrameIsArtificial,
81       ScriptFrame,
82       FunctionID,
83       FunctionDidChange,
84       FunctionInitialFunction,
85       FunctionName,
86       FunctionNameWithArgs,
87       FunctionNameNoArgs,
88       FunctionMangledName,
89       FunctionAddrOffset,
90       FunctionAddrOffsetConcrete,
91       FunctionLineOffset,
92       FunctionPCOffset,
93       FunctionInitial,
94       FunctionChanged,
95       FunctionIsOptimized,
96       LineEntryFile,
97       LineEntryLineNumber,
98       LineEntryColumn,
99       LineEntryStartAddress,
100       LineEntryEndAddress,
101       CurrentPCArrow
102     };
103 
104     struct Definition {
105       const char *name;
106       const char *string; // Insert this exact string into the output
107       Entry::Type type;
108       uint64_t data;
109       uint32_t num_children;
110       Definition *children; // An array of "num_children" Definition entries,
111       bool keep_separator;
112     };
113 
114     Entry(Type t = Type::Invalid, const char *s = nullptr,
115           const char *f = nullptr)
116         : string(s ? s : ""), printf_format(f ? f : ""), children(),
117           definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0),
118           deref(false) {}
119 
120     Entry(llvm::StringRef s);
121     Entry(char ch);
122 
123     void AppendChar(char ch);
124 
125     void AppendText(const llvm::StringRef &s);
126 
127     void AppendText(const char *cstr);
128 
129     void AppendEntry(const Entry &&entry) { children.push_back(entry); }
130 
131     void Clear() {
132       string.clear();
133       printf_format.clear();
134       children.clear();
135       definition = nullptr;
136       type = Type::Invalid;
137       fmt = lldb::eFormatDefault;
138       number = 0;
139       deref = false;
140     }
141 
142     static const char *TypeToCString(Type t);
143 
144     void Dump(Stream &s, int depth = 0) const;
145 
146     bool operator==(const Entry &rhs) const {
147       if (string != rhs.string)
148         return false;
149       if (printf_format != rhs.printf_format)
150         return false;
151       const size_t n = children.size();
152       const size_t m = rhs.children.size();
153       for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
154         if (!(children[i] == rhs.children[i]))
155           return false;
156       }
157       if (children != rhs.children)
158         return false;
159       if (definition != rhs.definition)
160         return false;
161       if (type != rhs.type)
162         return false;
163       if (fmt != rhs.fmt)
164         return false;
165       if (deref != rhs.deref)
166         return false;
167       return true;
168     }
169 
170     std::string string;
171     std::string printf_format;
172     std::vector<Entry> children;
173     Definition *definition;
174     Type type;
175     lldb::Format fmt;
176     lldb::addr_t number;
177     bool deref;
178   };
179 
180   static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,
181                      const ExecutionContext *exe_ctx, const Address *addr,
182                      ValueObject *valobj, bool function_changed,
183                      bool initial_function);
184 
185   static bool FormatStringRef(const llvm::StringRef &format, Stream &s,
186                               const SymbolContext *sc,
187                               const ExecutionContext *exe_ctx,
188                               const Address *addr, ValueObject *valobj,
189                               bool function_changed, bool initial_function);
190 
191   static bool FormatCString(const char *format, Stream &s,
192                             const SymbolContext *sc,
193                             const ExecutionContext *exe_ctx,
194                             const Address *addr, ValueObject *valobj,
195                             bool function_changed, bool initial_function);
196 
197   static Status Parse(const llvm::StringRef &format, Entry &entry);
198 
199   static Status ExtractVariableInfo(llvm::StringRef &format_str,
200                                     llvm::StringRef &variable_name,
201                                     llvm::StringRef &variable_format);
202 
203   static void AutoComplete(lldb_private::CompletionRequest &request);
204 
205   // Format the current elements into the stream \a s.
206   //
207   // The root element will be stripped off and the format str passed in will be
208   // either an empty string (print a description of this object), or contain a
209   // `.`-separated series like a domain name that identifies further
210   //  sub-elements to display.
211   static bool FormatFileSpec(const FileSpec &file, Stream &s,
212                              llvm::StringRef elements,
213                              llvm::StringRef element_format);
214 
215 protected:
216   static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
217                               uint32_t depth);
218 };
219 } // namespace lldb_private
220 
221 #endif // liblldb_FormatEntity_h_
222