LLDB mainline
REPL.cpp
Go to the documentation of this file.
1//===-- REPL.cpp ----------------------------------------------------------===//
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
10#include "lldb/Core/Debugger.h"
14#include "lldb/Host/HostInfo.h"
18#include "lldb/Target/Thread.h"
20
21#include <memory>
22
23using namespace lldb_private;
24
25char REPL::ID;
26
27REPL::REPL(Target &target) : m_target(target) {
28 // Make sure all option values have sane defaults
29 Debugger &debugger = m_target.GetDebugger();
30 debugger.SetShowProgress(false);
31 auto exe_ctx = debugger.GetCommandInterpreter().GetExecutionContext();
32 m_format_options.OptionParsingStarting(&exe_ctx);
33 m_varobj_options.OptionParsingStarting(&exe_ctx);
34}
35
36REPL::~REPL() = default;
37
39 Debugger *debugger, Target *target,
40 const char *repl_options) {
41 lldb::REPLSP ret;
42
43 for (auto &cbs : PluginManager::GetREPLCallbacks()) {
44 if (!cbs.supported_languages[language])
45 continue;
46 ret = (*cbs.create_callback)(err, language, debugger, target, repl_options);
47 if (ret)
48 break;
49 }
50
51 return ret;
52}
53
54std::string REPL::GetSourcePath() {
55 llvm::StringRef file_basename = GetSourceFileBasename();
56 FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
57 if (tmpdir_file_spec) {
58 tmpdir_file_spec.SetFilename(file_basename);
59 m_repl_source_path = tmpdir_file_spec.GetPath();
60 } else {
61 tmpdir_file_spec = FileSpec("/tmp");
62 tmpdir_file_spec.AppendPathComponent(file_basename);
63 }
64
65 return tmpdir_file_spec.GetPath();
66}
67
69 if (!m_io_handler_sp) {
70 Debugger &debugger = m_target.GetDebugger();
71 m_io_handler_sp = std::make_shared<IOHandlerEditline>(
72 debugger, IOHandler::Type::REPL,
73 "lldb-repl", // Name of input reader for history
74 llvm::StringRef("> "), // prompt
75 llvm::StringRef(". "), // Continuation prompt
76 true, // Multi-line
77 true, // The REPL prompt is always colored
78 1, // Line number
79 *this);
80
81 // Don't exit if CTRL+C is pressed
82 static_cast<IOHandlerEditline *>(m_io_handler_sp.get())
83 ->SetInterruptExits(false);
84
85 if (m_io_handler_sp->GetIsInteractive() &&
86 m_io_handler_sp->GetIsRealTerminal()) {
87 m_indent_str.assign(debugger.GetTabSize(), ' ');
89 } else {
90 m_indent_str.clear();
92 }
93 }
94 return m_io_handler_sp;
95}
96
97void REPL::IOHandlerActivated(IOHandler &io_handler, bool interactive) {
98 lldb::ProcessSP process_sp = m_target.GetProcessSP();
99 if (process_sp && process_sp->IsAlive())
100 return;
101 LockedStreamFile locked_stream = io_handler.GetErrorStreamFileSP()->Lock();
102 locked_stream.PutCString("REPL requires a running target process.\n");
103 io_handler.SetIsDone(true);
104}
105
106bool REPL::IOHandlerInterrupt(IOHandler &io_handler) { return false; }
107
108void REPL::IOHandlerInputInterrupted(IOHandler &io_handler, std::string &line) {
109}
110
114
115llvm::StringRef REPL::IOHandlerGetControlSequence(char ch) {
116 static constexpr llvm::StringLiteral control_sequence(":quit\n");
117 if (ch == 'd')
118 return control_sequence;
119 return {};
120}
121
122const char *REPL::IOHandlerGetCommandPrefix() { return ":"; }
123
125 return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
126 "Valid statements, expressions, and declarations are immediately "
127 "compiled and executed.\n\n"
128 "The complete set of LLDB debugging commands are also available as "
129 "described below.\n\nCommands "
130 "must be prefixed with a colon at the REPL prompt (:quit for "
131 "example.) Typing just a colon "
132 "followed by return will switch to the LLDB prompt.\n\n"
133 "Type “< path” to read in code from a text file “path”.\n\n";
134}
135
137 // Check for meta command
138 const size_t num_lines = lines.GetSize();
139 if (num_lines == 1) {
140 const char *first_line = lines.GetStringAtIndex(0);
141 if (first_line[0] == ':')
142 return true; // Meta command is a single line where that starts with ':'
143 }
144
145 // Check if REPL input is done
146 std::string source_string(lines.CopyList());
147 return SourceIsComplete(source_string);
148}
149
151 std::string last_line = lines[lines.GetSize() - 1];
152
153 int actual_indent = 0;
154 for (char &ch : last_line) {
155 if (ch != ' ')
156 break;
157 ++actual_indent;
158 }
159
160 return actual_indent;
161}
162
164 const StringList &lines,
165 int cursor_position) {
167 return 0;
168
169 if (!lines.GetSize()) {
170 return 0;
171 }
172
173 int tab_size = io_handler.GetDebugger().GetTabSize();
174
175 lldb::offset_t desired_indent =
176 GetDesiredIndentation(lines, cursor_position, tab_size);
177
178 int actual_indent = REPL::CalculateActualIndentation(lines);
179
180 if (desired_indent == LLDB_INVALID_OFFSET)
181 return 0;
182
183 return (int)desired_indent - actual_indent;
184}
185
186static bool ReadCode(const std::string &path, std::string &code,
187 lldb::LockableStreamFileSP &error_stream_sp) {
188 auto &fs = FileSystem::Instance();
189 llvm::Twine pathTwine(path);
190 if (!fs.Exists(pathTwine)) {
191 error_stream_sp->Lock().Printf("no such file at path '%s'\n", path.c_str());
192 return false;
193 }
194 if (!fs.Readable(pathTwine)) {
195 error_stream_sp->Lock().Printf("could not read file at path '%s'\n",
196 path.c_str());
197 return false;
198 }
199 const size_t file_size = fs.GetByteSize(pathTwine);
200 const size_t max_size = code.max_size();
201 if (file_size > max_size) {
202 error_stream_sp->Lock().Printf("file at path '%s' too large: "
203 "file_size = %zu, max_size = %zu\n",
204 path.c_str(), file_size, max_size);
205 return false;
206 }
207 auto data_sp = fs.CreateDataBuffer(pathTwine);
208 if (data_sp == nullptr) {
209 error_stream_sp->Lock().Printf(
210 "could not create buffer for file at path '%s'\n", path.c_str());
211 return false;
212 }
213 code.assign((const char *)data_sp->GetBytes(), data_sp->GetByteSize());
214 return true;
215}
216
217void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
218 lldb::LockableStreamFileSP output_stream_sp =
219 io_handler.GetOutputStreamFileSP();
220 lldb::LockableStreamFileSP error_stream_sp =
221 io_handler.GetErrorStreamFileSP();
222 bool extra_line = false;
223 bool did_quit = false;
224
225 if (code.empty()) {
226 m_code.AppendString("");
227 static_cast<IOHandlerEditline &>(io_handler)
228 .SetBaseLineNumber(m_code.GetSize() + 1);
229 } else {
230 Debugger &debugger = m_target.GetDebugger();
232 extra_line = ci.GetSpaceReplPrompts();
233
234 ExecutionContext exe_ctx(m_target.GetProcessSP()
235 ->GetThreadList()
236 .GetSelectedThread()
237 ->GetSelectedFrame(DoNoSelectMostRelevantFrame)
238 .get());
239
240 lldb::ProcessSP process_sp(exe_ctx.GetProcessSP());
241
242 if (code[0] == ':') {
243 // Meta command
244 // Strip the ':'
245 code.erase(0, 1);
246 if (!llvm::StringRef(code).trim().empty()) {
247 // "lldb" was followed by arguments, so just execute the command dump
248 // the results
249
250 // Turn off prompt on quit in case the user types ":quit"
251 const bool saved_prompt_on_quit = ci.GetPromptOnQuit();
252 if (saved_prompt_on_quit)
253 ci.SetPromptOnQuit(false);
254
255 // Execute the command
256 CommandReturnObject result(debugger.GetUseColor());
257 result.SetImmediateOutputStream(std::make_shared<StreamFile>(
258 output_stream_sp->GetUnlockedFileSP()));
260 std::make_shared<StreamFile>(error_stream_sp->GetUnlockedFileSP()));
261 ci.HandleCommand(code.c_str(), eLazyBoolNo, result);
262
263 if (saved_prompt_on_quit)
264 ci.SetPromptOnQuit(true);
265
266 if (result.GetStatus() == lldb::eReturnStatusQuit) {
267 did_quit = true;
268 io_handler.SetIsDone(true);
269 if (debugger.CheckTopIOHandlerTypes(
271 // We typed "quit" or an alias to quit so we need to check if the
272 // command interpreter is above us and tell it that it is done as
273 // well so we don't drop back into the command interpreter if we
274 // have already quit
275 lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
276 if (io_handler_sp)
277 io_handler_sp->SetIsDone(true);
278 }
279 }
280 } else {
281 // ":" was followed by no arguments, so push the LLDB command prompt
282 if (debugger.CheckTopIOHandlerTypes(
284 // If the user wants to get back to the command interpreter and the
285 // command interpreter is what launched the REPL, then just let the
286 // REPL exit and fall back to the command interpreter.
287 io_handler.SetIsDone(true);
288 } else {
289 // The REPL wasn't launched the by the command interpreter, it is the
290 // base IOHandler, so we need to get the command interpreter and
291 lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
292 if (io_handler_sp) {
293 io_handler_sp->SetIsDone(false);
294 debugger.RunIOHandlerAsync(ci.GetIOHandler());
295 }
296 }
297 }
298 } else {
299 if (code[0] == '<') {
300 // User wants to read code from a file.
301 // Interpret rest of line as a literal path.
302 auto path = llvm::StringRef(code.substr(1)).trim().str();
303 if (!ReadCode(path, code, error_stream_sp)) {
304 return;
305 }
306 }
307
308 // Unwind any expression we might have been running in case our REPL
309 // expression crashed and the user was looking around
311 Thread *thread = exe_ctx.GetThreadPtr();
312 if (thread && thread->UnwindInnermostExpression().Success()) {
313 thread->SetSelectedFrameByIndex(0, false);
314 exe_ctx.SetFrameSP(
315 thread->GetSelectedFrame(DoNoSelectMostRelevantFrame));
316 }
317 }
318
319 const bool colorize_err =
320 error_stream_sp->Lock().GetFile().GetIsTerminalWithColors();
321
323 expr_options.SetCoerceToId(m_varobj_options.use_object_desc);
324 expr_options.SetKeepInMemory(true);
325 expr_options.SetUseDynamic(m_varobj_options.use_dynamic);
326 expr_options.SetGenerateDebugInfo(true);
327 expr_options.SetREPLEnabled(true);
328 expr_options.SetColorizeErrors(colorize_err);
329 expr_options.SetPoundLine(m_repl_source_path.c_str(),
330 m_code.GetSize() + 1);
331
332 expr_options.SetLanguage(GetLanguage());
333
334 PersistentExpressionState *persistent_state =
335 m_target.GetPersistentExpressionStateForLanguage(GetLanguage());
336 if (!persistent_state)
337 return;
338
339 const size_t var_count_before = persistent_state->GetSize();
340
341 const char *expr_prefix = nullptr;
342 lldb::ValueObjectSP result_valobj_sp;
344 exe_ctx, expr_options, code.c_str(), expr_prefix, result_valobj_sp);
346 if (llvm::Error err = OnExpressionEvaluated(exe_ctx, code, expr_options,
347 execution_results,
348 result_valobj_sp, error)) {
349 error_stream_sp->Lock() << llvm::toString(std::move(err)) << "\n";
350 } else if (process_sp && process_sp->IsAlive()) {
351 bool add_to_code = true;
352 bool handled = false;
353 if (result_valobj_sp) {
354 lldb::Format format = m_format_options.GetFormat();
355
356 if (result_valobj_sp->GetError().Success()) {
357 handled |=
358 PrintOneVariable(debugger, output_stream_sp, result_valobj_sp);
359 } else if (result_valobj_sp->GetError().GetError() ==
361 if (format != lldb::eFormatVoid && debugger.GetNotifyVoid()) {
362 error_stream_sp->Lock().PutCString("(void)\n");
363 handled = true;
364 }
365 }
366 }
367
368 if (debugger.GetPrintDecls()) {
369 for (size_t vi = var_count_before, ve = persistent_state->GetSize();
370 vi != ve; ++vi) {
371 lldb::ExpressionVariableSP persistent_var_sp =
372 persistent_state->GetVariableAtIndex(vi);
373 lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
374
375 PrintOneVariable(debugger, output_stream_sp, valobj_sp,
376 persistent_var_sp.get());
377 }
378 }
379
380 bool run_command_interpreter = false;
381 if (!handled) {
382 LockedStreamFile locked_error_stream = error_stream_sp->Lock();
383 bool useColors =
384 locked_error_stream.GetFile().GetIsTerminalWithColors();
385 switch (execution_results) {
388 add_to_code = false;
389 [[fallthrough]];
391 locked_error_stream.Printf("%s\n", error.AsCString());
392 break;
393
395 break;
397 if (useColors) {
398 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
399 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
400 }
401 locked_error_stream.PutCString("Execution interrupted. ");
402 if (useColors)
403 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
404 locked_error_stream.Printf(
405 "Enter code to recover and continue.\nEnter LLDB "
406 "commands to investigate (type :help for "
407 "assistance.)\n");
408 break;
409
411 // Breakpoint was hit, drop into LLDB command interpreter
412 if (useColors) {
413 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED));
414 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD));
415 }
416 output_stream_sp->Lock().Printf(
417 "Execution stopped at breakpoint. ");
418 if (useColors)
419 locked_error_stream.Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL));
420 locked_error_stream.Printf(
421 "Enter LLDB commands to investigate (type help "
422 "for assistance.)\n");
423 run_command_interpreter = true;
424 break;
425
427 locked_error_stream.PutCString("error: timeout\n");
428 if (error.AsCString())
429 locked_error_stream.Printf("error: %s\n", error.AsCString());
430 break;
432 // Shoulnd't happen???
433 locked_error_stream.Printf("error: could not fetch result -- %s\n",
434 error.AsCString());
435 break;
437 // Shoulnd't happen???
438 locked_error_stream.Printf("error: stopped for debug -- %s\n",
439 error.AsCString());
440 break;
442 // Shoulnd't happen???
443 locked_error_stream.Printf(
444 "error: expression thread vanished -- %s\n", error.AsCString());
445 break;
446 }
447 }
448
449 // RunIOHandlerAsync takes the IOHandler stack mutex, and
450 // Debugger::PrintAsync takes that mutex before the mutex shared by the
451 // output and error streams. Don't call RunIOHandlerAsync while holding
452 // the error stream lock.
453 if (run_command_interpreter) {
454 lldb::IOHandlerSP io_handler_sp(ci.GetIOHandler());
455 if (io_handler_sp) {
456 io_handler_sp->SetIsDone(false);
457 debugger.RunIOHandlerAsync(ci.GetIOHandler());
458 }
459 }
460
461 if (add_to_code) {
462 const uint32_t new_default_line = m_code.GetSize() + 1;
463
464 m_code.SplitIntoLines(code);
465
466 // Update our code on disk
467 if (!m_repl_source_path.empty()) {
468 auto file = FileSystem::Instance().Open(
472 lldb::eFilePermissionsFileDefault);
473 if (file) {
474 std::string code(m_code.CopyList());
475 code.append(1, '\n');
476 size_t bytes_written = code.size();
477 file.get()->Write(code.c_str(), bytes_written);
478 file.get()->Close();
479 } else {
480 std::string message = llvm::toString(file.takeError());
481 error_stream_sp->Lock().Printf("error: couldn't open %s: %s\n",
482 m_repl_source_path.c_str(),
483 message.c_str());
484 }
485
486 // Now set the default file and line to the REPL source file
487 m_target.GetSourceManager().SetDefaultFileAndLine(
488 std::make_shared<SupportFile>(FileSpec(m_repl_source_path)),
489 new_default_line);
490 }
491 static_cast<IOHandlerEditline &>(io_handler)
492 .SetBaseLineNumber(m_code.GetSize() + 1);
493 }
494 if (extra_line)
495 output_stream_sp->Lock().Printf("\n");
496 }
497 }
498
499 // Don't complain about the REPL process going away if we are in the
500 // process of quitting.
501 if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
502 error_stream_sp->Lock().Printf(
503 "error: REPL process is no longer alive, exiting REPL\n");
504 io_handler.SetIsDone(true);
505 }
506 }
507}
508
510 CompletionRequest &request) {
511 // Complete an LLDB command if the first character is a colon...
512 if (request.GetRawLine().starts_with(":")) {
513 Debugger &debugger = m_target.GetDebugger();
514
515 // auto complete LLDB commands
516 llvm::StringRef new_line = request.GetRawLine().drop_front();
517 CompletionResult sub_result;
518 CompletionRequest sub_request(new_line, request.GetRawCursorPos() - 1,
519 sub_result);
520 debugger.GetCommandInterpreter().HandleCompletion(sub_request);
521 StringList matches, descriptions;
522 sub_result.GetMatches(matches);
523 // Prepend command prefix that was excluded in the completion request.
524 if (request.GetCursorIndex() == 0)
525 for (auto &match : matches)
526 match.insert(0, 1, ':');
527 sub_result.GetDescriptions(descriptions);
528 request.AddCompletions(matches, descriptions);
529 return;
530 }
531
532 // Strip spaces from the line and see if we had only spaces
533 if (request.GetRawLine().trim().empty()) {
534 // Only spaces on this line, so just indent
536 return;
537 }
538
539 std::string current_code;
540 current_code.append(m_code.CopyList());
541
542 IOHandlerEditline &editline = static_cast<IOHandlerEditline &>(io_handler);
543 StringList current_lines = editline.GetCurrentLines();
544 const uint32_t current_line_idx = editline.GetCurrentLineIndex();
545
546 if (current_line_idx < current_lines.GetSize()) {
547 for (uint32_t i = 0; i < current_line_idx; ++i) {
548 const char *line_cstr = current_lines.GetStringAtIndex(i);
549 if (line_cstr) {
550 current_code.append("\n");
551 current_code.append(line_cstr);
552 }
553 }
554 }
555
556 current_code.append("\n");
557 current_code += request.GetRawLine();
558
559 CompleteCode(current_code, request);
560}
561
562bool QuitCommandOverrideCallback(void *baton, const char **argv) {
563 Target *target = (Target *)baton;
564 lldb::ProcessSP process_sp(target->GetProcessSP());
565 if (process_sp) {
566 process_sp->Destroy(false);
567 process_sp->GetTarget().GetDebugger().ClearIOHandlers();
568 }
569 return false;
570}
571
574
577
578 if (!error.Success())
579 return error;
580
581 Debugger &debugger = m_target.GetDebugger();
582
583 lldb::IOHandlerSP io_handler_sp(GetIOHandler());
584
585 std::optional<SourceManager::SupportFileAndLine> default_file_line;
586
587 if (!m_repl_source_path.empty()) {
588 // Save the current default file and line
589 default_file_line = m_target.GetSourceManager().GetDefaultFileAndLine();
590 }
591
592 debugger.RunIOHandlerAsync(io_handler_sp);
593
594 // Check if we are in dedicated REPL mode where LLDB was start with the "--
595 // repl" option from the command line. Currently we know this by checking if
596 // the debugger already has a IOHandler thread.
597 if (!debugger.HasIOHandlerThread()) {
598 // The debugger doesn't have an existing IOHandler thread, so this must be
599 // dedicated REPL mode...
601 debugger.StartIOHandlerThread();
602 llvm::StringRef command_name_str("quit");
603 CommandObject *cmd_obj =
605 command_name_str);
606 if (cmd_obj) {
607 assert(command_name_str.empty());
609 }
610 }
611
612 // Wait for the REPL command interpreter to get popped
613 io_handler_sp->WaitForPop();
614
616 // If we were in dedicated REPL mode we would have started the IOHandler
617 // thread, and we should kill our process
618 lldb::ProcessSP process_sp = m_target.GetProcessSP();
619 if (process_sp && process_sp->IsAlive())
620 process_sp->Destroy(false);
621
622 // Wait for the IO handler thread to exit (TODO: don't do this if the IO
623 // handler thread already exists...)
624 debugger.JoinIOHandlerThread();
625 }
626
627 // Restore the default file and line
628 if (default_file_line)
629 m_target.GetSourceManager().SetDefaultFileAndLine(
630 default_file_line->support_file_nsp, default_file_line->line);
631 return error;
632}
#define ANSI_FG_COLOR_RED
#define ANSI_ESCAPE1(s)
#define ANSI_CTRL_NORMAL
#define ANSI_CTRL_BOLD
static llvm::raw_ostream & error(Stream &strm)
static bool ReadCode(const std::string &path, std::string &code, lldb::LockableStreamFileSP &error_stream_sp)
Definition REPL.cpp:186
bool QuitCommandOverrideCallback(void *baton, const char **argv)
Definition REPL.cpp:562
void HandleCompletion(CompletionRequest &request)
bool HandleCommand(const char *command_line, LazyBool add_to_history, const ExecutionContext &override_context, CommandReturnObject &result)
CommandObject * GetCommandObjectForCommand(llvm::StringRef &command_line)
lldb::IOHandlerSP GetIOHandler(bool force_create=false, CommandInterpreterRunOptions *options=nullptr)
void SetOverrideCallback(lldb::CommandOverrideCallback callback, void *baton)
void SetImmediateErrorStream(const lldb::StreamSP &stream_sp)
void SetImmediateOutputStream(const lldb::StreamSP &stream_sp)
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
void AddCompletions(const StringList &completions)
Adds multiple possible completion strings.
llvm::StringRef GetRawLine() const
Returns the raw user input used to create this CompletionRequest cut off at the cursor position.
void GetDescriptions(StringList &descriptions) const
Adds all collected completion descriptions to the given list.
void GetMatches(StringList &matches) const
Adds all collected completion matches to the given list.
A class to manage flag bits.
Definition Debugger.h:100
bool SetShowProgress(bool show_progress)
Definition Debugger.cpp:564
bool GetPrintDecls() const
Definition Debugger.cpp:798
CommandInterpreter & GetCommandInterpreter()
Definition Debugger.h:182
bool HasIOHandlerThread() const
bool GetUseColor() const
Definition Debugger.cpp:543
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
bool GetAutoIndent() const
Definition Debugger.cpp:787
bool CheckTopIOHandlerTypes(IOHandler::Type top_type, IOHandler::Type second_top_type)
uint64_t GetTabSize() const
Definition Debugger.cpp:809
bool GetNotifyVoid() const
Definition Debugger.cpp:413
void SetKeepInMemory(bool keep=true)
Definition Target.h:417
void SetCoerceToId(bool coerce=true)
Definition Target.h:403
void SetLanguage(lldb::LanguageType language_type)
Definition Target.h:371
void SetPoundLine(const char *path, uint32_t line) const
Definition Target.h:487
void SetUseDynamic(lldb::DynamicValueType dynamic=lldb::eDynamicCanRunTarget)
Definition Target.h:422
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void SetFrameSP(const lldb::StackFrameSP &frame_sp)
Set accessor to set only the frame shared pointer.
const lldb::ProcessSP & GetProcessSP() const
Get accessor to get the process shared pointer.
Thread * GetThreadPtr() const
Returns a pointer to the thread object.
size_t GetSize()
Implementation of methods in ExpressionVariableListBase.
lldb::ExpressionVariableSP GetVariableAtIndex(size_t index)
A file utility class.
Definition FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:454
void SetFilename(llvm::StringRef filename)
Filename string set accessor.
Definition FileSpec.cpp:363
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
static FileSystem & Instance()
bool GetIsTerminalWithColors()
Return true if this file is a terminal which supports colors.
Definition File.cpp:174
uint32_t GetCurrentLineIndex() const
StringList GetCurrentLines() const
Debugger & GetDebugger()
Definition IOHandler.h:130
lldb::LockableStreamFileSP GetErrorStreamFileSP()
Definition IOHandler.cpp:95
lldb::LockableStreamFileSP GetOutputStreamFileSP()
Definition IOHandler.cpp:93
void SetIsDone(bool b)
Definition IOHandler.h:81
static llvm::SmallVector< REPLCallbacks > GetREPLCallbacks()
const char * IOHandlerGetHelpPrologue() override
Definition REPL.cpp:124
static int CalculateActualIndentation(const StringList &lines)
Definition REPL.cpp:150
static char ID
LLVM RTTI support.
Definition REPL.h:26
virtual Status DoInitialization()=0
llvm::StringRef IOHandlerGetControlSequence(char ch) override
Definition REPL.cpp:115
virtual lldb::offset_t GetDesiredIndentation(const StringList &lines, int cursor_position, int tab_size)=0
const char * IOHandlerGetFixIndentationCharacters() override
Definition REPL.cpp:111
int IOHandlerFixIndentation(IOHandler &io_handler, const StringList &lines, int cursor_position) override
Called when a new line is created or one of an identified set of indentation characters is typed.
Definition REPL.cpp:163
virtual const char * GetAutoIndentCharacters()=0
OptionGroupValueObjectDisplay m_varobj_options
Definition REPL.h:155
REPL(Target &target)
Definition REPL.cpp:27
bool IOHandlerInterrupt(IOHandler &io_handler) override
Definition REPL.cpp:106
static lldb::REPLSP Create(Status &Status, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options)
Get a REPL with an existing target (or, failing that, a debugger to use), and (optional) extra argume...
Definition REPL.cpp:38
virtual llvm::StringRef GetSourceFileBasename()=0
std::string m_indent_str
Definition REPL.h:160
void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) override
Definition REPL.cpp:509
OptionGroupFormat m_format_options
Definition REPL.h:154
EvaluateExpressionOptions m_expr_options
Definition REPL.h:156
bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) override
Called to determine whether typing enter after the last line in lines should end input.
Definition REPL.cpp:136
std::string GetSourcePath()
Definition REPL.cpp:54
bool m_enable_auto_indent
Definition REPL.h:159
virtual bool SourceIsComplete(const std::string &source)=0
const char * IOHandlerGetCommandPrefix() override
Definition REPL.cpp:122
Status RunLoop()
Definition REPL.cpp:572
void IOHandlerInputInterrupted(IOHandler &io_handler, std::string &line) override
Definition REPL.cpp:108
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
Definition REPL.cpp:97
virtual lldb::LanguageType GetLanguage()=0
void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override
Called when a line or lines have been retrieved.
Definition REPL.cpp:217
lldb::IOHandlerSP m_io_handler_sp
Definition REPL.h:170
virtual bool PrintOneVariable(Debugger &debugger, lldb::LockableStreamFileSP &output_stream_sp, lldb::ValueObjectSP &valobj_sp, ExpressionVariable *var=nullptr)=0
StringList m_code
Definition REPL.h:167
std::string m_repl_source_path
Definition REPL.h:164
lldb::IOHandlerSP GetIOHandler()
Definition REPL.cpp:68
bool m_dedicated_repl_mode
Definition REPL.h:165
virtual void CompleteCode(const std::string &current_code, CompletionRequest &request)=0
Target & m_target
Definition REPL.h:169
virtual llvm::Error OnExpressionEvaluated(const ExecutionContext &exe_ctx, llvm::StringRef code, const EvaluateExpressionOptions &expr_options, lldb::ExpressionResults execution_results, const lldb::ValueObjectSP &result_valobj_sp, const Status &error)
Method that can be optionally overriden by subclasses to get notified whenever an expression has been...
Definition REPL.h:120
An error handling class.
Definition Status.h:118
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
const char * GetStringAtIndex(size_t idx) const
const lldb::ProcessSP & GetProcessSP() const
Definition Target.cpp:330
static lldb::ExpressionResults Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, llvm::StringRef expr_cstr, llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp, std::string *fixed_expression=nullptr, ValueObject *ctx_obj=nullptr)
Evaluate one expression in the scratch context of the target passed in the exe_ctx and return its res...
static const Status::ValueType kNoResult
ValueObject::GetError() returns this if there is no result from the expression.
#define LLDB_INVALID_OFFSET
@ DoNoSelectMostRelevantFrame
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::ExpressionVariable > ExpressionVariableSP
Format
Display format definitions.
@ eFormatVoid
Do not print this.
uint64_t offset_t
Definition lldb-types.h:86
LanguageType
Programming language type.
ExpressionResults
The results of expression evaluation.
@ eExpressionTimedOut
@ eExpressionCompleted
@ eExpressionHitBreakpoint
@ eExpressionInterrupted
@ eExpressionDiscarded
@ eExpressionParseError
@ eExpressionStoppedForDebug
@ eExpressionResultUnavailable
@ eExpressionThreadVanished
@ eExpressionSetupError
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::LockableStreamFile > LockableStreamFileSP
std::shared_ptr< lldb_private::REPL > REPLSP