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");
129 return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
130 "Valid statements, expressions, and declarations are immediately "
131 "compiled and executed.\n\n"
132 "The complete set of LLDB debugging commands are also available as "
133 "described below.\n\nCommands "
134 "must be prefixed with a colon at the REPL prompt (:quit for "
135 "example.) Typing just a colon "
136 "followed by return will switch to the LLDB prompt.\n\n"
137 "Type “< path” to read in code from a text file “path”.\n\n";
142 const size_t num_lines = lines.
GetSize();
143 if (num_lines == 1) {
145 if (first_line[0] ==
':')
150 std::string source_string(lines.
CopyList());
155 std::string last_line = lines[lines.
GetSize() - 1];
157 int actual_indent = 0;
158 for (
char &ch : last_line) {
164 return actual_indent;
169 int cursor_position) {
187 return (
int)desired_indent - actual_indent;
190static bool ReadCode(
const std::string &path, std::string &code,
191 lldb::StreamFileSP &error_sp) {
193 llvm::Twine pathTwine(path);
194 if (!fs.Exists(pathTwine)) {
195 error_sp->Printf(
"no such file at path '%s'\n", path.c_str());
198 if (!fs.Readable(pathTwine)) {
199 error_sp->Printf(
"could not read file at path '%s'\n", path.c_str());
202 const size_t file_size = fs.GetByteSize(pathTwine);
203 const size_t max_size = code.max_size();
204 if (file_size > max_size) {
205 error_sp->Printf(
"file at path '%s' too large: "
206 "file_size = %zu, max_size = %zu\n",
207 path.c_str(), file_size, max_size);
210 auto data_sp = fs.CreateDataBuffer(pathTwine);
211 if (data_sp ==
nullptr) {
212 error_sp->Printf(
"could not create buffer for file at path '%s'\n",
216 code.assign((
const char *)data_sp->GetBytes(), data_sp->GetByteSize());
223 bool extra_line =
false;
224 bool did_quit =
false;
243 if (code[0] ==
':') {
247 if (!llvm::StringRef(code).trim().empty()) {
253 if (saved_prompt_on_quit)
262 if (saved_prompt_on_quit)
276 io_handler_sp->SetIsDone(
true);
292 io_handler_sp->SetIsDone(
false);
298 if (code[0] ==
'<') {
301 auto path = llvm::StringRef(code.substr(1)).trim().str();
302 if (!
ReadCode(path, code, error_sp)) {
318 const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
334 if (!persistent_state)
337 const size_t var_count_before = persistent_state->
GetSize();
339 const char *expr_prefix =
nullptr;
340 lldb::ValueObjectSP result_valobj_sp;
344 expr_prefix, result_valobj_sp,
error,
349 result_valobj_sp,
error)) {
350 *error_sp << llvm::toString(std::move(err)) <<
"\n";
351 }
else if (process_sp && process_sp->IsAlive()) {
352 bool add_to_code =
true;
353 bool handled =
false;
354 if (result_valobj_sp) {
357 if (result_valobj_sp->GetError().Success()) {
359 }
else if (result_valobj_sp->GetError().GetError() ==
362 error_sp->PutCString(
"(void)\n");
369 for (
size_t vi = var_count_before, ve = persistent_state->
GetSize();
371 lldb::ExpressionVariableSP persistent_var_sp =
373 lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
376 persistent_var_sp.get());
381 bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
382 switch (execution_results) {
388 error_sp->Printf(
"%s\n",
error.AsCString());
398 error_sp->Printf(
"Execution interrupted. ");
401 error_sp->Printf(
"Enter code to recover and continue.\nEnter LLDB "
402 "commands to investigate (type :help for "
412 output_sp->Printf(
"Execution stopped at breakpoint. ");
415 output_sp->Printf(
"Enter LLDB commands to investigate (type help "
416 "for assistance.)\n");
420 io_handler_sp->SetIsDone(
false);
427 error_sp->Printf(
"error: timeout\n");
428 if (
error.AsCString())
429 error_sp->Printf(
"error: %s\n",
error.AsCString());
433 error_sp->Printf(
"error: could not fetch result -- %s\n",
438 error_sp->Printf(
"error: stopped for debug -- %s\n",
443 error_sp->Printf(
"error: expression thread vanished -- %s\n",
460 lldb::eFilePermissionsFileDefault);
463 code.append(1,
'\n');
464 size_t bytes_written = code.size();
465 file.get()->Write(code.c_str(), bytes_written);
468 std::string message = llvm::toString(file.takeError());
469 error_sp->Printf(
"error: couldn't open %s: %s\n",
481 output_sp->Printf(
"\n");
488 if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
490 "error: REPL process is no longer alive, exiting REPL\n");
503 llvm::StringRef new_line = request.
GetRawLine().drop_front();
512 for (
auto &match : matches)
513 match.insert(0, 1,
':');
526 std::string current_code;
534 if (current_line_idx < current_lines->GetSize()) {
535 for (
uint32_t i = 0; i < current_line_idx; ++i) {
538 current_code.append(
"\n");
539 current_code.append(line_cstr);
545 current_code.append(
"\n");
555 process_sp->Destroy(
false);
556 process_sp->GetTarget().GetDebugger().ClearIOHandlers();
567 if (!
error.Success())
593 llvm::StringRef command_name_str(
"quit");
598 assert(command_name_str.empty());
604 io_handler_sp->WaitForPop();
610 if (process_sp && process_sp->IsAlive())
611 process_sp->Destroy(
false);
619 if (save_default_file && save_default_line != 0)
#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 uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
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 SetLanguage(lldb::LanguageType language)
void SetKeepInMemory(bool keep=true)
void SetCoerceToId(bool coerce=true)
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)
Wraps ::open in a platform-independent way.
static FileSystem & Instance()
const StringList * GetCurrentLines() const
uint32_t GetCurrentLineIndex() 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
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...
ConstString IOHandlerGetControlSequence(char ch) override
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 ConstString GetSourceFileBasename()=0
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(const FileSpec &file_spec, uint32_t line)
bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line)
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 const Status::ValueType kNoResult
ValueObject::GetError() returns this if there is no result from the expression.
static lldb::ExpressionResults Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, llvm::StringRef expr_cstr, llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Status &error, 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...
#define LLDB_INVALID_OFFSET
@ DoNoSelectMostRelevantFrame
A class that represents a running process on the host machine.
Format
Display format definitions.
@ eFormatVoid
Do not print this.
LanguageType
Programming language type.
ExpressionResults
The results of expression evaluation.
@ eExpressionHitBreakpoint
@ eExpressionStoppedForDebug
@ eExpressionResultUnavailable
@ eExpressionThreadVanished
A SmallBitVector that represents a set of source languages (lldb::LanguageType).