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 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 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 /// The name/string placeholder that corresponds to this definition. 107 const char *name; 108 /// Insert this exact string into the output 109 const char *string = nullptr; 110 /// Entry::Type corresponding to this definition. 111 const Entry::Type type; 112 /// Data that is returned as the value of the format string. 113 const uint64_t data = 0; 114 /// The number of children of this node in the tree of format strings. 115 const uint32_t num_children = 0; 116 /// An array of "num_children" Definition entries. 117 const Definition *children = nullptr; 118 /// Whether the separator is kept during parsing or not. It's used 119 /// for entries with parameters. 120 const bool keep_separator = false; 121 122 constexpr Definition(const char *name, const FormatEntity::Entry::Type t) 123 : name(name), type(t) {} 124 125 constexpr Definition(const char *name, const char *string) 126 : name(name), string(string), type(Entry::Type::EscapeCode) {} 127 128 constexpr Definition(const char *name, const FormatEntity::Entry::Type t, 129 const uint64_t data) 130 : name(name), type(t), data(data) {} 131 132 constexpr Definition(const char *name, const FormatEntity::Entry::Type t, 133 const uint64_t num_children, 134 const Definition *children, 135 const bool keep_separator = false) 136 : name(name), type(t), num_children(num_children), children(children), 137 keep_separator(keep_separator) {} 138 }; 139 140 template <size_t N> 141 static constexpr Definition 142 DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t, 143 const Definition (&children)[N], 144 bool keep_separator = false) { 145 return Definition(name, t, N, children, keep_separator); 146 } 147 148 Entry(Type t = Type::Invalid, const char *s = nullptr, 149 const char *f = nullptr) 150 : string(s ? s : ""), printf_format(f ? f : ""), type(t) {} 151 152 Entry(llvm::StringRef s); 153 Entry(char ch); 154 155 void AppendChar(char ch); 156 157 void AppendText(const llvm::StringRef &s); 158 159 void AppendText(const char *cstr); 160 161 void AppendEntry(const Entry &&entry) { children.push_back(entry); } 162 163 void Clear() { 164 string.clear(); 165 printf_format.clear(); 166 children.clear(); 167 type = Type::Invalid; 168 fmt = lldb::eFormatDefault; 169 number = 0; 170 deref = false; 171 } 172 173 static const char *TypeToCString(Type t); 174 175 void Dump(Stream &s, int depth = 0) const; 176 177 bool operator==(const Entry &rhs) const { 178 if (string != rhs.string) 179 return false; 180 if (printf_format != rhs.printf_format) 181 return false; 182 const size_t n = children.size(); 183 const size_t m = rhs.children.size(); 184 for (size_t i = 0; i < std::min<size_t>(n, m); ++i) { 185 if (!(children[i] == rhs.children[i])) 186 return false; 187 } 188 if (children != rhs.children) 189 return false; 190 if (type != rhs.type) 191 return false; 192 if (fmt != rhs.fmt) 193 return false; 194 if (deref != rhs.deref) 195 return false; 196 return true; 197 } 198 199 std::string string; 200 std::string printf_format; 201 std::vector<Entry> children; 202 Type type; 203 lldb::Format fmt = lldb::eFormatDefault; 204 lldb::addr_t number = 0; 205 bool deref = false; 206 }; 207 208 bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, 209 const ExecutionContext *exe_ctx, const Address *addr, 210 ValueObject *valobj, bool function_changed, bool initial_function); 211 212 bool FormatStringRef(const llvm::StringRef &format, Stream &s, 213 const SymbolContext *sc, const ExecutionContext *exe_ctx, 214 const Address *addr, ValueObject *valobj, 215 bool function_changed, bool initial_function); 216 217 bool FormatCString(const char *format, Stream &s, const SymbolContext *sc, 218 const ExecutionContext *exe_ctx, const Address *addr, 219 ValueObject *valobj, bool function_changed, 220 bool initial_function); 221 222 Status Parse(const llvm::StringRef &format, Entry &entry); 223 224 Status ExtractVariableInfo(llvm::StringRef &format_str, 225 llvm::StringRef &variable_name, 226 llvm::StringRef &variable_format); 227 228 void AutoComplete(lldb_private::CompletionRequest &request); 229 230 // Format the current elements into the stream \a s. 231 // 232 // The root element will be stripped off and the format str passed in will be 233 // either an empty string (print a description of this object), or contain a 234 // `.`-separated series like a domain name that identifies further 235 // sub-elements to display. 236 bool FormatFileSpec(const FileSpec &file, Stream &s, llvm::StringRef elements, 237 llvm::StringRef element_format); 238 239 /// For each variable in 'args' this function writes the variable 240 /// name and it's pretty-printed value representation to 'out_stream' 241 /// in following format: 242 /// 243 /// \verbatim 244 /// name_1=repr_1, name_2=repr_2 ... 245 /// \endverbatim 246 void PrettyPrintFunctionArguments(Stream &out_stream, VariableList const &args, 247 ExecutionContextScope *exe_scope); 248 } // namespace FormatEntity 249 } // namespace lldb_private 250 251 #endif // LLDB_CORE_FORMATENTITY_H 252