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/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" 22 23 #include <memory> 24 #include <mutex> 25 #include <string> 26 #include <vector> 27 28 #include <stdint.h> 29 #include <stdio.h> 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 from the 67 // "in" and place output into "out" and "err and return when done. 68 virtual void Run() = 0; 69 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 73 74 virtual void Cancel() = 0; 75 76 // Called when CTRL+C is pressed which usually causes 77 // Debugger::DispatchInputInterrupt to be called. 78 79 virtual bool Interrupt() = 0; 80 81 virtual void GotEOF() = 0; 82 IsActive()83 virtual bool IsActive() { return m_active && !m_done; } 84 SetIsDone(bool b)85 virtual void SetIsDone(bool b) { m_done = b; } 86 GetIsDone()87 virtual bool GetIsDone() { return m_done; } 88 GetType()89 Type GetType() const { return m_type; } 90 Activate()91 virtual void Activate() { m_active = true; } 92 Deactivate()93 virtual void Deactivate() { m_active = false; } 94 GetPrompt()95 virtual const char *GetPrompt() { 96 // Prompt support isn't mandatory 97 return nullptr; 98 } 99 SetPrompt(llvm::StringRef prompt)100 virtual bool SetPrompt(llvm::StringRef prompt) { 101 // Prompt support isn't mandatory 102 return false; 103 } 104 bool SetPrompt(const char *) = delete; 105 GetControlSequence(char ch)106 virtual ConstString GetControlSequence(char ch) { return ConstString(); } 107 GetCommandPrefix()108 virtual const char *GetCommandPrefix() { return nullptr; } 109 GetHelpPrologue()110 virtual const char *GetHelpPrologue() { return nullptr; } 111 112 int GetInputFD(); 113 114 int GetOutputFD(); 115 116 int GetErrorFD(); 117 118 FILE *GetInputFILE(); 119 120 FILE *GetOutputFILE(); 121 122 FILE *GetErrorFILE(); 123 124 lldb::StreamFileSP &GetInputStreamFile(); 125 126 lldb::StreamFileSP &GetOutputStreamFile(); 127 128 lldb::StreamFileSP &GetErrorStreamFile(); 129 GetDebugger()130 Debugger &GetDebugger() { return m_debugger; } 131 GetUserData()132 void *GetUserData() { return m_user_data; } 133 SetUserData(void * user_data)134 void SetUserData(void *user_data) { m_user_data = user_data; } 135 GetFlags()136 Flags &GetFlags() { return m_flags; } 137 GetFlags()138 const Flags &GetFlags() const { return m_flags; } 139 140 //------------------------------------------------------------------ 141 /// Check if the input is being supplied interactively by a user 142 /// 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(); 148 149 //------------------------------------------------------------------ 150 /// Check if the input is coming from a real terminal. 151 /// 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(); 158 159 void SetPopped(bool b); 160 161 void WaitForPop(); 162 PrintAsync(Stream * stream,const char * s,size_t len)163 virtual void PrintAsync(Stream *stream, const char *s, size_t len) { 164 stream->Write(s, len); 165 stream->Flush(); 166 } 167 168 protected: 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; 174 Flags m_flags; 175 Type m_type; 176 void *m_user_data; 177 bool m_done; 178 bool m_active; 179 180 private: 181 DISALLOW_COPY_AND_ASSIGN(IOHandler); 182 }; 183 184 //------------------------------------------------------------------ 185 /// A delegate class for use with IOHandler subclasses. 186 /// 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 190 /// received. 191 //------------------------------------------------------------------ 192 class IOHandlerDelegate { 193 public: 194 enum class Completion { None, LLDBCommand, Expression }; 195 196 IOHandlerDelegate(Completion completion = Completion::None) m_completion(completion)197 : m_completion(completion) {} 198 199 virtual ~IOHandlerDelegate() = default; 200 IOHandlerActivated(IOHandler & io_handler)201 virtual void IOHandlerActivated(IOHandler &io_handler) {} 202 IOHandlerDeactivated(IOHandler & io_handler)203 virtual void IOHandlerDeactivated(IOHandler &io_handler) {} 204 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); 209 IOHandlerGetFixIndentationCharacters()210 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; } 211 212 //------------------------------------------------------------------ 213 /// Called when a new line is created or one of an identified set of 214 /// indentation characters is typed. 215 /// 216 /// This function determines how much indentation should be added 217 /// or removed to match the recommended amount for the final line. 218 /// 219 /// @param[in] io_handler 220 /// The IOHandler that responsible for input. 221 /// 222 /// @param[in] lines 223 /// The current input up to the line to be corrected. Lines 224 /// following the line containing the cursor are not included. 225 /// 226 /// @param[in] cursor_position 227 /// The number of characters preceding the cursor on the final 228 /// line at the time. 229 /// 230 /// @return 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 //------------------------------------------------------------------ IOHandlerFixIndentation(IOHandler & io_handler,const StringList & lines,int cursor_position)236 virtual int IOHandlerFixIndentation(IOHandler &io_handler, 237 const StringList &lines, 238 int cursor_position) { 239 return 0; 240 } 241 242 //------------------------------------------------------------------ 243 /// Called when a line or lines have been retrieved. 244 /// 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; 253 IOHandlerInputInterrupted(IOHandler & io_handler,std::string & data)254 virtual void IOHandlerInputInterrupted(IOHandler &io_handler, 255 std::string &data) {} 256 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. 263 /// 264 /// @param[in] lines 265 /// The current multi-line content. May be altered to provide 266 /// alternative input when complete. 267 /// 268 /// @return 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 //------------------------------------------------------------------ IOHandlerIsInputComplete(IOHandler & io_handler,StringList & lines)273 virtual bool IOHandlerIsInputComplete(IOHandler &io_handler, 274 StringList &lines) { 275 // Impose no requirements for input to be considered complete. subclasses 276 // should do something more intelligent. 277 return true; 278 } 279 IOHandlerGetControlSequence(char ch)280 virtual ConstString IOHandlerGetControlSequence(char ch) { 281 return ConstString(); 282 } 283 IOHandlerGetCommandPrefix()284 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; } 285 IOHandlerGetHelpPrologue()286 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; } 287 288 //------------------------------------------------------------------ 289 // Intercept the IOHandler::Interrupt() calls and do something. 290 // 291 // Return true if the interrupt was handled, false if the IOHandler should 292 // continue to try handle the interrupt itself. 293 //------------------------------------------------------------------ IOHandlerInterrupt(IOHandler & io_handler)294 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; } 295 296 protected: 297 Completion m_completion; // Support for common builtin completions 298 }; 299 300 //---------------------------------------------------------------------- 301 // IOHandlerDelegateMultiline 302 // 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 { 307 public: 308 IOHandlerDelegateMultiline(const char *end_line, 309 Completion completion = Completion::None) IOHandlerDelegate(completion)310 : IOHandlerDelegate(completion), 311 m_end_line((end_line && end_line[0]) ? end_line : "") {} 312 313 ~IOHandlerDelegateMultiline() override = default; 314 IOHandlerGetControlSequence(char ch)315 ConstString IOHandlerGetControlSequence(char ch) override { 316 if (ch == 'd') 317 return ConstString(m_end_line + "\n"); 318 return ConstString(); 319 } 320 IOHandlerIsInputComplete(IOHandler & io_handler,StringList & lines)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 328 lines.PopBack(); 329 return true; 330 } 331 return false; 332 } 333 334 protected: 335 const std::string m_end_line; 336 }; 337 338 class IOHandlerEditline : public IOHandler { 339 public: 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 345 // starting at 346 // 'line_number_start' 347 IOHandlerDelegate &delegate); 348 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 357 // starting at 358 // 'line_number_start' 359 IOHandlerDelegate &delegate); 360 361 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, 362 const char *, bool, bool, uint32_t, 363 IOHandlerDelegate &) = delete; 364 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; 369 370 ~IOHandlerEditline() override; 371 372 void Run() override; 373 374 void Cancel() override; 375 376 bool Interrupt() override; 377 378 void GotEOF() override; 379 380 void Activate() override; 381 382 void Deactivate() override; 383 GetControlSequence(char ch)384 ConstString GetControlSequence(char ch) override { 385 return m_delegate.IOHandlerGetControlSequence(ch); 386 } 387 GetCommandPrefix()388 const char *GetCommandPrefix() override { 389 return m_delegate.IOHandlerGetCommandPrefix(); 390 } 391 GetHelpPrologue()392 const char *GetHelpPrologue() override { 393 return m_delegate.IOHandlerGetHelpPrologue(); 394 } 395 396 const char *GetPrompt() override; 397 398 bool SetPrompt(llvm::StringRef prompt) override; 399 bool SetPrompt(const char *prompt) = delete; 400 401 const char *GetContinuationPrompt(); 402 403 void SetContinuationPrompt(llvm::StringRef prompt); 404 void SetContinuationPrompt(const char *) = delete; 405 406 bool GetLine(std::string &line, bool &interrupted); 407 408 bool GetLines(StringList &lines, bool &interrupted); 409 410 void SetBaseLineNumber(uint32_t line); 411 GetInterruptExits()412 bool GetInterruptExits() { return m_interrupt_exits; } 413 SetInterruptExits(bool b)414 void SetInterruptExits(bool b) { m_interrupt_exits = b; } 415 GetCurrentLines()416 const StringList *GetCurrentLines() const { return m_current_lines_ptr; } 417 418 uint32_t GetCurrentLineIndex() const; 419 420 void PrintAsync(Stream *stream, const char *s, size_t len) override; 421 422 private: 423 #ifndef LLDB_DISABLE_LIBEDIT 424 static bool IsInputCompleteCallback(Editline *editline, StringList &lines, 425 void *baton); 426 427 static int FixIndentationCallback(Editline *editline, const StringList &lines, 428 int cursor_position, void *baton); 429 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, 434 void *baton); 435 #endif 436 437 protected: 438 #ifndef LLDB_DISABLE_LIBEDIT 439 std::unique_ptr<Editline> m_editline_ap; 440 #endif 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; 447 bool m_multi_line; 448 bool m_color_prompts; 449 bool m_interrupt_exits; 450 bool m_editing; // Set to true when fetching a line manually (not using 451 // libedit) 452 }; 453 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 { 457 public: 458 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, 459 bool default_response); 460 461 ~IOHandlerConfirm() override; 462 GetResponse()463 bool GetResponse() const { return m_user_response; } 464 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; 469 470 void IOHandlerInputComplete(IOHandler &io_handler, 471 std::string &data) override; 472 473 protected: 474 const bool m_default_response; 475 bool m_user_response; 476 }; 477 478 class IOHandlerCursesGUI : public IOHandler { 479 public: 480 IOHandlerCursesGUI(Debugger &debugger); 481 482 ~IOHandlerCursesGUI() override; 483 484 void Run() override; 485 486 void Cancel() override; 487 488 bool Interrupt() override; 489 490 void GotEOF() override; 491 492 void Activate() override; 493 494 void Deactivate() override; 495 496 protected: 497 curses::ApplicationAP m_app_ap; 498 }; 499 500 class IOHandlerCursesValueObjectList : public IOHandler { 501 public: 502 IOHandlerCursesValueObjectList(Debugger &debugger, 503 ValueObjectList &valobj_list); 504 505 ~IOHandlerCursesValueObjectList() override; 506 507 void Run() override; 508 509 void GotEOF() override; 510 511 protected: 512 ValueObjectList m_valobj_list; 513 }; 514 515 class IOHandlerStack { 516 public: IOHandlerStack()517 IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {} 518 519 ~IOHandlerStack() = default; 520 GetSize()521 size_t GetSize() const { 522 std::lock_guard<std::recursive_mutex> guard(m_mutex); 523 return m_stack.size(); 524 } 525 Push(const lldb::IOHandlerSP & sp)526 void Push(const lldb::IOHandlerSP &sp) { 527 if (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 532 m_top = sp.get(); 533 } 534 } 535 IsEmpty()536 bool IsEmpty() const { 537 std::lock_guard<std::recursive_mutex> guard(m_mutex); 538 return m_stack.empty(); 539 } 540 Top()541 lldb::IOHandlerSP Top() { 542 lldb::IOHandlerSP sp; 543 { 544 std::lock_guard<std::recursive_mutex> guard(m_mutex); 545 if (!m_stack.empty()) 546 sp = m_stack.back(); 547 } 548 return sp; 549 } 550 Pop()551 void Pop() { 552 std::lock_guard<std::recursive_mutex> guard(m_mutex); 553 if (!m_stack.empty()) { 554 lldb::IOHandlerSP sp(m_stack.back()); 555 m_stack.pop_back(); 556 sp->SetPopped(true); 557 } 558 // Set m_top the non-locking IsTop() call 559 560 m_top = (m_stack.empty() ? nullptr : m_stack.back().get()); 561 } 562 GetMutex()563 std::recursive_mutex &GetMutex() { return m_mutex; } 564 IsTop(const lldb::IOHandlerSP & io_handler_sp)565 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const { 566 return m_top == io_handler_sp.get(); 567 } 568 CheckTopIOHandlerTypes(IOHandler::Type top_type,IOHandler::Type second_top_type)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); 576 } 577 GetTopIOHandlerControlSequence(char ch)578 ConstString GetTopIOHandlerControlSequence(char ch) { 579 return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString()); 580 } 581 GetTopIOHandlerCommandPrefix()582 const char *GetTopIOHandlerCommandPrefix() { 583 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr); 584 } 585 GetTopIOHandlerHelpPrologue()586 const char *GetTopIOHandlerHelpPrologue() { 587 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr); 588 } 589 590 void PrintAsync(Stream *stream, const char *s, size_t len); 591 592 protected: 593 typedef std::vector<lldb::IOHandlerSP> collection; 594 collection m_stack; 595 mutable std::recursive_mutex m_mutex; 596 IOHandler *m_top; 597 598 private: 599 DISALLOW_COPY_AND_ASSIGN(IOHandlerStack); 600 }; 601 602 } // namespace lldb_private 603 604 #endif // liblldb_IOHandler_h_ 605