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 "SBReproducerPrivate.h"
11 #include "Utils.h"
12 #include "lldb/API/SBError.h"
13 #include "lldb/API/SBFile.h"
14 #include "lldb/API/SBStream.h"
15 #include "lldb/Interpreter/CommandReturnObject.h"
16 #include "lldb/Utility/ConstString.h"
17 #include "lldb/Utility/Status.h"
18
19 using namespace lldb;
20 using namespace lldb_private;
21
22 class lldb_private::SBCommandReturnObjectImpl {
23 public:
SBCommandReturnObjectImpl()24 SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {}
SBCommandReturnObjectImpl(CommandReturnObject & ref)25 SBCommandReturnObjectImpl(CommandReturnObject &ref)
26 : m_ptr(&ref), m_owned(false) {}
SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl & rhs)27 SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs)
28 : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {}
operator =(const SBCommandReturnObjectImpl & rhs)29 SBCommandReturnObjectImpl &operator=(const SBCommandReturnObjectImpl &rhs) {
30 SBCommandReturnObjectImpl copy(rhs);
31 std::swap(*this, copy);
32 return *this;
33 }
34 // rvalue ctor+assignment are not used by SBCommandReturnObject.
~SBCommandReturnObjectImpl()35 ~SBCommandReturnObjectImpl() {
36 if (m_owned)
37 delete m_ptr;
38 }
39
operator *() const40 CommandReturnObject &operator*() const { return *m_ptr; }
41
42 private:
43 CommandReturnObject *m_ptr;
44 bool m_owned = true;
45 };
46
SBCommandReturnObject()47 SBCommandReturnObject::SBCommandReturnObject()
48 : m_opaque_up(new SBCommandReturnObjectImpl()) {
49 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandReturnObject);
50 }
51
SBCommandReturnObject(CommandReturnObject & ref)52 SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject &ref)
53 : m_opaque_up(new SBCommandReturnObjectImpl(ref)) {
54 LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject,
55 (lldb_private::CommandReturnObject &), ref);
56 }
57
SBCommandReturnObject(const SBCommandReturnObject & rhs)58 SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs)
59 : m_opaque_up() {
60 LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject,
61 (const lldb::SBCommandReturnObject &), rhs);
62
63 m_opaque_up = clone(rhs.m_opaque_up);
64 }
65
66 SBCommandReturnObject &SBCommandReturnObject::
operator =(const SBCommandReturnObject & rhs)67 operator=(const SBCommandReturnObject &rhs) {
68 LLDB_RECORD_METHOD(
69 lldb::SBCommandReturnObject &,
70 SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &),
71 rhs);
72
73 if (this != &rhs)
74 m_opaque_up = clone(rhs.m_opaque_up);
75 return LLDB_RECORD_RESULT(*this);
76 }
77
78 SBCommandReturnObject::~SBCommandReturnObject() = default;
79
IsValid() const80 bool SBCommandReturnObject::IsValid() const {
81 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, IsValid);
82 return this->operator bool();
83 }
operator bool() const84 SBCommandReturnObject::operator bool() const {
85 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, operator bool);
86
87 // This method is not useful but it needs to stay to keep SB API stable.
88 return true;
89 }
90
GetOutput()91 const char *SBCommandReturnObject::GetOutput() {
92 LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetOutput);
93
94 ConstString output(ref().GetOutputData());
95 return output.AsCString(/*value_if_empty*/ "");
96 }
97
GetError()98 const char *SBCommandReturnObject::GetError() {
99 LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommandReturnObject, GetError);
100
101 ConstString output(ref().GetErrorData());
102 return output.AsCString(/*value_if_empty*/ "");
103 }
104
GetOutputSize()105 size_t SBCommandReturnObject::GetOutputSize() {
106 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetOutputSize);
107
108 return ref().GetOutputData().size();
109 }
110
GetErrorSize()111 size_t SBCommandReturnObject::GetErrorSize() {
112 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetErrorSize);
113
114 return ref().GetErrorData().size();
115 }
116
PutOutput(FILE * fh)117 size_t SBCommandReturnObject::PutOutput(FILE *fh) {
118 LLDB_RECORD_DUMMY(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh);
119 if (fh) {
120 size_t num_bytes = GetOutputSize();
121 if (num_bytes)
122 return ::fprintf(fh, "%s", GetOutput());
123 }
124 return 0;
125 }
126
PutOutput(FileSP file_sp)127 size_t SBCommandReturnObject::PutOutput(FileSP file_sp) {
128 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP),
129 file_sp);
130 if (!file_sp)
131 return 0;
132 return file_sp->Printf("%s", GetOutput());
133 }
134
PutOutput(SBFile file)135 size_t SBCommandReturnObject::PutOutput(SBFile file) {
136 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile), file);
137 if (!file.m_opaque_sp)
138 return 0;
139 return file.m_opaque_sp->Printf("%s", GetOutput());
140 }
141
PutError(FILE * fh)142 size_t SBCommandReturnObject::PutError(FILE *fh) {
143 LLDB_RECORD_DUMMY(size_t, SBCommandReturnObject, PutError, (FILE *), fh);
144 if (fh) {
145 size_t num_bytes = GetErrorSize();
146 if (num_bytes)
147 return ::fprintf(fh, "%s", GetError());
148 }
149 return 0;
150 }
151
PutError(FileSP file_sp)152 size_t SBCommandReturnObject::PutError(FileSP file_sp) {
153 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP),
154 file_sp);
155 if (!file_sp)
156 return 0;
157 return file_sp->Printf("%s", GetError());
158 }
159
PutError(SBFile file)160 size_t SBCommandReturnObject::PutError(SBFile file) {
161 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile), file);
162 if (!file.m_opaque_sp)
163 return 0;
164 return file.m_opaque_sp->Printf("%s", GetError());
165 }
166
Clear()167 void SBCommandReturnObject::Clear() {
168 LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear);
169
170 ref().Clear();
171 }
172
GetStatus()173 lldb::ReturnStatus SBCommandReturnObject::GetStatus() {
174 LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject,
175 GetStatus);
176
177 return ref().GetStatus();
178 }
179
SetStatus(lldb::ReturnStatus status)180 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) {
181 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetStatus,
182 (lldb::ReturnStatus), status);
183
184 ref().SetStatus(status);
185 }
186
Succeeded()187 bool SBCommandReturnObject::Succeeded() {
188 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded);
189
190 return ref().Succeeded();
191 }
192
HasResult()193 bool SBCommandReturnObject::HasResult() {
194 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult);
195
196 return ref().HasResult();
197 }
198
AppendMessage(const char * message)199 void SBCommandReturnObject::AppendMessage(const char *message) {
200 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendMessage, (const char *),
201 message);
202
203 ref().AppendMessage(message);
204 }
205
AppendWarning(const char * message)206 void SBCommandReturnObject::AppendWarning(const char *message) {
207 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendWarning, (const char *),
208 message);
209
210 ref().AppendWarning(message);
211 }
212
operator ->() const213 CommandReturnObject *SBCommandReturnObject::operator->() const {
214 return &**m_opaque_up;
215 }
216
get() const217 CommandReturnObject *SBCommandReturnObject::get() const {
218 return &**m_opaque_up;
219 }
220
operator *() const221 CommandReturnObject &SBCommandReturnObject::operator*() const {
222 return **m_opaque_up;
223 }
224
ref() const225 CommandReturnObject &SBCommandReturnObject::ref() const {
226 return **m_opaque_up;
227 }
228
GetDescription(SBStream & description)229 bool SBCommandReturnObject::GetDescription(SBStream &description) {
230 LLDB_RECORD_METHOD(bool, SBCommandReturnObject, GetDescription,
231 (lldb::SBStream &), description);
232
233 Stream &strm = description.ref();
234
235 description.Printf("Error: ");
236 lldb::ReturnStatus status = ref().GetStatus();
237 if (status == lldb::eReturnStatusStarted)
238 strm.PutCString("Started");
239 else if (status == lldb::eReturnStatusInvalid)
240 strm.PutCString("Invalid");
241 else if (ref().Succeeded())
242 strm.PutCString("Success");
243 else
244 strm.PutCString("Fail");
245
246 if (GetOutputSize() > 0)
247 strm.Printf("\nOutput Message:\n%s", GetOutput());
248
249 if (GetErrorSize() > 0)
250 strm.Printf("\nError Message:\n%s", GetError());
251
252 return true;
253 }
254
SetImmediateOutputFile(FILE * fh)255 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) {
256 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile,
257 (FILE *), fh);
258
259 SetImmediateOutputFile(fh, false);
260 }
261
SetImmediateErrorFile(FILE * fh)262 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
263 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile,
264 (FILE *), fh);
265
266 SetImmediateErrorFile(fh, false);
267 }
268
SetImmediateOutputFile(FILE * fh,bool transfer_ownership)269 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
270 bool transfer_ownership) {
271 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile,
272 (FILE *, bool), fh, transfer_ownership);
273 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
274 ref().SetImmediateOutputFile(file);
275 }
276
SetImmediateErrorFile(FILE * fh,bool transfer_ownership)277 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
278 bool transfer_ownership) {
279 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile,
280 (FILE *, bool), fh, transfer_ownership);
281 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership);
282 ref().SetImmediateErrorFile(file);
283 }
284
SetImmediateOutputFile(SBFile file)285 void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) {
286 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
287 (SBFile), file);
288 ref().SetImmediateOutputFile(file.m_opaque_sp);
289 }
290
SetImmediateErrorFile(SBFile file)291 void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) {
292 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
293 (SBFile), file);
294 ref().SetImmediateErrorFile(file.m_opaque_sp);
295 }
296
SetImmediateOutputFile(FileSP file_sp)297 void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) {
298 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
299 (FileSP), file_sp);
300 SetImmediateOutputFile(SBFile(file_sp));
301 }
302
SetImmediateErrorFile(FileSP file_sp)303 void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) {
304 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
305 (FileSP), file_sp);
306 SetImmediateErrorFile(SBFile(file_sp));
307 }
308
PutCString(const char * string,int len)309 void SBCommandReturnObject::PutCString(const char *string, int len) {
310 LLDB_RECORD_METHOD(void, SBCommandReturnObject, PutCString,
311 (const char *, int), string, len);
312
313 if (len == 0 || string == nullptr || *string == 0) {
314 return;
315 } else if (len > 0) {
316 std::string buffer(string, len);
317 ref().AppendMessage(buffer.c_str());
318 } else
319 ref().AppendMessage(string);
320 }
321
GetOutput(bool only_if_no_immediate)322 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) {
323 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetOutput, (bool),
324 only_if_no_immediate);
325
326 if (!only_if_no_immediate ||
327 ref().GetImmediateOutputStream().get() == nullptr)
328 return GetOutput();
329 return nullptr;
330 }
331
GetError(bool only_if_no_immediate)332 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) {
333 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetError, (bool),
334 only_if_no_immediate);
335
336 if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr)
337 return GetError();
338 return nullptr;
339 }
340
Printf(const char * format,...)341 size_t SBCommandReturnObject::Printf(const char *format, ...) {
342 va_list args;
343 va_start(args, format);
344 size_t result = ref().GetOutputStream().PrintfVarArg(format, args);
345 va_end(args);
346 return result;
347 }
348
SetError(lldb::SBError & error,const char * fallback_error_cstr)349 void SBCommandReturnObject::SetError(lldb::SBError &error,
350 const char *fallback_error_cstr) {
351 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError,
352 (lldb::SBError &, const char *), error,
353 fallback_error_cstr);
354
355 if (error.IsValid())
356 ref().SetError(error.ref(), fallback_error_cstr);
357 else if (fallback_error_cstr)
358 ref().SetError(Status(), fallback_error_cstr);
359 }
360
SetError(const char * error_cstr)361 void SBCommandReturnObject::SetError(const char *error_cstr) {
362 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, (const char *),
363 error_cstr);
364
365 if (error_cstr)
366 ref().AppendError(error_cstr);
367 }
368
369 namespace lldb_private {
370 namespace repro {
371
372 template <>
RegisterMethods(Registry & R)373 void RegisterMethods<SBCommandReturnObject>(Registry &R) {
374 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ());
375 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject,
376 (lldb_private::CommandReturnObject &));
377 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject,
378 (const lldb::SBCommandReturnObject &));
379 LLDB_REGISTER_METHOD(
380 lldb::SBCommandReturnObject &,
381 SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &));
382 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, IsValid, ());
383 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, operator bool, ());
384 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, ());
385 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, ());
386 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetOutputSize, ());
387 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ());
388 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *));
389 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *));
390 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile));
391 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile));
392 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP));
393 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP));
394 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ());
395 LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus,
396 ());
397 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetStatus,
398 (lldb::ReturnStatus));
399 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, Succeeded, ());
400 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, HasResult, ());
401 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendMessage,
402 (const char *));
403 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendWarning,
404 (const char *));
405 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, GetDescription,
406 (lldb::SBStream &));
407 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
408 (FILE *));
409 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
410 (FILE *));
411 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
412 (SBFile));
413 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
414 (SBFile));
415 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
416 (FileSP));
417 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
418 (FileSP));
419 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile,
420 (FILE *, bool));
421 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile,
422 (FILE *, bool));
423 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, PutCString,
424 (const char *, int));
425 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput,
426 (bool));
427 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, (bool));
428 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError,
429 (lldb::SBError &, const char *));
430 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, (const char *));
431 }
432
433 }
434 }
435