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