LLDB mainline
IOHandler.h
Go to the documentation of this file.
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
13#include "lldb/Host/Config.h"
15#include "lldb/Utility/Flags.h"
17#include "lldb/Utility/Stream.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 <optional>
26#include <string>
27#include <vector>
28
29#include <cstdint>
30#include <cstdio>
31
32namespace lldb_private {
33class Debugger;
34} // namespace lldb_private
35
36namespace curses {
37class Application;
38typedef std::unique_ptr<Application> ApplicationAP;
39} // namespace curses
40
41namespace lldb_private {
42
43class IOHandler {
44public:
45 enum class Type {
48 Confirm,
49 Curses,
51 REPL,
56 Other
57 };
58
59 IOHandler(Debugger &debugger, IOHandler::Type type);
60
61 IOHandler(Debugger &debugger, IOHandler::Type type,
62 const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp,
63 const lldb::StreamFileSP &error_sp, uint32_t flags);
64
65 virtual ~IOHandler();
66
67 // Each IOHandler gets to run until it is done. It should read data from the
68 // "in" and place output into "out" and "err and return when done.
69 virtual void Run() = 0;
70
71 // Called when an input reader should relinquish its control so another can
72 // be pushed onto the IO handler stack, or so the current IO handler can pop
73 // 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 bool IsActive() { return m_active && !m_done; }
85
86 void SetIsDone(bool b) { m_done = b; }
87
88 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 void TerminalSizeChanged() {}
97
98 virtual const char *GetPrompt() {
99 // Prompt support isn't mandatory
100 return nullptr;
101 }
102
103 virtual bool SetPrompt(llvm::StringRef prompt) {
104 // Prompt support isn't mandatory
105 return false;
106 }
107 bool SetPrompt(const char *) = delete;
108
109 virtual llvm::StringRef GetControlSequence(char ch) { return {}; }
110
111 virtual const char *GetCommandPrefix() { return nullptr; }
112
113 virtual const char *GetHelpPrologue() { return nullptr; }
114
115 int GetInputFD();
116
117 int GetOutputFD();
118
119 int GetErrorFD();
120
121 FILE *GetInputFILE();
122
123 FILE *GetOutputFILE();
124
125 FILE *GetErrorFILE();
126
128
130
132
134
135 void *GetUserData() { return m_user_data; }
136
137 void SetUserData(void *user_data) { m_user_data = user_data; }
138
139 Flags &GetFlags() { return m_flags; }
140
141 const Flags &GetFlags() const { return m_flags; }
142
143 /// Check if the input is being supplied interactively by a user
144 ///
145 /// This will return true if the input stream is a terminal (tty or
146 /// pty) and can cause IO handlers to do different things (like
147 /// for a confirmation when deleting all breakpoints).
148 bool GetIsInteractive();
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 bool GetIsRealTerminal();
157
158 void SetPopped(bool b);
159
160 void WaitForPop();
161
162 virtual void PrintAsync(const char *s, size_t len, bool is_stdout);
163
164 std::recursive_mutex &GetOutputMutex() { return m_output_mutex; }
165
166protected:
171 std::recursive_mutex m_output_mutex;
176 bool m_done;
178
179private:
180 IOHandler(const IOHandler &) = delete;
181 const IOHandler &operator=(const IOHandler &) = delete;
182};
183
184/// A delegate class for use with IOHandler subclasses.
185///
186/// The IOHandler delegate is designed to be mixed into classes so
187/// they can use an IOHandler subclass to fetch input and notify the
188/// object that inherits from this delegate class when a token is
189/// received.
191public:
193
195 : m_completion(completion) {}
196
197 virtual ~IOHandlerDelegate() = default;
198
199 virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive) {}
200
201 virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
202
203 virtual std::optional<std::string> IOHandlerSuggestion(IOHandler &io_handler,
204 llvm::StringRef line);
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 llvm::StringRef IOHandlerGetControlSequence(char ch) { return {}; }
274
275 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
276
277 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
278
279 // Intercept the IOHandler::Interrupt() calls and do something.
280 //
281 // Return true if the interrupt was handled, false if the IOHandler should
282 // continue to try handle the interrupt itself.
283 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
284
285protected:
286 Completion m_completion; // Support for common builtin completions
287};
288
289// IOHandlerDelegateMultiline
290//
291// A IOHandlerDelegate that handles terminating multi-line input when
292// the last line is equal to "end_line" which is specified in the constructor.
294public:
295 IOHandlerDelegateMultiline(llvm::StringRef end_line,
296 Completion completion = Completion::None)
297 : IOHandlerDelegate(completion), m_end_line(end_line.str() + "\n") {}
298
299 ~IOHandlerDelegateMultiline() override = default;
300
301 llvm::StringRef IOHandlerGetControlSequence(char ch) override {
302 if (ch == 'd')
303 return m_end_line;
304 return {};
305 }
306
308 StringList &lines) override {
309 // Determine whether the end of input signal has been entered
310 const size_t num_lines = lines.GetSize();
311 const llvm::StringRef end_line =
312 llvm::StringRef(m_end_line).drop_back(1); // Drop '\n'
313 if (num_lines > 0 && llvm::StringRef(lines[num_lines - 1]) == end_line) {
314 // Remove the terminal line from "lines" so it doesn't appear in the
315 // resulting input and return true to indicate we are done getting lines
316 lines.PopBack();
317 return true;
318 }
319 return false;
320 }
321
322protected:
323 const std::string m_end_line;
324};
325
327public:
329 const char *editline_name, // Used for saving history files
330 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
331 bool multi_line, bool color,
332 uint32_t line_number_start, // If non-zero show line numbers
333 // starting at
334 // 'line_number_start'
335 IOHandlerDelegate &delegate);
336
338 const lldb::FileSP &input_sp,
339 const lldb::StreamFileSP &output_sp,
340 const lldb::StreamFileSP &error_sp, uint32_t flags,
341 const char *editline_name, // Used for saving history files
342 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
343 bool multi_line, bool color,
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 &, IOHandler::Type, const char *, const char *,
350 const char *, bool, bool, uint32_t,
351 IOHandlerDelegate &) = delete;
352
354 const lldb::StreamFileSP &, const lldb::StreamFileSP &,
355 uint32_t, const char *, const char *, const char *, bool,
356 bool, uint32_t, IOHandlerDelegate &) = delete;
357
358 ~IOHandlerEditline() override;
359
360 void Run() override;
361
362 void Cancel() override;
363
364 bool Interrupt() override;
365
366 void GotEOF() override;
367
368 void Activate() override;
369
370 void Deactivate() override;
371
372 void TerminalSizeChanged() override;
373
374 llvm::StringRef GetControlSequence(char ch) override {
376 }
377
378 const char *GetCommandPrefix() override {
380 }
381
382 const char *GetHelpPrologue() override {
384 }
385
386 const char *GetPrompt() override;
387
388 bool SetPrompt(llvm::StringRef prompt) override;
389 bool SetPrompt(const char *prompt) = delete;
390
391 const char *GetContinuationPrompt();
392
393 void SetContinuationPrompt(llvm::StringRef prompt);
394 void SetContinuationPrompt(const char *) = delete;
395
396 bool GetLine(std::string &line, bool &interrupted);
397
398 bool GetLines(StringList &lines, bool &interrupted);
399
400 void SetBaseLineNumber(uint32_t line);
401
403
405
407
408 uint32_t GetCurrentLineIndex() const;
409
410 void PrintAsync(const char *s, size_t len, bool is_stdout) override;
411
412private:
413#if LLDB_ENABLE_LIBEDIT
414 bool IsInputCompleteCallback(Editline *editline, StringList &lines);
415
416 int FixIndentationCallback(Editline *editline, const StringList &lines,
417 int cursor_position);
418
419 std::optional<std::string> SuggestionCallback(llvm::StringRef line);
420
421 void AutoCompleteCallback(CompletionRequest &request);
422#endif
423
424protected:
425#if LLDB_ENABLE_LIBEDIT
426 std::unique_ptr<Editline> m_editline_up;
427#endif
429 std::string m_prompt;
432 uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
437 std::string m_line_buffer;
438};
439
440// The order of base classes is important. Look at the constructor of
441// IOHandlerConfirm to see how.
443public:
444 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
445 bool default_response);
446
448
449 bool GetResponse() const { return m_user_response; }
450
451 void IOHandlerComplete(IOHandler &io_handler,
452 CompletionRequest &request) override;
453
454 void IOHandlerInputComplete(IOHandler &io_handler,
455 std::string &data) override;
456
457protected:
460};
461
463public:
464 IOHandlerStack() = default;
465
466 size_t GetSize() const {
467 std::lock_guard<std::recursive_mutex> guard(m_mutex);
468 return m_stack.size();
469 }
470
471 void Push(const lldb::IOHandlerSP &sp) {
472 if (sp) {
473 std::lock_guard<std::recursive_mutex> guard(m_mutex);
474 sp->SetPopped(false);
475 m_stack.push_back(sp);
476 // Set m_top the non-locking IsTop() call
477 m_top = sp.get();
478 }
479 }
480
481 bool IsEmpty() const {
482 std::lock_guard<std::recursive_mutex> guard(m_mutex);
483 return m_stack.empty();
484 }
485
488 {
489 std::lock_guard<std::recursive_mutex> guard(m_mutex);
490 if (!m_stack.empty())
491 sp = m_stack.back();
492 }
493 return sp;
494 }
495
496 void Pop() {
497 std::lock_guard<std::recursive_mutex> guard(m_mutex);
498 if (!m_stack.empty()) {
500 m_stack.pop_back();
501 sp->SetPopped(true);
502 }
503 // Set m_top the non-locking IsTop() call
504
505 m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
506 }
507
508 std::recursive_mutex &GetMutex() { return m_mutex; }
509
510 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
511 return m_top == io_handler_sp.get();
512 }
513
515 IOHandler::Type second_top_type) {
516 std::lock_guard<std::recursive_mutex> guard(m_mutex);
517 const size_t num_io_handlers = m_stack.size();
518 return (num_io_handlers >= 2 &&
519 m_stack[num_io_handlers - 1]->GetType() == top_type &&
520 m_stack[num_io_handlers - 2]->GetType() == second_top_type);
521 }
522
523 llvm::StringRef GetTopIOHandlerControlSequence(char ch) {
524 return ((m_top != nullptr) ? m_top->GetControlSequence(ch)
525 : llvm::StringRef());
526 }
527
529 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
530 }
531
533 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
534 }
535
536 bool PrintAsync(const char *s, size_t len, bool is_stdout);
537
538protected:
539 typedef std::vector<lldb::IOHandlerSP> collection;
541 mutable std::recursive_mutex m_mutex;
542 IOHandler *m_top = nullptr;
543
544private:
546 const IOHandlerStack &operator=(const IOHandlerStack &) = delete;
547};
548
549} // namespace lldb_private
550
551#endif // LLDB_CORE_IOHANDLER_H
"lldb/Utility/ArgCompletionRequest.h"
A class to manage flag bits.
Definition: Debugger.h:80
Instances of Editline provide an abstraction over libedit's EditLine facility.
Definition: Editline.h:155
Encapsulates a single expression for use in lldb.
Definition: Expression.h:31
A class to manage flags.
Definition: Flags.h:22
void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override
Called when a line or lines have been retrieved.
Definition: IOHandler.cpp:166
void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) override
Definition: IOHandler.cpp:159
bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) override
Called to determine whether typing enter after the last line in lines should end input.
Definition: IOHandler.h:307
llvm::StringRef IOHandlerGetControlSequence(char ch) override
Definition: IOHandler.h:301
~IOHandlerDelegateMultiline() override=default
IOHandlerDelegateMultiline(llvm::StringRef end_line, Completion completion=Completion::None)
Definition: IOHandler.h:295
A delegate class for use with IOHandler subclasses.
Definition: IOHandler.h:190
virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive)
Definition: IOHandler.h:199
virtual void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request)
Definition: IOHandler.cpp:209
virtual const char * IOHandlerGetFixIndentationCharacters()
Definition: IOHandler.h:209
virtual llvm::StringRef IOHandlerGetControlSequence(char ch)
Definition: IOHandler.h:273
virtual const char * IOHandlerGetHelpPrologue()
Definition: IOHandler.h:277
virtual void IOHandlerInputComplete(IOHandler &io_handler, std::string &data)=0
Called when a line or lines have been retrieved.
virtual bool IOHandlerInterrupt(IOHandler &io_handler)
Definition: IOHandler.h:283
virtual void IOHandlerDeactivated(IOHandler &io_handler)
Definition: IOHandler.h:201
virtual bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines)
Called to determine whether typing enter after the last line in lines should end input.
Definition: IOHandler.h:266
virtual std::optional< std::string > IOHandlerSuggestion(IOHandler &io_handler, llvm::StringRef line)
Definition: IOHandler.cpp:202
virtual ~IOHandlerDelegate()=default
IOHandlerDelegate(Completion completion=Completion::None)
Definition: IOHandler.h:194
virtual int IOHandlerFixIndentation(IOHandler &io_handler, const StringList &lines, int cursor_position)
Called when a new line is created or one of an identified set of indentation characters is typed.
Definition: IOHandler.h:233
virtual const char * IOHandlerGetCommandPrefix()
Definition: IOHandler.h:275
virtual void IOHandlerInputInterrupted(IOHandler &io_handler, std::string &data)
Definition: IOHandler.h:249
void PrintAsync(const char *s, size_t len, bool is_stdout) override
Definition: IOHandler.cpp:634
bool SetPrompt(llvm::StringRef prompt) override
Definition: IOHandler.cpp:475
const char * GetHelpPrologue() override
Definition: IOHandler.h:382
bool GetLine(std::string &line, bool &interrupted)
Definition: IOHandler.cpp:351
const char * GetCommandPrefix() override
Definition: IOHandler.h:378
void TerminalSizeChanged() override
Definition: IOHandler.cpp:323
bool GetLines(StringList &lines, bool &interrupted)
Definition: IOHandler.cpp:535
bool SetPrompt(const char *prompt)=delete
llvm::StringRef GetControlSequence(char ch) override
Definition: IOHandler.h:374
void SetContinuationPrompt(const char *)=delete
const char * GetContinuationPrompt()
Definition: IOHandler.cpp:492
IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &, const lldb::StreamFileSP &, const lldb::StreamFileSP &, uint32_t, const char *, const char *, const char *, bool, bool, uint32_t, IOHandlerDelegate &)=delete
void SetBaseLineNumber(uint32_t line)
Definition: IOHandler.cpp:508
void SetContinuationPrompt(llvm::StringRef prompt)
Definition: IOHandler.cpp:497
IOHandlerDelegate & m_delegate
Definition: IOHandler.h:428
const char * GetPrompt() override
Definition: IOHandler.cpp:461
uint32_t GetCurrentLineIndex() const
Definition: IOHandler.cpp:512
StringList GetCurrentLines() const
Definition: IOHandler.cpp:520
IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, const char *, bool, bool, uint32_t, IOHandlerDelegate &)=delete
const char * GetTopIOHandlerHelpPrologue()
Definition: IOHandler.h:532
const IOHandlerStack & operator=(const IOHandlerStack &)=delete
bool PrintAsync(const char *s, size_t len, bool is_stdout)
Definition: IOHandler.cpp:128
lldb::IOHandlerSP Top()
Definition: IOHandler.h:486
llvm::StringRef GetTopIOHandlerControlSequence(char ch)
Definition: IOHandler.h:523
bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const
Definition: IOHandler.h:510
void Push(const lldb::IOHandlerSP &sp)
Definition: IOHandler.h:471
std::recursive_mutex & GetMutex()
Definition: IOHandler.h:508
IOHandlerStack(const IOHandlerStack &)=delete
bool CheckTopIOHandlerTypes(IOHandler::Type top_type, IOHandler::Type second_top_type)
Definition: IOHandler.h:514
std::recursive_mutex m_mutex
Definition: IOHandler.h:541
std::vector< lldb::IOHandlerSP > collection
Definition: IOHandler.h:539
const char * GetTopIOHandlerCommandPrefix()
Definition: IOHandler.h:528
virtual void TerminalSizeChanged()
Definition: IOHandler.h:96
const Flags & GetFlags() const
Definition: IOHandler.h:141
virtual void PrintAsync(const char *s, size_t len, bool is_stdout)
Definition: IOHandler.cpp:121
Predicate< bool > m_popped
Definition: IOHandler.h:172
virtual bool SetPrompt(llvm::StringRef prompt)
Definition: IOHandler.h:103
virtual void Run()=0
virtual const char * GetHelpPrologue()
Definition: IOHandler.h:113
virtual void Activate()
Definition: IOHandler.h:92
virtual void Cancel()=0
lldb::StreamFileSP GetErrorStreamFileSP()
Definition: IOHandler.cpp:107
bool GetIsRealTerminal()
Check if the input is coming from a real terminal.
Definition: IOHandler.cpp:113
virtual const char * GetPrompt()
Definition: IOHandler.h:98
lldb::FileSP GetInputFileSP()
Definition: IOHandler.cpp:103
std::recursive_mutex & GetOutputMutex()
Definition: IOHandler.h:164
virtual bool Interrupt()=0
Debugger & GetDebugger()
Definition: IOHandler.h:133
const IOHandler & operator=(const IOHandler &)=delete
std::recursive_mutex m_output_mutex
Definition: IOHandler.h:171
Type GetType() const
Definition: IOHandler.h:90
virtual void Deactivate()
Definition: IOHandler.h:94
virtual void GotEOF()=0
lldb::StreamFileSP m_error_sp
Definition: IOHandler.h:170
virtual llvm::StringRef GetControlSequence(char ch)
Definition: IOHandler.h:109
virtual const char * GetCommandPrefix()
Definition: IOHandler.h:111
lldb::StreamFileSP GetOutputStreamFileSP()
Definition: IOHandler.cpp:105
bool GetIsInteractive()
Check if the input is being supplied interactively by a user.
Definition: IOHandler.cpp:109
lldb::FileSP m_input_sp
Definition: IOHandler.h:168
bool SetPrompt(const char *)=delete
void SetPopped(bool b)
Definition: IOHandler.cpp:117
lldb::StreamFileSP m_output_sp
Definition: IOHandler.h:169
IOHandler(const IOHandler &)=delete
void SetUserData(void *user_data)
Definition: IOHandler.h:137
void SetIsDone(bool b)
Definition: IOHandler.h:86
A C++ wrapper class for providing threaded access to a value of type T.
Definition: Predicate.h:42
size_t GetSize() const
Definition: StringList.cpp:74
std::unique_ptr< Application > ApplicationAP
Definition: IOHandler.h:38
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
Definition: lldb-forward.h:359
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:429
std::shared_ptr< lldb_private::File > FileSP
Definition: lldb-forward.h:351