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