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
12#include "lldb/Host/Config.h"
14#include "lldb/Utility/Flags.h"
16#include "lldb/Utility/Stream.h"
18#include "lldb/lldb-defines.h"
19#include "lldb/lldb-forward.h"
20#include "llvm/ADT/StringRef.h"
21
22#include <memory>
23#include <mutex>
24#include <optional>
25#include <string>
26#include <vector>
27
28#include <cstdint>
29#include <cstdio>
30
31namespace lldb_private {
32class Debugger;
33} // namespace lldb_private
34
35namespace curses {
36class Application;
37typedef std::unique_ptr<Application> ApplicationAP;
38} // namespace curses
39
40namespace lldb_private {
41
42class IOHandler {
43public:
44 enum class Type {
47 Confirm,
48 Curses,
50 REPL,
55 Other
56 };
57
58 IOHandler(Debugger &debugger, IOHandler::Type type);
59
60 IOHandler(Debugger &debugger, IOHandler::Type type,
61 const lldb::FileSP &input_sp, 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
83 bool IsActive() { return m_active && !m_done; }
84
85 void SetIsDone(bool b) { m_done = b; }
86
87 bool GetIsDone() { return m_done; }
88
89 Type GetType() const { return m_type; }
90
91 virtual void Activate() { m_active = true; }
92
93 virtual void Deactivate() { m_active = false; }
94
95 virtual void TerminalSizeChanged() {}
96
97 virtual const char *GetPrompt() {
98 // Prompt support isn't mandatory
99 return nullptr;
100 }
101
102 virtual bool SetPrompt(llvm::StringRef prompt) {
103 // Prompt support isn't mandatory
104 return false;
105 }
106 bool SetPrompt(const char *) = delete;
107
108 virtual llvm::StringRef GetControlSequence(char ch) { return {}; }
109
110 virtual const char *GetCommandPrefix() { return nullptr; }
111
112 virtual const char *GetHelpPrologue() { return nullptr; }
113
114 int GetInputFD();
115
116 int GetOutputFD();
117
118 int GetErrorFD();
119
120 FILE *GetInputFILE();
121
122 FILE *GetOutputFILE();
123
124 FILE *GetErrorFILE();
125
127
129
131
133
134 void *GetUserData() { return m_user_data; }
135
136 void SetUserData(void *user_data) { m_user_data = user_data; }
137
138 Flags &GetFlags() { return m_flags; }
139
140 const Flags &GetFlags() const { return m_flags; }
141
142 /// Check if the input is being supplied interactively by a user
143 ///
144 /// This will return true if the input stream is a terminal (tty or
145 /// pty) and can cause IO handlers to do different things (like
146 /// for a confirmation when deleting all breakpoints).
147 bool GetIsInteractive();
148
149 /// Check if the input is coming from a real terminal.
150 ///
151 /// A real terminal has a valid size with a certain number of rows
152 /// and columns. If this function returns true, then terminal escape
153 /// sequences are expected to work (cursor movement escape sequences,
154 /// clearing lines, etc).
155 bool GetIsRealTerminal();
156
157 void SetPopped(bool b);
158
159 void WaitForPop();
160
161 virtual void PrintAsync(const char *s, size_t len, bool is_stdout);
162
163 std::recursive_mutex &GetOutputMutex() { return m_output_mutex; }
164
165protected:
170 std::recursive_mutex m_output_mutex;
175 bool m_done;
177
178private:
179 IOHandler(const IOHandler &) = delete;
180 const IOHandler &operator=(const IOHandler &) = delete;
181};
182
183/// A delegate class for use with IOHandler subclasses.
184///
185/// The IOHandler delegate is designed to be mixed into classes so
186/// they can use an IOHandler subclass to fetch input and notify the
187/// object that inherits from this delegate class when a token is
188/// received.
190public:
192
194 : m_completion(completion) {}
195
196 virtual ~IOHandlerDelegate() = default;
197
198 virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive) {}
199
200 virtual void IOHandlerDeactivated(IOHandler &io_handler) {}
201
202 virtual std::optional<std::string> IOHandlerSuggestion(IOHandler &io_handler,
203 llvm::StringRef line);
204
205 virtual void IOHandlerComplete(IOHandler &io_handler,
206 CompletionRequest &request);
207
208 virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
209
210 /// Called when a new line is created or one of an identified set of
211 /// indentation characters is typed.
212 ///
213 /// This function determines how much indentation should be added
214 /// or removed to match the recommended amount for the final line.
215 ///
216 /// \param[in] io_handler
217 /// The IOHandler that responsible for input.
218 ///
219 /// \param[in] lines
220 /// The current input up to the line to be corrected. Lines
221 /// following the line containing the cursor are not included.
222 ///
223 /// \param[in] cursor_position
224 /// The number of characters preceding the cursor on the final
225 /// line at the time.
226 ///
227 /// \return
228 /// Returns an integer describing the number of spaces needed
229 /// to correct the indentation level. Positive values indicate
230 /// that spaces should be added, while negative values represent
231 /// spaces that should be removed.
232 virtual int IOHandlerFixIndentation(IOHandler &io_handler,
233 const StringList &lines,
234 int cursor_position) {
235 return 0;
236 }
237
238 /// Called when a line or lines have been retrieved.
239 ///
240 /// This function can handle the current line and possibly call
241 /// IOHandler::SetIsDone(true) when the IO handler is done like when
242 /// "quit" is entered as a command, of when an empty line is
243 /// received. It is up to the delegate to determine when a line
244 /// should cause a IOHandler to exit.
245 virtual void IOHandlerInputComplete(IOHandler &io_handler,
246 std::string &data) = 0;
247
248 virtual void IOHandlerInputInterrupted(IOHandler &io_handler,
249 std::string &data) {}
250
251 /// Called to determine whether typing enter after the last line in
252 /// \a lines should end input. This function will not be called on
253 /// IOHandler objects that are getting single lines.
254 /// \param[in] io_handler
255 /// The IOHandler that responsible for updating the lines.
256 ///
257 /// \param[in] lines
258 /// The current multi-line content. May be altered to provide
259 /// alternative input when complete.
260 ///
261 /// \return
262 /// Return an boolean to indicate whether input is complete,
263 /// true indicates that no additional input is necessary, while
264 /// false indicates that more input is required.
265 virtual bool IOHandlerIsInputComplete(IOHandler &io_handler,
266 StringList &lines) {
267 // Impose no requirements for input to be considered complete. subclasses
268 // should do something more intelligent.
269 return true;
270 }
271
272 virtual llvm::StringRef IOHandlerGetControlSequence(char ch) { return {}; }
273
274 virtual const char *IOHandlerGetCommandPrefix() { return nullptr; }
275
276 virtual const char *IOHandlerGetHelpPrologue() { return nullptr; }
277
278 // Intercept the IOHandler::Interrupt() calls and do something.
279 //
280 // Return true if the interrupt was handled, false if the IOHandler should
281 // continue to try handle the interrupt itself.
282 virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; }
283
284protected:
285 Completion m_completion; // Support for common builtin completions
286};
287
288// IOHandlerDelegateMultiline
289//
290// A IOHandlerDelegate that handles terminating multi-line input when
291// the last line is equal to "end_line" which is specified in the constructor.
293public:
294 IOHandlerDelegateMultiline(llvm::StringRef end_line,
295 Completion completion = Completion::None)
296 : IOHandlerDelegate(completion), m_end_line(end_line.str() + "\n") {}
297
298 ~IOHandlerDelegateMultiline() override = default;
299
300 llvm::StringRef IOHandlerGetControlSequence(char ch) override {
301 if (ch == 'd')
302 return m_end_line;
303 return {};
304 }
305
307 StringList &lines) override {
308 // Determine whether the end of input signal has been entered
309 const size_t num_lines = lines.GetSize();
310 const llvm::StringRef end_line =
311 llvm::StringRef(m_end_line).drop_back(1); // Drop '\n'
312 if (num_lines > 0 && llvm::StringRef(lines[num_lines - 1]) == end_line) {
313 // Remove the terminal line from "lines" so it doesn't appear in the
314 // resulting input and return true to indicate we are done getting lines
315 lines.PopBack();
316 return true;
317 }
318 return false;
319 }
320
321protected:
322 const std::string m_end_line;
323};
324
326public:
328 const char *editline_name, // Used for saving history files
329 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
330 bool multi_line, bool color,
331 uint32_t line_number_start, // If non-zero show line numbers
332 // starting at
333 // 'line_number_start'
334 IOHandlerDelegate &delegate);
335
337 const lldb::FileSP &input_sp,
338 const lldb::StreamFileSP &output_sp,
339 const lldb::StreamFileSP &error_sp, uint32_t flags,
340 const char *editline_name, // Used for saving history files
341 llvm::StringRef prompt, llvm::StringRef continuation_prompt,
342 bool multi_line, bool color,
343 uint32_t line_number_start, // If non-zero show line numbers
344 // starting at
345 // 'line_number_start'
346 IOHandlerDelegate &delegate);
347
348 IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *,
349 const char *, bool, bool, uint32_t,
350 IOHandlerDelegate &) = delete;
351
353 const lldb::StreamFileSP &, const lldb::StreamFileSP &,
354 uint32_t, const char *, const char *, const char *, bool,
355 bool, uint32_t, IOHandlerDelegate &) = delete;
356
357 ~IOHandlerEditline() override;
358
359 void Run() override;
360
361 void Cancel() override;
362
363 bool Interrupt() override;
364
365 void GotEOF() override;
366
367 void Activate() override;
368
369 void Deactivate() override;
370
371 void TerminalSizeChanged() override;
372
373 llvm::StringRef GetControlSequence(char ch) override {
375 }
376
377 const char *GetCommandPrefix() override {
379 }
380
381 const char *GetHelpPrologue() override {
383 }
384
385 const char *GetPrompt() override;
386
387 bool SetPrompt(llvm::StringRef prompt) override;
388 bool SetPrompt(const char *prompt) = delete;
389
390 const char *GetContinuationPrompt();
391
392 void SetContinuationPrompt(llvm::StringRef prompt);
393 void SetContinuationPrompt(const char *) = delete;
394
395 bool GetLine(std::string &line, bool &interrupted);
396
397 bool GetLines(StringList &lines, bool &interrupted);
398
399 void SetBaseLineNumber(uint32_t line);
400
402
404
406
407 uint32_t GetCurrentLineIndex() const;
408
409 void PrintAsync(const char *s, size_t len, bool is_stdout) override;
410
411private:
412#if LLDB_ENABLE_LIBEDIT
413 bool IsInputCompleteCallback(Editline *editline, StringList &lines);
414
415 int FixIndentationCallback(Editline *editline, const StringList &lines,
416 int cursor_position);
417
418 std::optional<std::string> SuggestionCallback(llvm::StringRef line);
419
420 void AutoCompleteCallback(CompletionRequest &request);
421#endif
422
423protected:
424#if LLDB_ENABLE_LIBEDIT
425 std::unique_ptr<Editline> m_editline_up;
426#endif
428 std::string m_prompt;
431 uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt
436 std::string m_line_buffer;
437};
438
439// The order of base classes is important. Look at the constructor of
440// IOHandlerConfirm to see how.
442public:
443 IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
444 bool default_response);
445
447
448 bool GetResponse() const { return m_user_response; }
449
450 void IOHandlerComplete(IOHandler &io_handler,
451 CompletionRequest &request) override;
452
453 void IOHandlerInputComplete(IOHandler &io_handler,
454 std::string &data) override;
455
456protected:
459};
460
462public:
463 IOHandlerStack() = default;
464
465 size_t GetSize() const {
466 std::lock_guard<std::recursive_mutex> guard(m_mutex);
467 return m_stack.size();
468 }
469
470 void Push(const lldb::IOHandlerSP &sp) {
471 if (sp) {
472 std::lock_guard<std::recursive_mutex> guard(m_mutex);
473 sp->SetPopped(false);
474 m_stack.push_back(sp);
475 // Set m_top the non-locking IsTop() call
476 m_top = sp.get();
477 }
478 }
479
480 bool IsEmpty() const {
481 std::lock_guard<std::recursive_mutex> guard(m_mutex);
482 return m_stack.empty();
483 }
484
487 {
488 std::lock_guard<std::recursive_mutex> guard(m_mutex);
489 if (!m_stack.empty())
490 sp = m_stack.back();
491 }
492 return sp;
493 }
494
495 void Pop() {
496 std::lock_guard<std::recursive_mutex> guard(m_mutex);
497 if (!m_stack.empty()) {
499 m_stack.pop_back();
500 sp->SetPopped(true);
501 }
502 // Set m_top the non-locking IsTop() call
503
504 m_top = (m_stack.empty() ? nullptr : m_stack.back().get());
505 }
506
507 std::recursive_mutex &GetMutex() { return m_mutex; }
508
509 bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const {
510 return m_top == io_handler_sp.get();
511 }
512
514 IOHandler::Type second_top_type) {
515 std::lock_guard<std::recursive_mutex> guard(m_mutex);
516 const size_t num_io_handlers = m_stack.size();
517 return (num_io_handlers >= 2 &&
518 m_stack[num_io_handlers - 1]->GetType() == top_type &&
519 m_stack[num_io_handlers - 2]->GetType() == second_top_type);
520 }
521
522 llvm::StringRef GetTopIOHandlerControlSequence(char ch) {
523 return ((m_top != nullptr) ? m_top->GetControlSequence(ch)
524 : llvm::StringRef());
525 }
526
528 return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr);
529 }
530
532 return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr);
533 }
534
535 bool PrintAsync(const char *s, size_t len, bool is_stdout);
536
537protected:
538 typedef std::vector<lldb::IOHandlerSP> collection;
540 mutable std::recursive_mutex m_mutex;
541 IOHandler *m_top = nullptr;
542
543private:
545 const IOHandlerStack &operator=(const IOHandlerStack &) = delete;
546};
547
548} // namespace lldb_private
549
550#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:152
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:306
llvm::StringRef IOHandlerGetControlSequence(char ch) override
Definition: IOHandler.h:300
~IOHandlerDelegateMultiline() override=default
IOHandlerDelegateMultiline(llvm::StringRef end_line, Completion completion=Completion::None)
Definition: IOHandler.h:294
A delegate class for use with IOHandler subclasses.
Definition: IOHandler.h:189
virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive)
Definition: IOHandler.h:198
virtual void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request)
Definition: IOHandler.cpp:209
virtual const char * IOHandlerGetFixIndentationCharacters()
Definition: IOHandler.h:208
virtual llvm::StringRef IOHandlerGetControlSequence(char ch)
Definition: IOHandler.h:272
virtual const char * IOHandlerGetHelpPrologue()
Definition: IOHandler.h:276
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:282
virtual void IOHandlerDeactivated(IOHandler &io_handler)
Definition: IOHandler.h:200
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:265
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:193
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:232
virtual const char * IOHandlerGetCommandPrefix()
Definition: IOHandler.h:274
virtual void IOHandlerInputInterrupted(IOHandler &io_handler, std::string &data)
Definition: IOHandler.h:248
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:381
bool GetLine(std::string &line, bool &interrupted)
Definition: IOHandler.cpp:351
const char * GetCommandPrefix() override
Definition: IOHandler.h:377
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:373
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:427
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:531
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:485
llvm::StringRef GetTopIOHandlerControlSequence(char ch)
Definition: IOHandler.h:522
bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const
Definition: IOHandler.h:509
void Push(const lldb::IOHandlerSP &sp)
Definition: IOHandler.h:470
std::recursive_mutex & GetMutex()
Definition: IOHandler.h:507
IOHandlerStack(const IOHandlerStack &)=delete
bool CheckTopIOHandlerTypes(IOHandler::Type top_type, IOHandler::Type second_top_type)
Definition: IOHandler.h:513
std::recursive_mutex m_mutex
Definition: IOHandler.h:540
std::vector< lldb::IOHandlerSP > collection
Definition: IOHandler.h:538
const char * GetTopIOHandlerCommandPrefix()
Definition: IOHandler.h:527
virtual void TerminalSizeChanged()
Definition: IOHandler.h:95
const Flags & GetFlags() const
Definition: IOHandler.h:140
virtual void PrintAsync(const char *s, size_t len, bool is_stdout)
Definition: IOHandler.cpp:121
Predicate< bool > m_popped
Definition: IOHandler.h:171
virtual bool SetPrompt(llvm::StringRef prompt)
Definition: IOHandler.h:102
virtual void Run()=0
virtual const char * GetHelpPrologue()
Definition: IOHandler.h:112
virtual void Activate()
Definition: IOHandler.h:91
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:97
lldb::FileSP GetInputFileSP()
Definition: IOHandler.cpp:103
std::recursive_mutex & GetOutputMutex()
Definition: IOHandler.h:163
virtual bool Interrupt()=0
Debugger & GetDebugger()
Definition: IOHandler.h:132
const IOHandler & operator=(const IOHandler &)=delete
std::recursive_mutex m_output_mutex
Definition: IOHandler.h:170
Type GetType() const
Definition: IOHandler.h:89
virtual void Deactivate()
Definition: IOHandler.h:93
virtual void GotEOF()=0
lldb::StreamFileSP m_error_sp
Definition: IOHandler.h:169
virtual llvm::StringRef GetControlSequence(char ch)
Definition: IOHandler.h:108
virtual const char * GetCommandPrefix()
Definition: IOHandler.h:110
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:167
bool SetPrompt(const char *)=delete
void SetPopped(bool b)
Definition: IOHandler.cpp:117
lldb::StreamFileSP m_output_sp
Definition: IOHandler.h:168
IOHandler(const IOHandler &)=delete
void SetUserData(void *user_data)
Definition: IOHandler.h:136
void SetIsDone(bool b)
Definition: IOHandler.h:85
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:37
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
Definition: lldb-forward.h:361
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:433
std::shared_ptr< lldb_private::File > FileSP
Definition: lldb-forward.h:353