40 const char *repl_options) {
44 if (!cbs.supported_languages[language])
46 ret = (*cbs.create_callback)(err, language, debugger, target, repl_options);
56 FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
57 if (tmpdir_file_spec) {
65 return tmpdir_file_spec.
GetPath();
74 llvm::StringRef(
"> "),
75 llvm::StringRef(
". "),
99 if (process_sp && process_sp->IsAlive())
102 locked_stream.
Printf(
"REPL requires a running target process.\n");
116 static constexpr llvm::StringLiteral control_sequence(
":quit\n");
118 return control_sequence;
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";
138 const size_t num_lines = lines.
GetSize();
139 if (num_lines == 1) {
141 if (first_line[0] ==
':')
146 std::string source_string(lines.
CopyList());
151 std::string last_line = lines[lines.
GetSize() - 1];
153 int actual_indent = 0;
154 for (
char &ch : last_line) {
160 return actual_indent;
165 int cursor_position) {
183 return (
int)desired_indent - actual_indent;
186static bool ReadCode(
const std::string &path, std::string &code,
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());
194 if (!fs.Readable(pathTwine)) {
195 error_stream_sp->Lock().Printf(
"could not read file at path '%s'\n",
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);
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());
213 code.assign((
const char *)data_sp->GetBytes(), data_sp->GetByteSize());
222 bool extra_line =
false;
223 bool did_quit =
false;
228 .SetBaseLineNumber(
m_code.GetSize() + 1);
242 if (code[0] ==
':') {
246 if (!llvm::StringRef(code).trim().empty()) {
252 if (saved_prompt_on_quit)
258 output_stream_sp->GetUnlockedFileSP()));
260 std::make_shared<StreamFile>(error_stream_sp->GetUnlockedFileSP()));
263 if (saved_prompt_on_quit)
277 io_handler_sp->SetIsDone(
true);
293 io_handler_sp->SetIsDone(
false);
299 if (code[0] ==
'<') {
302 auto path = llvm::StringRef(code.substr(1)).trim().str();
303 if (!
ReadCode(path, code, error_stream_sp)) {
312 if (thread && thread->UnwindInnermostExpression().Success()) {
313 thread->SetSelectedFrameByIndex(0,
false);
319 const bool colorize_err =
320 error_stream_sp->Lock().GetFile().GetIsTerminalWithColors();
336 if (!persistent_state)
339 const size_t var_count_before = persistent_state->
GetSize();
341 const char *expr_prefix =
nullptr;
344 exe_ctx, expr_options, code.c_str(), expr_prefix, result_valobj_sp);
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) {
356 if (result_valobj_sp->GetError().Success()) {
359 }
else if (result_valobj_sp->GetError().GetError() ==
362 error_stream_sp->Lock().PutCString(
"(void)\n");
369 for (
size_t vi = var_count_before, ve = persistent_state->
GetSize();
376 persistent_var_sp.get());
384 switch (execution_results) {
390 locked_error_stream.
Printf(
"%s\n",
error.AsCString());
400 locked_error_stream.
Printf(
"Execution interrupted. ");
403 locked_error_stream.
Printf(
404 "Enter code to recover and continue.\nEnter LLDB "
405 "commands to investigate (type :help for "
415 output_stream_sp->Lock().Printf(
416 "Execution stopped at breakpoint. ");
419 locked_error_stream.
Printf(
420 "Enter LLDB commands to investigate (type help "
421 "for assistance.)\n");
425 io_handler_sp->SetIsDone(
false);
432 locked_error_stream.
Printf(
"error: timeout\n");
433 if (
error.AsCString())
434 locked_error_stream.
Printf(
"error: %s\n",
error.AsCString());
438 locked_error_stream.
Printf(
"error: could not fetch result -- %s\n",
443 locked_error_stream.
Printf(
"error: stopped for debug -- %s\n",
448 locked_error_stream.
Printf(
449 "error: expression thread vanished -- %s\n",
error.AsCString());
455 const uint32_t new_default_line =
m_code.GetSize() + 1;
457 m_code.SplitIntoLines(code);
465 lldb::eFilePermissionsFileDefault);
467 std::string code(
m_code.CopyList());
468 code.append(1,
'\n');
469 size_t bytes_written = code.size();
470 file.get()->Write(code.c_str(), bytes_written);
473 std::string message = llvm::toString(file.takeError());
474 error_stream_sp->Lock().Printf(
"error: couldn't open %s: %s\n",
480 m_target.GetSourceManager().SetDefaultFileAndLine(
485 .SetBaseLineNumber(
m_code.GetSize() + 1);
488 output_stream_sp->Lock().Printf(
"\n");
494 if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
495 error_stream_sp->Lock().Printf(
496 "error: REPL process is no longer alive, exiting REPL\n");
509 llvm::StringRef new_line = request.
GetRawLine().drop_front();
518 for (
auto &match : matches)
519 match.insert(0, 1,
':');
532 std::string current_code;
533 current_code.append(
m_code.CopyList());
539 if (current_line_idx < current_lines.
GetSize()) {
540 for (uint32_t i = 0; i < current_line_idx; ++i) {
543 current_code.append(
"\n");
544 current_code.append(line_cstr);
549 current_code.append(
"\n");
559 process_sp->Destroy(
false);
560 process_sp->GetTarget().GetDebugger().ClearIOHandlers();
571 if (!
error.Success())
578 std::optional<SourceManager::SupportFileAndLine> default_file_line;
582 default_file_line =
m_target.GetSourceManager().GetDefaultFileAndLine();
595 llvm::StringRef command_name_str(
"quit");
600 assert(command_name_str.empty());
606 io_handler_sp->WaitForPop();
612 if (process_sp && process_sp->IsAlive())
613 process_sp->Destroy(
false);
621 if (default_file_line)
622 m_target.GetSourceManager().SetDefaultFileAndLine(
623 default_file_line->support_file_nsp, default_file_line->line);
#define ANSI_FG_COLOR_RED
static llvm::raw_ostream & error(Stream &strm)
static bool ReadCode(const std::string &path, std::string &code, lldb::LockableStreamFileSP &error_stream_sp)
bool QuitCommandOverrideCallback(void *baton, const char **argv)
void SetPromptOnQuit(bool enable)
void HandleCompletion(CompletionRequest &request)
bool GetSpaceReplPrompts() const
bool HandleCommand(const char *command_line, LazyBool add_to_history, const ExecutionContext &override_context, CommandReturnObject &result)
bool GetPromptOnQuit() const
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::ReturnStatus GetStatus() const
"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.
unsigned GetRawCursorPos() const
size_t GetCursorIndex() const
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.
bool SetShowProgress(bool show_progress)
bool GetPrintDecls() const
CommandInterpreter & GetCommandInterpreter()
bool StartIOHandlerThread()
bool HasIOHandlerThread() const
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
bool GetAutoIndent() const
void JoinIOHandlerThread()
bool CheckTopIOHandlerTypes(IOHandler::Type top_type, IOHandler::Type second_top_type)
uint64_t GetTabSize() const
bool GetNotifyVoid() const
void SetKeepInMemory(bool keep=true)
void SetCoerceToId(bool coerce=true)
void SetLanguage(lldb::LanguageType language_type)
void SetPoundLine(const char *path, uint32_t line) const
void SetColorizeErrors(bool b)
void SetREPLEnabled(bool b)
void SetUseDynamic(lldb::DynamicValueType dynamic=lldb::eDynamicCanRunTarget)
void SetGenerateDebugInfo(bool b)
"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)
void AppendPathComponent(llvm::StringRef component)
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void SetFilename(ConstString filename)
Filename string set accessor.
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.
void SetInterruptExits(bool b)
uint32_t GetCurrentLineIndex() const
StringList GetCurrentLines() const
lldb::LockableStreamFileSP GetErrorStreamFileSP()
lldb::LockableStreamFileSP GetOutputStreamFileSP()
static llvm::SmallVector< REPLCallbacks > GetREPLCallbacks()
const char * IOHandlerGetHelpPrologue() override
static int CalculateActualIndentation(const StringList &lines)
static char ID
LLVM RTTI support.
virtual Status DoInitialization()=0
llvm::StringRef IOHandlerGetControlSequence(char ch) override
virtual lldb::offset_t GetDesiredIndentation(const StringList &lines, int cursor_position, int tab_size)=0
const char * IOHandlerGetFixIndentationCharacters() override
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.
virtual const char * GetAutoIndentCharacters()=0
OptionGroupValueObjectDisplay m_varobj_options
bool IOHandlerInterrupt(IOHandler &io_handler) override
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...
virtual llvm::StringRef GetSourceFileBasename()=0
void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) override
OptionGroupFormat m_format_options
EvaluateExpressionOptions m_expr_options
bool IOHandlerIsInputComplete(IOHandler &io_handler, StringList &lines) override
Called to determine whether typing enter after the last line in lines should end input.
std::string GetSourcePath()
bool m_enable_auto_indent
virtual bool SourceIsComplete(const std::string &source)=0
const char * IOHandlerGetCommandPrefix() override
void IOHandlerInputInterrupted(IOHandler &io_handler, std::string &line) override
void IOHandlerActivated(IOHandler &io_handler, bool interactive) override
virtual lldb::LanguageType GetLanguage()=0
void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override
Called when a line or lines have been retrieved.
lldb::IOHandlerSP m_io_handler_sp
virtual bool PrintOneVariable(Debugger &debugger, lldb::LockableStreamFileSP &output_stream_sp, lldb::ValueObjectSP &valobj_sp, ExpressionVariable *var=nullptr)=0
std::string m_repl_source_path
lldb::IOHandlerSP GetIOHandler()
bool m_dedicated_repl_mode
virtual void CompleteCode(const std::string ¤t_code, CompletionRequest &request)=0
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...
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
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
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.
LanguageType
Programming language type.
ExpressionResults
The results of expression evaluation.
@ eExpressionHitBreakpoint
@ eExpressionStoppedForDebug
@ eExpressionResultUnavailable
@ eExpressionThreadVanished
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::LockableStreamFile > LockableStreamFileSP
std::shared_ptr< lldb_private::REPL > REPLSP