]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h
sys/contrib/zstd: Import zstd 1.4.8
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / include / lldb / Core / IOHandler.h
1 //===-- IOHandler.h ---------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLDB_CORE_IOHANDLER_H
10 #define LLDB_CORE_IOHANDLER_H
11
12 #include "lldb/Core/ValueObjectList.h"
13 #include "lldb/Host/Config.h"
14 #include "lldb/Utility/CompletionRequest.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/Flags.h"
17 #include "lldb/Utility/Predicate.h"
18 #include "lldb/Utility/Reproducer.h"
19 #include "lldb/Utility/Stream.h"
20 #include "lldb/Utility/StringList.h"
21 #include "lldb/lldb-defines.h"
22 #include "lldb/lldb-forward.h"
23 #include "llvm/ADT/StringRef.h"
24
25 #include <memory>
26 #include <mutex>
27 #include <string>
28 #include <vector>
29
30 #include <stdint.h>
31 #include <stdio.h>
32
33 namespace lldb_private {
34 class Debugger;
35 }
36
37 namespace curses {
38 class Application;
39 typedef std::unique_ptr<Application> ApplicationAP;
40 } // namespace curses
41
42 namespace lldb_private {
43
44 class IOHandler {
45 public:
46   enum class Type {
47     CommandInterpreter,
48     CommandList,
49     Confirm,
50     Curses,
51     Expression,
52     REPL,
53     ProcessIO,
54     PythonInterpreter,
55     LuaInterpreter,
56     PythonCode,
57     Other
58   };
59
60   IOHandler(Debugger &debugger, IOHandler::Type type);
61
62   IOHandler(Debugger &debugger, IOHandler::Type type,
63             const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp,
64             const lldb::StreamFileSP &error_sp, uint32_t flags,
65             repro::DataRecorder *data_recorder);
66
67   virtual ~IOHandler();
68
69   // Each IOHandler gets to run until it is done. It should read data from the
70   // "in" and place output into "out" and "err and return when done.
71   virtual void Run() = 0;
72
73   // Called when an input reader should relinquish its control so another can
74   // be pushed onto the IO handler stack, or so the current IO handler can pop
75   // itself off the stack
76
77   virtual void Cancel() = 0;
78
79   // Called when CTRL+C is pressed which usually causes
80   // Debugger::DispatchInputInterrupt to be called.
81
82   virtual bool Interrupt() = 0;
83
84   virtual void GotEOF() = 0;
85
86   virtual bool IsActive() { return m_active && !m_done; }
87
88   virtual void SetIsDone(bool b) { m_done = b; }
89
90   virtual bool GetIsDone() { return m_done; }
91
92   Type GetType() const { return m_type; }
93
94   virtual void Activate() { m_active = true; }
95
96   virtual void Deactivate() { m_active = false; }
97
98   virtual void TerminalSizeChanged() {}
99
100   virtual const char *GetPrompt() {
101     // Prompt support isn't mandatory
102     return nullptr;
103   }
104
105   virtual bool SetPrompt(llvm::StringRef prompt) {
106     // Prompt support isn't mandatory
107     return false;
108   }
109   bool SetPrompt(const char *) = delete;
110
111   virtual ConstString GetControlSequence(char ch) { return ConstString(); }
112
113   virtual const char *GetCommandPrefix() { return nullptr; }
114
115   virtual const char *GetHelpPrologue() { return nullptr; }
116
117   int GetInputFD();
118
119   int GetOutputFD();
120
121   int GetErrorFD();
122
123   FILE *GetInputFILE();
124
125   FILE *GetOutputFILE();
126
127   FILE *GetErrorFILE();
128
129   lldb::FileSP &GetInputFileSP();
130
131   lldb::StreamFileSP &GetOutputStreamFileSP();
132
133   lldb::StreamFileSP &GetErrorStreamFileSP();
134
135   Debugger &GetDebugger() { return m_debugger; }
136
137   void *GetUserData() { return m_user_data; }
138
139   void SetUserData(void *user_data) { m_user_data = user_data; }
140
141   Flags &GetFlags() { return m_flags; }
142
143   const Flags &GetFlags() const { return m_flags; }
144
145   /// Check if the input is being supplied interactively by a user
146   ///
147   /// This will return true if the input stream is a terminal (tty or
148   /// pty) and can cause IO handlers to do different things (like
149   /// for a confirmation when deleting all breakpoints).
150   bool GetIsInteractive();
151
152   /// Check if the input is coming from a real terminal.
153   ///
154   /// A real terminal has a valid size with a certain number of rows
155   /// and columns. If this function returns true, then terminal escape
156   /// sequences are expected to work (cursor movement escape sequences,
157   /// clearing lines, etc).
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::FileSP m_input_sp;
172   lldb::StreamFileSP m_output_sp;
173   lldb::StreamFileSP m_error_sp;
174   repro::DataRecorder *m_data_recorder;
175   Predicate<bool> m_popped;
176   Flags m_flags;
177   Type m_type;
178   void *m_user_data;
179   bool m_done;
180   bool m_active;
181
182 private:
183   IOHandler(const IOHandler &) = delete;
184   const IOHandler &operator=(const IOHandler &) = delete;
185 };
186
187 /// A delegate class for use with IOHandler subclasses.
188 ///
189 /// The IOHandler delegate is designed to be mixed into classes so
190 /// they can use an IOHandler subclass to fetch input and notify the
191 /// object that inherits from this delegate class when a token is
192 /// received.
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, bool interactive) {}
203
204   virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
205
206   virtual void IOHandlerComplete(IOHandler &io_handler,
207                                  CompletionRequest &request);
208
209   virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
210
211   /// Called when a new line is created or one of an identified set of
212   /// indentation characters is typed.
213   ///
214   /// This function determines how much indentation should be added
215   /// or removed to match the recommended amount for the final line.
216   ///
217   /// \param[in] io_handler
218   ///     The IOHandler that responsible for input.
219   ///
220   /// \param[in] lines
221   ///     The current input up to the line to be corrected.  Lines
222   ///     following the line containing the cursor are not included.
223   ///
224   /// \param[in] cursor_position
225   ///     The number of characters preceding the cursor on the final
226   ///     line at the time.
227   ///
228   /// \return
229   ///     Returns an integer describing the number of spaces needed
230   ///     to correct the indentation level.  Positive values indicate
231   ///     that spaces should be added, while negative values represent
232   ///     spaces that should be removed.
233   virtual int IOHandlerFixIndentation(IOHandler &io_handler,
234                                       const StringList &lines,
235                                       int cursor_position) {
236     return 0;
237   }
238
239   /// Called when a line or lines have been retrieved.
240   ///
241   /// This function can handle the current line and possibly call
242   /// IOHandler::SetIsDone(true) when the IO handler is done like when
243   /// "quit" is entered as a command, of when an empty line is
244   /// received. It is up to the delegate to determine when a line
245   /// should cause a IOHandler to exit.
246   virtual void IOHandlerInputComplete(IOHandler &io_handler,
247                                       std::string &data) = 0;
248
249   virtual void IOHandlerInputInterrupted(IOHandler &io_handler,
250                                          std::string &data) {}
251
252   /// Called to determine whether typing enter after the last line in
253   /// \a lines should end input.  This function will not be called on
254   /// IOHandler objects that are getting single lines.
255   /// \param[in] io_handler
256   ///     The IOHandler that responsible for updating the lines.
257   ///
258   /// \param[in] lines
259   ///     The current multi-line content.  May be altered to provide
260   ///     alternative input when complete.
261   ///
262   /// \return
263   ///     Return an boolean to indicate whether input is complete,
264   ///     true indicates that no additional input is necessary, while
265   ///     false indicates that more input is required.
266   virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
267                                         StringList &lines) {
268     // Impose no requirements for input to be considered complete.  subclasses
269     // should do something more intelligent.
270     return true;
271   }
272
273   virtual ConstString IOHandlerGetControlSequence(char ch) {
274     return ConstString();
275   }
276
277   virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
278
279   virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
280
281   // Intercept the IOHandler::Interrupt() calls and do something.
282   //
283   // Return true if the interrupt was handled, false if the IOHandler should
284   // continue to try handle the interrupt itself.
285   virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
286
287 protected:
288   Completion m_completion; // Support for common builtin completions
289 };
290
291 // IOHandlerDelegateMultiline
292 //
293 // A IOHandlerDelegate that handles terminating multi-line input when
294 // the last line is equal to "end_line" which is specified in the constructor.
295 class IOHandlerDelegateMultiline : public IOHandlerDelegate {
296 public:
297   IOHandlerDelegateMultiline(const char *end_line,
298                              Completion completion = Completion::None)
299       : IOHandlerDelegate(completion),
300         m_end_line((end_line && end_line[0]) ? end_line : "") {}
301
302   ~IOHandlerDelegateMultiline() override = default;
303
304   ConstString IOHandlerGetControlSequence(char ch) override {
305     if (ch == 'd')
306       return ConstString(m_end_line + "\n");
307     return ConstString();
308   }
309
310   bool IOHandlerIsInputComplete(IOHandler &io_handler,
311                                 StringList &lines) override {
312     // Determine whether the end of input signal has been entered
313     const size_t num_lines = lines.GetSize();
314     if (num_lines > 0 && lines[num_lines - 1] == m_end_line) {
315       // Remove the terminal line from "lines" so it doesn't appear in the
316       // resulting input and return true to indicate we are done getting lines
317       lines.PopBack();
318       return true;
319     }
320     return false;
321   }
322
323 protected:
324   const std::string m_end_line;
325 };
326
327 class IOHandlerEditline : public IOHandler {
328 public:
329   IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
330                     const char *editline_name, // Used for saving history files
331                     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
332                     bool multi_line, bool color_prompts,
333                     uint32_t line_number_start, // If non-zero show line numbers
334                                                 // starting at
335                                                 // 'line_number_start'
336                     IOHandlerDelegate &delegate,
337                     repro::DataRecorder *data_recorder);
338
339   IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
340                     const lldb::FileSP &input_sp,
341                     const lldb::StreamFileSP &output_sp,
342                     const lldb::StreamFileSP &error_sp, uint32_t flags,
343                     const char *editline_name, // Used for saving history files
344                     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
345                     bool multi_line, bool color_prompts,
346                     uint32_t line_number_start, // If non-zero show line numbers
347                                                 // starting at
348                                                 // 'line_number_start'
349                     IOHandlerDelegate &delegate,
350                     repro::DataRecorder *data_recorder);
351
352   IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *,
353                     const char *, bool, bool, uint32_t,
354                     IOHandlerDelegate &) = delete;
355
356   IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &,
357                     const lldb::StreamFileSP &, const lldb::StreamFileSP &,
358                     uint32_t, const char *, const char *, const char *, bool,
359                     bool, uint32_t, IOHandlerDelegate &) = delete;
360
361   ~IOHandlerEditline() override;
362
363   void Run() override;
364
365   void Cancel() override;
366
367   bool Interrupt() override;
368
369   void GotEOF() override;
370
371   void Activate() override;
372
373   void Deactivate() override;
374
375   void TerminalSizeChanged() override;
376
377   ConstString GetControlSequence(char ch) override {
378     return m_delegate.IOHandlerGetControlSequence(ch);
379   }
380
381   const char *GetCommandPrefix() override {
382     return m_delegate.IOHandlerGetCommandPrefix();
383   }
384
385   const char *GetHelpPrologue() override {
386     return m_delegate.IOHandlerGetHelpPrologue();
387   }
388
389   const char *GetPrompt() override;
390
391   bool SetPrompt(llvm::StringRef prompt) override;
392   bool SetPrompt(const char *prompt) = delete;
393
394   const char *GetContinuationPrompt();
395
396   void SetContinuationPrompt(llvm::StringRef prompt);
397   void SetContinuationPrompt(const char *) = delete;
398
399   bool GetLine(std::string &line, bool &interrupted);
400
401   bool GetLines(StringList &lines, bool &interrupted);
402
403   void SetBaseLineNumber(uint32_t line);
404
405   bool GetInterruptExits() { return m_interrupt_exits; }
406
407   void SetInterruptExits(bool b) { m_interrupt_exits = b; }
408
409   const StringList *GetCurrentLines() const { return m_current_lines_ptr; }
410
411   uint32_t GetCurrentLineIndex() const;
412
413   void PrintAsync(Stream *stream, const char *s, size_t len) override;
414
415 private:
416 #if LLDB_ENABLE_LIBEDIT
417   static bool IsInputCompleteCallback(Editline *editline, StringList &lines,
418                                       void *baton);
419
420   static int FixIndentationCallback(Editline *editline, const StringList &lines,
421                                     int cursor_position, void *baton);
422
423   static void AutoCompleteCallback(CompletionRequest &request, void *baton);
424 #endif
425
426 protected:
427 #if LLDB_ENABLE_LIBEDIT
428   std::unique_ptr<Editline> m_editline_up;
429 #endif
430   IOHandlerDelegate &m_delegate;
431   std::string m_prompt;
432   std::string m_continuation_prompt;
433   StringList *m_current_lines_ptr;
434   uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
435   uint32_t m_curr_line_idx;
436   bool m_multi_line;
437   bool m_color_prompts;
438   bool m_interrupt_exits;
439   bool m_editing; // Set to true when fetching a line manually (not using
440                   // libedit)
441   std::string m_line_buffer;
442 };
443
444 // The order of base classes is important. Look at the constructor of
445 // IOHandlerConfirm to see how.
446 class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline {
447 public:
448   IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
449                    bool default_response);
450
451   ~IOHandlerConfirm() override;
452
453   bool GetResponse() const { return m_user_response; }
454
455   void IOHandlerComplete(IOHandler &io_handler,
456                          CompletionRequest &request) override;
457
458   void IOHandlerInputComplete(IOHandler &io_handler,
459                               std::string &data) override;
460
461 protected:
462   const bool m_default_response;
463   bool m_user_response;
464 };
465
466 class IOHandlerStack {
467 public:
468   IOHandlerStack() = default;
469
470   size_t GetSize() const {
471     std::lock_guard<std::recursive_mutex> guard(m_mutex);
472     return m_stack.size();
473   }
474
475   void Push(const lldb::IOHandlerSP &sp) {
476     if (sp) {
477       std::lock_guard<std::recursive_mutex> guard(m_mutex);
478       sp->SetPopped(false);
479       m_stack.push_back(sp);
480       // Set m_top the non-locking IsTop() call
481       m_top = sp.get();
482     }
483   }
484
485   bool IsEmpty() const {
486     std::lock_guard<std::recursive_mutex> guard(m_mutex);
487     return m_stack.empty();
488   }
489
490   lldb::IOHandlerSP Top() {
491     lldb::IOHandlerSP sp;
492     {
493       std::lock_guard<std::recursive_mutex> guard(m_mutex);
494       if (!m_stack.empty())
495         sp = m_stack.back();
496     }
497     return sp;
498   }
499
500   void Pop() {
501     std::lock_guard<std::recursive_mutex> guard(m_mutex);
502     if (!m_stack.empty()) {
503       lldb::IOHandlerSP sp(m_stack.back());
504       m_stack.pop_back();
505       sp->SetPopped(true);
506     }
507     // Set m_top the non-locking IsTop() call
508
509     m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
510   }
511
512   std::recursive_mutex &GetMutex() { return m_mutex; }
513
514   bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
515     return m_top == io_handler_sp.get();
516   }
517
518   bool CheckTopIOHandlerTypes(IOHandler::Type top_type,
519                               IOHandler::Type second_top_type) {
520     std::lock_guard<std::recursive_mutex> guard(m_mutex);
521     const size_t num_io_handlers = m_stack.size();
522     return (num_io_handlers >= 2 &&
523             m_stack[num_io_handlers - 1]->GetType() == top_type &&
524             m_stack[num_io_handlers - 2]->GetType() == second_top_type);
525   }
526
527   ConstString GetTopIOHandlerControlSequence(char ch) {
528     return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString());
529   }
530
531   const char *GetTopIOHandlerCommandPrefix() {
532     return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
533   }
534
535   const char *GetTopIOHandlerHelpPrologue() {
536     return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
537   }
538
539   void PrintAsync(Stream *stream, const char *s, size_t len);
540
541 protected:
542   typedef std::vector<lldb::IOHandlerSP> collection;
543   collection m_stack;
544   mutable std::recursive_mutex m_mutex;
545   IOHandler *m_top = nullptr;
546
547 private:
548   IOHandlerStack(const IOHandlerStack &) = delete;
549   const IOHandlerStack &operator=(const IOHandlerStack &) = delete;
550 };
551
552 } // namespace lldb_private
553
554 #endif // LLDB_CORE_IOHANDLER_H