40 const char *repl_options) {
48 if (!supported_languages[language])
50 ret = (*create_instance)(err, language, debugger, target, repl_options);
61 FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
62 if (tmpdir_file_spec) {
70 return tmpdir_file_spec.
GetPath();
79 llvm::StringRef(
"> "),
80 llvm::StringRef(
". "),
88 ->SetInterruptExits(
false);
104 if (process_sp && process_sp->IsAlive())
107 error_sp->Printf(
"REPL requires a running target process.\n");
121 static constexpr llvm::StringLiteral control_sequence(
":quit\n");
123 return control_sequence;
130 return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
131 "Valid statements, expressions, and declarations are immediately "
132 "compiled and executed.\n\n"
133 "The complete set of LLDB debugging commands are also available as "
134 "described below.\n\nCommands "
135 "must be prefixed with a colon at the REPL prompt (:quit for "
136 "example.) Typing just a colon "
137 "followed by return will switch to the LLDB prompt.\n\n"
138 "Type “< path” to read in code from a text file “path”.\n\n";
143 const size_t num_lines = lines.
GetSize();
144 if (num_lines == 1) {
146 if (first_line[0] ==
':')
151 std::string source_string(lines.
CopyList());
156 std::string last_line = lines[lines.
GetSize() - 1];
158 int actual_indent = 0;
159 for (
char &ch : last_line) {
165 return actual_indent;
170 int cursor_position) {
188 return (
int)desired_indent - actual_indent;
191static bool ReadCode(
const std::string &path, std::string &code,
194 llvm::Twine pathTwine(path);
195 if (!fs.Exists(pathTwine)) {
196 error_sp->Printf(
"no such file at path '%s'\n", path.c_str());
199 if (!fs.Readable(pathTwine)) {
200 error_sp->Printf(
"could not read file at path '%s'\n", path.c_str());
203 const size_t file_size = fs.GetByteSize(pathTwine);
204 const size_t max_size = code.max_size();
205 if (file_size > max_size) {
206 error_sp->Printf(
"file at path '%s' too large: "
207 "file_size = %zu, max_size = %zu\n",
208 path.c_str(), file_size, max_size);
211 auto data_sp = fs.CreateDataBuffer(pathTwine);
212 if (data_sp ==
nullptr) {
213 error_sp->Printf(
"could not create buffer for file at path '%s'\n",
217 code.assign((
const char *)data_sp->GetBytes(), data_sp->GetByteSize());
224 bool extra_line =
false;
225 bool did_quit =
false;
244 if (code[0] ==
':') {
248 if (!llvm::StringRef(code).trim().empty()) {
254 if (saved_prompt_on_quit)
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_sp)) {
319 const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
335 if (!persistent_state)
338 const size_t var_count_before = persistent_state->
GetSize();
340 const char *expr_prefix =
nullptr;
343 exe_ctx, expr_options, code.c_str(), expr_prefix, result_valobj_sp);
347 result_valobj_sp,
error)) {
348 *error_sp << llvm::toString(std::move(err)) <<
"\n";
349 }
else if (process_sp && process_sp->IsAlive()) {
350 bool add_to_code =
true;
351 bool handled =
false;
352 if (result_valobj_sp) {
355 if (result_valobj_sp->GetError().Success()) {
357 }
else if (result_valobj_sp->GetError().GetError() ==
360 error_sp->PutCString(
"(void)\n");
367 for (
size_t vi = var_count_before, ve = persistent_state->
GetSize();
374 persistent_var_sp.get());
379 bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
380 switch (execution_results) {
386 error_sp->Printf(
"%s\n",
error.AsCString());
396 error_sp->Printf(
"Execution interrupted. ");
399 error_sp->Printf(
"Enter code to recover and continue.\nEnter LLDB "
400 "commands to investigate (type :help for "
410 output_sp->Printf(
"Execution stopped at breakpoint. ");
413 output_sp->Printf(
"Enter LLDB commands to investigate (type help "
414 "for assistance.)\n");
418 io_handler_sp->SetIsDone(
false);
425 error_sp->Printf(
"error: timeout\n");
426 if (
error.AsCString())
427 error_sp->Printf(
"error: %s\n",
error.AsCString());
431 error_sp->Printf(
"error: could not fetch result -- %s\n",
436 error_sp->Printf(
"error: stopped for debug -- %s\n",
441 error_sp->Printf(
"error: expression thread vanished -- %s\n",
458 lldb::eFilePermissionsFileDefault);
461 code.append(1,
'\n');
462 size_t bytes_written = code.size();
463 file.get()->Write(code.c_str(), bytes_written);
466 std::string message = llvm::toString(file.takeError());
467 error_sp->Printf(
"error: couldn't open %s: %s\n",
480 output_sp->Printf(
"\n");
487 if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
489 "error: REPL process is no longer alive, exiting REPL\n");
502 llvm::StringRef new_line = request.
GetRawLine().drop_front();
511 for (
auto &match : matches)
512 match.insert(0, 1,
':');
525 std::string current_code;
532 if (current_line_idx < current_lines.
GetSize()) {
533 for (uint32_t i = 0; i < current_line_idx; ++i) {
536 current_code.append(
"\n");
537 current_code.append(line_cstr);
542 current_code.append(
"\n");
552 process_sp->Destroy(
false);
553 process_sp->GetTarget().GetDebugger().ClearIOHandlers();
564 if (!
error.Success())
571 std::optional<SourceManager::SupportFileAndLine> default_file_line;
588 llvm::StringRef command_name_str(
"quit");
593 assert(command_name_str.empty());
599 io_handler_sp->WaitForPop();
605 if (process_sp && process_sp->IsAlive())
606 process_sp->Destroy(
false);
614 if (default_file_line)
616 default_file_line->support_file_sp, 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::StreamFileSP &error_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)
ExecutionContext GetExecutionContext() const
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()
uint32_t GetCurrentLineIndex() const
StringList GetCurrentLines() const
lldb::StreamFileSP GetErrorStreamFileSP()
lldb::StreamFileSP GetOutputStreamFileSP()
void OptionParsingStarting(ExecutionContext *execution_context) override
lldb::DynamicValueType use_dynamic
static REPLCreateInstance GetREPLCreateCallbackAtIndex(uint32_t idx)
static LanguageSet GetREPLSupportedLanguagesAtIndex(uint32_t idx)
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
virtual bool PrintOneVariable(Debugger &debugger, lldb::StreamFileSP &output_sp, lldb::ValueObjectSP &valobj_sp, ExpressionVariable *var=nullptr)=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
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...
bool SetDefaultFileAndLine(lldb::SupportFileSP support_file_sp, uint32_t line)
std::optional< SupportFileAndLine > GetDefaultFileAndLine()
bool Success() const
Test for success condition.
std::string CopyList(const char *item_preamble=nullptr, const char *items_sep="\n") const
size_t SplitIntoLines(const std::string &lines)
void AppendString(const std::string &s)
const char * GetStringAtIndex(size_t idx) const
SourceManager & GetSourceManager()
PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language)
const lldb::ProcessSP & GetProcessSP() const
Status UnwindInnermostExpression()
Unwinds the thread stack for the innermost expression plan currently on the thread plan stack.
lldb::StackFrameSP GetSelectedFrame(SelectMostRelevant select_most_relevant)
bool SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast=false)
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::StreamFile > StreamFileSP
std::shared_ptr< lldb_private::REPL > REPLSP
A SmallBitVector that represents a set of source languages (lldb::LanguageType).