summaryrefslogtreecommitdiff
path: root/source/Interpreter/CommandInterpreter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Interpreter/CommandInterpreter.cpp
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
Notes
Diffstat (limited to 'source/Interpreter/CommandInterpreter.cpp')
-rw-r--r--source/Interpreter/CommandInterpreter.cpp484
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;