1 //===-- IOHandler.h ---------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_IOHandler_h_
11 #define liblldb_IOHandler_h_
13 #include "lldb/Core/ValueObjectList.h"
14 #include "lldb/Host/Predicate.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/Flags.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/StringList.h"
19 #include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
20 #include "lldb/lldb-forward.h" // for IOHandlerSP, StreamFileSP
21 #include "llvm/ADT/StringRef.h" // for StringRef
28 #include <stdint.h> // for uint32_t
29 #include <stdio.h> // for FILE
31 namespace lldb_private {
37 typedef std::unique_ptr<Application> ApplicationAP;
40 namespace lldb_private {
57 IOHandler(Debugger &debugger, IOHandler::Type type);
59 IOHandler(Debugger &debugger, IOHandler::Type type,
60 const lldb::StreamFileSP &input_sp,
61 const lldb::StreamFileSP &output_sp,
62 const lldb::StreamFileSP &error_sp, uint32_t flags);
66 // Each IOHandler gets to run until it is done. It should read data
67 // from the "in" and place output into "out" and "err and return
69 virtual void Run() = 0;
71 // Called when an input reader should relinquish its control so another
72 // can be pushed onto the IO handler stack, or so the current IO
73 // handler can pop itself off the stack
75 virtual void Cancel() = 0;
77 // Called when CTRL+C is pressed which usually causes
78 // Debugger::DispatchInputInterrupt to be called.
80 virtual bool Interrupt() = 0;
82 virtual void GotEOF() = 0;
84 virtual bool IsActive() { return m_active && !m_done; }
86 virtual void SetIsDone(bool b) { m_done = b; }
88 virtual bool GetIsDone() { return m_done; }
90 Type GetType() const { return m_type; }
92 virtual void Activate() { m_active = true; }
94 virtual void Deactivate() { m_active = false; }
96 virtual const char *GetPrompt() {
97 // Prompt support isn't mandatory
101 virtual bool SetPrompt(llvm::StringRef prompt) {
102 // Prompt support isn't mandatory
105 bool SetPrompt(const char *) = delete;
107 virtual ConstString GetControlSequence(char ch) { return ConstString(); }
109 virtual const char *GetCommandPrefix() { return nullptr; }
111 virtual const char *GetHelpPrologue() { return nullptr; }
119 FILE *GetInputFILE();
121 FILE *GetOutputFILE();
123 FILE *GetErrorFILE();
125 lldb::StreamFileSP &GetInputStreamFile();
127 lldb::StreamFileSP &GetOutputStreamFile();
129 lldb::StreamFileSP &GetErrorStreamFile();
131 Debugger &GetDebugger() { return m_debugger; }
133 void *GetUserData() { return m_user_data; }
135 void SetUserData(void *user_data) { m_user_data = user_data; }
137 Flags &GetFlags() { return m_flags; }
139 const Flags &GetFlags() const { return m_flags; }
141 //------------------------------------------------------------------
142 /// Check if the input is being supplied interactively by a user
144 /// This will return true if the input stream is a terminal (tty or
145 /// pty) and can cause IO handlers to do different things (like
146 /// for a confirmation when deleting all breakpoints).
147 //------------------------------------------------------------------
148 bool GetIsInteractive();
150 //------------------------------------------------------------------
151 /// Check if the input is coming from a real terminal.
153 /// A real terminal has a valid size with a certain number of rows
154 /// and columns. If this function returns true, then terminal escape
155 /// sequences are expected to work (cursor movement escape sequences,
156 /// clearing lines, etc).
157 //------------------------------------------------------------------
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::StreamFileSP m_input_sp;
172 lldb::StreamFileSP m_output_sp;
173 lldb::StreamFileSP m_error_sp;
174 Predicate<bool> m_popped;
182 DISALLOW_COPY_AND_ASSIGN(IOHandler);
185 //------------------------------------------------------------------
186 /// A delegate class for use with IOHandler subclasses.
188 /// The IOHandler delegate is designed to be mixed into classes so
189 /// they can use an IOHandler subclass to fetch input and notify the
190 /// object that inherits from this delegate class when a token is
192 //------------------------------------------------------------------
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) {}
204 virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
206 virtual int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
207 const char *cursor, const char *last_char,
208 int skip_first_n_matches, int max_matches,
209 StringList &matches);
211 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
213 //------------------------------------------------------------------
214 /// Called when a new line is created or one of an identified set of
215 /// indentation characters is typed.
217 /// This function determines how much indentation should be added
218 /// or removed to match the recommended amount for the final line.
220 /// @param[in] io_handler
221 /// The IOHandler that responsible for input.
224 /// The current input up to the line to be corrected. Lines
225 /// following the line containing the cursor are not included.
227 /// @param[in] cursor_position
228 /// The number of characters preceding the cursor on the final
229 /// line at the time.
232 /// Returns an integer describing the number of spaces needed
233 /// to correct the indentation level. Positive values indicate
234 /// that spaces should be added, while negative values represent
235 /// spaces that should be removed.
236 //------------------------------------------------------------------
237 virtual int IOHandlerFixIndentation(IOHandler &io_handler,
238 const StringList &lines,
239 int cursor_position) {
243 //------------------------------------------------------------------
244 /// Called when a line or lines have been retrieved.
246 /// This function can handle the current line and possibly call
247 /// IOHandler::SetIsDone(true) when the IO handler is done like when
248 /// "quit" is entered as a command, of when an empty line is
249 /// received. It is up to the delegate to determine when a line
250 /// should cause a IOHandler to exit.
251 //------------------------------------------------------------------
252 virtual void IOHandlerInputComplete(IOHandler &io_handler,
253 std::string &data) = 0;
255 virtual void IOHandlerInputInterrupted(IOHandler &io_handler,
256 std::string &data) {}
258 //------------------------------------------------------------------
259 /// Called to determine whether typing enter after the last line in
260 /// \a lines should end input. This function will not be called on
261 /// IOHandler objects that are getting single lines.
262 /// @param[in] io_handler
263 /// The IOHandler that responsible for updating the lines.
266 /// The current multi-line content. May be altered to provide
267 /// alternative input when complete.
270 /// Return an boolean to indicate whether input is complete,
271 /// true indicates that no additional input is necessary, while
272 /// false indicates that more input is required.
273 //------------------------------------------------------------------
274 virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
276 // Impose no requirements for input to be considered
277 // complete. subclasses should do something more intelligent.
281 virtual ConstString IOHandlerGetControlSequence(char ch) {
282 return ConstString();
285 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
287 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
289 //------------------------------------------------------------------
290 // Intercept the IOHandler::Interrupt() calls and do something.
292 // Return true if the interrupt was handled, false if the IOHandler
293 // should continue to try handle the interrupt itself.
294 //------------------------------------------------------------------
295 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
298 Completion m_completion; // Support for common builtin completions
301 //----------------------------------------------------------------------
302 // IOHandlerDelegateMultiline
304 // A IOHandlerDelegate that handles terminating multi-line input when
305 // the last line is equal to "end_line" which is specified in the
307 //----------------------------------------------------------------------
308 class IOHandlerDelegateMultiline : public IOHandlerDelegate {
310 IOHandlerDelegateMultiline(const char *end_line,
311 Completion completion = Completion::None)
312 : IOHandlerDelegate(completion),
313 m_end_line((end_line && end_line[0]) ? end_line : "") {}
315 ~IOHandlerDelegateMultiline() override = default;
317 ConstString IOHandlerGetControlSequence(char ch) override {
319 return ConstString(m_end_line + "\n");
320 return ConstString();
323 bool IOHandlerIsInputComplete(IOHandler &io_handler,
324 StringList &lines) override {
325 // Determine whether the end of input signal has been entered
326 const size_t num_lines = lines.GetSize();
327 if (num_lines > 0 && lines[num_lines - 1] == m_end_line) {
328 // Remove the terminal line from "lines" so it doesn't appear in
329 // the resulting input and return true to indicate we are done
338 const std::string m_end_line;
341 class IOHandlerEditline : public IOHandler {
343 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
344 const char *editline_name, // Used for saving history files
345 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
346 bool multi_line, bool color_prompts,
347 uint32_t line_number_start, // If non-zero show line numbers
349 // 'line_number_start'
350 IOHandlerDelegate &delegate);
352 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
353 const lldb::StreamFileSP &input_sp,
354 const lldb::StreamFileSP &output_sp,
355 const lldb::StreamFileSP &error_sp, uint32_t flags,
356 const char *editline_name, // Used for saving history files
357 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
358 bool multi_line, bool color_prompts,
359 uint32_t line_number_start, // If non-zero show line numbers
361 // 'line_number_start'
362 IOHandlerDelegate &delegate);
364 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *,
365 const char *, bool, bool, uint32_t,
366 IOHandlerDelegate &) = delete;
368 IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::StreamFileSP &,
369 const lldb::StreamFileSP &, const lldb::StreamFileSP &,
370 uint32_t, const char *, const char *, const char *, bool,
371 bool, uint32_t, IOHandlerDelegate &) = delete;
373 ~IOHandlerEditline() override;
377 void Cancel() override;
379 bool Interrupt() override;
381 void GotEOF() override;
383 void Activate() override;
385 void Deactivate() override;
387 ConstString GetControlSequence(char ch) override {
388 return m_delegate.IOHandlerGetControlSequence(ch);
391 const char *GetCommandPrefix() override {
392 return m_delegate.IOHandlerGetCommandPrefix();
395 const char *GetHelpPrologue() override {
396 return m_delegate.IOHandlerGetHelpPrologue();
399 const char *GetPrompt() override;
401 bool SetPrompt(llvm::StringRef prompt) override;
402 bool SetPrompt(const char *prompt) = delete;
404 const char *GetContinuationPrompt();
406 void SetContinuationPrompt(llvm::StringRef prompt);
407 void SetContinuationPrompt(const char *) = delete;
409 bool GetLine(std::string &line, bool &interrupted);
411 bool GetLines(StringList &lines, bool &interrupted);
413 void SetBaseLineNumber(uint32_t line);
415 bool GetInterruptExits() { return m_interrupt_exits; }
417 void SetInterruptExits(bool b) { m_interrupt_exits = b; }
419 const StringList *GetCurrentLines() const { return m_current_lines_ptr; }
421 uint32_t GetCurrentLineIndex() const;
423 void PrintAsync(Stream *stream, const char *s, size_t len) override;
426 #ifndef LLDB_DISABLE_LIBEDIT
427 static bool IsInputCompleteCallback(Editline *editline, StringList &lines,
430 static int FixIndentationCallback(Editline *editline, const StringList &lines,
431 int cursor_position, void *baton);
433 static int AutoCompleteCallback(const char *current_line, const char *cursor,
434 const char *last_char,
435 int skip_first_n_matches, int max_matches,
436 StringList &matches, void *baton);
440 #ifndef LLDB_DISABLE_LIBEDIT
441 std::unique_ptr<Editline> m_editline_ap;
443 IOHandlerDelegate &m_delegate;
444 std::string m_prompt;
445 std::string m_continuation_prompt;
446 StringList *m_current_lines_ptr;
447 uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
448 uint32_t m_curr_line_idx;
450 bool m_color_prompts;
451 bool m_interrupt_exits;
452 bool m_editing; // Set to true when fetching a line manually (not using
456 // The order of base classes is important. Look at the constructor of
459 class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline {
461 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
462 bool default_response);
464 ~IOHandlerConfirm() override;
466 bool GetResponse() const { return m_user_response; }
468 int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
469 const char *cursor, const char *last_char,
470 int skip_first_n_matches, int max_matches,
471 StringList &matches) override;
473 void IOHandlerInputComplete(IOHandler &io_handler,
474 std::string &data) override;
477 const bool m_default_response;
478 bool m_user_response;
481 class IOHandlerCursesGUI : public IOHandler {
483 IOHandlerCursesGUI(Debugger &debugger);
485 ~IOHandlerCursesGUI() override;
489 void Cancel() override;
491 bool Interrupt() override;
493 void GotEOF() override;
495 void Activate() override;
497 void Deactivate() override;
500 curses::ApplicationAP m_app_ap;
503 class IOHandlerCursesValueObjectList : public IOHandler {
505 IOHandlerCursesValueObjectList(Debugger &debugger,
506 ValueObjectList &valobj_list);
508 ~IOHandlerCursesValueObjectList() override;
512 void GotEOF() override;
515 ValueObjectList m_valobj_list;
518 class IOHandlerStack {
520 IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {}
522 ~IOHandlerStack() = default;
524 size_t GetSize() const {
525 std::lock_guard<std::recursive_mutex> guard(m_mutex);
526 return m_stack.size();
529 void Push(const lldb::IOHandlerSP &sp) {
531 std::lock_guard<std::recursive_mutex> guard(m_mutex);
532 sp->SetPopped(false);
533 m_stack.push_back(sp);
534 // Set m_top the non-locking IsTop() call
539 bool IsEmpty() const {
540 std::lock_guard<std::recursive_mutex> guard(m_mutex);
541 return m_stack.empty();
544 lldb::IOHandlerSP Top() {
545 lldb::IOHandlerSP sp;
547 std::lock_guard<std::recursive_mutex> guard(m_mutex);
548 if (!m_stack.empty())
555 std::lock_guard<std::recursive_mutex> guard(m_mutex);
556 if (!m_stack.empty()) {
557 lldb::IOHandlerSP sp(m_stack.back());
561 // Set m_top the non-locking IsTop() call
563 m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
566 std::recursive_mutex &GetMutex() { return m_mutex; }
568 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
569 return m_top == io_handler_sp.get();
572 bool CheckTopIOHandlerTypes(IOHandler::Type top_type,
573 IOHandler::Type second_top_type) {
574 std::lock_guard<std::recursive_mutex> guard(m_mutex);
575 const size_t num_io_handlers = m_stack.size();
576 return (num_io_handlers >= 2 &&
577 m_stack[num_io_handlers - 1]->GetType() == top_type &&
578 m_stack[num_io_handlers - 2]->GetType() == second_top_type);
581 ConstString GetTopIOHandlerControlSequence(char ch) {
582 return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString());
585 const char *GetTopIOHandlerCommandPrefix() {
586 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
589 const char *GetTopIOHandlerHelpPrologue() {
590 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
593 void PrintAsync(Stream *stream, const char *s, size_t len);
596 typedef std::vector<lldb::IOHandlerSP> collection;
598 mutable std::recursive_mutex m_mutex;
602 DISALLOW_COPY_AND_ASSIGN(IOHandlerStack);
605 } // namespace lldb_private
607 #endif // liblldb_IOHandler_h_