1 | //===-- CommandReturnObject.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/Interpreter/CommandReturnObject.h" |
10 | |
11 | #include "lldb/Utility/Status.h" |
12 | #include "lldb/Utility/StreamString.h" |
13 | |
14 | using namespace lldb; |
15 | using namespace lldb_private; |
16 | |
17 | static llvm::raw_ostream &error(Stream &strm) { |
18 | return llvm::WithColor(strm.AsRawOstream(), llvm::HighlightColor::Error, |
19 | llvm::ColorMode::Enable) |
20 | << "error: " ; |
21 | } |
22 | |
23 | static llvm::raw_ostream &warning(Stream &strm) { |
24 | return llvm::WithColor(strm.AsRawOstream(), llvm::HighlightColor::Warning, |
25 | llvm::ColorMode::Enable) |
26 | << "warning: " ; |
27 | } |
28 | |
29 | static void DumpStringToStreamWithNewline(Stream &strm, const std::string &s) { |
30 | bool add_newline = false; |
31 | if (!s.empty()) { |
32 | // We already checked for empty above, now make sure there is a newline in |
33 | // the error, and if there isn't one, add one. |
34 | strm.Write(src: s.c_str(), src_len: s.size()); |
35 | |
36 | const char last_char = *s.rbegin(); |
37 | add_newline = last_char != '\n' && last_char != '\r'; |
38 | } |
39 | if (add_newline) |
40 | strm.EOL(); |
41 | } |
42 | |
43 | CommandReturnObject::CommandReturnObject(bool colors) |
44 | : m_out_stream(colors), m_err_stream(colors) {} |
45 | |
46 | void CommandReturnObject::AppendErrorWithFormat(const char *format, ...) { |
47 | SetStatus(eReturnStatusFailed); |
48 | |
49 | if (!format) |
50 | return; |
51 | va_list args; |
52 | va_start(args, format); |
53 | StreamString sstrm; |
54 | sstrm.PrintfVarArg(format, args); |
55 | va_end(args); |
56 | |
57 | const std::string &s = std::string(sstrm.GetString()); |
58 | if (!s.empty()) { |
59 | error(strm&: GetErrorStream()); |
60 | DumpStringToStreamWithNewline(strm&: GetErrorStream(), s); |
61 | } |
62 | } |
63 | |
64 | void CommandReturnObject::AppendMessageWithFormat(const char *format, ...) { |
65 | if (!format) |
66 | return; |
67 | va_list args; |
68 | va_start(args, format); |
69 | StreamString sstrm; |
70 | sstrm.PrintfVarArg(format, args); |
71 | va_end(args); |
72 | |
73 | GetOutputStream() << sstrm.GetString(); |
74 | } |
75 | |
76 | void CommandReturnObject::AppendWarningWithFormat(const char *format, ...) { |
77 | if (!format) |
78 | return; |
79 | va_list args; |
80 | va_start(args, format); |
81 | StreamString sstrm; |
82 | sstrm.PrintfVarArg(format, args); |
83 | va_end(args); |
84 | |
85 | warning(strm&: GetErrorStream()) << sstrm.GetString(); |
86 | } |
87 | |
88 | void CommandReturnObject::AppendMessage(llvm::StringRef in_string) { |
89 | if (in_string.empty()) |
90 | return; |
91 | GetOutputStream() << in_string.rtrim() << '\n'; |
92 | } |
93 | |
94 | void CommandReturnObject::AppendWarning(llvm::StringRef in_string) { |
95 | if (in_string.empty()) |
96 | return; |
97 | warning(strm&: GetErrorStream()) << in_string.rtrim() << '\n'; |
98 | } |
99 | |
100 | void CommandReturnObject::AppendError(llvm::StringRef in_string) { |
101 | SetStatus(eReturnStatusFailed); |
102 | if (in_string.empty()) |
103 | return; |
104 | // Workaround to deal with already fully formatted compiler diagnostics. |
105 | llvm::StringRef msg(in_string.rtrim()); |
106 | msg.consume_front(Prefix: "error: " ); |
107 | error(strm&: GetErrorStream()) << msg << '\n'; |
108 | } |
109 | |
110 | void CommandReturnObject::SetError(const Status &error, |
111 | const char *fallback_error_cstr) { |
112 | if (error.Fail()) |
113 | AppendError(in_string: error.AsCString(default_error_str: fallback_error_cstr)); |
114 | } |
115 | |
116 | void CommandReturnObject::SetError(llvm::Error error) { |
117 | if (error) |
118 | AppendError(in_string: llvm::toString(E: std::move(error))); |
119 | } |
120 | |
121 | // Similar to AppendError, but do not prepend 'Status: ' to message, and don't |
122 | // append "\n" to the end of it. |
123 | |
124 | void CommandReturnObject::AppendRawError(llvm::StringRef in_string) { |
125 | SetStatus(eReturnStatusFailed); |
126 | assert(!in_string.empty() && "Expected a non-empty error message" ); |
127 | GetErrorStream() << in_string; |
128 | } |
129 | |
130 | void CommandReturnObject::SetStatus(ReturnStatus status) { m_status = status; } |
131 | |
132 | ReturnStatus CommandReturnObject::GetStatus() const { return m_status; } |
133 | |
134 | bool CommandReturnObject::Succeeded() const { |
135 | return m_status <= eReturnStatusSuccessContinuingResult; |
136 | } |
137 | |
138 | bool CommandReturnObject::HasResult() const { |
139 | return (m_status == eReturnStatusSuccessFinishResult || |
140 | m_status == eReturnStatusSuccessContinuingResult); |
141 | } |
142 | |
143 | void CommandReturnObject::Clear() { |
144 | lldb::StreamSP stream_sp; |
145 | stream_sp = m_out_stream.GetStreamAtIndex(idx: eStreamStringIndex); |
146 | if (stream_sp) |
147 | static_cast<StreamString *>(stream_sp.get())->Clear(); |
148 | stream_sp = m_err_stream.GetStreamAtIndex(idx: eStreamStringIndex); |
149 | if (stream_sp) |
150 | static_cast<StreamString *>(stream_sp.get())->Clear(); |
151 | m_status = eReturnStatusStarted; |
152 | m_did_change_process_state = false; |
153 | m_suppress_immediate_output = false; |
154 | m_interactive = true; |
155 | } |
156 | |
157 | bool CommandReturnObject::GetDidChangeProcessState() const { |
158 | return m_did_change_process_state; |
159 | } |
160 | |
161 | void CommandReturnObject::SetDidChangeProcessState(bool b) { |
162 | m_did_change_process_state = b; |
163 | } |
164 | |
165 | bool CommandReturnObject::GetInteractive() const { return m_interactive; } |
166 | |
167 | void CommandReturnObject::SetInteractive(bool b) { m_interactive = b; } |
168 | |
169 | bool CommandReturnObject::GetSuppressImmediateOutput() const { |
170 | return m_suppress_immediate_output; |
171 | } |
172 | |
173 | void CommandReturnObject::SetSuppressImmediateOutput(bool b) { |
174 | m_suppress_immediate_output = b; |
175 | } |
176 | |