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/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       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       const char *name;
107       const char *string; // Insert this exact string into the output
108       Entry::Type type;
109       uint64_t data;
110       uint32_t num_children;
111       Definition *children; // An array of "num_children" Definition entries,
112       bool keep_separator;
113     };
114 
115     Entry(Type t = Type::Invalid, const char *s = nullptr,
116           const char *f = nullptr)
117         : string(s ? s : ""), printf_format(f ? f : ""), children(),
118           definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0),
119           deref(false) {}
120 
121     Entry(llvm::StringRef s);
122     Entry(char ch);
123 
124     void AppendChar(char ch);
125 
126     void AppendText(const llvm::StringRef &s);
127 
128     void AppendText(const char *cstr);
129 
130     void AppendEntry(const Entry &&entry) { children.push_back(entry); }
131 
132     void Clear() {
133       string.clear();
134       printf_format.clear();
135       children.clear();
136       definition = nullptr;
137       type = Type::Invalid;
138       fmt = lldb::eFormatDefault;
139       number = 0;
140       deref = false;
141     }
142 
143     static const char *TypeToCString(Type t);
144 
145     void Dump(Stream &s, int depth = 0) const;
146 
147     bool operator==(const Entry &rhs) const {
148       if (string != rhs.string)
149         return false;
150       if (printf_format != rhs.printf_format)
151         return false;
152       const size_t n = children.size();
153       const size_t m = rhs.children.size();
154       for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
155         if (!(children[i] == rhs.children[i]))
156           return false;
157       }
158       if (children != rhs.children)
159         return false;
160       if (definition != rhs.definition)
161         return false;
162       if (type != rhs.type)
163         return false;
164       if (fmt != rhs.fmt)
165         return false;
166       if (deref != rhs.deref)
167         return false;
168       return true;
169     }
170 
171     std::string string;
172     std::string printf_format;
173     std::vector<Entry> children;
174     Definition *definition;
175     Type type;
176     lldb::Format fmt;
177     lldb::addr_t number;
178     bool deref;
179   };
180 
181   static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,
182                      const ExecutionContext *exe_ctx, const Address *addr,
183                      ValueObject *valobj, bool function_changed,
184                      bool initial_function);
185 
186   static bool FormatStringRef(const llvm::StringRef &format, Stream &s,
187                               const SymbolContext *sc,
188                               const ExecutionContext *exe_ctx,
189                               const Address *addr, ValueObject *valobj,
190                               bool function_changed, bool initial_function);
191 
192   static bool FormatCString(const char *format, Stream &s,
193                             const SymbolContext *sc,
194                             const ExecutionContext *exe_ctx,
195                             const Address *addr, ValueObject *valobj,
196                             bool function_changed, bool initial_function);
197 
198   static Status Parse(const llvm::StringRef &format, Entry &entry);
199 
200   static Status ExtractVariableInfo(llvm::StringRef &format_str,
201                                     llvm::StringRef &variable_name,
202                                     llvm::StringRef &variable_format);
203 
204   static void AutoComplete(lldb_private::CompletionRequest &request);
205 
206   // Format the current elements into the stream \a s.
207   //
208   // The root element will be stripped off and the format str passed in will be
209   // either an empty string (print a description of this object), or contain a
210   // `.`-separated series like a domain name that identifies further
211   //  sub-elements to display.
212   static bool FormatFileSpec(const FileSpec &file, Stream &s,
213                              llvm::StringRef elements,
214                              llvm::StringRef element_format);
215 
216 protected:
217   static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
218                               uint32_t depth);
219 };
220 } // namespace lldb_private
221 
222 #endif // LLDB_CORE_FORMATENTITY_H
223