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 "Utils.h"
11 #include "lldb/API/SBError.h"
12 #include "lldb/API/SBStream.h"
13 #include "lldb/Interpreter/CommandReturnObject.h"
14 #include "lldb/Utility/ConstString.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Status.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 SBCommandReturnObject::SBCommandReturnObject()
22     : m_opaque_up(new CommandReturnObject()) {}
23 
24 SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs)
25     : m_opaque_up() {
26   m_opaque_up = clone(rhs.m_opaque_up);
27 }
28 
29 SBCommandReturnObject::SBCommandReturnObject(CommandReturnObject *ptr)
30     : m_opaque_up(ptr) {}
31 
32 SBCommandReturnObject::~SBCommandReturnObject() = default;
33 
34 CommandReturnObject *SBCommandReturnObject::Release() {
35   return m_opaque_up.release();
36 }
37 
38 const SBCommandReturnObject &SBCommandReturnObject::
39 operator=(const SBCommandReturnObject &rhs) {
40   if (this != &rhs)
41     m_opaque_up = clone(rhs.m_opaque_up);
42   return *this;
43 }
44 
45 bool SBCommandReturnObject::IsValid() const { return m_opaque_up != nullptr; }
46 
47 const char *SBCommandReturnObject::GetOutput() {
48   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
49 
50   if (m_opaque_up) {
51     llvm::StringRef output = m_opaque_up->GetOutputData();
52     ConstString result(output.empty() ? llvm::StringRef("") : output);
53 
54     if (log)
55       log->Printf("SBCommandReturnObject(%p)::GetOutput () => \"%s\"",
56                   static_cast<void *>(m_opaque_up.get()), result.AsCString());
57 
58     return result.AsCString();
59   }
60 
61   if (log)
62     log->Printf("SBCommandReturnObject(%p)::GetOutput () => nullptr",
63                 static_cast<void *>(m_opaque_up.get()));
64 
65   return nullptr;
66 }
67 
68 const char *SBCommandReturnObject::GetError() {
69   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
70 
71   if (m_opaque_up) {
72     llvm::StringRef output = m_opaque_up->GetErrorData();
73     ConstString result(output.empty() ? llvm::StringRef("") : output);
74     if (log)
75       log->Printf("SBCommandReturnObject(%p)::GetError () => \"%s\"",
76                   static_cast<void *>(m_opaque_up.get()), result.AsCString());
77 
78     return result.AsCString();
79   }
80 
81   if (log)
82     log->Printf("SBCommandReturnObject(%p)::GetError () => nullptr",
83                 static_cast<void *>(m_opaque_up.get()));
84 
85   return nullptr;
86 }
87 
88 size_t SBCommandReturnObject::GetOutputSize() {
89   return (m_opaque_up ? m_opaque_up->GetOutputData().size() : 0);
90 }
91 
92 size_t SBCommandReturnObject::GetErrorSize() {
93   return (m_opaque_up ? m_opaque_up->GetErrorData().size() : 0);
94 }
95 
96 size_t SBCommandReturnObject::PutOutput(FILE *fh) {
97   if (fh) {
98     size_t num_bytes = GetOutputSize();
99     if (num_bytes)
100       return ::fprintf(fh, "%s", GetOutput());
101   }
102   return 0;
103 }
104 
105 size_t SBCommandReturnObject::PutError(FILE *fh) {
106   if (fh) {
107     size_t num_bytes = GetErrorSize();
108     if (num_bytes)
109       return ::fprintf(fh, "%s", GetError());
110   }
111   return 0;
112 }
113 
114 void SBCommandReturnObject::Clear() {
115   if (m_opaque_up)
116     m_opaque_up->Clear();
117 }
118 
119 lldb::ReturnStatus SBCommandReturnObject::GetStatus() {
120   return (m_opaque_up ? m_opaque_up->GetStatus() : lldb::eReturnStatusInvalid);
121 }
122 
123 void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) {
124   if (m_opaque_up)
125     m_opaque_up->SetStatus(status);
126 }
127 
128 bool SBCommandReturnObject::Succeeded() {
129   return (m_opaque_up ? m_opaque_up->Succeeded() : false);
130 }
131 
132 bool SBCommandReturnObject::HasResult() {
133   return (m_opaque_up ? m_opaque_up->HasResult() : false);
134 }
135 
136 void SBCommandReturnObject::AppendMessage(const char *message) {
137   if (m_opaque_up)
138     m_opaque_up->AppendMessage(message);
139 }
140 
141 void SBCommandReturnObject::AppendWarning(const char *message) {
142   if (m_opaque_up)
143     m_opaque_up->AppendWarning(message);
144 }
145 
146 CommandReturnObject *SBCommandReturnObject::operator->() const {
147   return m_opaque_up.get();
148 }
149 
150 CommandReturnObject *SBCommandReturnObject::get() const {
151   return m_opaque_up.get();
152 }
153 
154 CommandReturnObject &SBCommandReturnObject::operator*() const {
155   assert(m_opaque_up.get());
156   return *(m_opaque_up.get());
157 }
158 
159 CommandReturnObject &SBCommandReturnObject::ref() const {
160   assert(m_opaque_up.get());
161   return *(m_opaque_up.get());
162 }
163 
164 void SBCommandReturnObject::SetLLDBObjectPtr(CommandReturnObject *ptr) {
165   if (m_opaque_up)
166     m_opaque_up.reset(ptr);
167 }
168 
169 bool SBCommandReturnObject::GetDescription(SBStream &description) {
170   Stream &strm = description.ref();
171 
172   if (m_opaque_up) {
173     description.Printf("Error:  ");
174     lldb::ReturnStatus status = m_opaque_up->GetStatus();
175     if (status == lldb::eReturnStatusStarted)
176       strm.PutCString("Started");
177     else if (status == lldb::eReturnStatusInvalid)
178       strm.PutCString("Invalid");
179     else if (m_opaque_up->Succeeded())
180       strm.PutCString("Success");
181     else
182       strm.PutCString("Fail");
183 
184     if (GetOutputSize() > 0)
185       strm.Printf("\nOutput Message:\n%s", GetOutput());
186 
187     if (GetErrorSize() > 0)
188       strm.Printf("\nError Message:\n%s", GetError());
189   } else
190     strm.PutCString("No value");
191 
192   return true;
193 }
194 
195 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) {
196   SetImmediateOutputFile(fh, false);
197 }
198 
199 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) {
200   SetImmediateErrorFile(fh, false);
201 }
202 
203 void SBCommandReturnObject::SetImmediateOutputFile(FILE *fh,
204                                                    bool transfer_ownership) {
205   if (m_opaque_up)
206     m_opaque_up->SetImmediateOutputFile(fh, transfer_ownership);
207 }
208 
209 void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh,
210                                                   bool transfer_ownership) {
211   if (m_opaque_up)
212     m_opaque_up->SetImmediateErrorFile(fh, transfer_ownership);
213 }
214 
215 void SBCommandReturnObject::PutCString(const char *string, int len) {
216   if (m_opaque_up) {
217     if (len == 0 || string == nullptr || *string == 0) {
218       return;
219     } else if (len > 0) {
220       std::string buffer(string, len);
221       m_opaque_up->AppendMessage(buffer.c_str());
222     } else
223       m_opaque_up->AppendMessage(string);
224   }
225 }
226 
227 const char *SBCommandReturnObject::GetOutput(bool only_if_no_immediate) {
228   if (!m_opaque_up)
229     return nullptr;
230   if (!only_if_no_immediate ||
231       m_opaque_up->GetImmediateOutputStream().get() == nullptr)
232     return GetOutput();
233   return nullptr;
234 }
235 
236 const char *SBCommandReturnObject::GetError(bool only_if_no_immediate) {
237   if (!m_opaque_up)
238     return nullptr;
239   if (!only_if_no_immediate ||
240       m_opaque_up->GetImmediateErrorStream().get() == nullptr)
241     return GetError();
242   return nullptr;
243 }
244 
245 size_t SBCommandReturnObject::Printf(const char *format, ...) {
246   if (m_opaque_up) {
247     va_list args;
248     va_start(args, format);
249     size_t result = m_opaque_up->GetOutputStream().PrintfVarArg(format, args);
250     va_end(args);
251     return result;
252   }
253   return 0;
254 }
255 
256 void SBCommandReturnObject::SetError(lldb::SBError &error,
257                                      const char *fallback_error_cstr) {
258   if (m_opaque_up) {
259     if (error.IsValid())
260       m_opaque_up->SetError(error.ref(), fallback_error_cstr);
261     else if (fallback_error_cstr)
262       m_opaque_up->SetError(Status(), fallback_error_cstr);
263   }
264 }
265 
266 void SBCommandReturnObject::SetError(const char *error_cstr) {
267   if (m_opaque_up && error_cstr)
268     m_opaque_up->SetError(error_cstr);
269 }
270