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/Utility/ConstString.h"
15 #include "lldb/Utility/Flags.h"
16 #include "lldb/Utility/Predicate.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/Utility/StringList.h"
19 #include "lldb/lldb-defines.h"
20 #include "lldb/lldb-forward.h"
21 #include "llvm/ADT/StringRef.h"
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 from the
67 // "in" and place output into "out" and "err and return when done.
68 virtual void Run() = 0;
70 // Called when an input reader should relinquish its control so another can
71 // be pushed onto the IO handler stack, or so the current IO handler can pop
72 // itself off the stack
74 virtual void Cancel() = 0;
76 // Called when CTRL+C is pressed which usually causes
77 // Debugger::DispatchInputInterrupt to be called.
79 virtual bool Interrupt() = 0;
81 virtual void GotEOF() = 0;
83 virtual bool IsActive() { return m_active && !m_done; }
85 virtual void SetIsDone(bool b) { m_done = b; }
87 virtual bool GetIsDone() { return m_done; }
89 Type GetType() const { return m_type; }
91 virtual void Activate() { m_active = true; }
93 virtual void Deactivate() { m_active = false; }
95 virtual const char *GetPrompt() {
96 // Prompt support isn't mandatory
100 virtual bool SetPrompt(llvm::StringRef prompt) {
101 // Prompt support isn't mandatory
104 bool SetPrompt(const char *) = delete;
106 virtual ConstString GetControlSequence(char ch) { return ConstString(); }
108 virtual const char *GetCommandPrefix() { return nullptr; }
110 virtual const char *GetHelpPrologue() { return nullptr; }
118 FILE *GetInputFILE();
120 FILE *GetOutputFILE();
122 FILE *GetErrorFILE();
124 lldb::StreamFileSP &GetInputStreamFile();
126 lldb::StreamFileSP &GetOutputStreamFile();
128 lldb::StreamFileSP &GetErrorStreamFile();
130 Debugger &GetDebugger() { return m_debugger; }
132 void *GetUserData() { return m_user_data; }
134 void SetUserData(void *user_data) { m_user_data = user_data; }
136 Flags &GetFlags() { return m_flags; }
138 const Flags &GetFlags() const { return m_flags; }
140 //------------------------------------------------------------------
141 /// Check if the input is being supplied interactively by a user
143 /// This will return true if the input stream is a terminal (tty or
144 /// pty) and can cause IO handlers to do different things (like
145 /// for a confirmation when deleting all breakpoints).
146 //------------------------------------------------------------------
147 bool GetIsInteractive();
149 //------------------------------------------------------------------
150 /// Check if the input is coming from a real terminal.
152 /// A real terminal has a valid size with a certain number of rows
153 /// and columns. If this function returns true, then terminal escape
154 /// sequences are expected to work (cursor movement escape sequences,
155 /// clearing lines, etc).
156 //------------------------------------------------------------------
157 bool GetIsRealTerminal();
159 void SetPopped(bool b);
163 virtual void PrintAsync(Stream *stream, const char *s, size_t len) {
164 stream->Write(s, len);
169 Debugger &m_debugger;
170 lldb::StreamFileSP m_input_sp;
171 lldb::StreamFileSP m_output_sp;
172 lldb::StreamFileSP m_error_sp;
173 Predicate<bool> m_popped;
181 DISALLOW_COPY_AND_ASSIGN(IOHandler);
184 //------------------------------------------------------------------
185 /// A delegate class for use with IOHandler subclasses.
187 /// The IOHandler delegate is designed to be mixed into classes so
188 /// they can use an IOHandler subclass to fetch input and notify the
189 /// object that inherits from this delegate class when a token is
191 //------------------------------------------------------------------
192 class IOHandlerDelegate {
194 enum class Completion { None, LLDBCommand, Expression };
196 IOHandlerDelegate(Completion completion = Completion::None)
197 : m_completion(completion) {}
199 virtual ~IOHandlerDelegate() = default;
201 virtual void IOHandlerActivated(IOHandler &io_handler) {}
203 virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
205 virtual int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
206 const char *cursor, const char *last_char,
207 int skip_first_n_matches, int max_matches,
208 StringList &matches, StringList &descriptions);
210 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
212 //------------------------------------------------------------------
213 /// Called when a new line is created or one of an identified set of
214 /// indentation characters is typed.
216 /// This function determines how much indentation should be added
217 /// or removed to match the recommended amount for the final line.
219 /// @param[in] io_handler
220 /// The IOHandler that responsible for input.
223 /// The current input up to the line to be corrected. Lines
224 /// following the line containing the cursor are not included.
226 /// @param[in] cursor_position
227 /// The number of characters preceding the cursor on the final
228 /// line at the time.
231 /// Returns an integer describing the number of spaces needed
232 /// to correct the indentation level. Positive values indicate
233 /// that spaces should be added, while negative values represent
234 /// spaces that should be removed.
235 //------------------------------------------------------------------
236 virtual int IOHandlerFixIndentation(IOHandler &io_handler,
237 const StringList &lines,
238 int cursor_position) {
242 //------------------------------------------------------------------
243 /// Called when a line or lines have been retrieved.
245 /// This function can handle the current line and possibly call
246 /// IOHandler::SetIsDone(true) when the IO handler is done like when
247 /// "quit" is entered as a command, of when an empty line is
248 /// received. It is up to the delegate to determine when a line
249 /// should cause a IOHandler to exit.
250 //------------------------------------------------------------------
251 virtual void IOHandlerInputComplete(IOHandler &io_handler,
252 std::string &data) = 0;
254 virtual void IOHandlerInputInterrupted(IOHandler &io_handler,
255 std::string &data) {}
257 //------------------------------------------------------------------
258 /// Called to determine whether typing enter after the last line in
259 /// \a lines should end input. This function will not be called on
260 /// IOHandler objects that are getting single lines.
261 /// @param[in] io_handler
262 /// The IOHandler that responsible for updating the lines.
265 /// The current multi-line content. May be altered to provide
266 /// alternative input when complete.
269 /// Return an boolean to indicate whether input is complete,
270 /// true indicates that no additional input is necessary, while
271 /// false indicates that more input is required.
272 //------------------------------------------------------------------
273 virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
275 // Impose no requirements for input to be considered complete. subclasses
276 // should do something more intelligent.
280 virtual ConstString IOHandlerGetControlSequence(char ch) {
281 return ConstString();
284 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
286 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
288 //------------------------------------------------------------------
289 // Intercept the IOHandler::Interrupt() calls and do something.
291 // Return true if the interrupt was handled, false if the IOHandler should
292 // continue to try handle the interrupt itself.
293 //------------------------------------------------------------------
294 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
297 Completion m_completion; // Support for common builtin completions
300 //----------------------------------------------------------------------
301 // IOHandlerDelegateMultiline
303 // A IOHandlerDelegate that handles terminating multi-line input when
304 // the last line is equal to "end_line" which is specified in the constructor.
305 //----------------------------------------------------------------------
306 class IOHandlerDelegateMultiline : public IOHandlerDelegate {
308 IOHandlerDelegateMultiline(const char *end_line,
309 Completion completion = Completion::None)
310 : IOHandlerDelegate(completion),
311 m_end_line((end_line && end_line[0]) ? end_line : "") {}
313 ~IOHandlerDelegateMultiline() override = default;
315 ConstString IOHandlerGetControlSequence(char ch) override {
317 return ConstString(m_end_line + "\n");
318 return ConstString();
321 bool IOHandlerIsInputComplete(IOHandler &io_handler,
322 StringList &lines) override {
323 // Determine whether the end of input signal has been entered
324 const size_t num_lines = lines.GetSize();
325 if (num_lines > 0 && lines[num_lines - 1] == m_end_line) {
326 // Remove the terminal line from "lines" so it doesn't appear in the
327 // resulting input and return true to indicate we are done getting lines
335 const std::string m_end_line;
338 class IOHandlerEditline : public IOHandler {
340 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
341 const char *editline_name, // Used for saving history files
342 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
343 bool multi_line, bool color_prompts,
344 uint32_t line_number_start, // If non-zero show line numbers
346 // 'line_number_start'
347 IOHandlerDelegate &delegate);
349 IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
350 const lldb::StreamFileSP &input_sp,
351 const lldb::StreamFileSP &output_sp,
352 const lldb::StreamFileSP &error_sp, uint32_t flags,
353 const char *editline_name, // Used for saving history files
354 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
355 bool multi_line, bool color_prompts,
356 uint32_t line_number_start, // If non-zero show line numbers
358 // 'line_number_start'
359 IOHandlerDelegate &delegate);
361 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *,
362 const char *, bool, bool, uint32_t,
363 IOHandlerDelegate &) = delete;
365 IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::StreamFileSP &,
366 const lldb::StreamFileSP &, const lldb::StreamFileSP &,
367 uint32_t, const char *, const char *, const char *, bool,
368 bool, uint32_t, IOHandlerDelegate &) = delete;
370 ~IOHandlerEditline() override;
374 void Cancel() override;
376 bool Interrupt() override;
378 void GotEOF() override;
380 void Activate() override;
382 void Deactivate() override;
384 ConstString GetControlSequence(char ch) override {
385 return m_delegate.IOHandlerGetControlSequence(ch);
388 const char *GetCommandPrefix() override {
389 return m_delegate.IOHandlerGetCommandPrefix();
392 const char *GetHelpPrologue() override {
393 return m_delegate.IOHandlerGetHelpPrologue();
396 const char *GetPrompt() override;
398 bool SetPrompt(llvm::StringRef prompt) override;
399 bool SetPrompt(const char *prompt) = delete;
401 const char *GetContinuationPrompt();
403 void SetContinuationPrompt(llvm::StringRef prompt);
404 void SetContinuationPrompt(const char *) = delete;
406 bool GetLine(std::string &line, bool &interrupted);
408 bool GetLines(StringList &lines, bool &interrupted);
410 void SetBaseLineNumber(uint32_t line);
412 bool GetInterruptExits() { return m_interrupt_exits; }
414 void SetInterruptExits(bool b) { m_interrupt_exits = b; }
416 const StringList *GetCurrentLines() const { return m_current_lines_ptr; }
418 uint32_t GetCurrentLineIndex() const;
420 void PrintAsync(Stream *stream, const char *s, size_t len) override;
423 #ifndef LLDB_DISABLE_LIBEDIT
424 static bool IsInputCompleteCallback(Editline *editline, StringList &lines,
427 static int FixIndentationCallback(Editline *editline, const StringList &lines,
428 int cursor_position, void *baton);
430 static int AutoCompleteCallback(const char *current_line, const char *cursor,
431 const char *last_char,
432 int skip_first_n_matches, int max_matches,
433 StringList &matches, StringList &descriptions,
438 #ifndef LLDB_DISABLE_LIBEDIT
439 std::unique_ptr<Editline> m_editline_ap;
441 IOHandlerDelegate &m_delegate;
442 std::string m_prompt;
443 std::string m_continuation_prompt;
444 StringList *m_current_lines_ptr;
445 uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
446 uint32_t m_curr_line_idx;
448 bool m_color_prompts;
449 bool m_interrupt_exits;
450 bool m_editing; // Set to true when fetching a line manually (not using
454 // The order of base classes is important. Look at the constructor of
455 // IOHandlerConfirm to see how.
456 class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline {
458 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
459 bool default_response);
461 ~IOHandlerConfirm() override;
463 bool GetResponse() const { return m_user_response; }
465 int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
466 const char *cursor, const char *last_char,
467 int skip_first_n_matches, int max_matches,
468 StringList &matches, StringList &descriptions) override;
470 void IOHandlerInputComplete(IOHandler &io_handler,
471 std::string &data) override;
474 const bool m_default_response;
475 bool m_user_response;
478 class IOHandlerCursesGUI : public IOHandler {
480 IOHandlerCursesGUI(Debugger &debugger);
482 ~IOHandlerCursesGUI() override;
486 void Cancel() override;
488 bool Interrupt() override;
490 void GotEOF() override;
492 void Activate() override;
494 void Deactivate() override;
497 curses::ApplicationAP m_app_ap;
500 class IOHandlerCursesValueObjectList : public IOHandler {
502 IOHandlerCursesValueObjectList(Debugger &debugger,
503 ValueObjectList &valobj_list);
505 ~IOHandlerCursesValueObjectList() override;
509 void GotEOF() override;
512 ValueObjectList m_valobj_list;
515 class IOHandlerStack {
517 IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {}
519 ~IOHandlerStack() = default;
521 size_t GetSize() const {
522 std::lock_guard<std::recursive_mutex> guard(m_mutex);
523 return m_stack.size();
526 void Push(const lldb::IOHandlerSP &sp) {
528 std::lock_guard<std::recursive_mutex> guard(m_mutex);
529 sp->SetPopped(false);
530 m_stack.push_back(sp);
531 // Set m_top the non-locking IsTop() call
536 bool IsEmpty() const {
537 std::lock_guard<std::recursive_mutex> guard(m_mutex);
538 return m_stack.empty();
541 lldb::IOHandlerSP Top() {
542 lldb::IOHandlerSP sp;
544 std::lock_guard<std::recursive_mutex> guard(m_mutex);
545 if (!m_stack.empty())
552 std::lock_guard<std::recursive_mutex> guard(m_mutex);
553 if (!m_stack.empty()) {
554 lldb::IOHandlerSP sp(m_stack.back());
558 // Set m_top the non-locking IsTop() call
560 m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
563 std::recursive_mutex &GetMutex() { return m_mutex; }
565 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
566 return m_top == io_handler_sp.get();
569 bool CheckTopIOHandlerTypes(IOHandler::Type top_type,
570 IOHandler::Type second_top_type) {
571 std::lock_guard<std::recursive_mutex> guard(m_mutex);
572 const size_t num_io_handlers = m_stack.size();
573 return (num_io_handlers >= 2 &&
574 m_stack[num_io_handlers - 1]->GetType() == top_type &&
575 m_stack[num_io_handlers - 2]->GetType() == second_top_type);
578 ConstString GetTopIOHandlerControlSequence(char ch) {
579 return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString());
582 const char *GetTopIOHandlerCommandPrefix() {
583 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
586 const char *GetTopIOHandlerHelpPrologue() {
587 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
590 void PrintAsync(Stream *stream, const char *s, size_t len);
593 typedef std::vector<lldb::IOHandlerSP> collection;
595 mutable std::recursive_mutex m_mutex;
599 DISALLOW_COPY_AND_ASSIGN(IOHandlerStack);
602 } // namespace lldb_private
604 #endif // liblldb_IOHandler_h_