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_DUMMY(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_DUMMY(size_t, SBCommandReturnObject, PutError, (FILE *), fh); 145 if (fh) { 146 size_t num_bytes = GetErrorSize(); 147 if (num_bytes) 148 return ::fprintf(fh, "%s", GetError()); 149 } 150 return 0; 151 } 152 153 size_t SBCommandReturnObject::PutError(FileSP file_sp) { 154 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP), 155 file_sp); 156 if (!file_sp) 157 return 0; 158 return file_sp->Printf("%s", GetError()); 159 } 160 161 size_t SBCommandReturnObject::PutError(SBFile file) { 162 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile), file); 163 if (!file.m_opaque_sp) 164 return 0; 165 return file.m_opaque_sp->Printf("%s", GetError()); 166 } 167 168 void SBCommandReturnObject::Clear() { 169 LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear); 170 171 ref().Clear(); 172 } 173 174 lldb::ReturnStatus SBCommandReturnObject::GetStatus() { 175 LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject, 176 GetStatus); 177 178 return ref().GetStatus(); 179 } 180 181 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) { 182 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetStatus, 183 (lldb::ReturnStatus), status); 184 185 ref().SetStatus(status); 186 } 187 188 bool SBCommandReturnObject::Succeeded() { 189 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded); 190 191 return ref().Succeeded(); 192 } 193 194 bool SBCommandReturnObject::HasResult() { 195 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult); 196 197 return ref().HasResult(); 198 } 199 200 void SBCommandReturnObject::AppendMessage(const char *message) { 201 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendMessage, (const char *), 202 message); 203 204 ref().AppendMessage(message); 205 } 206 207 void SBCommandReturnObject::AppendWarning(const char *message) { 208 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendWarning, (const char *), 209 message); 210 211 ref().AppendWarning(message); 212 } 213 214 CommandReturnObject *SBCommandReturnObject::operator->() const { 215 return &**m_opaque_up; 216 } 217 218 CommandReturnObject *SBCommandReturnObject::get() const { 219 return &**m_opaque_up; 220 } 221 222 CommandReturnObject &SBCommandReturnObject::operator*() const { 223 return **m_opaque_up; 224 } 225 226 CommandReturnObject &SBCommandReturnObject::ref() const { 227 return **m_opaque_up; 228 } 229 230 bool SBCommandReturnObject::GetDescription(SBStream &description) { 231 LLDB_RECORD_METHOD(bool, SBCommandReturnObject, GetDescription, 232 (lldb::SBStream &), description); 233 234 Stream &strm = description.ref(); 235 236 description.Printf("Error: "); 237 lldb::ReturnStatus status = ref().GetStatus(); 238 if (status == lldb::eReturnStatusStarted) 239 strm.PutCString("Started"); 240 else if (status == lldb::eReturnStatusInvalid) 241 strm.PutCString("Invalid"); 242 else if (ref().Succeeded()) 243 strm.PutCString("Success"); 244 else 245 strm.PutCString("Fail"); 246 247 if (GetOutputSize() > 0) 248 strm.Printf("\nOutput Message:\n%s", GetOutput()); 249 250 if (GetErrorSize() > 0) 251 strm.Printf("\nError Message:\n%s", GetError()); 252 253 return true; 254 } 255 256 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { 257 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile, 258 (FILE *), fh); 259 260 SetImmediateOutputFile(fh, false); 261 } 262 263 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { 264 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile, 265 (FILE *), fh); 266 267 SetImmediateErrorFile(fh, false); 268 } 269 270 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh, 271 bool transfer_ownership) { 272 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile, 273 (FILE *, bool), fh, transfer_ownership); 274 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); 275 ref().SetImmediateOutputFile(file); 276 } 277 278 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh, 279 bool transfer_ownership) { 280 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile, 281 (FILE *, bool), fh, transfer_ownership); 282 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); 283 ref().SetImmediateErrorFile(file); 284 } 285 286 void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) { 287 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 288 (SBFile), file); 289 ref().SetImmediateOutputFile(file.m_opaque_sp); 290 } 291 292 void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) { 293 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 294 (SBFile), file); 295 ref().SetImmediateErrorFile(file.m_opaque_sp); 296 } 297 298 void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) { 299 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 300 (FileSP), file_sp); 301 SetImmediateOutputFile(SBFile(file_sp)); 302 } 303 304 void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) { 305 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 306 (FileSP), file_sp); 307 SetImmediateErrorFile(SBFile(file_sp)); 308 } 309 310 void SBCommandReturnObject::PutCString(const char *string, int len) { 311 LLDB_RECORD_METHOD(void, SBCommandReturnObject, PutCString, 312 (const char *, int), string, len); 313 314 if (len == 0 || string == nullptr || *string == 0) { 315 return; 316 } else if (len > 0) { 317 std::string buffer(string, len); 318 ref().AppendMessage(buffer.c_str()); 319 } else 320 ref().AppendMessage(string); 321 } 322 323 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) { 324 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetOutput, (bool), 325 only_if_no_immediate); 326 327 if (!only_if_no_immediate || 328 ref().GetImmediateOutputStream().get() == nullptr) 329 return GetOutput(); 330 return nullptr; 331 } 332 333 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) { 334 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetError, (bool), 335 only_if_no_immediate); 336 337 if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr) 338 return GetError(); 339 return nullptr; 340 } 341 342 size_t SBCommandReturnObject::Printf(const char *format, ...) { 343 va_list args; 344 va_start(args, format); 345 size_t result = ref().GetOutputStream().PrintfVarArg(format, args); 346 va_end(args); 347 return result; 348 } 349 350 void SBCommandReturnObject::SetError(lldb::SBError &error, 351 const char *fallback_error_cstr) { 352 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, 353 (lldb::SBError &, const char *), error, 354 fallback_error_cstr); 355 356 if (error.IsValid()) 357 ref().SetError(error.ref(), fallback_error_cstr); 358 else if (fallback_error_cstr) 359 ref().SetError(Status(), fallback_error_cstr); 360 } 361 362 void SBCommandReturnObject::SetError(const char *error_cstr) { 363 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, (const char *), 364 error_cstr); 365 366 if (error_cstr) 367 ref().SetError(error_cstr); 368 } 369 370 namespace lldb_private { 371 namespace repro { 372 373 template <> 374 void RegisterMethods<SBCommandReturnObject>(Registry &R) { 375 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ()); 376 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, 377 (lldb_private::CommandReturnObject &)); 378 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, 379 (const lldb::SBCommandReturnObject &)); 380 LLDB_REGISTER_METHOD( 381 lldb::SBCommandReturnObject &, 382 SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &)); 383 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, IsValid, ()); 384 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, operator bool, ()); 385 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, ()); 386 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, ()); 387 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetOutputSize, ()); 388 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ()); 389 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *)); 390 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *)); 391 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile)); 392 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile)); 393 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP)); 394 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP)); 395 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ()); 396 LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus, 397 ()); 398 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetStatus, 399 (lldb::ReturnStatus)); 400 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, Succeeded, ()); 401 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, HasResult, ()); 402 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendMessage, 403 (const char *)); 404 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendWarning, 405 (const char *)); 406 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, GetDescription, 407 (lldb::SBStream &)); 408 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 409 (FILE *)); 410 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 411 (FILE *)); 412 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 413 (SBFile)); 414 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 415 (SBFile)); 416 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 417 (FileSP)); 418 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 419 (FileSP)); 420 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 421 (FILE *, bool)); 422 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 423 (FILE *, bool)); 424 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, PutCString, 425 (const char *, int)); 426 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, 427 (bool)); 428 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, (bool)); 429 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, 430 (lldb::SBError &, const char *)); 431 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, (const char *)); 432 } 433 434 } 435 } 436