1 //===-- IOHandler.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_IOHandler_h_ 11 #define liblldb_IOHandler_h_ 12 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 22 23 #include <memory> 24 #include <mutex> 25 #include <string> 26 #include <vector> 27 28 #include <stdint.h> // for uint32_t 29 #include <stdio.h> // for FILE 30 31 namespace lldb_private { 32 class Debugger; 33 } 34 35 namespace curses { 36 class Application; 37 typedef std::unique_ptr<Application> ApplicationAP; 38 } // namespace curses 39 40 namespace lldb_private { 41 42 class IOHandler { 43 public: 44 enum class Type { 45 CommandInterpreter, 46 CommandList, 47 Confirm, 48 Curses, 49 Expression, 50 REPL, 51 ProcessIO, 52 PythonInterpreter, 53 PythonCode, 54 Other 55 }; 56 57 IOHandler(Debugger &debugger, IOHandler::Type type); 58 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); 63 64 virtual ~IOHandler(); 65 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 68 // when done. 69 virtual void Run() = 0; 70 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 74 75 virtual void Cancel() = 0; 76 77 // Called when CTRL+C is pressed which usually causes 78 // Debugger::DispatchInputInterrupt to be called. 79 80 virtual bool Interrupt() = 0; 81 82 virtual void GotEOF() = 0; 83 84 virtual bool IsActive() { return m_active && !m_done; } 85 86 virtual void SetIsDone(bool b) { m_done = b; } 87 88 virtual bool GetIsDone() { return m_done; } 89 90 Type GetType() const { return m_type; } 91 92 virtual void Activate() { m_active = true; } 93 94 virtual void Deactivate() { m_active = false; } 95 96 virtual const char *GetPrompt() { 97 // Prompt support isn't mandatory 98 return nullptr; 99 } 100 101 virtual bool SetPrompt(llvm::StringRef prompt) { 102 // Prompt support isn't mandatory 103 return false; 104 } 105 bool SetPrompt(const char *) = delete; 106 107 virtual ConstString GetControlSequence(char ch) { return ConstString(); } 108 109 virtual const char *GetCommandPrefix() { return nullptr; } 110 111 virtual const char *GetHelpPrologue() { return nullptr; } 112 113 int GetInputFD(); 114 115 int GetOutputFD(); 116 117 int GetErrorFD(); 118 119 FILE *GetInputFILE(); 120 121 FILE *GetOutputFILE(); 122 123 FILE *GetErrorFILE(); 124 125 lldb::StreamFileSP &GetInputStreamFile(); 126 127 lldb::StreamFileSP &GetOutputStreamFile(); 128 129 lldb::StreamFileSP &GetErrorStreamFile(); 130 131 Debugger &GetDebugger() { return m_debugger; } 132 133 void *GetUserData() { return m_user_data; } 134 135 void SetUserData(void *user_data) { m_user_data = user_data; } 136 137 Flags &GetFlags() { return m_flags; } 138 139 const Flags &GetFlags() const { return m_flags; } 140 141 //------------------------------------------------------------------ 142 /// Check if the input is being supplied interactively by a user 143 /// 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(); 149 150 //------------------------------------------------------------------ 151 /// Check if the input is coming from a real terminal. 152 /// 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(); 159 160 void SetPopped(bool b); 161 162 void WaitForPop(); 163 164 virtual void PrintAsync(Stream *stream, const char *s, size_t len) { 165 stream->Write(s, len); 166 stream->Flush(); 167 } 168 169 protected: 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; 175 Flags m_flags; 176 Type m_type; 177 void *m_user_data; 178 bool m_done; 179 bool m_active; 180 181 private: 182 DISALLOW_COPY_AND_ASSIGN(IOHandler); 183 }; 184 185 //------------------------------------------------------------------ 186 /// A delegate class for use with IOHandler subclasses. 187 /// 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 191 /// received. 192 //------------------------------------------------------------------ 193 class IOHandlerDelegate { 194 public: 195 enum class Completion { None, LLDBCommand, Expression }; 196 197 IOHandlerDelegate(Completion completion = Completion::None) 198 : m_completion(completion) {} 199 200 virtual ~IOHandlerDelegate() = default; 201 202 virtual void IOHandlerActivated(IOHandler &io_handler) {} 203 204 virtual void IOHandlerDeactivated(IOHandler &io_handler) {} 205 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); 210 211 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; } 212 213 //------------------------------------------------------------------ 214 /// Called when a new line is created or one of an identified set of 215 /// indentation characters is typed. 216 /// 217 /// This function determines how much indentation should be added 218 /// or removed to match the recommended amount for the final line. 219 /// 220 /// @param[in] io_handler 221 /// The IOHandler that responsible for input. 222 /// 223 /// @param[in] lines 224 /// The current input up to the line to be corrected. Lines 225 /// following the line containing the cursor are not included. 226 /// 227 /// @param[in] cursor_position 228 /// The number of characters preceding the cursor on the final 229 /// line at the time. 230 /// 231 /// @return 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) { 240 return 0; 241 } 242 243 //------------------------------------------------------------------ 244 /// Called when a line or lines have been retrieved. 245 /// 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; 254 255 virtual void IOHandlerInputInterrupted(IOHandler &io_handler, 256 std::string &data) {} 257 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. 264 /// 265 /// @param[in] lines 266 /// The current multi-line content. May be altered to provide 267 /// alternative input when complete. 268 /// 269 /// @return 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, 275 StringList &lines) { 276 // Impose no requirements for input to be considered 277 // complete. subclasses should do something more intelligent. 278 return true; 279 } 280 281 virtual ConstString IOHandlerGetControlSequence(char ch) { 282 return ConstString(); 283 } 284 285 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; } 286 287 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; } 288 289 //------------------------------------------------------------------ 290 // Intercept the IOHandler::Interrupt() calls and do something. 291 // 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; } 296 297 protected: 298 Completion m_completion; // Support for common builtin completions 299 }; 300 301 //---------------------------------------------------------------------- 302 // IOHandlerDelegateMultiline 303 // 304 // A IOHandlerDelegate that handles terminating multi-line input when 305 // the last line is equal to "end_line" which is specified in the 306 // constructor. 307 //---------------------------------------------------------------------- 308 class IOHandlerDelegateMultiline : public IOHandlerDelegate { 309 public: 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 : "") {} 314 315 ~IOHandlerDelegateMultiline() override = default; 316 317 ConstString IOHandlerGetControlSequence(char ch) override { 318 if (ch == 'd') 319 return ConstString(m_end_line + "\n"); 320 return ConstString(); 321 } 322 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 330 // getting lines 331 lines.PopBack(); 332 return true; 333 } 334 return false; 335 } 336 337 protected: 338 const std::string m_end_line; 339 }; 340 341 class IOHandlerEditline : public IOHandler { 342 public: 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 348 // starting at 349 // 'line_number_start' 350 IOHandlerDelegate &delegate); 351 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 360 // starting at 361 // 'line_number_start' 362 IOHandlerDelegate &delegate); 363 364 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, 365 const char *, bool, bool, uint32_t, 366 IOHandlerDelegate &) = delete; 367 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; 372 373 ~IOHandlerEditline() override; 374 375 void Run() override; 376 377 void Cancel() override; 378 379 bool Interrupt() override; 380 381 void GotEOF() override; 382 383 void Activate() override; 384 385 void Deactivate() override; 386 387 ConstString GetControlSequence(char ch) override { 388 return m_delegate.IOHandlerGetControlSequence(ch); 389 } 390 391 const char *GetCommandPrefix() override { 392 return m_delegate.IOHandlerGetCommandPrefix(); 393 } 394 395 const char *GetHelpPrologue() override { 396 return m_delegate.IOHandlerGetHelpPrologue(); 397 } 398 399 const char *GetPrompt() override; 400 401 bool SetPrompt(llvm::StringRef prompt) override; 402 bool SetPrompt(const char *prompt) = delete; 403 404 const char *GetContinuationPrompt(); 405 406 void SetContinuationPrompt(llvm::StringRef prompt); 407 void SetContinuationPrompt(const char *) = delete; 408 409 bool GetLine(std::string &line, bool &interrupted); 410 411 bool GetLines(StringList &lines, bool &interrupted); 412 413 void SetBaseLineNumber(uint32_t line); 414 415 bool GetInterruptExits() { return m_interrupt_exits; } 416 417 void SetInterruptExits(bool b) { m_interrupt_exits = b; } 418 419 const StringList *GetCurrentLines() const { return m_current_lines_ptr; } 420 421 uint32_t GetCurrentLineIndex() const; 422 423 void PrintAsync(Stream *stream, const char *s, size_t len) override; 424 425 private: 426 #ifndef LLDB_DISABLE_LIBEDIT 427 static bool IsInputCompleteCallback(Editline *editline, StringList &lines, 428 void *baton); 429 430 static int FixIndentationCallback(Editline *editline, const StringList &lines, 431 int cursor_position, void *baton); 432 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); 437 #endif 438 439 protected: 440 #ifndef LLDB_DISABLE_LIBEDIT 441 std::unique_ptr<Editline> m_editline_ap; 442 #endif 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; 449 bool m_multi_line; 450 bool m_color_prompts; 451 bool m_interrupt_exits; 452 bool m_editing; // Set to true when fetching a line manually (not using 453 // libedit) 454 }; 455 456 // The order of base classes is important. Look at the constructor of 457 // IOHandlerConfirm 458 // to see how. 459 class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline { 460 public: 461 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, 462 bool default_response); 463 464 ~IOHandlerConfirm() override; 465 466 bool GetResponse() const { return m_user_response; } 467 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; 472 473 void IOHandlerInputComplete(IOHandler &io_handler, 474 std::string &data) override; 475 476 protected: 477 const bool m_default_response; 478 bool m_user_response; 479 }; 480 481 class IOHandlerCursesGUI : public IOHandler { 482 public: 483 IOHandlerCursesGUI(Debugger &debugger); 484 485 ~IOHandlerCursesGUI() override; 486 487 void Run() override; 488 489 void Cancel() override; 490 491 bool Interrupt() override; 492 493 void GotEOF() override; 494 495 void Activate() override; 496 497 void Deactivate() override; 498 499 protected: 500 curses::ApplicationAP m_app_ap; 501 }; 502 503 class IOHandlerCursesValueObjectList : public IOHandler { 504 public: 505 IOHandlerCursesValueObjectList(Debugger &debugger, 506 ValueObjectList &valobj_list); 507 508 ~IOHandlerCursesValueObjectList() override; 509 510 void Run() override; 511 512 void GotEOF() override; 513 514 protected: 515 ValueObjectList m_valobj_list; 516 }; 517 518 class IOHandlerStack { 519 public: 520 IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {} 521 522 ~IOHandlerStack() = default; 523 524 size_t GetSize() const { 525 std::lock_guard<std::recursive_mutex> guard(m_mutex); 526 return m_stack.size(); 527 } 528 529 void Push(const lldb::IOHandlerSP &sp) { 530 if (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 535 m_top = sp.get(); 536 } 537 } 538 539 bool IsEmpty() const { 540 std::lock_guard<std::recursive_mutex> guard(m_mutex); 541 return m_stack.empty(); 542 } 543 544 lldb::IOHandlerSP Top() { 545 lldb::IOHandlerSP sp; 546 { 547 std::lock_guard<std::recursive_mutex> guard(m_mutex); 548 if (!m_stack.empty()) 549 sp = m_stack.back(); 550 } 551 return sp; 552 } 553 554 void Pop() { 555 std::lock_guard<std::recursive_mutex> guard(m_mutex); 556 if (!m_stack.empty()) { 557 lldb::IOHandlerSP sp(m_stack.back()); 558 m_stack.pop_back(); 559 sp->SetPopped(true); 560 } 561 // Set m_top the non-locking IsTop() call 562 563 m_top = (m_stack.empty() ? nullptr : m_stack.back().get()); 564 } 565 566 std::recursive_mutex &GetMutex() { return m_mutex; } 567 568 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const { 569 return m_top == io_handler_sp.get(); 570 } 571 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); 579 } 580 581 ConstString GetTopIOHandlerControlSequence(char ch) { 582 return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString()); 583 } 584 585 const char *GetTopIOHandlerCommandPrefix() { 586 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr); 587 } 588 589 const char *GetTopIOHandlerHelpPrologue() { 590 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr); 591 } 592 593 void PrintAsync(Stream *stream, const char *s, size_t len); 594 595 protected: 596 typedef std::vector<lldb::IOHandlerSP> collection; 597 collection m_stack; 598 mutable std::recursive_mutex m_mutex; 599 IOHandler *m_top; 600 601 private: 602 DISALLOW_COPY_AND_ASSIGN(IOHandlerStack); 603 }; 604 605 } // namespace lldb_private 606 607 #endif // liblldb_IOHandler_h_ 608