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