1 //===-- CommandReturnObject.h -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_CommandReturnObject_h_
11 #define liblldb_CommandReturnObject_h_
12 
13 #include "lldb/Core/STLUtils.h"
14 #include "lldb/Core/StreamFile.h"
15 #include "lldb/Utility/StreamString.h"
16 #include "lldb/Utility/StreamTee.h"
17 #include "lldb/lldb-private.h"
18 
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/FormatVariadic.h"
21 
22 #include <memory>
23 
24 namespace lldb_private {
25 
26 class CommandReturnObject {
27 public:
28   CommandReturnObject();
29 
30   ~CommandReturnObject();
31 
GetOutputData()32   llvm::StringRef GetOutputData() {
33     lldb::StreamSP stream_sp(m_out_stream.GetStreamAtIndex(eStreamStringIndex));
34     if (stream_sp)
35       return static_pointer_cast<StreamString>(stream_sp)->GetString();
36     return llvm::StringRef();
37   }
38 
GetErrorData()39   llvm::StringRef GetErrorData() {
40     lldb::StreamSP stream_sp(m_err_stream.GetStreamAtIndex(eStreamStringIndex));
41     if (stream_sp)
42       return static_pointer_cast<StreamString>(stream_sp)->GetString();
43     return llvm::StringRef();
44   }
45 
GetOutputStream()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.reset(new StreamString());
51       m_out_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp);
52     }
53     return m_out_stream;
54   }
55 
GetErrorStream()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.reset(new StreamString());
61       m_err_stream.SetStreamAtIndex(eStreamStringIndex, stream_sp);
62     }
63     return m_err_stream;
64   }
65 
66   void SetImmediateOutputFile(FILE *fh, bool transfer_fh_ownership = false) {
67     lldb::StreamSP stream_sp(new StreamFile(fh, transfer_fh_ownership));
68     m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
69   }
70 
71   void SetImmediateErrorFile(FILE *fh, bool transfer_fh_ownership = false) {
72     lldb::StreamSP stream_sp(new StreamFile(fh, transfer_fh_ownership));
73     m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
74   }
75 
SetImmediateOutputStream(const lldb::StreamSP & stream_sp)76   void SetImmediateOutputStream(const lldb::StreamSP &stream_sp) {
77     m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
78   }
79 
SetImmediateErrorStream(const lldb::StreamSP & stream_sp)80   void SetImmediateErrorStream(const lldb::StreamSP &stream_sp) {
81     m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp);
82   }
83 
GetImmediateOutputStream()84   lldb::StreamSP GetImmediateOutputStream() {
85     return m_out_stream.GetStreamAtIndex(eImmediateStreamIndex);
86   }
87 
GetImmediateErrorStream()88   lldb::StreamSP GetImmediateErrorStream() {
89     return m_err_stream.GetStreamAtIndex(eImmediateStreamIndex);
90   }
91 
92   void Clear();
93 
94   void AppendMessage(llvm::StringRef in_string);
95 
96   void AppendMessageWithFormat(const char *format, ...)
97       __attribute__((format(printf, 2, 3)));
98 
99   void AppendRawWarning(llvm::StringRef in_string);
100 
101   void AppendWarning(llvm::StringRef in_string);
102 
103   void AppendWarningWithFormat(const char *format, ...)
104       __attribute__((format(printf, 2, 3)));
105 
106   void AppendError(llvm::StringRef in_string);
107 
108   void AppendRawError(llvm::StringRef in_string);
109 
110   void AppendErrorWithFormat(const char *format, ...)
111       __attribute__((format(printf, 2, 3)));
112 
113   template <typename... Args>
AppendMessageWithFormatv(const char * format,Args &&...args)114   void AppendMessageWithFormatv(const char *format, Args &&... args) {
115     AppendMessage(llvm::formatv(format, std::forward<Args>(args)...).str());
116   }
117 
118   template <typename... Args>
AppendWarningWithFormatv(const char * format,Args &&...args)119   void AppendWarningWithFormatv(const char *format, Args &&... args) {
120     AppendWarning(llvm::formatv(format, std::forward<Args>(args)...).str());
121   }
122 
123   template <typename... Args>
AppendErrorWithFormatv(const char * format,Args &&...args)124   void AppendErrorWithFormatv(const char *format, Args &&... args) {
125     AppendError(llvm::formatv(format, std::forward<Args>(args)...).str());
126   }
127 
128   void SetError(const Status &error, const char *fallback_error_cstr = nullptr);
129 
130   void SetError(llvm::StringRef error_cstr);
131 
132   lldb::ReturnStatus GetStatus();
133 
134   void SetStatus(lldb::ReturnStatus status);
135 
136   bool Succeeded();
137 
138   bool HasResult();
139 
140   bool GetDidChangeProcessState();
141 
142   void SetDidChangeProcessState(bool b);
143 
144   bool GetInteractive() const;
145 
146   void SetInteractive(bool b);
147 
GetAbnormalStopWasExpected()148   bool GetAbnormalStopWasExpected() const {
149     return m_abnormal_stop_was_expected;
150   }
151 
SetAbnormalStopWasExpected(bool signal_was_expected)152   void SetAbnormalStopWasExpected(bool signal_was_expected) {
153     m_abnormal_stop_was_expected = signal_was_expected;
154   }
155 
156 private:
157   enum { eStreamStringIndex = 0, eImmediateStreamIndex = 1 };
158 
159   StreamTee m_out_stream;
160   StreamTee m_err_stream;
161 
162   lldb::ReturnStatus m_status;
163   bool m_did_change_process_state;
164   bool m_interactive; // If true, then the input handle from the debugger will
165                       // be hooked up
166   bool m_abnormal_stop_was_expected; // This is to support
167                                      // eHandleCommandFlagStopOnCrash vrs.
168                                      // attach.
169   // The attach command often ends up with the process stopped due to a signal.
170   // Normally that would mean stop on crash should halt batch execution, but we
171   // obviously don't want that for attach.  Using this flag, the attach command
172   // (and anything else for which this is relevant) can say that the signal is
173   // expected, and batch command execution can continue.
174 };
175 
176 } // namespace lldb_private
177 
178 #endif // liblldb_CommandReturnObject_h_
179