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/SBStream.h" 14 #include "lldb/Interpreter/CommandReturnObject.h" 15 #include "lldb/Utility/ConstString.h" 16 #include "lldb/Utility/Status.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 class lldb_private::SBCommandReturnObjectImpl { 22 public: 23 SBCommandReturnObjectImpl() 24 : m_ptr(new CommandReturnObject()), m_owned(true) {} 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; 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_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh); 119 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::PutError(FILE *fh) { 129 LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *), fh); 130 131 if (fh) { 132 size_t num_bytes = GetErrorSize(); 133 if (num_bytes) 134 return ::fprintf(fh, "%s", GetError()); 135 } 136 return 0; 137 } 138 139 void SBCommandReturnObject::Clear() { 140 LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear); 141 142 ref().Clear(); 143 } 144 145 lldb::ReturnStatus SBCommandReturnObject::GetStatus() { 146 LLDB_RECORD_METHOD_NO_ARGS(lldb::ReturnStatus, SBCommandReturnObject, 147 GetStatus); 148 149 return ref().GetStatus(); 150 } 151 152 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) { 153 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetStatus, 154 (lldb::ReturnStatus), status); 155 156 ref().SetStatus(status); 157 } 158 159 bool SBCommandReturnObject::Succeeded() { 160 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, Succeeded); 161 162 return ref().Succeeded(); 163 } 164 165 bool SBCommandReturnObject::HasResult() { 166 LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandReturnObject, HasResult); 167 168 return ref().HasResult(); 169 } 170 171 void SBCommandReturnObject::AppendMessage(const char *message) { 172 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendMessage, (const char *), 173 message); 174 175 ref().AppendMessage(message); 176 } 177 178 void SBCommandReturnObject::AppendWarning(const char *message) { 179 LLDB_RECORD_METHOD(void, SBCommandReturnObject, AppendWarning, (const char *), 180 message); 181 182 ref().AppendWarning(message); 183 } 184 185 CommandReturnObject *SBCommandReturnObject::operator->() const { 186 return &**m_opaque_up; 187 } 188 189 CommandReturnObject *SBCommandReturnObject::get() const { 190 return &**m_opaque_up; 191 } 192 193 CommandReturnObject &SBCommandReturnObject::operator*() const { 194 return **m_opaque_up; 195 } 196 197 CommandReturnObject &SBCommandReturnObject::ref() const { 198 return **m_opaque_up; 199 } 200 201 bool SBCommandReturnObject::GetDescription(SBStream &description) { 202 LLDB_RECORD_METHOD(bool, SBCommandReturnObject, GetDescription, 203 (lldb::SBStream &), description); 204 205 Stream &strm = description.ref(); 206 207 description.Printf("Error: "); 208 lldb::ReturnStatus status = ref().GetStatus(); 209 if (status == lldb::eReturnStatusStarted) 210 strm.PutCString("Started"); 211 else if (status == lldb::eReturnStatusInvalid) 212 strm.PutCString("Invalid"); 213 else if (ref().Succeeded()) 214 strm.PutCString("Success"); 215 else 216 strm.PutCString("Fail"); 217 218 if (GetOutputSize() > 0) 219 strm.Printf("\nOutput Message:\n%s", GetOutput()); 220 221 if (GetErrorSize() > 0) 222 strm.Printf("\nError Message:\n%s", GetError()); 223 224 return true; 225 } 226 227 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { 228 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 229 (FILE *), fh); 230 231 SetImmediateOutputFile(fh, false); 232 } 233 234 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { 235 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 236 (FILE *), fh); 237 238 SetImmediateErrorFile(fh, false); 239 } 240 241 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh, 242 bool transfer_ownership) { 243 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 244 (FILE *, bool), fh, transfer_ownership); 245 246 ref().SetImmediateOutputFile(fh, transfer_ownership); 247 } 248 249 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh, 250 bool transfer_ownership) { 251 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 252 (FILE *, bool), fh, transfer_ownership); 253 254 ref().SetImmediateErrorFile(fh, transfer_ownership); 255 } 256 257 void SBCommandReturnObject::PutCString(const char *string, int len) { 258 LLDB_RECORD_METHOD(void, SBCommandReturnObject, PutCString, 259 (const char *, int), string, len); 260 261 if (len == 0 || string == nullptr || *string == 0) { 262 return; 263 } else if (len > 0) { 264 std::string buffer(string, len); 265 ref().AppendMessage(buffer.c_str()); 266 } else 267 ref().AppendMessage(string); 268 } 269 270 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) { 271 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetOutput, (bool), 272 only_if_no_immediate); 273 274 if (!only_if_no_immediate || 275 ref().GetImmediateOutputStream().get() == nullptr) 276 return GetOutput(); 277 return nullptr; 278 } 279 280 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) { 281 LLDB_RECORD_METHOD(const char *, SBCommandReturnObject, GetError, (bool), 282 only_if_no_immediate); 283 284 if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr) 285 return GetError(); 286 return nullptr; 287 } 288 289 size_t SBCommandReturnObject::Printf(const char *format, ...) { 290 va_list args; 291 va_start(args, format); 292 size_t result = ref().GetOutputStream().PrintfVarArg(format, args); 293 va_end(args); 294 return result; 295 } 296 297 void SBCommandReturnObject::SetError(lldb::SBError &error, 298 const char *fallback_error_cstr) { 299 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, 300 (lldb::SBError &, const char *), error, 301 fallback_error_cstr); 302 303 if (error.IsValid()) 304 ref().SetError(error.ref(), fallback_error_cstr); 305 else if (fallback_error_cstr) 306 ref().SetError(Status(), fallback_error_cstr); 307 } 308 309 void SBCommandReturnObject::SetError(const char *error_cstr) { 310 LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetError, (const char *), 311 error_cstr); 312 313 if (error_cstr) 314 ref().SetError(error_cstr); 315 } 316 317 namespace lldb_private { 318 namespace repro { 319 320 template <> 321 void RegisterMethods<SBCommandReturnObject>(Registry &R) { 322 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, ()); 323 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, 324 (lldb_private::CommandReturnObject &)); 325 LLDB_REGISTER_CONSTRUCTOR(SBCommandReturnObject, 326 (const lldb::SBCommandReturnObject &)); 327 LLDB_REGISTER_METHOD( 328 lldb::SBCommandReturnObject &, 329 SBCommandReturnObject, operator=,(const lldb::SBCommandReturnObject &)); 330 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, IsValid, ()); 331 LLDB_REGISTER_METHOD_CONST(bool, SBCommandReturnObject, operator bool, ()); 332 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, ()); 333 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, ()); 334 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetOutputSize, ()); 335 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ()); 336 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *)); 337 LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *)); 338 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ()); 339 LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus, 340 ()); 341 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetStatus, 342 (lldb::ReturnStatus)); 343 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, Succeeded, ()); 344 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, HasResult, ()); 345 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendMessage, 346 (const char *)); 347 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, AppendWarning, 348 (const char *)); 349 LLDB_REGISTER_METHOD(bool, SBCommandReturnObject, GetDescription, 350 (lldb::SBStream &)); 351 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 352 (FILE *)); 353 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 354 (FILE *)); 355 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, 356 (FILE *, bool)); 357 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, 358 (FILE *, bool)); 359 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, PutCString, 360 (const char *, int)); 361 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetOutput, 362 (bool)); 363 LLDB_REGISTER_METHOD(const char *, SBCommandReturnObject, GetError, (bool)); 364 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, 365 (lldb::SBError &, const char *)); 366 LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetError, (const char *)); 367 } 368 369 } 370 } 371