diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Interpreter/CommandInterpreter.cpp | |
parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) |
Notes
Diffstat (limited to 'source/Interpreter/CommandInterpreter.cpp')
-rw-r--r-- | source/Interpreter/CommandInterpreter.cpp | 484 |
1 files changed, 295 insertions, 189 deletions
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 64d2c3222fb6..6d75ec57c83b 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -31,6 +31,7 @@ #include "Commands/CommandObjectProcess.h" #include "Commands/CommandObjectQuit.h" #include "Commands/CommandObjectRegister.h" +#include "Commands/CommandObjectReproducer.h" #include "Commands/CommandObjectSettings.h" #include "Commands/CommandObjectSource.h" #include "Commands/CommandObjectStats.h" @@ -42,9 +43,9 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" @@ -76,28 +77,43 @@ using namespace lldb_private; static const char *k_white_space = " \t\v"; -static PropertyDefinition g_properties[] = { - {"expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, "If true, regular expression alias commands will show the " - "expanded command that will be executed. This can be used to " - "debug new regular expression alias commands."}, - {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, +static constexpr bool NoGlobalSetting = true; +static constexpr uintptr_t DefaultValueTrue = true; +static constexpr uintptr_t DefaultValueFalse = false; +static constexpr const char *NoCStrDefault = nullptr; + +static constexpr PropertyDefinition g_properties[] = { + {"expand-regex-aliases", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueFalse, NoCStrDefault, {}, + "If true, regular expression alias commands will show the " + "expanded command that will be executed. This can be used to " + "debug new regular expression alias commands."}, + {"prompt-on-quit", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueTrue, NoCStrDefault, {}, "If true, LLDB will prompt you before quitting if there are any live " "processes being debugged. If false, LLDB will quit without asking in any " "case."}, - {"stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, - nullptr, nullptr, "If true, LLDB will stop running a 'command source' " - "script upon encountering an error."}, - {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, - nullptr, + {"stop-command-source-on-error", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueTrue, NoCStrDefault, {}, + "If true, LLDB will stop running a 'command source' " + "script upon encountering an error."}, + {"space-repl-prompts", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueFalse, NoCStrDefault, {}, "If true, blank lines will be printed between between REPL submissions."}, - {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; + {"echo-commands", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueTrue, NoCStrDefault, {}, + "If true, commands will be echoed before they are evaluated."}, + {"echo-comment-commands", OptionValue::eTypeBoolean, NoGlobalSetting, + DefaultValueTrue, NoCStrDefault, {}, + "If true, commands will be echoed even if they are pure comment lines."}}; enum { ePropertyExpandRegexAliases = 0, ePropertyPromptOnQuit = 1, ePropertyStopCmdSourceOnError = 2, - eSpaceReplPrompts = 3 + eSpaceReplPrompts = 3, + eEchoCommands = 4, + eEchoCommentCommands = 5 }; ConstString &CommandInterpreter::GetStaticBroadcasterClass() { @@ -144,6 +160,28 @@ void CommandInterpreter::SetPromptOnQuit(bool b) { m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); } +bool CommandInterpreter::GetEchoCommands() const { + const uint32_t idx = eEchoCommands; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::SetEchoCommands(bool b) { + const uint32_t idx = eEchoCommands; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + +bool CommandInterpreter::GetEchoCommentCommands() const { + const uint32_t idx = eEchoCommentCommands; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void CommandInterpreter::SetEchoCommentCommands(bool b) { + const uint32_t idx = eEchoCommentCommands; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + void CommandInterpreter::AllowExitCodeOnQuit(bool allow) { m_allow_exit_code = allow; if (!allow) @@ -386,6 +424,13 @@ void CommandInterpreter::Initialize() { if (cmd_obj_sp) { AddAlias("rbreak", cmd_obj_sp, "--func-regex %1"); } + + cmd_obj_sp = GetCommandSPExact("frame variable", false); + if (cmd_obj_sp) { + AddAlias("v", cmd_obj_sp); + AddAlias("var", cmd_obj_sp); + AddAlias("vo", cmd_obj_sp, "--object-description"); + } } void CommandInterpreter::Clear() { @@ -439,6 +484,8 @@ void CommandInterpreter::LoadCommandDictionary() { m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this)); m_command_dict["register"] = CommandObjectSP(new CommandObjectRegister(*this)); + m_command_dict["reproducer"] = + CommandObjectSP(new CommandObjectReproducer(*this)); m_command_dict["script"] = CommandObjectSP(new CommandObjectScript(*this, script_language)); m_command_dict["settings"] = @@ -794,20 +841,23 @@ void CommandInterpreter::LoadCommandDictionary() { } int CommandInterpreter::GetCommandNamesMatchingPartialString( - const char *cmd_str, bool include_aliases, StringList &matches) { - AddNamesMatchingPartialString(m_command_dict, cmd_str, matches); + const char *cmd_str, bool include_aliases, StringList &matches, + StringList &descriptions) { + AddNamesMatchingPartialString(m_command_dict, cmd_str, matches, + &descriptions); if (include_aliases) { - AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches); + AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches, + &descriptions); } return matches.GetSize(); } -CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, - bool include_aliases, - bool exact, - StringList *matches) const { +CommandObjectSP +CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases, + bool exact, StringList *matches, + StringList *descriptions) const { CommandObjectSP command_sp; std::string cmd = cmd_str; @@ -848,8 +898,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, // empty CommandObjectSP and the list of matches. if (HasCommands()) { - num_cmd_matches = - AddNamesMatchingPartialString(m_command_dict, cmd_str, *matches); + num_cmd_matches = AddNamesMatchingPartialString(m_command_dict, cmd_str, + *matches, descriptions); } if (num_cmd_matches == 1) { @@ -860,8 +910,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, } if (include_aliases && HasAliases()) { - num_alias_matches = - AddNamesMatchingPartialString(m_alias_dict, cmd_str, *matches); + num_alias_matches = AddNamesMatchingPartialString(m_alias_dict, cmd_str, + *matches, descriptions); } if (num_alias_matches == 1) { @@ -872,8 +922,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, } if (HasUserCommands()) { - num_user_matches = - AddNamesMatchingPartialString(m_user_dict, cmd_str, *matches); + num_user_matches = AddNamesMatchingPartialString(m_user_dict, cmd_str, + *matches, descriptions); } if (num_user_matches == 1) { @@ -898,6 +948,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, } } else if (matches && command_sp) { matches->AppendString(cmd_str); + if (descriptions) + descriptions->AppendString(command_sp->GetHelp()); } return command_sp; @@ -935,16 +987,16 @@ bool CommandInterpreter::AddUserCommand(llvm::StringRef name, if (!name.empty()) { // do not allow replacement of internal commands if (CommandExists(name)) { - if (can_replace == false) + if (!can_replace) return false; - if (m_command_dict[name]->IsRemovable() == false) + if (!m_command_dict[name]->IsRemovable()) return false; } if (UserCommandExists(name)) { - if (can_replace == false) + if (!can_replace) return false; - if (m_user_dict[name]->IsRemovable() == false) + if (!m_user_dict[name]->IsRemovable()) return false; } @@ -997,10 +1049,12 @@ CommandObjectSP CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str, return ret_val; } -CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, - StringList *matches) const { +CommandObject * +CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, + StringList *matches, + StringList *descriptions) const { CommandObject *command_obj = - GetCommandSP(cmd_str, false, true, matches).get(); + GetCommandSP(cmd_str, false, true, matches, descriptions).get(); // If we didn't find an exact match to the command string in the commands, // look in the aliases. @@ -1008,7 +1062,7 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, if (command_obj) return command_obj; - command_obj = GetCommandSP(cmd_str, true, true, matches).get(); + command_obj = GetCommandSP(cmd_str, true, true, matches, descriptions).get(); if (command_obj) return command_obj; @@ -1023,10 +1077,12 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str, if (command_obj) { if (matches) matches->AppendString(command_obj->GetCommandName()); + if (descriptions) + descriptions->AppendString(command_obj->GetHelp()); return command_obj; } - return GetCommandSP(cmd_str, true, false, matches).get(); + return GetCommandSP(cmd_str, true, false, matches, descriptions).get(); } bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const { @@ -1337,7 +1393,7 @@ CommandObject *CommandInterpreter::BuildAliasResult( alias_cmd_obj = desugared.first.get(); std::string alias_name_str = alias_name; if ((cmd_args.GetArgumentCount() == 0) || - (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0)) + (alias_name_str != cmd_args.GetArgumentAtIndex(0))) cmd_args.Unshift(alias_name_str); result_str.Printf("%s", alias_cmd_obj->GetCommandName().str().c_str()); @@ -1399,130 +1455,140 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) { size_t start_backtick; size_t pos = 0; while ((start_backtick = command.find('`', pos)) != std::string::npos) { + // Stop if an error was encountered during the previous iteration. + if (error.Fail()) + break; + if (start_backtick > 0 && command[start_backtick - 1] == '\\') { // The backtick was preceded by a '\' character, remove the slash and - // don't treat the backtick as the start of an expression + // don't treat the backtick as the start of an expression. command.erase(start_backtick - 1, 1); - // No need to add one to start_backtick since we just deleted a char + // No need to add one to start_backtick since we just deleted a char. pos = start_backtick; - } else { - const size_t expr_content_start = start_backtick + 1; - const size_t end_backtick = command.find('`', expr_content_start); - if (end_backtick == std::string::npos) - return error; - else if (end_backtick == expr_content_start) { - // Empty expression (two backticks in a row) - command.erase(start_backtick, 2); - } else { - std::string expr_str(command, expr_content_start, - end_backtick - expr_content_start); - - ExecutionContext exe_ctx(GetExecutionContext()); - Target *target = exe_ctx.GetTargetPtr(); - // Get a dummy target to allow for calculator mode while processing - // backticks. This also helps break the infinite loop caused when - // target is null. - if (!target) - target = m_debugger.GetDummyTarget(); - if (target) { - ValueObjectSP expr_result_valobj_sp; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetKeepInMemory(false); - options.SetTryAllThreads(true); - options.SetTimeout(llvm::None); - - ExpressionResults expr_result = target->EvaluateExpression( - expr_str.c_str(), exe_ctx.GetFramePtr(), expr_result_valobj_sp, - options); - - if (expr_result == eExpressionCompleted) { - Scalar scalar; - if (expr_result_valobj_sp) - expr_result_valobj_sp = - expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable( - expr_result_valobj_sp->GetDynamicValueType(), true); - if (expr_result_valobj_sp->ResolveValue(scalar)) { - command.erase(start_backtick, end_backtick - start_backtick + 1); - StreamString value_strm; - const bool show_type = false; - scalar.GetValue(&value_strm, show_type); - size_t value_string_size = value_strm.GetSize(); - if (value_string_size) { - command.insert(start_backtick, value_strm.GetString()); - pos = start_backtick + value_string_size; - continue; - } else { - error.SetErrorStringWithFormat("expression value didn't result " - "in a scalar value for the " - "expression '%s'", - expr_str.c_str()); - } - } else { - error.SetErrorStringWithFormat("expression value didn't result " - "in a scalar value for the " - "expression '%s'", - expr_str.c_str()); - } - } else { - if (expr_result_valobj_sp) - error = expr_result_valobj_sp->GetError(); - if (error.Success()) { - - switch (expr_result) { - case eExpressionSetupError: - error.SetErrorStringWithFormat( - "expression setup error for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionParseError: - error.SetErrorStringWithFormat( - "expression parse error for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionResultUnavailable: - error.SetErrorStringWithFormat( - "expression error fetching result for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionCompleted: - break; - case eExpressionDiscarded: - error.SetErrorStringWithFormat( - "expression discarded for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionInterrupted: - error.SetErrorStringWithFormat( - "expression interrupted for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionHitBreakpoint: - error.SetErrorStringWithFormat( - "expression hit breakpoint for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionTimedOut: - error.SetErrorStringWithFormat( - "expression timed out for the expression '%s'", - expr_str.c_str()); - break; - case eExpressionStoppedForDebug: - error.SetErrorStringWithFormat("expression stop at entry point " - "for debugging for the " - "expression '%s'", - expr_str.c_str()); - break; - } - } - } + continue; + } + + const size_t expr_content_start = start_backtick + 1; + const size_t end_backtick = command.find('`', expr_content_start); + + if (end_backtick == std::string::npos) { + // Stop if there's no end backtick. + break; + } + + if (end_backtick == expr_content_start) { + // Skip over empty expression. (two backticks in a row) + command.erase(start_backtick, 2); + continue; + } + + std::string expr_str(command, expr_content_start, + end_backtick - expr_content_start); + + ExecutionContext exe_ctx(GetExecutionContext()); + Target *target = exe_ctx.GetTargetPtr(); + + // Get a dummy target to allow for calculator mode while processing + // backticks. This also helps break the infinite loop caused when target is + // null. + if (!target) + target = m_debugger.GetDummyTarget(); + + if (!target) + continue; + + ValueObjectSP expr_result_valobj_sp; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetKeepInMemory(false); + options.SetTryAllThreads(true); + options.SetTimeout(llvm::None); + + ExpressionResults expr_result = + target->EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(), + expr_result_valobj_sp, options); + + if (expr_result == eExpressionCompleted) { + Scalar scalar; + if (expr_result_valobj_sp) + expr_result_valobj_sp = + expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable( + expr_result_valobj_sp->GetDynamicValueType(), true); + if (expr_result_valobj_sp->ResolveValue(scalar)) { + command.erase(start_backtick, end_backtick - start_backtick + 1); + StreamString value_strm; + const bool show_type = false; + scalar.GetValue(&value_strm, show_type); + size_t value_string_size = value_strm.GetSize(); + if (value_string_size) { + command.insert(start_backtick, value_strm.GetString()); + pos = start_backtick + value_string_size; + continue; + } else { + error.SetErrorStringWithFormat("expression value didn't result " + "in a scalar value for the " + "expression '%s'", + expr_str.c_str()); + break; } + } else { + error.SetErrorStringWithFormat("expression value didn't result " + "in a scalar value for the " + "expression '%s'", + expr_str.c_str()); + break; } - if (error.Fail()) + + continue; + } + + if (expr_result_valobj_sp) + error = expr_result_valobj_sp->GetError(); + + if (error.Success()) { + switch (expr_result) { + case eExpressionSetupError: + error.SetErrorStringWithFormat( + "expression setup error for the expression '%s'", expr_str.c_str()); + break; + case eExpressionParseError: + error.SetErrorStringWithFormat( + "expression parse error for the expression '%s'", expr_str.c_str()); + break; + case eExpressionResultUnavailable: + error.SetErrorStringWithFormat( + "expression error fetching result for the expression '%s'", + expr_str.c_str()); + break; + case eExpressionCompleted: + break; + case eExpressionDiscarded: + error.SetErrorStringWithFormat( + "expression discarded for the expression '%s'", expr_str.c_str()); + break; + case eExpressionInterrupted: + error.SetErrorStringWithFormat( + "expression interrupted for the expression '%s'", expr_str.c_str()); + break; + case eExpressionHitBreakpoint: + error.SetErrorStringWithFormat( + "expression hit breakpoint for the expression '%s'", + expr_str.c_str()); break; + case eExpressionTimedOut: + error.SetErrorStringWithFormat( + "expression timed out for the expression '%s'", expr_str.c_str()); + break; + case eExpressionStoppedForDebug: + error.SetErrorStringWithFormat("expression stop at entry point " + "for debugging for the " + "expression '%s'", + expr_str.c_str()); + break; + } } } return error; @@ -1712,16 +1778,17 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { if (request.GetCursorIndex() == -1) { // We got nothing on the command line, so return the list of commands bool include_aliases = true; - StringList new_matches; - num_command_matches = - GetCommandNamesMatchingPartialString("", include_aliases, new_matches); - request.AddCompletions(new_matches); + StringList new_matches, descriptions; + num_command_matches = GetCommandNamesMatchingPartialString( + "", include_aliases, new_matches, descriptions); + request.AddCompletions(new_matches, descriptions); } else if (request.GetCursorIndex() == 0) { // The cursor is in the first argument, so just do a lookup in the // dictionary. - StringList new_matches; - CommandObject *cmd_obj = GetCommandObject( - request.GetParsedLine().GetArgumentAtIndex(0), &new_matches); + StringList new_matches, new_descriptions; + CommandObject *cmd_obj = + GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0), + &new_matches, &new_descriptions); if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() && new_matches.GetStringAtIndex(0) != nullptr && @@ -1733,12 +1800,13 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { look_for_subcommand = true; num_command_matches = 0; new_matches.DeleteStringAtIndex(0); + new_descriptions.DeleteStringAtIndex(0); request.GetParsedLine().AppendArgument(llvm::StringRef()); request.SetCursorIndex(request.GetCursorIndex() + 1); request.SetCursorCharPosition(0); } } - request.AddCompletions(new_matches); + request.AddCompletions(new_matches, new_descriptions); num_command_matches = request.GetNumberOfMatches(); } @@ -1762,12 +1830,13 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { int CommandInterpreter::HandleCompletion( const char *current_line, const char *cursor, const char *last_char, - int match_start_point, int max_return_elements, StringList &matches) { + int match_start_point, int max_return_elements, StringList &matches, + StringList &descriptions) { llvm::StringRef command_line(current_line, last_char - current_line); + CompletionResult result; CompletionRequest request(command_line, cursor - current_line, - match_start_point, max_return_elements, matches); - + match_start_point, max_return_elements, result); // Don't complete comments, and if the line we are completing is just the // history repeat character, substitute the appropriate history line. const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0); @@ -1777,6 +1846,7 @@ int CommandInterpreter::HandleCompletion( else if (first_arg[0] == CommandHistory::g_repeat_char) { if (auto hist_str = m_command_history.FindString(first_arg)) { matches.InsertStringAtIndex(0, *hist_str); + descriptions.InsertStringAtIndex(0, "Previous command history event"); return -2; } else return 0; @@ -1787,6 +1857,8 @@ int CommandInterpreter::HandleCompletion( lldbassert(max_return_elements == -1); int num_command_matches = HandleCompletionMatches(request); + result.GetMatches(matches); + result.GetDescriptions(descriptions); if (num_command_matches <= 0) return num_command_matches; @@ -1794,6 +1866,7 @@ int CommandInterpreter::HandleCompletion( if (request.GetParsedLine().GetArgumentCount() == 0) { // If we got an empty string, insert nothing. matches.InsertStringAtIndex(0, ""); + descriptions.InsertStringAtIndex(0, ""); } else { // Now figure out if there is a common substring, and if so put that in // element 0, otherwise put an empty string in element 0. @@ -1815,6 +1888,7 @@ int CommandInterpreter::HandleCompletion( common_prefix.push_back(' '); } matches.InsertStringAtIndex(0, common_prefix.c_str()); + descriptions.InsertStringAtIndex(0, ""); } return num_command_matches; } @@ -1873,7 +1947,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj, // Make sure that the alias name is the 0th element in cmd_args std::string alias_name_str = alias_name; - if (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0) + if (alias_name_str != cmd_args.GetArgumentAtIndex(0)) cmd_args.Unshift(alias_name_str); Args new_args(alias_cmd_obj->GetCommandName()); @@ -2025,13 +2099,14 @@ void CommandInterpreter::SourceInitFile(bool in_cwd, LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile(); if (should_load == eLoadCWDlldbinitWarn) { - FileSpec dot_lldb(".lldbinit", true); + FileSpec dot_lldb(".lldbinit"); + FileSystem::Instance().Resolve(dot_lldb); llvm::SmallString<64> home_dir_path; llvm::sys::path::home_directory(home_dir_path); - FileSpec homedir_dot_lldb(home_dir_path.c_str(), false); + FileSpec homedir_dot_lldb(home_dir_path.c_str()); homedir_dot_lldb.AppendPathComponent(".lldbinit"); - homedir_dot_lldb.ResolvePath(); - if (dot_lldb.Exists() && + FileSystem::Instance().Resolve(homedir_dot_lldb); + if (FileSystem::Instance().Exists(dot_lldb) && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) { result.AppendErrorWithFormat( "There is a .lldbinit file in the current directory which is not " @@ -2049,7 +2124,8 @@ void CommandInterpreter::SourceInitFile(bool in_cwd, return; } } else if (should_load == eLoadCWDlldbinitTrue) { - init_file.SetFile("./.lldbinit", true, FileSpec::Style::native); + init_file.SetFile("./.lldbinit", FileSpec::Style::native); + FileSystem::Instance().Resolve(init_file); } } } else { @@ -2061,11 +2137,11 @@ void CommandInterpreter::SourceInitFile(bool in_cwd, // init files. llvm::SmallString<64> home_dir_path; llvm::sys::path::home_directory(home_dir_path); - FileSpec profilePath(home_dir_path.c_str(), false); + FileSpec profilePath(home_dir_path.c_str()); profilePath.AppendPathComponent(".lldbinit"); std::string init_file_path = profilePath.GetPath(); - if (m_skip_app_init_files == false) { + if (!m_skip_app_init_files) { FileSpec program_file_spec(HostInfo::GetProgramFileSpec()); const char *program_name = program_file_spec.GetFilename().AsCString(); @@ -2073,22 +2149,22 @@ void CommandInterpreter::SourceInitFile(bool in_cwd, char program_init_file_name[PATH_MAX]; ::snprintf(program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name); - init_file.SetFile(program_init_file_name, true, - FileSpec::Style::native); - if (!init_file.Exists()) + init_file.SetFile(program_init_file_name, FileSpec::Style::native); + FileSystem::Instance().Resolve(init_file); + if (!FileSystem::Instance().Exists(init_file)) init_file.Clear(); } } if (!init_file && !m_skip_lldbinit_files) - init_file.SetFile(init_file_path, false, FileSpec::Style::native); + init_file.SetFile(init_file_path, FileSpec::Style::native); } // If the file exists, tell HandleCommand to 'source' it; this will do the // actual broadcasting of the commands back to any appropriate listener (see // CommandObjectSource::Execute for more details). - if (init_file.Exists()) { + if (FileSystem::Instance().Exists(init_file)) { const bool saved_batch = SetBatchCommandMode(true); CommandInterpreterRunOptions options; options.SetSilent(true); @@ -2281,20 +2357,20 @@ enum { eHandleCommandFlagStopOnContinue = (1u << 0), eHandleCommandFlagStopOnError = (1u << 1), eHandleCommandFlagEchoCommand = (1u << 2), - eHandleCommandFlagPrintResult = (1u << 3), - eHandleCommandFlagStopOnCrash = (1u << 4) + eHandleCommandFlagEchoCommentCommand = (1u << 3), + eHandleCommandFlagPrintResult = (1u << 4), + eHandleCommandFlagStopOnCrash = (1u << 5) }; void CommandInterpreter::HandleCommandsFromFile( FileSpec &cmd_file, ExecutionContext *context, CommandInterpreterRunOptions &options, CommandReturnObject &result) { - if (cmd_file.Exists()) { + if (FileSystem::Instance().Exists(cmd_file)) { StreamFileSP input_file_sp(new StreamFile()); std::string cmd_file_path = cmd_file.GetPath(); - Status error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), - File::eOpenOptionRead); - + Status error = FileSystem::Instance().Open(input_file_sp->GetFile(), + cmd_file, File::eOpenOptionRead); if (error.Success()) { Debugger &debugger = GetDebugger(); @@ -2324,9 +2400,10 @@ void CommandInterpreter::HandleCommandsFromFile( flags |= eHandleCommandFlagStopOnError; } + // stop-on-crash can only be set, if it is present in all levels of + // pushed flag sets. if (options.GetStopOnCrash()) { if (m_command_source_flags.empty()) { - // Echo command by default flags |= eHandleCommandFlagStopOnCrash; } else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) { @@ -2346,6 +2423,19 @@ void CommandInterpreter::HandleCommandsFromFile( flags |= eHandleCommandFlagEchoCommand; } + // We will only ever ask for this flag, if we echo commands in general. + if (options.m_echo_comment_commands == eLazyBoolCalculate) { + if (m_command_source_flags.empty()) { + // Echo comments by default + flags |= eHandleCommandFlagEchoCommentCommand; + } else if (m_command_source_flags.back() & + eHandleCommandFlagEchoCommentCommand) { + flags |= eHandleCommandFlagEchoCommentCommand; + } + } else if (options.m_echo_comment_commands == eLazyBoolYes) { + flags |= eHandleCommandFlagEchoCommentCommand; + } + if (options.m_print_results == eLazyBoolCalculate) { if (m_command_source_flags.empty()) { // Print output by default @@ -2667,6 +2757,21 @@ void CommandInterpreter::PrintCommandOutput(Stream &stream, } } +bool CommandInterpreter::EchoCommandNonInteractive( + llvm::StringRef line, const Flags &io_handler_flags) const { + if (!io_handler_flags.Test(eHandleCommandFlagEchoCommand)) + return false; + + llvm::StringRef command = line.trim(); + if (command.empty()) + return true; + + if (command.front() == m_comment_char) + return io_handler_flags.Test(eHandleCommandFlagEchoCommentCommand); + + return true; +} + void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, std::string &line) { // If we were interrupted, bail out... @@ -2674,7 +2779,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, return; const bool is_interactive = io_handler.GetIsInteractive(); - if (is_interactive == false) { + if (!is_interactive) { // When we are not interactive, don't execute blank lines. This will happen // sourcing a commands file. We don't want blank lines to repeat the // previous command and cause any errors to occur (like redefining an @@ -2685,7 +2790,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler, // When using a non-interactive file handle (like when sourcing commands // from a file) we need to echo the command out so we don't just see the // command output and no command... - if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) + if (EchoCommandNonInteractive(line, io_handler.GetFlags())) io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str()); } @@ -2859,6 +2964,8 @@ CommandInterpreter::GetIOHandler(bool force_create, flags |= eHandleCommandFlagStopOnCrash; if (options->m_echo_commands != eLazyBoolNo) flags |= eHandleCommandFlagEchoCommand; + if (options->m_echo_comment_commands != eLazyBoolNo) + flags |= eHandleCommandFlagEchoCommentCommand; if (options->m_print_results != eLazyBoolNo) flags |= eHandleCommandFlagPrintResult; } else { @@ -2921,8 +3028,7 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, bool is_alias = GetAliasFullName(next_word, full_name); cmd_obj = GetCommandObject(next_word, &matches); bool is_real_command = - (is_alias == false) || - (cmd_obj != nullptr && cmd_obj->IsAlias() == false); + (!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias()); if (!is_real_command) { matches.Clear(); std::string alias_result; |