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