1 //===-- IOHandler.h ---------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_CORE_IOHANDLER_H
10 #define LLDB_CORE_IOHANDLER_H
12 #include "lldb/Core/ValueObjectList.h"
13 #include "lldb/Host/Config.h"
14 #include "lldb/Utility/CompletionRequest.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/Flags.h"
17 #include "lldb/Utility/Predicate.h"
18 #include "lldb/Utility/Reproducer.h"
19 #include "lldb/Utility/Stream.h"
20 #include "lldb/Utility/StringList.h"
21 #include "lldb/lldb-defines.h"
22 #include "lldb/lldb-forward.h"
23 #include "llvm/ADT/StringRef.h"
33 namespace lldb_private {
39 typedef std::unique_ptr<Application> ApplicationAP;
42 namespace lldb_private {
60 IOHandler(Debugger &debugger, IOHandler::Type type);
62 IOHandler(Debugger &debugger, IOHandler::Type type,
63 const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp,
64 const lldb::StreamFileSP &error_sp, uint32_t flags,
65 repro::DataRecorder *data_recorder);
69 // Each IOHandler gets to run until it is done. It should read data from the
70 // "in" and place output into "out" and "err and return when done.
71 virtual void Run() = 0;
73 // Called when an input reader should relinquish its control so another can
74 // be pushed onto the IO handler stack, or so the current IO handler can pop
75 // itself off the stack
77 virtual void Cancel() = 0;
79 // Called when CTRL+C is pressed which usually causes
80 // Debugger::DispatchInputInterrupt to be called.
82 virtual bool Interrupt() = 0;
84 virtual void GotEOF() = 0;
86 virtual bool IsActive() { return m_active && !m_done; }
88 virtual void SetIsDone(bool b) { m_done = b; }
90 virtual bool GetIsDone() { return m_done; }
92 Type GetType() const { return m_type; }
94 virtual void Activate() { m_active = true; }
96 virtual void Deactivate() { m_active = false; }
98 virtual void TerminalSizeChanged() {}
100 virtual const char *GetPrompt() {
101 // Prompt support isn't mandatory
105 virtual bool SetPrompt(llvm::StringRef prompt) {
106 // Prompt support isn't mandatory
109 bool SetPrompt(const char *) = delete;
111 virtual ConstString GetControlSequence(char ch) { return ConstString(); }
113 virtual const char *GetCommandPrefix() { return nullptr; }
115 virtual const char *GetHelpPrologue() { return nullptr; }
123 FILE *GetInputFILE();
125 FILE *GetOutputFILE();
127 FILE *GetErrorFILE();
129 lldb::FileSP &GetInputFileSP();
131 lldb::StreamFileSP &GetOutputStreamFileSP();
133 lldb::StreamFileSP &GetErrorStreamFileSP();
135 Debugger &GetDebugger() { return m_debugger; }
137 void *GetUserData() { return m_user_data; }
139 void SetUserData(void *user_data) { m_user_data = user_data; }
141 Flags &GetFlags() { return m_flags; }
143 const Flags &GetFlags() const { return m_flags; }
145 /// Check if the input is being supplied interactively by a user
147 /// This will return true if the input stream is a terminal (tty or
148 /// pty) and can cause IO handlers to do different things (like
149 /// for a confirmation when deleting all breakpoints).
150 bool GetIsInteractive();
152 /// Check if the input is coming from a real terminal.
154 /// A real terminal has a valid size with a certain number of rows
155 /// and columns. If this function returns true, then terminal escape
156 /// sequences are expected to work (cursor movement escape sequences,
157 /// clearing lines, etc).
158 bool GetIsRealTerminal();
160 void SetPopped(bool b);
164 virtual void PrintAsync(Stream *stream, const char *s, size_t len) {
165 stream->Write(s, len);
170 Debugger &m_debugger;
171 lldb::FileSP m_input_sp;
172 lldb::StreamFileSP m_output_sp;
173 lldb::StreamFileSP m_error_sp;
174 repro::DataRecorder *m_data_recorder;
175 Predicate<bool> m_popped;
183 IOHandler(const IOHandler &) = delete;
184 const IOHandler &operator=(const IOHandler &) = delete;
187 /// A delegate class for use with IOHandler subclasses.
189 /// The IOHandler delegate is designed to be mixed into classes so
190 /// they can use an IOHandler subclass to fetch input and notify the
191 /// object that inherits from this delegate class when a token is
193 class IOHandlerDelegate {
195 enum class Completion { None, LLDBCommand, Expression };
197 IOHandlerDelegate(Completion completion = Completion::None)
198 : m_completion(completion) {}
200 virtual ~IOHandlerDelegate() = default;
202 virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive) {}
204 virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
206 virtual void IOHandlerComplete(IOHandler &io_handler,
207 CompletionRequest &request);
209 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
211 /// Called when a new line is created or one of an identified set of
212 /// indentation characters is typed.
214 /// This function determines how much indentation should be added
215 /// or removed to match the recommended amount for the final line.
217 /// \param[in] io_handler
218 /// The IOHandler that responsible for input.
221 /// The current input up to the line to be corrected. Lines
222 /// following the line containing the cursor are not included.
224 /// \param[in] cursor_position
225 /// The number of characters preceding the cursor on the final
226 /// line at the time.
229 /// Returns an integer describing the number of spaces needed
230 /// to correct the indentation level. Positive values indicate
231 /// that spaces should be added, while negative values represent
232 /// spaces that should be removed.
233 virtual int IOHandlerFixIndentation(IOHandler &io_handler,
234 const StringList &lines,
235 int cursor_position) {
239 /// Called when a line or lines have been retrieved.
241 /// This function can handle the current line and possibly call
242 /// IOHandler::SetIsDone(true) when the IO handler is done like when
243 /// "quit" is entered as a command, of when an empty line is
244 /// received. It is up to the delegate to determine when a line
245 /// should cause a IOHandler to exit.
246 virtual void IOHandlerInputComplete(IOHandler &io_handler,
247 std::string &data) = 0;
249 virtual void IOHandlerInputInterrupted(IOHandler &io_handler,
250 std::string &data) {}
252 /// Called to determine whether typing enter after the last line in
253 /// \a lines should end input. This function will not be called on
254 /// IOHandler objects that are getting single lines.
255 /// \param[in] io_handler
256 /// The IOHandler that responsible for updating the lines.
259 /// The current multi-line content. May be altered to provide
260 /// alternative input when complete.
263 /// Return an boolean to indicate whether input is complete,
264 /// true indicates that no additional input is necessary, while
265 /// false indicates that more input is required.
266 virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
268 // Impose no requirements for input to be considered complete. subclasses
269 // should do something more intelligent.
273 virtual ConstString IOHandlerGetControlSequence(char ch) {
274 return ConstString();
277 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
279 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
281 // Intercept the IOHandler::Interrupt() calls and do something.
283 // Return true if the interrupt was handled, false if the IOHandler should
284 // continue to try handle the interrupt itself.
285 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
288 Completion m_completion; // Support for common builtin completions
291 // IOHandlerDelegateMultiline
293 // A IOHandlerDelegate that handles terminating multi-line input when
294 // the last line is equal to "end_line" which is specified in the constructor.
295 class IOHandlerDelegateMultiline : public IOHandlerDelegate {
297 IOHandlerDelegateMultiline(const char *end_line,
298 Completion completion = Completion::None)
299 : IOHandlerDelegate(completion),
300 m_end_line((end_line && end_line[0]) ? end_line : "") {}
302 ~IOHandlerDelegateMultiline() override = default;
304 ConstString IOHandlerGetControlSequence(char ch) override {
306 return ConstString(m_end_line + "\n");
307 return ConstString();
310 bool IOHandlerIsInputComplete(IOHandler &io_handler,
311 StringList &lines) override {
312 // Determine whether the end of input signal has been entered
313 const size_t num_lines = lines.GetSize();
314 if (num_lines > 0 && lines[num_lines - 1] == m_end_line) {
315 // Remove the terminal line from "lines" so it doesn't appear in the
316 // resulting input and return true to indicate we are done getting lines
324 const std::string m_end_line;
327 class IOHandlerEditline : public IOHandler {
329 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
330 const char *editline_name, // Used for saving history files
331 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
332 bool multi_line, bool color_prompts,
333 uint32_t line_number_start, // If non-zero show line numbers
335 // 'line_number_start'
336 IOHandlerDelegate &delegate,
337 repro::DataRecorder *data_recorder);
339 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
340 const lldb::FileSP &input_sp,
341 const lldb::StreamFileSP &output_sp,
342 const lldb::StreamFileSP &error_sp, uint32_t flags,
343 const char *editline_name, // Used for saving history files
344 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
345 bool multi_line, bool color_prompts,
346 uint32_t line_number_start, // If non-zero show line numbers
348 // 'line_number_start'
349 IOHandlerDelegate &delegate,
350 repro::DataRecorder *data_recorder);
352 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *,
353 const char *, bool, bool, uint32_t,
354 IOHandlerDelegate &) = delete;
356 IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &,
357 const lldb::StreamFileSP &, const lldb::StreamFileSP &,
358 uint32_t, const char *, const char *, const char *, bool,
359 bool, uint32_t, IOHandlerDelegate &) = delete;
361 ~IOHandlerEditline() override;
365 void Cancel() override;
367 bool Interrupt() override;
369 void GotEOF() override;
371 void Activate() override;
373 void Deactivate() override;
375 void TerminalSizeChanged() override;
377 ConstString GetControlSequence(char ch) override {
378 return m_delegate.IOHandlerGetControlSequence(ch);
381 const char *GetCommandPrefix() override {
382 return m_delegate.IOHandlerGetCommandPrefix();
385 const char *GetHelpPrologue() override {
386 return m_delegate.IOHandlerGetHelpPrologue();
389 const char *GetPrompt() override;
391 bool SetPrompt(llvm::StringRef prompt) override;
392 bool SetPrompt(const char *prompt) = delete;
394 const char *GetContinuationPrompt();
396 void SetContinuationPrompt(llvm::StringRef prompt);
397 void SetContinuationPrompt(const char *) = delete;
399 bool GetLine(std::string &line, bool &interrupted);
401 bool GetLines(StringList &lines, bool &interrupted);
403 void SetBaseLineNumber(uint32_t line);
405 bool GetInterruptExits() { return m_interrupt_exits; }
407 void SetInterruptExits(bool b) { m_interrupt_exits = b; }
409 const StringList *GetCurrentLines() const { return m_current_lines_ptr; }
411 uint32_t GetCurrentLineIndex() const;
413 void PrintAsync(Stream *stream, const char *s, size_t len) override;
416 #if LLDB_ENABLE_LIBEDIT
417 static bool IsInputCompleteCallback(Editline *editline, StringList &lines,
420 static int FixIndentationCallback(Editline *editline, const StringList &lines,
421 int cursor_position, void *baton);
423 static void AutoCompleteCallback(CompletionRequest &request, void *baton);
427 #if LLDB_ENABLE_LIBEDIT
428 std::unique_ptr<Editline> m_editline_up;
430 IOHandlerDelegate &m_delegate;
431 std::string m_prompt;
432 std::string m_continuation_prompt;
433 StringList *m_current_lines_ptr;
434 uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
435 uint32_t m_curr_line_idx;
437 bool m_color_prompts;
438 bool m_interrupt_exits;
439 bool m_editing; // Set to true when fetching a line manually (not using
441 std::string m_line_buffer;
444 // The order of base classes is important. Look at the constructor of
445 // IOHandlerConfirm to see how.
446 class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline {
448 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
449 bool default_response);
451 ~IOHandlerConfirm() override;
453 bool GetResponse() const { return m_user_response; }
455 void IOHandlerComplete(IOHandler &io_handler,
456 CompletionRequest &request) override;
458 void IOHandlerInputComplete(IOHandler &io_handler,
459 std::string &data) override;
462 const bool m_default_response;
463 bool m_user_response;
466 class IOHandlerStack {
468 IOHandlerStack() = default;
470 size_t GetSize() const {
471 std::lock_guard<std::recursive_mutex> guard(m_mutex);
472 return m_stack.size();
475 void Push(const lldb::IOHandlerSP &sp) {
477 std::lock_guard<std::recursive_mutex> guard(m_mutex);
478 sp->SetPopped(false);
479 m_stack.push_back(sp);
480 // Set m_top the non-locking IsTop() call
485 bool IsEmpty() const {
486 std::lock_guard<std::recursive_mutex> guard(m_mutex);
487 return m_stack.empty();
490 lldb::IOHandlerSP Top() {
491 lldb::IOHandlerSP sp;
493 std::lock_guard<std::recursive_mutex> guard(m_mutex);
494 if (!m_stack.empty())
501 std::lock_guard<std::recursive_mutex> guard(m_mutex);
502 if (!m_stack.empty()) {
503 lldb::IOHandlerSP sp(m_stack.back());
507 // Set m_top the non-locking IsTop() call
509 m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
512 std::recursive_mutex &GetMutex() { return m_mutex; }
514 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
515 return m_top == io_handler_sp.get();
518 bool CheckTopIOHandlerTypes(IOHandler::Type top_type,
519 IOHandler::Type second_top_type) {
520 std::lock_guard<std::recursive_mutex> guard(m_mutex);
521 const size_t num_io_handlers = m_stack.size();
522 return (num_io_handlers >= 2 &&
523 m_stack[num_io_handlers - 1]->GetType() == top_type &&
524 m_stack[num_io_handlers - 2]->GetType() == second_top_type);
527 ConstString GetTopIOHandlerControlSequence(char ch) {
528 return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString());
531 const char *GetTopIOHandlerCommandPrefix() {
532 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
535 const char *GetTopIOHandlerHelpPrologue() {
536 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
539 void PrintAsync(Stream *stream, const char *s, size_t len);
542 typedef std::vector<lldb::IOHandlerSP> collection;
544 mutable std::recursive_mutex m_mutex;
545 IOHandler *m_top = nullptr;
548 IOHandlerStack(const IOHandlerStack &) = delete;
549 const IOHandlerStack &operator=(const IOHandlerStack &) = delete;
552 } // namespace lldb_private
554 #endif // LLDB_CORE_IOHANDLER_H