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: 24 SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {} 25 SBCommandReturnObjectImpl(CommandReturnObject &ref) 26 : m_ptr(&ref), m_owned(false) {} 27 SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs) 28 : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {} 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. 35 ~SBCommandReturnObjectImpl() { 36 if (m_owned) 37 delete m_ptr; 38 } 39 40 CommandReturnObject &operator*() const { return *m_ptr; } 41 42 private: 43 CommandReturnObject *m_ptr; 44 bool m_owned = true; 45 }; 46 47 SBCommandReturnObject::SBCommandReturnObject() 48 : m_opaque_up(new SBCommandReturnObjectImpl()) { 49 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandReturnObject); 50 } 51 52 SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject &ref) 53 : m_opaque_up(new SBCommandReturnObjectImpl(ref)) { 54 LLDB_RECORD_CONSTRUCTOR(SBCommandReturnObject, 55 (lldb_private::CommandReturnObject &), ref); 56 } 57 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:: 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 80 bool SBCommandReturnObject::IsValid() const { 81 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandReturnObject, IsValid); 82 return this->operator bool(); 83 } 84 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 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 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 105 size_t SBCommandReturnObject::GetOutputSize() { 106 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetOutputSize); 107 108 return ref().GetOutputData().size(); 109 } 110 111 size_t SBCommandReturnObject::GetErrorSize() { 112 LLDB_RECORD_METHOD_NO_ARGS(size_t, SBCommandReturnObject, GetErrorSize); 113 114 return ref().GetErrorData().size(); 115 } 116 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 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 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 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 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 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 167 void SBCommandReturnObject::Clear() { 168 LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear); 169 170 ref().Clear(); 171 } 172 173 lldb::ReturnStatus SBCommandReturnObject::GetStatus() { 174 LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject, 175 GetStatus); 176 177 return ref().GetStatus(); 178 } 179 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 187 bool SBCommandReturnObject::Succeeded() { 188 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded); 189 190 return ref().Succeeded(); 191 } 192 193 bool SBCommandReturnObject::HasResult() { 194 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult); 195 196 return ref().HasResult(); 197 } 198 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 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 213 CommandReturnObject *SBCommandReturnObject::operator->() const { 214 return &**m_opaque_up; 215 } 216 217 CommandReturnObject *SBCommandReturnObject::get() const { 218 return &**m_opaque_up; 219 } 220 221 CommandReturnObject &SBCommandReturnObject::operator*() const { 222 return **m_opaque_up; 223 } 224 225 CommandReturnObject &SBCommandReturnObject::ref() const { 226 return **m_opaque_up; 227 } 228 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 255 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { 256 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateOutputFile, 257 (FILE *), fh); 258 259 SetImmediateOutputFile(fh, false); 260 } 261 262 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { 263 LLDB_RECORD_DUMMY(void, SBCommandReturnObject, SetImmediateErrorFile, 264 (FILE *), fh); 265 266 SetImmediateErrorFile(fh, false); 267 } 268 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 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 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 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 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 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 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 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 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 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 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 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 <> 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