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