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 "Utils.h" 11 #include "lldb/API/SBError.h" 12 #include "lldb/API/SBFile.h" 13 #include "lldb/API/SBStream.h" 14 #include "lldb/Interpreter/CommandReturnObject.h" 15 #include "lldb/Utility/ConstString.h" 16 #include "lldb/Utility/Instrumentation.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_INSTRUMENT_VA(this); 50 } 51 52 SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject &ref) 53 : m_opaque_up(new SBCommandReturnObjectImpl(ref)) { 54 LLDB_INSTRUMENT_VA(this, ref); 55 } 56 57 SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) { 58 LLDB_INSTRUMENT_VA(this, rhs); 59 60 m_opaque_up = clone(rhs.m_opaque_up); 61 } 62 63 SBCommandReturnObject &SBCommandReturnObject:: 64 operator=(const SBCommandReturnObject &rhs) { 65 LLDB_INSTRUMENT_VA(this, rhs); 66 67 if (this != &rhs) 68 m_opaque_up = clone(rhs.m_opaque_up); 69 return *this; 70 } 71 72 SBCommandReturnObject::~SBCommandReturnObject() = default; 73 74 bool SBCommandReturnObject::IsValid() const { 75 LLDB_INSTRUMENT_VA(this); 76 return this->operator bool(); 77 } 78 SBCommandReturnObject::operator bool() const { 79 LLDB_INSTRUMENT_VA(this); 80 81 // This method is not useful but it needs to stay to keep SB API stable. 82 return true; 83 } 84 85 const char *SBCommandReturnObject::GetOutput() { 86 LLDB_INSTRUMENT_VA(this); 87 88 ConstString output(ref().GetOutputData()); 89 return output.AsCString(/*value_if_empty*/ ""); 90 } 91 92 const char *SBCommandReturnObject::GetError() { 93 LLDB_INSTRUMENT_VA(this); 94 95 ConstString output(ref().GetErrorData()); 96 return output.AsCString(/*value_if_empty*/ ""); 97 } 98 99 size_t SBCommandReturnObject::GetOutputSize() { 100 LLDB_INSTRUMENT_VA(this); 101 102 return ref().GetOutputData().size(); 103 } 104 105 size_t SBCommandReturnObject::GetErrorSize() { 106 LLDB_INSTRUMENT_VA(this); 107 108 return ref().GetErrorData().size(); 109 } 110 111 size_t SBCommandReturnObject::PutOutput(FILE *fh) { 112 LLDB_INSTRUMENT_VA(this, fh); 113 if (fh) { 114 size_t num_bytes = GetOutputSize(); 115 if (num_bytes) 116 return ::fprintf(fh, "%s", GetOutput()); 117 } 118 return 0; 119 } 120 121 size_t SBCommandReturnObject::PutOutput(FileSP file_sp) { 122 LLDB_INSTRUMENT_VA(this, file_sp); 123 if (!file_sp) 124 return 0; 125 return file_sp->Printf("%s", GetOutput()); 126 } 127 128 size_t SBCommandReturnObject::PutOutput(SBFile file) { 129 LLDB_INSTRUMENT_VA(this, file); 130 if (!file.m_opaque_sp) 131 return 0; 132 return file.m_opaque_sp->Printf("%s", GetOutput()); 133 } 134 135 size_t SBCommandReturnObject::PutError(FILE *fh) { 136 LLDB_INSTRUMENT_VA(this, fh); 137 if (fh) { 138 size_t num_bytes = GetErrorSize(); 139 if (num_bytes) 140 return ::fprintf(fh, "%s", GetError()); 141 } 142 return 0; 143 } 144 145 size_t SBCommandReturnObject::PutError(FileSP file_sp) { 146 LLDB_INSTRUMENT_VA(this, file_sp); 147 if (!file_sp) 148 return 0; 149 return file_sp->Printf("%s", GetError()); 150 } 151 152 size_t SBCommandReturnObject::PutError(SBFile file) { 153 LLDB_INSTRUMENT_VA(this, file); 154 if (!file.m_opaque_sp) 155 return 0; 156 return file.m_opaque_sp->Printf("%s", GetError()); 157 } 158 159 void SBCommandReturnObject::Clear() { 160 LLDB_INSTRUMENT_VA(this); 161 162 ref().Clear(); 163 } 164 165 lldb::ReturnStatus SBCommandReturnObject::GetStatus() { 166 LLDB_INSTRUMENT_VA(this); 167 168 return ref().GetStatus(); 169 } 170 171 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) { 172 LLDB_INSTRUMENT_VA(this, status); 173 174 ref().SetStatus(status); 175 } 176 177 bool SBCommandReturnObject::Succeeded() { 178 LLDB_INSTRUMENT_VA(this); 179 180 return ref().Succeeded(); 181 } 182 183 bool SBCommandReturnObject::HasResult() { 184 LLDB_INSTRUMENT_VA(this); 185 186 return ref().HasResult(); 187 } 188 189 void SBCommandReturnObject::AppendMessage(const char *message) { 190 LLDB_INSTRUMENT_VA(this, message); 191 192 ref().AppendMessage(message); 193 } 194 195 void SBCommandReturnObject::AppendWarning(const char *message) { 196 LLDB_INSTRUMENT_VA(this, message); 197 198 ref().AppendWarning(message); 199 } 200 201 CommandReturnObject *SBCommandReturnObject::operator->() const { 202 return &**m_opaque_up; 203 } 204 205 CommandReturnObject *SBCommandReturnObject::get() const { 206 return &**m_opaque_up; 207 } 208 209 CommandReturnObject &SBCommandReturnObject::operator*() const { 210 return **m_opaque_up; 211 } 212 213 CommandReturnObject &SBCommandReturnObject::ref() const { 214 return **m_opaque_up; 215 } 216 217 bool SBCommandReturnObject::GetDescription(SBStream &description) { 218 LLDB_INSTRUMENT_VA(this, description); 219 220 Stream &strm = description.ref(); 221 222 description.Printf("Error: "); 223 lldb::ReturnStatus status = ref().GetStatus(); 224 if (status == lldb::eReturnStatusStarted) 225 strm.PutCString("Started"); 226 else if (status == lldb::eReturnStatusInvalid) 227 strm.PutCString("Invalid"); 228 else if (ref().Succeeded()) 229 strm.PutCString("Success"); 230 else 231 strm.PutCString("Fail"); 232 233 if (GetOutputSize() > 0) 234 strm.Printf("\nOutput Message:\n%s", GetOutput()); 235 236 if (GetErrorSize() > 0) 237 strm.Printf("\nError Message:\n%s", GetError()); 238 239 return true; 240 } 241 242 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { 243 LLDB_INSTRUMENT_VA(this, fh); 244 245 SetImmediateOutputFile(fh, false); 246 } 247 248 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { 249 LLDB_INSTRUMENT_VA(this, fh); 250 251 SetImmediateErrorFile(fh, false); 252 } 253 254 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh, 255 bool transfer_ownership) { 256 LLDB_INSTRUMENT_VA(this, fh, transfer_ownership); 257 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); 258 ref().SetImmediateOutputFile(file); 259 } 260 261 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh, 262 bool transfer_ownership) { 263 LLDB_INSTRUMENT_VA(this, fh, transfer_ownership); 264 FileSP file = std::make_shared<NativeFile>(fh, transfer_ownership); 265 ref().SetImmediateErrorFile(file); 266 } 267 268 void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) { 269 LLDB_INSTRUMENT_VA(this, file); 270 ref().SetImmediateOutputFile(file.m_opaque_sp); 271 } 272 273 void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) { 274 LLDB_INSTRUMENT_VA(this, file); 275 ref().SetImmediateErrorFile(file.m_opaque_sp); 276 } 277 278 void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) { 279 LLDB_INSTRUMENT_VA(this, file_sp); 280 SetImmediateOutputFile(SBFile(file_sp)); 281 } 282 283 void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) { 284 LLDB_INSTRUMENT_VA(this, file_sp); 285 SetImmediateErrorFile(SBFile(file_sp)); 286 } 287 288 void SBCommandReturnObject::PutCString(const char *string, int len) { 289 LLDB_INSTRUMENT_VA(this, string, len); 290 291 if (len == 0 || string == nullptr || *string == 0) { 292 return; 293 } else if (len > 0) { 294 std::string buffer(string, len); 295 ref().AppendMessage(buffer.c_str()); 296 } else 297 ref().AppendMessage(string); 298 } 299 300 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) { 301 LLDB_INSTRUMENT_VA(this, only_if_no_immediate); 302 303 if (!only_if_no_immediate || 304 ref().GetImmediateOutputStream().get() == nullptr) 305 return GetOutput(); 306 return nullptr; 307 } 308 309 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) { 310 LLDB_INSTRUMENT_VA(this, only_if_no_immediate); 311 312 if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr) 313 return GetError(); 314 return nullptr; 315 } 316 317 size_t SBCommandReturnObject::Printf(const char *format, ...) { 318 va_list args; 319 va_start(args, format); 320 size_t result = ref().GetOutputStream().PrintfVarArg(format, args); 321 va_end(args); 322 return result; 323 } 324 325 void SBCommandReturnObject::SetError(lldb::SBError &error, 326 const char *fallback_error_cstr) { 327 LLDB_INSTRUMENT_VA(this, error, fallback_error_cstr); 328 329 if (error.IsValid()) 330 ref().SetError(error.ref(), fallback_error_cstr); 331 else if (fallback_error_cstr) 332 ref().SetError(Status(), fallback_error_cstr); 333 } 334 335 void SBCommandReturnObject::SetError(const char *error_cstr) { 336 LLDB_INSTRUMENT_VA(this, error_cstr); 337 338 if (error_cstr) 339 ref().AppendError(error_cstr); 340 } 341