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