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 DefinitionEntry::Definition123 constexpr Definition(const char *name, const FormatEntity::Entry::Type t) 124 : name(name), type(t) {} 125 DefinitionEntry::Definition126 constexpr Definition(const char *name, const char *string) 127 : name(name), string(string), type(Entry::Type::EscapeCode) {} 128 DefinitionEntry::Definition129 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) nameEntry::Definition137 : 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 : ""), 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 AppendEntryEntry162 void AppendEntry(const Entry &&entry) { children.push_back(entry); } 163 ClearEntry164 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 /// For each variable in 'args' this function writes the variable 245 /// name and it's pretty-printed value representation to 'out_stream' 246 /// in following format: 247 /// 248 /// \verbatim 249 /// name_1=repr_1, name_2=repr_2 ... 250 /// \endverbatim 251 static void PrettyPrintFunctionArguments(Stream &out_stream, 252 VariableList const &args, 253 ExecutionContextScope *exe_scope); 254 255 protected: 256 static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, 257 uint32_t depth); 258 }; 259 } // namespace lldb_private 260 261 #endif // LLDB_CORE_FORMATENTITY_H 262