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
21namespace lldb_private {
22class Address;
23class CompletionRequest;
24class ExecutionContext;
25class FileSpec;
26class Status;
27class Stream;
28class StringList;
29class SymbolContext;
30class ValueObject;
31}
32
33namespace llvm {
34class StringRef;
35}
36
37namespace lldb_private {
38namespace FormatEntity {
39struct 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
208bool 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
212bool 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
217bool 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
222Status Parse(const llvm::StringRef &format, Entry &entry);
223
224Status ExtractVariableInfo(llvm::StringRef &format_str,
225                           llvm::StringRef &variable_name,
226                           llvm::StringRef &variable_format);
227
228void 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.
236bool 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
246void 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