380 lines · cpp
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-exception6//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/API/SBStructuredData.h"15#include "lldb/API/SBValue.h"16#include "lldb/API/SBValueList.h"17#include "lldb/Core/StructuredDataImpl.h"18#include "lldb/Host/File.h"19#include "lldb/Interpreter/CommandReturnObject.h"20#include "lldb/Utility/ConstString.h"21#include "lldb/Utility/Instrumentation.h"22#include "lldb/Utility/Status.h"23#include "lldb/lldb-forward.h"24 25using namespace lldb;26using namespace lldb_private;27 28class lldb_private::SBCommandReturnObjectImpl {29public:30 SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {}31 SBCommandReturnObjectImpl(CommandReturnObject &ref)32 : m_ptr(&ref), m_owned(false) {}33 SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs)34 : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {}35 SBCommandReturnObjectImpl &operator=(const SBCommandReturnObjectImpl &rhs) {36 SBCommandReturnObjectImpl copy(rhs);37 std::swap(*this, copy);38 return *this;39 }40 // rvalue ctor+assignment are not used by SBCommandReturnObject.41 ~SBCommandReturnObjectImpl() {42 if (m_owned)43 delete m_ptr;44 }45 46 CommandReturnObject &operator*() const { return *m_ptr; }47 48private:49 CommandReturnObject *m_ptr;50 bool m_owned = true;51};52 53SBCommandReturnObject::SBCommandReturnObject()54 : m_opaque_up(new SBCommandReturnObjectImpl()) {55 LLDB_INSTRUMENT_VA(this);56}57 58SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject &ref)59 : m_opaque_up(new SBCommandReturnObjectImpl(ref)) {60 LLDB_INSTRUMENT_VA(this, ref);61}62 63SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) {64 LLDB_INSTRUMENT_VA(this, rhs);65 66 m_opaque_up = clone(rhs.m_opaque_up);67}68 69SBCommandReturnObject &SBCommandReturnObject::70operator=(const SBCommandReturnObject &rhs) {71 LLDB_INSTRUMENT_VA(this, rhs);72 73 if (this != &rhs)74 m_opaque_up = clone(rhs.m_opaque_up);75 return *this;76}77 78SBCommandReturnObject::~SBCommandReturnObject() = default;79 80bool SBCommandReturnObject::IsValid() const {81 LLDB_INSTRUMENT_VA(this);82 return this->operator bool();83}84SBCommandReturnObject::operator bool() const {85 LLDB_INSTRUMENT_VA(this);86 87 // This method is not useful but it needs to stay to keep SB API stable.88 return true;89}90 91const char *SBCommandReturnObject::GetCommand() {92 LLDB_INSTRUMENT_VA(this);93 94 ConstString output(ref().GetCommand());95 return output.AsCString(/*value_if_empty*/ "");96}97 98const char *SBCommandReturnObject::GetOutput() {99 LLDB_INSTRUMENT_VA(this);100 101 ConstString output(ref().GetOutputString());102 return output.AsCString(/*value_if_empty*/ "");103}104 105const char *SBCommandReturnObject::GetError() {106 LLDB_INSTRUMENT_VA(this);107 108 ConstString output(ref().GetErrorString());109 return output.AsCString(/*value_if_empty*/ "");110}111 112SBStructuredData SBCommandReturnObject::GetErrorData() {113 LLDB_INSTRUMENT_VA(this);114 115 StructuredData::ObjectSP data(ref().GetErrorData());116 SBStructuredData sb_data;117 sb_data.m_impl_up->SetObjectSP(data);118 return sb_data;119}120 121size_t SBCommandReturnObject::GetOutputSize() {122 LLDB_INSTRUMENT_VA(this);123 124 return ref().GetOutputString().size();125}126 127size_t SBCommandReturnObject::GetErrorSize() {128 LLDB_INSTRUMENT_VA(this);129 130 return ref().GetErrorString().size();131}132 133size_t SBCommandReturnObject::PutOutput(FILE *fh) {134 LLDB_INSTRUMENT_VA(this, fh);135 if (fh) {136 size_t num_bytes = GetOutputSize();137 if (num_bytes)138 return ::fprintf(fh, "%s", GetOutput());139 }140 return 0;141}142 143size_t SBCommandReturnObject::PutOutput(FileSP file_sp) {144 LLDB_INSTRUMENT_VA(this, file_sp);145 if (!file_sp)146 return 0;147 return file_sp->Printf("%s", GetOutput());148}149 150size_t SBCommandReturnObject::PutOutput(SBFile file) {151 LLDB_INSTRUMENT_VA(this, file);152 if (!file.m_opaque_sp)153 return 0;154 return file.m_opaque_sp->Printf("%s", GetOutput());155}156 157size_t SBCommandReturnObject::PutError(FILE *fh) {158 LLDB_INSTRUMENT_VA(this, fh);159 if (fh) {160 size_t num_bytes = GetErrorSize();161 if (num_bytes)162 return ::fprintf(fh, "%s", GetError());163 }164 return 0;165}166 167size_t SBCommandReturnObject::PutError(FileSP file_sp) {168 LLDB_INSTRUMENT_VA(this, file_sp);169 if (!file_sp)170 return 0;171 return file_sp->Printf("%s", GetError());172}173 174size_t SBCommandReturnObject::PutError(SBFile file) {175 LLDB_INSTRUMENT_VA(this, file);176 if (!file.m_opaque_sp)177 return 0;178 return file.m_opaque_sp->Printf("%s", GetError());179}180 181void SBCommandReturnObject::Clear() {182 LLDB_INSTRUMENT_VA(this);183 184 ref().Clear();185}186 187lldb::ReturnStatus SBCommandReturnObject::GetStatus() {188 LLDB_INSTRUMENT_VA(this);189 190 return ref().GetStatus();191}192 193void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) {194 LLDB_INSTRUMENT_VA(this, status);195 196 ref().SetStatus(status);197}198 199bool SBCommandReturnObject::Succeeded() {200 LLDB_INSTRUMENT_VA(this);201 202 return ref().Succeeded();203}204 205bool SBCommandReturnObject::HasResult() {206 LLDB_INSTRUMENT_VA(this);207 208 return ref().HasResult();209}210 211void SBCommandReturnObject::AppendMessage(const char *message) {212 LLDB_INSTRUMENT_VA(this, message);213 214 ref().AppendMessage(message);215}216 217void SBCommandReturnObject::AppendWarning(const char *message) {218 LLDB_INSTRUMENT_VA(this, message);219 220 ref().AppendWarning(message);221}222 223CommandReturnObject *SBCommandReturnObject::operator->() const {224 return &**m_opaque_up;225}226 227CommandReturnObject *SBCommandReturnObject::get() const {228 return &**m_opaque_up;229}230 231CommandReturnObject &SBCommandReturnObject::operator*() const {232 return **m_opaque_up;233}234 235CommandReturnObject &SBCommandReturnObject::ref() const {236 return **m_opaque_up;237}238 239bool SBCommandReturnObject::GetDescription(SBStream &description) {240 LLDB_INSTRUMENT_VA(this, description);241 242 Stream &strm = description.ref();243 244 description.Printf("Error: ");245 lldb::ReturnStatus status = ref().GetStatus();246 if (status == lldb::eReturnStatusStarted)247 strm.PutCString("Started");248 else if (status == lldb::eReturnStatusInvalid)249 strm.PutCString("Invalid");250 else if (ref().Succeeded())251 strm.PutCString("Success");252 else253 strm.PutCString("Fail");254 255 if (GetOutputSize() > 0)256 strm.Printf("\nOutput Message:\n%s", GetOutput());257 258 if (GetErrorSize() > 0)259 strm.Printf("\nError Message:\n%s", GetError());260 261 return true;262}263 264void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) {265 LLDB_INSTRUMENT_VA(this, fh);266 267 SetImmediateOutputFile(fh, false);268}269 270void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {271 LLDB_INSTRUMENT_VA(this, fh);272 273 SetImmediateErrorFile(fh, false);274}275 276void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,277 bool transfer_ownership) {278 LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);279 FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,280 transfer_ownership);281 ref().SetImmediateOutputFile(file);282}283 284void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,285 bool transfer_ownership) {286 LLDB_INSTRUMENT_VA(this, fh, transfer_ownership);287 FileSP file = std::make_shared<NativeFile>(fh, File::eOpenOptionWriteOnly,288 transfer_ownership);289 ref().SetImmediateErrorFile(file);290}291 292void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) {293 LLDB_INSTRUMENT_VA(this, file);294 ref().SetImmediateOutputFile(file.m_opaque_sp);295}296 297void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) {298 LLDB_INSTRUMENT_VA(this, file);299 ref().SetImmediateErrorFile(file.m_opaque_sp);300}301 302void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) {303 LLDB_INSTRUMENT_VA(this, file_sp);304 SetImmediateOutputFile(SBFile(file_sp));305}306 307void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) {308 LLDB_INSTRUMENT_VA(this, file_sp);309 SetImmediateErrorFile(SBFile(file_sp));310}311 312void SBCommandReturnObject::PutCString(const char *string, int len) {313 LLDB_INSTRUMENT_VA(this, 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 } else321 ref().AppendMessage(string);322}323 324const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) {325 LLDB_INSTRUMENT_VA(this, only_if_no_immediate);326 327 if (!only_if_no_immediate ||328 ref().GetImmediateOutputStream().get() == nullptr)329 return GetOutput();330 return nullptr;331}332 333const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) {334 LLDB_INSTRUMENT_VA(this, only_if_no_immediate);335 336 if (!only_if_no_immediate || ref().GetImmediateErrorStream().get() == nullptr)337 return GetError();338 return nullptr;339}340 341size_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 349void SBCommandReturnObject::SetError(lldb::SBError &error,350 const char *fallback_error_cstr) {351 LLDB_INSTRUMENT_VA(this, error, fallback_error_cstr);352 353 if (error.IsValid() && !error.Fail())354 ref().SetError(error.ref().Clone());355 else if (fallback_error_cstr)356 ref().SetError(Status::FromErrorString(fallback_error_cstr));357}358 359void SBCommandReturnObject::SetError(const char *error_cstr) {360 LLDB_INSTRUMENT_VA(this, error_cstr);361 362 if (error_cstr)363 ref().AppendError(error_cstr);364}365 366SBValueList367SBCommandReturnObject::GetValues(lldb::DynamicValueType use_dynamic) {368 LLDB_INSTRUMENT_VA(this, use_dynamic);369 370 SBValueList value_list;371 for (ValueObjectSP value_object_sp :372 ref().GetValueObjectList().GetObjects()) {373 SBValue value_sb;374 value_sb.SetSP(value_object_sp, use_dynamic);375 value_list.Append(value_sb);376 }377 378 return value_list;379}380