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 LLDB_RECORD_RESULT(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 LLDB_RECORD_RESULT(*this);
59 }
60 
61 bool SBCommandReturnObject::IsValid() const {
62   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, IsValid);
63   return this->operator bool();
64 }
65 SBCommandReturnObject::operator bool() const {
66   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, operator bool);
67 
68   return m_opaque_up != nullptr;
69 }
70 
71 const char *SBCommandReturnObject::GetOutput() {
72   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetOutput);
73 
74   if (m_opaque_up) {
75     ConstString output(m_opaque_up->GetOutputData());
76     return output.AsCString(/*value_if_empty*/ "");
77   }
78 
79   return nullptr;
80 }
81 
82 const char *SBCommandReturnObject::GetError() {
83   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetError);
84 
85   if (m_opaque_up) {
86     ConstString output(m_opaque_up->GetErrorData());
87     return output.AsCString(/*value_if_empty*/ "");
88   }
89 
90   return nullptr;
91 }
92 
93 size_t SBCommandReturnObject::GetOutputSize() {
94   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetOutputSize);
95 
96   return (m_opaque_up ? m_opaque_up->GetOutputData().size() : 0);
97 }
98 
99 size_t SBCommandReturnObject::GetErrorSize() {
100   LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetErrorSize);
101 
102   return (m_opaque_up ? m_opaque_up->GetErrorData().size() : 0);
103 }
104 
105 size_t SBCommandReturnObject::PutOutput(FILE *fh) {
106   LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh);
107 
108   if (fh) {
109     size_t num_bytes = GetOutputSize();
110     if (num_bytes)
111       return ::fprintf(fh, "%s", GetOutput());
112   }
113   return 0;
114 }
115 
116 size_t SBCommandReturnObject::PutError(FILE *fh) {
117   LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *), fh);
118 
119   if (fh) {
120     size_t num_bytes = GetErrorSize();
121     if (num_bytes)
122       return ::fprintf(fh, "%s", GetError());
123   }
124   return 0;
125 }
126 
127 void SBCommandReturnObject::Clear() {
128   LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear);
129 
130   if (m_opaque_up)
131     m_opaque_up->Clear();
132 }
133 
134 lldb::ReturnStatus SBCommandReturnObject::GetStatus() {
135   LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject,
136                              GetStatus);
137 
138   return (m_opaque_up ? m_opaque_up->GetStatus() : lldb::eReturnStatusInvalid);
139 }
140 
141 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) {
142   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetStatus,
143                      (lldb::ReturnStatus), status);
144 
145   if (m_opaque_up)
146     m_opaque_up->SetStatus(status);
147 }
148 
149 bool SBCommandReturnObject::Succeeded() {
150   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded);
151 
152   return (m_opaque_up ? m_opaque_up->Succeeded() : false);
153 }
154 
155 bool SBCommandReturnObject::HasResult() {
156   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult);
157 
158   return (m_opaque_up ? m_opaque_up->HasResult() : false);
159 }
160 
161 void SBCommandReturnObject::AppendMessage(const char *message) {
162   LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendMessage, (const char *),
163                      message);
164 
165   if (m_opaque_up)
166     m_opaque_up->AppendMessage(message);
167 }
168 
169 void SBCommandReturnObject::AppendWarning(const char *message) {
170   LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendWarning, (const char *),
171                      message);
172 
173   if (m_opaque_up)
174     m_opaque_up->AppendWarning(message);
175 }
176 
177 CommandReturnObject *SBCommandReturnObject::operator->() const {
178   return m_opaque_up.get();
179 }
180 
181 CommandReturnObject *SBCommandReturnObject::get() const {
182   return m_opaque_up.get();
183 }
184 
185 CommandReturnObject &SBCommandReturnObject::operator*() const {
186   assert(m_opaque_up.get());
187   return *(m_opaque_up.get());
188 }
189 
190 CommandReturnObject &SBCommandReturnObject::ref() const {
191   assert(m_opaque_up.get());
192   return *(m_opaque_up.get());
193 }
194 
195 void SBCommandReturnObject::SetLLDBObjectPtr(CommandReturnObject *ptr) {
196   if (m_opaque_up)
197     m_opaque_up.reset(ptr);
198 }
199 
200 bool SBCommandReturnObject::GetDescription(SBStream &description) {
201   LLDB_RECORD_METHOD(bool, SBCommandReturnObject, GetDescription,
202                      (lldb::SBStream &), description);
203 
204   Stream &strm = description.ref();
205 
206   if (m_opaque_up) {
207     description.Printf("Error:  ");
208     lldb::ReturnStatus status = m_opaque_up->GetStatus();
209     if (status == lldb::eReturnStatusStarted)
210       strm.PutCString("Started");
211     else if (status == lldb::eReturnStatusInvalid)
212       strm.PutCString("Invalid");
213     else if (m_opaque_up->Succeeded())
214       strm.PutCString("Success");
215     else
216       strm.PutCString("Fail");
217 
218     if (GetOutputSize() > 0)
219       strm.Printf("\nOutput Message:\n%s", GetOutput());
220 
221     if (GetErrorSize() > 0)
222       strm.Printf("\nError Message:\n%s", GetError());
223   } else
224     strm.PutCString("No value");
225 
226   return true;
227 }
228 
229 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) {
230   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
231                      (FILE *), fh);
232 
233   SetImmediateOutputFile(fh, false);
234 }
235 
236 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
237   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
238                      (FILE *), fh);
239 
240   SetImmediateErrorFile(fh, false);
241 }
242 
243 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
244                                                    bool transfer_ownership) {
245   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
246                      (FILE *, bool), fh, transfer_ownership);
247 
248   if (m_opaque_up)
249     m_opaque_up->SetImmediateOutputFile(fh, transfer_ownership);
250 }
251 
252 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
253                                                   bool transfer_ownership) {
254   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
255                      (FILE *, bool), fh, transfer_ownership);
256 
257   if (m_opaque_up)
258     m_opaque_up->SetImmediateErrorFile(fh, transfer_ownership);
259 }
260 
261 void SBCommandReturnObject::PutCString(const char *string, int len) {
262   LLDB_RECORD_METHOD(void, SBCommandReturnObject, PutCString,
263                      (const char *, int), string, len);
264 
265   if (m_opaque_up) {
266     if (len == 0 || string == nullptr || *string == 0) {
267       return;
268     } else if (len > 0) {
269       std::string buffer(string, len);
270       m_opaque_up->AppendMessage(buffer.c_str());
271     } else
272       m_opaque_up->AppendMessage(string);
273   }
274 }
275 
276 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) {
277   LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetOutput, (bool),
278                      only_if_no_immediate);
279 
280   if (!m_opaque_up)
281     return nullptr;
282   if (!only_if_no_immediate ||
283       m_opaque_up->GetImmediateOutputStream().get() == nullptr)
284     return GetOutput();
285   return nullptr;
286 }
287 
288 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) {
289   LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetError, (bool),
290                      only_if_no_immediate);
291 
292   if (!m_opaque_up)
293     return nullptr;
294   if (!only_if_no_immediate ||
295       m_opaque_up->GetImmediateErrorStream().get() == nullptr)
296     return GetError();
297   return nullptr;
298 }
299 
300 size_t SBCommandReturnObject::Printf(const char *format, ...) {
301   if (m_opaque_up) {
302     va_list args;
303     va_start(args, format);
304     size_t result = m_opaque_up->GetOutputStream().PrintfVarArg(format, args);
305     va_end(args);
306     return result;
307   }
308   return 0;
309 }
310 
311 void SBCommandReturnObject::SetError(lldb::SBError &error,
312                                      const char *fallback_error_cstr) {
313   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError,
314                      (lldb::SBError &, const char *), error,
315                      fallback_error_cstr);
316 
317   if (m_opaque_up) {
318     if (error.IsValid())
319       m_opaque_up->SetError(error.ref(), fallback_error_cstr);
320     else if (fallback_error_cstr)
321       m_opaque_up->SetError(Status(), fallback_error_cstr);
322   }
323 }
324 
325 void SBCommandReturnObject::SetError(const char *error_cstr) {
326   LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, (const char *),
327                      error_cstr);
328 
329   if (m_opaque_up && error_cstr)
330     m_opaque_up->SetError(error_cstr);
331 }
332 
333 namespace lldb_private {
334 namespace repro {
335 
336 template <>
337 void RegisterMethods<SBCommandReturnObject>(Registry &R) {
338   LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ());
339   LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject,
340                             (const lldb::SBCommandReturnObject &));
341   LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject,
342                             (lldb_private::CommandReturnObject *));
343   LLDB_REGISTER_METHOD(lldb_private::CommandReturnObject *,
344                        SBCommandReturnObject, Release, ());
345   LLDB_REGISTER_METHOD(
346       const lldb::SBCommandReturnObject &,
347       SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &));
348   LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, IsValid, ());
349   LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, operator bool, ());
350   LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, ());
351   LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, ());
352   LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetOutputSize, ());
353   LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ());
354   LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *));
355   LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *));
356   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ());
357   LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus,
358                        ());
359   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetStatus,
360                        (lldb::ReturnStatus));
361   LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, Succeeded, ());
362   LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, HasResult, ());
363   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendMessage,
364                        (const char *));
365   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendWarning,
366                        (const char *));
367   LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, GetDescription,
368                        (lldb::SBStream &));
369   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
370                        (FILE *));
371   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
372                        (FILE *));
373   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
374                        (FILE *, bool));
375   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
376                        (FILE *, bool));
377   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, PutCString,
378                        (const char *, int));
379   LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput,
380                        (bool));
381   LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, (bool));
382   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError,
383                        (lldb::SBError &, const char *));
384   LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, (const char *));
385 }
386 
387 }
388 }
389