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 "llvm/ADT/SmallVector.h" 15 #include <algorithm> 16 #include <cstddef> 17 #include <cstdint> 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 TargetFile, 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 FunctionPrefix, 92 FunctionScope, 93 FunctionBasename, 94 FunctionTemplateArguments, 95 FunctionFormattedArguments, 96 FunctionReturnLeft, 97 FunctionReturnRight, 98 FunctionQualifiers, 99 FunctionSuffix, 100 FunctionAddrOffset, 101 FunctionAddrOffsetConcrete, 102 FunctionLineOffset, 103 FunctionPCOffset, 104 FunctionInitial, 105 FunctionChanged, 106 FunctionIsOptimized, 107 FunctionIsInlined, 108 LineEntryFile, 109 LineEntryLineNumber, 110 LineEntryColumn, 111 LineEntryStartAddress, 112 LineEntryEndAddress, 113 CurrentPCArrow, 114 ProgressCount, 115 ProgressMessage, 116 Separator, 117 }; 118 119 struct Definition { 120 /// The name/string placeholder that corresponds to this definition. 121 const char *name; 122 /// Insert this exact string into the output 123 const char *string = nullptr; 124 /// Entry::Type corresponding to this definition. 125 const Entry::Type type; 126 /// Data that is returned as the value of the format string. 127 const uint64_t data = 0; 128 /// The number of children of this node in the tree of format strings. 129 const uint32_t num_children = 0; 130 /// An array of "num_children" Definition entries. 131 const Definition *children = nullptr; 132 /// Whether the separator is kept during parsing or not. It's used 133 /// for entries with parameters. 134 const bool keep_separator = false; 135 DefinitionEntry::Definition136 constexpr Definition(const char *name, const FormatEntity::Entry::Type t) 137 : name(name), type(t) {} 138 DefinitionEntry::Definition139 constexpr Definition(const char *name, const char *string) 140 : name(name), string(string), type(Entry::Type::EscapeCode) {} 141 DefinitionEntry::Definition142 constexpr Definition(const char *name, const FormatEntity::Entry::Type t, 143 const uint64_t data) 144 : name(name), type(t), data(data) {} 145 146 constexpr Definition(const char *name, const FormatEntity::Entry::Type t, 147 const uint64_t num_children, 148 const Definition *children, 149 const bool keep_separator = false) nameEntry::Definition150 : name(name), type(t), num_children(num_children), children(children), 151 keep_separator(keep_separator) {} 152 }; 153 154 template <size_t N> 155 static constexpr Definition 156 DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t, 157 const Definition (&children)[N], 158 bool keep_separator = false) { 159 return Definition(name, t, N, children, keep_separator); 160 } 161 162 Entry(Type t = Type::Invalid, const char *s = nullptr, 163 const char *f = nullptr); 164 Entry(llvm::StringRef s); 165 Entry(char ch); 166 167 void AppendChar(char ch); 168 169 void AppendText(const llvm::StringRef &s); 170 171 void AppendText(const char *cstr); 172 173 void AppendEntry(const Entry &&entry); 174 175 void StartAlternative(); 176 ClearEntry177 void Clear() { 178 string.clear(); 179 printf_format.clear(); 180 children_stack.clear(); 181 children_stack.emplace_back(); 182 type = Type::Invalid; 183 fmt = lldb::eFormatDefault; 184 number = 0; 185 level = 0; 186 deref = false; 187 } 188 189 static const char *TypeToCString(Type t); 190 191 void Dump(Stream &s, int depth = 0) const; 192 193 bool operator==(const Entry &rhs) const { 194 if (string != rhs.string) 195 return false; 196 if (printf_format != rhs.printf_format) 197 return false; 198 if (children_stack != rhs.children_stack) 199 return false; 200 if (type != rhs.type) 201 return false; 202 if (fmt != rhs.fmt) 203 return false; 204 if (deref != rhs.deref) 205 return false; 206 return true; 207 } 208 209 operator bool() const { return type != Type::Invalid; } 210 211 std::vector<Entry> &GetChildren(); 212 213 std::string string; 214 std::string printf_format; 215 216 /// A stack of children entries, used by Scope entries to provide alterantive 217 /// children. All other entries have a stack of size 1. 218 /// @{ 219 llvm::SmallVector<std::vector<Entry>, 1> children_stack; 220 size_t level = 0; 221 /// @} 222 223 Type type = Type::Invalid; 224 lldb::Format fmt = lldb::eFormatDefault; 225 lldb::addr_t number = 0; 226 bool deref = false; 227 }; 228 229 bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, 230 const ExecutionContext *exe_ctx, const Address *addr, 231 ValueObject *valobj, bool function_changed, bool initial_function); 232 233 bool FormatStringRef(const llvm::StringRef &format, Stream &s, 234 const SymbolContext *sc, const ExecutionContext *exe_ctx, 235 const Address *addr, ValueObject *valobj, 236 bool function_changed, bool initial_function); 237 238 Status Parse(const llvm::StringRef &format, Entry &entry); 239 240 Status ExtractVariableInfo(llvm::StringRef &format_str, 241 llvm::StringRef &variable_name, 242 llvm::StringRef &variable_format); 243 244 void AutoComplete(lldb_private::CompletionRequest &request); 245 246 // Format the current elements into the stream \a s. 247 // 248 // The root element will be stripped off and the format str passed in will be 249 // either an empty string (print a description of this object), or contain a 250 // `.`-separated series like a domain name that identifies further 251 // sub-elements to display. 252 bool FormatFileSpec(const FileSpec &file, Stream &s, llvm::StringRef elements, 253 llvm::StringRef element_format); 254 255 /// For each variable in 'args' this function writes the variable 256 /// name and it's pretty-printed value representation to 'out_stream' 257 /// in following format: 258 /// 259 /// \verbatim 260 /// name_1=repr_1, name_2=repr_2 ... 261 /// \endverbatim 262 void PrettyPrintFunctionArguments(Stream &out_stream, VariableList const &args, 263 ExecutionContextScope *exe_scope); 264 } // namespace FormatEntity 265 } // namespace lldb_private 266 267 #endif // LLDB_CORE_FORMATENTITY_H 268