38 const char *repl_options) {
46 if (!supported_languages[language])
48 ret = (*create_instance)(err, language, debugger, target, repl_options);
59 FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
60 if (tmpdir_file_spec) {
68 return tmpdir_file_spec.
GetPath();
77 llvm::StringRef(
"> "),
78 llvm::StringRef(
". "),
86 ->SetInterruptExits(
false);
102 if (process_sp && process_sp->IsAlive())
105 error_sp->Printf(
"REPL requires a running target process.\n");
127 return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. "
128 "Valid statements, expressions, and declarations are immediately "
129 "compiled and executed.\n\n"
130 "The complete set of LLDB debugging commands are also available as "
131 "described below.\n\nCommands "
132 "must be prefixed with a colon at the REPL prompt (:quit for "
133 "example.) Typing just a colon "
134 "followed by return will switch to the LLDB prompt.\n\n"
135 "Type “< path” to read in code from a text file “path”.\n\n";
140 const size_t num_lines = lines.
GetSize();
141 if (num_lines == 1) {
143 if (first_line[0] ==
':')
148 std::string source_string(lines.
CopyList());
153 std::string last_line = lines[lines.
GetSize() - 1];
155 int actual_indent = 0;
156 for (
char &ch : last_line) {
162 return actual_indent;
167 int cursor_position) {
185 return (
int)desired_indent - actual_indent;
188static bool ReadCode(
const std::string &path, std::string &code,
189 lldb::StreamFileSP &error_sp) {
191 llvm::Twine pathTwine(path);
192 if (!fs.Exists(pathTwine)) {
193 error_sp->Printf(
"no such file at path '%s'\n", path.c_str());
196 if (!fs.Readable(pathTwine)) {
197 error_sp->Printf(
"could not read file at path '%s'\n", path.c_str());
200 const size_t file_size = fs.GetByteSize(pathTwine);
201 const size_t max_size = code.max_size();
202 if (file_size > max_size) {
203 error_sp->Printf(
"file at path '%s' too large: "
204 "file_size = %zu, max_size = %zu\n",
205 path.c_str(), file_size, max_size);
208 auto data_sp = fs.CreateDataBuffer(pathTwine);
209 if (data_sp ==
nullptr) {
210 error_sp->Printf(
"could not create buffer for file at path '%s'\n",
214 code.assign((
const char *)data_sp->GetBytes(), data_sp->GetByteSize());
221 bool extra_line =
false;
222 bool did_quit =
false;
241 if (code[0] ==
':') {
245 if (!llvm::StringRef(code).trim().empty()) {
251 if (saved_prompt_on_quit)
260 if (saved_prompt_on_quit)
274 io_handler_sp->SetIsDone(
true);
290 io_handler_sp->SetIsDone(
false);
296 if (code[0] ==
'<') {
299 auto path = llvm::StringRef(code.substr(1)).trim().str();
300 if (!
ReadCode(path, code, error_sp)) {
315 const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors();
331 if (!persistent_state)
334 const size_t var_count_before = persistent_state->
GetSize();
336 const char *expr_prefix =
nullptr;
337 lldb::ValueObjectSP result_valobj_sp;
341 expr_prefix, result_valobj_sp,
error,
346 if (process_sp && process_sp->IsAlive()) {
347 bool add_to_code =
true;
348 bool handled =
false;
349 if (result_valobj_sp) {
352 if (result_valobj_sp->GetError().Success()) {
354 }
else if (result_valobj_sp->GetError().GetError() ==
357 error_sp->PutCString(
"(void)\n");
364 for (
size_t vi = var_count_before, ve = persistent_state->
GetSize();
366 lldb::ExpressionVariableSP persistent_var_sp =
368 lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject();
371 persistent_var_sp.get());
376 bool useColors = error_sp->GetFile().GetIsTerminalWithColors();
377 switch (execution_results) {
383 error_sp->Printf(
"%s\n",
error.AsCString());
393 error_sp->Printf(
"Execution interrupted. ");
396 error_sp->Printf(
"Enter code to recover and continue.\nEnter LLDB "
397 "commands to investigate (type :help for "
407 output_sp->Printf(
"Execution stopped at breakpoint. ");
410 output_sp->Printf(
"Enter LLDB commands to investigate (type help "
411 "for assistance.)\n");
415 io_handler_sp->SetIsDone(
false);
422 error_sp->Printf(
"error: timeout\n");
423 if (
error.AsCString())
424 error_sp->Printf(
"error: %s\n",
error.AsCString());
428 error_sp->Printf(
"error: could not fetch result -- %s\n",
433 error_sp->Printf(
"error: stopped for debug -- %s\n",
438 error_sp->Printf(
"error: expression thread vanished -- %s\n",
455 lldb::eFilePermissionsFileDefault);
458 code.append(1,
'\n');
459 size_t bytes_written = code.size();
460 file.get()->Write(code.c_str(), bytes_written);
463 std::string message = llvm::toString(file.takeError());
464 error_sp->Printf(
"error: couldn't open %s: %s\n",
476 output_sp->Printf(
"\n");
483 if (!did_quit && (!process_sp || !process_sp->IsAlive())) {
485 "error: REPL process is no longer alive, exiting REPL\n");
498 llvm::StringRef new_line = request.
GetRawLine().drop_front();
507 for (
auto &match : matches)
508 match.insert(0, 1,
':');
521 std::string current_code;
529 if (current_line_idx < current_lines->GetSize()) {
530 for (
uint32_t i = 0; i < current_line_idx; ++i) {
533 current_code.append(
"\n");
534 current_code.append(line_cstr);
540 current_code.append(
"\n");
550 process_sp->Destroy(
false);
551 process_sp->GetTarget().GetDebugger().ClearIOHandlers();
562 if (!
error.Success())
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 (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 HasIOHandlerThread()
bool SetShowProgress(bool show_progress)
bool GetPrintDecls() const
CommandInterpreter & GetCommandInterpreter()
bool StartIOHandlerThread()
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
bool GetAutoIndent() const
uint32_t GetTabSize() const
void JoinIOHandlerThread()
bool CheckTopIOHandlerTypes(IOHandler::Type top_type, IOHandler::Type second_top_type)
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)
REPL(LLVMCastKind kind, Target &target)
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
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()
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
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).