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