1 //===-- SBCommandReturnObject.cpp -------------------------------*- 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 #include "lldb/API/SBCommandReturnObject.h"
10 #include "lldb/API/SBError.h"
11 #include "lldb/API/SBStream.h"
12 
13 #include "lldb/Interpreter/CommandReturnObject.h"
14 #include "lldb/Utility/ConstString.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Status.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 SBCommandReturnObject::SBCommandReturnObject()
22     : m_opaque_ap(new CommandReturnObject()) {}
23 
24 SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs)
25     : m_opaque_ap() {
26   if (rhs.m_opaque_ap)
27     m_opaque_ap.reset(new CommandReturnObject(*rhs.m_opaque_ap));
28 }
29 
30 SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject *ptr)
31     : m_opaque_ap(ptr) {}
32 
33 SBCommandReturnObject::~SBCommandReturnObject() = default;
34 
35 CommandReturnObject *SBCommandReturnObject::Release() {
36   return m_opaque_ap.release();
37 }
38 
39 const SBCommandReturnObject &SBCommandReturnObject::
40 operator=(const SBCommandReturnObject &rhs) {
41   if (this != &rhs) {
42     if (rhs.m_opaque_ap)
43       m_opaque_ap.reset(new CommandReturnObject(*rhs.m_opaque_ap));
44     else
45       m_opaque_ap.reset();
46   }
47   return *this;
48 }
49 
50 bool SBCommandReturnObject::IsValid() const { return m_opaque_ap != nullptr; }
51 
52 const char *SBCommandReturnObject::GetOutput() {
53   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
54 
55   if (m_opaque_ap) {
56     llvm::StringRef output = m_opaque_ap->GetOutputData();
57     ConstString result(output.empty() ? llvm::StringRef("") : output);
58 
59     if (log)
60       log->Printf("SBCommandReturnObject(%p)::GetOutput () => \"%s\"",
61                   static_cast<void *>(m_opaque_ap.get()), result.AsCString());
62 
63     return result.AsCString();
64   }
65 
66   if (log)
67     log->Printf("SBCommandReturnObject(%p)::GetOutput () => nullptr",
68                 static_cast<void *>(m_opaque_ap.get()));
69 
70   return nullptr;
71 }
72 
73 const char *SBCommandReturnObject::GetError() {
74   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
75 
76   if (m_opaque_ap) {
77     llvm::StringRef output = m_opaque_ap->GetErrorData();
78     ConstString result(output.empty() ? llvm::StringRef("") : output);
79     if (log)
80       log->Printf("SBCommandReturnObject(%p)::GetError () => \"%s\"",
81                   static_cast<void *>(m_opaque_ap.get()), result.AsCString());
82 
83     return result.AsCString();
84   }
85 
86   if (log)
87     log->Printf("SBCommandReturnObject(%p)::GetError () => nullptr",
88                 static_cast<void *>(m_opaque_ap.get()));
89 
90   return nullptr;
91 }
92 
93 size_t SBCommandReturnObject::GetOutputSize() {
94   return (m_opaque_ap ? m_opaque_ap->GetOutputData().size() : 0);
95 }
96 
97 size_t SBCommandReturnObject::GetErrorSize() {
98   return (m_opaque_ap ? m_opaque_ap->GetErrorData().size() : 0);
99 }
100 
101 size_t SBCommandReturnObject::PutOutput(FILE *fh) {
102   if (fh) {
103     size_t num_bytes = GetOutputSize();
104     if (num_bytes)
105       return ::fprintf(fh, "%s", GetOutput());
106   }
107   return 0;
108 }
109 
110 size_t SBCommandReturnObject::PutError(FILE *fh) {
111   if (fh) {
112     size_t num_bytes = GetErrorSize();
113     if (num_bytes)
114       return ::fprintf(fh, "%s", GetError());
115   }
116   return 0;
117 }
118 
119 void SBCommandReturnObject::Clear() {
120   if (m_opaque_ap)
121     m_opaque_ap->Clear();
122 }
123 
124 lldb::ReturnStatus SBCommandReturnObject::GetStatus() {
125   return (m_opaque_ap ? m_opaque_ap->GetStatus() : lldb::eReturnStatusInvalid);
126 }
127 
128 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) {
129   if (m_opaque_ap)
130     m_opaque_ap->SetStatus(status);
131 }
132 
133 bool SBCommandReturnObject::Succeeded() {
134   return (m_opaque_ap ? m_opaque_ap->Succeeded() : false);
135 }
136 
137 bool SBCommandReturnObject::HasResult() {
138   return (m_opaque_ap ? m_opaque_ap->HasResult() : false);
139 }
140 
141 void SBCommandReturnObject::AppendMessage(const char *message) {
142   if (m_opaque_ap)
143     m_opaque_ap->AppendMessage(message);
144 }
145 
146 void SBCommandReturnObject::AppendWarning(const char *message) {
147   if (m_opaque_ap)
148     m_opaque_ap->AppendWarning(message);
149 }
150 
151 CommandReturnObject *SBCommandReturnObject::operator->() const {
152   return m_opaque_ap.get();
153 }
154 
155 CommandReturnObject *SBCommandReturnObject::get() const {
156   return m_opaque_ap.get();
157 }
158 
159 CommandReturnObject &SBCommandReturnObject::operator*() const {
160   assert(m_opaque_ap.get());
161   return *(m_opaque_ap.get());
162 }
163 
164 CommandReturnObject &SBCommandReturnObject::ref() const {
165   assert(m_opaque_ap.get());
166   return *(m_opaque_ap.get());
167 }
168 
169 void SBCommandReturnObject::SetLLDBObjectPtr(CommandReturnObject *ptr) {
170   if (m_opaque_ap)
171     m_opaque_ap.reset(ptr);
172 }
173 
174 bool SBCommandReturnObject::GetDescription(SBStream &description) {
175   Stream &strm = description.ref();
176 
177   if (m_opaque_ap) {
178     description.Printf("Error:  ");
179     lldb::ReturnStatus status = m_opaque_ap->GetStatus();
180     if (status == lldb::eReturnStatusStarted)
181       strm.PutCString("Started");
182     else if (status == lldb::eReturnStatusInvalid)
183       strm.PutCString("Invalid");
184     else if (m_opaque_ap->Succeeded())
185       strm.PutCString("Success");
186     else
187       strm.PutCString("Fail");
188 
189     if (GetOutputSize() > 0)
190       strm.Printf("\nOutput Message:\n%s", GetOutput());
191 
192     if (GetErrorSize() > 0)
193       strm.Printf("\nError Message:\n%s", GetError());
194   } else
195     strm.PutCString("No value");
196 
197   return true;
198 }
199 
200 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) {
201   SetImmediateOutputFile(fh, false);
202 }
203 
204 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
205   SetImmediateErrorFile(fh, false);
206 }
207 
208 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
209                                                    bool transfer_ownership) {
210   if (m_opaque_ap)
211     m_opaque_ap->SetImmediateOutputFile(fh, transfer_ownership);
212 }
213 
214 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
215                                                   bool transfer_ownership) {
216   if (m_opaque_ap)
217     m_opaque_ap->SetImmediateErrorFile(fh, transfer_ownership);
218 }
219 
220 void SBCommandReturnObject::PutCString(const char *string, int len) {
221   if (m_opaque_ap) {
222     if (len == 0 || string == nullptr || *string == 0) {
223       return;
224     } else if (len > 0) {
225       std::string buffer(string, len);
226       m_opaque_ap->AppendMessage(buffer.c_str());
227     } else
228       m_opaque_ap->AppendMessage(string);
229   }
230 }
231 
232 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) {
233   if (!m_opaque_ap)
234     return nullptr;
235   if (!only_if_no_immediate ||
236       m_opaque_ap->GetImmediateOutputStream().get() == nullptr)
237     return GetOutput();
238   return nullptr;
239 }
240 
241 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) {
242   if (!m_opaque_ap)
243     return nullptr;
244   if (!only_if_no_immediate ||
245       m_opaque_ap->GetImmediateErrorStream().get() == nullptr)
246     return GetError();
247   return nullptr;
248 }
249 
250 size_t SBCommandReturnObject::Printf(const char *format, ...) {
251   if (m_opaque_ap) {
252     va_list args;
253     va_start(args, format);
254     size_t result = m_opaque_ap->GetOutputStream().PrintfVarArg(format, args);
255     va_end(args);
256     return result;
257   }
258   return 0;
259 }
260 
261 void SBCommandReturnObject::SetError(lldb::SBError &error,
262                                      const char *fallback_error_cstr) {
263   if (m_opaque_ap) {
264     if (error.IsValid())
265       m_opaque_ap->SetError(error.ref(), fallback_error_cstr);
266     else if (fallback_error_cstr)
267       m_opaque_ap->SetError(Status(), fallback_error_cstr);
268   }
269 }
270 
271 void SBCommandReturnObject::SetError(const char *error_cstr) {
272   if (m_opaque_ap && error_cstr)
273     m_opaque_ap->SetError(error_cstr);
274 }
275