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 <string.h> 14 15 #include <stack> 16 17 #include "lldb/lldb-public.h" 18 #include "lldb/lldb-enumerations.h" 19 #include "lldb/Core/ConstString.h" 20 #include "lldb/Core/Error.h" 21 #include "lldb/Core/Flags.h" 22 #include "lldb/Core/StringList.h" 23 #include "lldb/Core/ValueObjectList.h" 24 #include "lldb/Host/Mutex.h" 25 26 namespace curses 27 { 28 class Application; 29 typedef std::unique_ptr<Application> ApplicationAP; 30 } 31 32 namespace lldb_private { 33 34 class IOHandler 35 { 36 public: 37 IOHandler (Debugger &debugger); 38 39 IOHandler (Debugger &debugger, 40 const lldb::StreamFileSP &input_sp, 41 const lldb::StreamFileSP &output_sp, 42 const lldb::StreamFileSP &error_sp, 43 uint32_t flags); 44 45 virtual 46 ~IOHandler (); 47 48 // Each IOHandler gets to run until it is done. It should read data 49 // from the "in" and place output into "out" and "err and return 50 // when done. 51 virtual void 52 Run () = 0; 53 54 // Hide any characters that have been displayed so far so async 55 // output can be displayed. Refresh() will be called after the 56 // output has been displayed. 57 virtual void 58 Hide () = 0; 59 60 // Called when the async output has been received in order to update 61 // the input reader (refresh the prompt and redisplay any current 62 // line(s) that are being edited 63 virtual void 64 Refresh () = 0; 65 66 // Called when an input reader should relinquish its control so another 67 // can be pushed onto the IO handler stack, or so the current IO 68 // handler can pop itself off the stack 69 70 virtual void 71 Cancel () = 0; 72 73 // Called when CTRL+C is pressed which usually causes 74 // Debugger::DispatchInputInterrupt to be called. 75 76 virtual void 77 Interrupt () = 0; 78 79 virtual void 80 GotEOF() = 0; 81 82 virtual bool IsActive()83 IsActive () 84 { 85 return m_active && !m_done; 86 } 87 88 virtual void SetIsDone(bool b)89 SetIsDone (bool b) 90 { 91 m_done = b; 92 } 93 94 virtual bool GetIsDone()95 GetIsDone () 96 { 97 return m_done; 98 } 99 100 virtual void Activate()101 Activate () 102 { 103 m_active = true; 104 } 105 106 virtual void Deactivate()107 Deactivate () 108 { 109 m_active = false; 110 } 111 112 virtual const char * GetPrompt()113 GetPrompt () 114 { 115 // Prompt support isn't mandatory 116 return NULL; 117 } 118 119 virtual bool SetPrompt(const char * prompt)120 SetPrompt (const char *prompt) 121 { 122 // Prompt support isn't mandatory 123 return false; 124 } 125 126 virtual ConstString GetControlSequence(char ch)127 GetControlSequence (char ch) 128 { 129 return ConstString(); 130 } 131 132 int 133 GetInputFD(); 134 135 int 136 GetOutputFD(); 137 138 int 139 GetErrorFD(); 140 141 FILE * 142 GetInputFILE(); 143 144 FILE * 145 GetOutputFILE(); 146 147 FILE * 148 GetErrorFILE(); 149 150 lldb::StreamFileSP & 151 GetInputStreamFile(); 152 153 lldb::StreamFileSP & 154 GetOutputStreamFile(); 155 156 lldb::StreamFileSP & 157 GetErrorStreamFile(); 158 159 Debugger & GetDebugger()160 GetDebugger() 161 { 162 return m_debugger; 163 } 164 165 void * GetUserData()166 GetUserData () 167 { 168 return m_user_data; 169 } 170 171 void SetUserData(void * user_data)172 SetUserData (void *user_data) 173 { 174 m_user_data = user_data; 175 } 176 177 Flags & GetFlags()178 GetFlags () 179 { 180 return m_flags; 181 } 182 183 const Flags & GetFlags()184 GetFlags () const 185 { 186 return m_flags; 187 } 188 189 //------------------------------------------------------------------ 190 /// Check if the input is being supplied interactively by a user 191 /// 192 /// This will return true if the input stream is a terminal (tty or 193 /// pty) and can cause IO handlers to do different things (like 194 /// for a comfirmation when deleting all breakpoints). 195 //------------------------------------------------------------------ 196 bool 197 GetIsInteractive (); 198 199 //------------------------------------------------------------------ 200 /// Check if the input is coming from a real terminal. 201 /// 202 /// A real terminal has a valid size with a certain number of rows 203 /// and colums. If this function returns true, then terminal escape 204 /// sequences are expected to work (cursor movement escape sequences, 205 /// clearning lines, etc). 206 //------------------------------------------------------------------ 207 bool 208 GetIsRealTerminal (); 209 210 protected: 211 Debugger &m_debugger; 212 lldb::StreamFileSP m_input_sp; 213 lldb::StreamFileSP m_output_sp; 214 lldb::StreamFileSP m_error_sp; 215 Flags m_flags; 216 void *m_user_data; 217 bool m_done; 218 bool m_active; 219 220 private: 221 DISALLOW_COPY_AND_ASSIGN (IOHandler); 222 }; 223 224 225 //------------------------------------------------------------------ 226 /// A delegate class for use with IOHandler subclasses. 227 /// 228 /// The IOHandler delegate is designed to be mixed into classes so 229 /// they can use an IOHandler subclass to fetch input and notify the 230 /// object that inherits from this delegate class when a token is 231 /// received. 232 //------------------------------------------------------------------ 233 class IOHandlerDelegate 234 { 235 public: 236 enum class Completion { 237 None, 238 LLDBCommand, 239 Expression 240 }; 241 242 IOHandlerDelegate (Completion completion = Completion::None) : m_completion(completion)243 m_completion(completion), 244 m_io_handler_done (false) 245 { 246 } 247 248 virtual ~IOHandlerDelegate()249 ~IOHandlerDelegate() 250 { 251 } 252 253 virtual void IOHandlerActivated(IOHandler & io_handler)254 IOHandlerActivated (IOHandler &io_handler) 255 { 256 } 257 258 virtual int 259 IOHandlerComplete (IOHandler &io_handler, 260 const char *current_line, 261 const char *cursor, 262 const char *last_char, 263 int skip_first_n_matches, 264 int max_matches, 265 StringList &matches); 266 267 //------------------------------------------------------------------ 268 /// Called when a line or lines have been retrieved. 269 /// 270 /// This funtion can handle the current line and possibly call 271 /// IOHandler::SetIsDone(true) when the IO handler is done like when 272 /// "quit" is entered as a command, of when an empty line is 273 /// received. It is up to the delegate to determine when a line 274 /// should cause a IOHandler to exit. 275 //------------------------------------------------------------------ 276 virtual void 277 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) = 0; 278 279 //------------------------------------------------------------------ 280 /// Called when a line in \a lines has been updated when doing 281 /// multi-line input. 282 /// 283 /// @return 284 /// Return an enumeration to indicate the status of the current 285 /// line: 286 /// Success - The line is good and should be added to the 287 /// multiple lines 288 /// Error - There is an error with the current line and it 289 /// need to be re-edited before it is acceptable 290 /// Done - The lines collection is complete and ready to be 291 /// returned. 292 //------------------------------------------------------------------ 293 virtual LineStatus IOHandlerLinesUpdated(IOHandler & io_handler,StringList & lines,uint32_t line_idx,Error & error)294 IOHandlerLinesUpdated (IOHandler &io_handler, 295 StringList &lines, 296 uint32_t line_idx, 297 Error &error) 298 { 299 return LineStatus::Done; // Stop getting lines on the first line that is updated 300 // subclasses should do something more intelligent here. 301 // This function will not be called on IOHandler objects 302 // that are getting single lines. 303 } 304 305 306 virtual ConstString GetControlSequence(char ch)307 GetControlSequence (char ch) 308 { 309 return ConstString(); 310 } 311 312 protected: 313 Completion m_completion; // Support for common builtin completions 314 bool m_io_handler_done; 315 }; 316 317 //---------------------------------------------------------------------- 318 // IOHandlerDelegateMultiline 319 // 320 // A IOHandlerDelegate that handles terminating multi-line input when 321 // the last line is equal to "end_line" which is specified in the 322 // constructor. 323 //---------------------------------------------------------------------- 324 class IOHandlerDelegateMultiline : 325 public IOHandlerDelegate 326 { 327 public: 328 IOHandlerDelegateMultiline (const char *end_line, 329 Completion completion = Completion::None) : IOHandlerDelegate(completion)330 IOHandlerDelegate (completion), 331 m_end_line((end_line && end_line[0]) ? end_line : "") 332 { 333 } 334 335 virtual ~IOHandlerDelegateMultiline()336 ~IOHandlerDelegateMultiline () 337 { 338 } 339 340 virtual ConstString GetControlSequence(char ch)341 GetControlSequence (char ch) 342 { 343 if (ch == 'd') 344 return ConstString (m_end_line + "\n"); 345 return ConstString(); 346 } 347 348 virtual LineStatus IOHandlerLinesUpdated(IOHandler & io_handler,StringList & lines,uint32_t line_idx,Error & error)349 IOHandlerLinesUpdated (IOHandler &io_handler, 350 StringList &lines, 351 uint32_t line_idx, 352 Error &error) 353 { 354 if (line_idx == UINT32_MAX) 355 { 356 // Remove the last empty line from "lines" so it doesn't appear 357 // in our final expression and return true to indicate we are done 358 // getting lines 359 lines.PopBack(); 360 return LineStatus::Done; 361 } 362 else if (line_idx + 1 == lines.GetSize()) 363 { 364 // The last line was edited, if this line is empty, then we are done 365 // getting our multiple lines. 366 if (lines[line_idx] == m_end_line) 367 return LineStatus::Done; 368 } 369 return LineStatus::Success; 370 } 371 protected: 372 const std::string m_end_line; 373 }; 374 375 376 class IOHandlerEditline : public IOHandler 377 { 378 public: 379 IOHandlerEditline (Debugger &debugger, 380 const char *editline_name, // Used for saving history files 381 const char *prompt, 382 bool multi_line, 383 IOHandlerDelegate &delegate); 384 385 IOHandlerEditline (Debugger &debugger, 386 const lldb::StreamFileSP &input_sp, 387 const lldb::StreamFileSP &output_sp, 388 const lldb::StreamFileSP &error_sp, 389 uint32_t flags, 390 const char *editline_name, // Used for saving history files 391 const char *prompt, 392 bool multi_line, 393 IOHandlerDelegate &delegate); 394 395 virtual 396 ~IOHandlerEditline (); 397 398 virtual void 399 Run (); 400 401 virtual void 402 Hide (); 403 404 virtual void 405 Refresh (); 406 407 virtual void 408 Cancel (); 409 410 virtual void 411 Interrupt (); 412 413 virtual void 414 GotEOF(); 415 416 virtual void Activate()417 Activate () 418 { 419 IOHandler::Activate(); 420 m_delegate.IOHandlerActivated(*this); 421 } 422 423 virtual ConstString GetControlSequence(char ch)424 GetControlSequence (char ch) 425 { 426 return m_delegate.GetControlSequence (ch); 427 } 428 429 virtual const char * 430 GetPrompt (); 431 432 virtual bool 433 SetPrompt (const char *prompt); 434 435 bool 436 GetLine (std::string &line); 437 438 bool 439 GetLines (StringList &lines); 440 441 private: 442 static LineStatus 443 LineCompletedCallback (Editline *editline, 444 StringList &lines, 445 uint32_t line_idx, 446 Error &error, 447 void *baton); 448 449 static int AutoCompleteCallback (const char *current_line, 450 const char *cursor, 451 const char *last_char, 452 int skip_first_n_matches, 453 int max_matches, 454 StringList &matches, 455 void *baton); 456 457 protected: 458 std::unique_ptr<Editline> m_editline_ap; 459 IOHandlerDelegate &m_delegate; 460 std::string m_prompt; 461 bool m_multi_line; 462 }; 463 464 class IOHandlerConfirm : 465 public IOHandlerEditline, 466 public IOHandlerDelegate 467 { 468 public: 469 IOHandlerConfirm (Debugger &debugger, 470 const char *prompt, 471 bool default_response); 472 473 virtual 474 ~IOHandlerConfirm (); 475 476 bool GetResponse()477 GetResponse () const 478 { 479 return m_user_response; 480 } 481 482 virtual int 483 IOHandlerComplete (IOHandler &io_handler, 484 const char *current_line, 485 const char *cursor, 486 const char *last_char, 487 int skip_first_n_matches, 488 int max_matches, 489 StringList &matches); 490 491 virtual void 492 IOHandlerInputComplete (IOHandler &io_handler, std::string &data); 493 494 protected: 495 const bool m_default_response; 496 bool m_user_response; 497 }; 498 499 class IOHandlerCursesGUI : 500 public IOHandler 501 { 502 public: 503 IOHandlerCursesGUI (Debugger &debugger); 504 505 virtual 506 ~IOHandlerCursesGUI (); 507 508 virtual void 509 Run (); 510 511 virtual void 512 Hide (); 513 514 virtual void 515 Refresh (); 516 517 virtual void 518 Cancel (); 519 520 virtual void 521 Interrupt (); 522 523 virtual void 524 GotEOF(); 525 526 virtual void 527 Activate (); 528 529 virtual void 530 Deactivate (); 531 532 protected: 533 curses::ApplicationAP m_app_ap; 534 }; 535 536 class IOHandlerCursesValueObjectList : 537 public IOHandler 538 { 539 public: 540 IOHandlerCursesValueObjectList (Debugger &debugger, ValueObjectList &valobj_list); 541 542 virtual 543 ~IOHandlerCursesValueObjectList (); 544 545 virtual void 546 Run (); 547 548 virtual void 549 Hide (); 550 551 virtual void 552 Refresh (); 553 554 virtual void 555 Interrupt (); 556 557 virtual void 558 GotEOF(); 559 protected: 560 ValueObjectList m_valobj_list; 561 }; 562 563 class IOHandlerStack 564 { 565 public: 566 IOHandlerStack()567 IOHandlerStack () : 568 m_stack(), 569 m_mutex(Mutex::eMutexTypeRecursive), 570 m_top (NULL) 571 { 572 } 573 ~IOHandlerStack()574 ~IOHandlerStack () 575 { 576 } 577 578 size_t GetSize()579 GetSize () const 580 { 581 Mutex::Locker locker (m_mutex); 582 return m_stack.size(); 583 } 584 585 void Push(const lldb::IOHandlerSP & sp)586 Push (const lldb::IOHandlerSP& sp) 587 { 588 if (sp) 589 { 590 Mutex::Locker locker (m_mutex); 591 m_stack.push (sp); 592 // Set m_top the non-locking IsTop() call 593 m_top = sp.get(); 594 } 595 } 596 597 bool IsEmpty()598 IsEmpty () const 599 { 600 Mutex::Locker locker (m_mutex); 601 return m_stack.empty(); 602 } 603 604 lldb::IOHandlerSP Top()605 Top () 606 { 607 lldb::IOHandlerSP sp; 608 { 609 Mutex::Locker locker (m_mutex); 610 if (!m_stack.empty()) 611 sp = m_stack.top(); 612 } 613 return sp; 614 } 615 616 void Pop()617 Pop () 618 { 619 Mutex::Locker locker (m_mutex); 620 if (!m_stack.empty()) 621 m_stack.pop(); 622 // Set m_top the non-locking IsTop() call 623 if (m_stack.empty()) 624 m_top = NULL; 625 else 626 m_top = m_stack.top().get(); 627 } 628 629 Mutex & GetMutex()630 GetMutex() 631 { 632 return m_mutex; 633 } 634 635 bool IsTop(const lldb::IOHandlerSP & io_handler_sp)636 IsTop (const lldb::IOHandlerSP &io_handler_sp) const 637 { 638 return m_top == io_handler_sp.get(); 639 } 640 641 ConstString GetTopIOHandlerControlSequence(char ch)642 GetTopIOHandlerControlSequence (char ch) 643 { 644 if (m_top) 645 return m_top->GetControlSequence(ch); 646 return ConstString(); 647 } 648 649 protected: 650 651 std::stack<lldb::IOHandlerSP> m_stack; 652 mutable Mutex m_mutex; 653 IOHandler *m_top; 654 655 private: 656 657 DISALLOW_COPY_AND_ASSIGN (IOHandlerStack); 658 }; 659 660 } // namespace lldb_private 661 662 #endif // #ifndef liblldb_IOHandler_h_ 663