1 //===-- CommandReturnObject.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_INTERPRETER_COMMANDRETURNOBJECT_H
10 #define LLDB_INTERPRETER_COMMANDRETURNOBJECT_H
11 
12 #include "lldb/Core/StreamFile.h"
13 #include "lldb/Utility/StreamString.h"
14 #include "lldb/Utility/StreamTee.h"
15 #include "lldb/lldb-private.h"
16 
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/WithColor.h"
21 
22 #include <memory>
23 
24 namespace lldb_private {
25 
26 class CommandReturnObject {
27 public:
28   CommandReturnObject(bool colors);
29 
30   ~CommandReturnObject() = default;
31 
32   llvm::StringRef GetOutputData() {
33     lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex));
34     if (stream_sp)
35       return std::static_pointer_cast<StreamString>(stream_sp)->GetString();
36     return llvm::StringRef();
37   }
38 
39   llvm::StringRef GetErrorData() {
40     lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex));
41     if (stream_sp)
42       return std::static_pointer_cast<StreamString>(stream_sp)->GetString();
43     return llvm::StringRef();
44   }
45 
46   Stream &GetOutputStream() {
47     // Make sure we at least have our normal string stream output stream
48     lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex));
49     if (!stream_sp) {
50       stream_sp = std::make_shared<StreamString>();
51       m_out_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp);
52     }
53     return m_out_stream;
54   }
55 
56   Stream &GetErrorStream() {
57     // Make sure we at least have our normal string stream output stream
58     lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex));
59     if (!stream_sp) {
60       stream_sp = std::make_shared<StreamString>();
61       m_err_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp);
62     }
63     return m_err_stream;
64   }
65 
66   void SetImmediateOutputFile(lldb::FileSP file_sp) {
67     if (m_suppress_immediate_output)
68       return;
69     lldb::StreamSP stream_sp(new StreamFile(file_sp));
70     m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
71   }
72 
73   void SetImmediateErrorFile(lldb::FileSP file_sp) {
74     if (m_suppress_immediate_output)
75       return;
76     lldb::StreamSP stream_sp(new StreamFile(file_sp));
77     m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
78   }
79 
80   void SetImmediateOutputStream(const lldb::StreamSP &stream_sp) {
81     if (m_suppress_immediate_output)
82       return;
83     m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
84   }
85 
86   void SetImmediateErrorStream(const lldb::StreamSP &stream_sp) {
87     if (m_suppress_immediate_output)
88       return;
89     m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
90   }
91 
92   lldb::StreamSP GetImmediateOutputStream() {
93     return m_out_stream.GetStreamAtIndex(eImmediateStreamIndex);
94   }
95 
96   lldb::StreamSP GetImmediateErrorStream() {
97     return m_err_stream.GetStreamAtIndex(eImmediateStreamIndex);
98   }
99 
100   void Clear();
101 
102   void AppendMessage(llvm::StringRef in_string);
103 
104   void AppendMessageWithFormat(const char *format, ...)
105       __attribute__((format(printf, 2, 3)));
106 
107   void AppendWarning(llvm::StringRef in_string);
108 
109   void AppendWarningWithFormat(const char *format, ...)
110       __attribute__((format(printf, 2, 3)));
111 
112   void AppendError(llvm::StringRef in_string);
113 
114   void AppendRawError(llvm::StringRef in_string);
115 
116   void AppendErrorWithFormat(const char *format, ...)
117       __attribute__((format(printf, 2, 3)));
118 
119   template <typename... Args>
120   void AppendMessageWithFormatv(const char *format, Args &&... args) {
121     AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str());
122   }
123 
124   template <typename... Args>
125   void AppendWarningWithFormatv(const char *format, Args &&... args) {
126     AppendWarning(llvm::formatv(format, std::forward<Args>(args)...).str());
127   }
128 
129   template <typename... Args>
130   void AppendErrorWithFormatv(const char *format, Args &&... args) {
131     AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
132   }
133 
134   void SetError(const Status &error, const char *fallback_error_cstr = nullptr);
135 
136   void SetError(llvm::Error error);
137 
138   lldb::ReturnStatus GetStatus() const;
139 
140   void SetStatus(lldb::ReturnStatus status);
141 
142   bool Succeeded() const;
143 
144   bool HasResult() const;
145 
146   bool GetDidChangeProcessState() const;
147 
148   void SetDidChangeProcessState(bool b);
149 
150   bool GetInteractive() const;
151 
152   void SetInteractive(bool b);
153 
154   bool GetSuppressImmediateOutput() const;
155 
156   void SetSuppressImmediateOutput(bool b);
157 
158 private:
159   enum { eStreamStringIndex = 0, eImmediateStreamIndex = 1 };
160 
161   StreamTee m_out_stream;
162   StreamTee m_err_stream;
163 
164   lldb::ReturnStatus m_status = lldb::eReturnStatusStarted;
165 
166   bool m_did_change_process_state = false;
167   bool m_suppress_immediate_output = false;
168 
169   /// If true, then the input handle from the debugger will be hooked up.
170   bool m_interactive = true;
171 };
172 
173 } // namespace lldb_private
174 
175 #endif // LLDB_INTERPRETER_COMMANDRETURNOBJECT_H
176