aboutsummaryrefslogtreecommitdiff
path: root/source/Interpreter
diff options
context:
space:
mode:
Diffstat (limited to 'source/Interpreter')
-rw-r--r--source/Interpreter/Args.cpp100
-rw-r--r--source/Interpreter/CMakeLists.txt1
-rw-r--r--source/Interpreter/CommandAlias.cpp307
-rw-r--r--source/Interpreter/CommandHistory.cpp21
-rw-r--r--source/Interpreter/CommandInterpreter.cpp660
-rw-r--r--source/Interpreter/CommandObject.cpp265
-rw-r--r--source/Interpreter/CommandObjectScript.cpp9
-rw-r--r--source/Interpreter/Makefile51
-rw-r--r--source/Interpreter/OptionGroupValueObjectDisplay.cpp12
-rw-r--r--source/Interpreter/OptionValueArray.cpp1
-rw-r--r--source/Interpreter/OptionValueFileSpecLIst.cpp1
-rw-r--r--source/Interpreter/OptionValuePathMappings.cpp81
-rw-r--r--source/Interpreter/OptionValueProperties.cpp19
-rw-r--r--source/Interpreter/Options.cpp315
14 files changed, 1072 insertions, 771 deletions
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp
index 81e6b0aa1dbc..d90ef1d256a4 100644
--- a/source/Interpreter/Args.cpp
+++ b/source/Interpreter/Args.cpp
@@ -83,19 +83,22 @@ Args::~Args ()
}
void
-Args::Dump (Stream *s)
+Args::Dump (Stream &s, const char *label_name) const
{
+ if (!label_name)
+ return;
+
const size_t argc = m_argv.size();
for (size_t i=0; i<argc; ++i)
{
- s->Indent();
+ s.Indent();
const char *arg_cstr = m_argv[i];
if (arg_cstr)
- s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
+ s.Printf("%s[%zi]=\"%s\"\n", label_name, i, arg_cstr);
else
- s->Printf("argv[%zi]=NULL\n", i);
+ s.Printf("%s[%zi]=NULL\n", label_name, i);
}
- s->EOL();
+ s.EOL();
}
bool
@@ -575,8 +578,8 @@ Args::ParseOptions (Options &options)
}
}
}
- Mutex::Locker options_locker(NULL);
- OptionParser::Prepare(options_locker);
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
int val;
while (1)
{
@@ -887,14 +890,43 @@ Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t
}
const char *
-Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
+Args::GetShellSafeArgument (const FileSpec& shell,
+ const char *unsafe_arg,
+ std::string &safe_arg)
{
+ struct ShellDescriptor
+ {
+ ConstString m_basename;
+ const char* m_escapables;
+ };
+
+ static ShellDescriptor g_Shells[] = {
+ {ConstString("bash")," '\"<>()&"},
+ {ConstString("tcsh")," '\"<>()&$"},
+ {ConstString("sh")," '\"<>()&"}
+ };
+
+ // safe minimal set
+ const char* escapables = " '\"";
+
+ if (auto basename = shell.GetFilename())
+ {
+ for (const auto& Shell : g_Shells)
+ {
+ if (Shell.m_basename == basename)
+ {
+ escapables = Shell.m_escapables;
+ break;
+ }
+ }
+ }
+
safe_arg.assign (unsafe_arg);
size_t prev_pos = 0;
while (prev_pos < safe_arg.size())
{
// Escape spaces and quotes
- size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
+ size_t pos = safe_arg.find_first_of(escapables, prev_pos);
if (pos != std::string::npos)
{
safe_arg.insert (pos, 1, '\\');
@@ -906,7 +938,6 @@ Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
return safe_arg.c_str();
}
-
int64_t
Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
{
@@ -1108,6 +1139,47 @@ Args::LongestCommonPrefix (std::string &common_prefix)
}
}
+bool
+Args::ContainsEnvironmentVariable(const char *env_var_name) const
+{
+ // Validate args.
+ if (!env_var_name)
+ return false;
+
+ // Check each arg to see if it matches the env var name.
+ for (size_t i = 0; i < GetArgumentCount(); ++i)
+ {
+ // Get the arg value.
+ const char *argument_value = GetArgumentAtIndex(i);
+ if (!argument_value)
+ continue;
+
+ // Check if we are the "{env_var_name}={env_var_value}" style.
+ const char *equal_p = strchr(argument_value, '=');
+ if (equal_p)
+ {
+ if (strncmp(env_var_name, argument_value,
+ equal_p - argument_value) == 0)
+ {
+ // We matched.
+ return true;
+ }
+ }
+ else
+ {
+ // We're a simple {env_var_name}-style entry.
+ if (strcmp(argument_value, env_var_name) == 0)
+ {
+ // We matched.
+ return true;
+ }
+ }
+ }
+
+ // We didn't find a match.
+ return false;
+}
+
size_t
Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
{
@@ -1190,8 +1262,8 @@ Args::ParseAliasOptions (Options &options,
}
}
- Mutex::Locker options_locker(NULL);
- OptionParser::Prepare(options_locker);
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
int val;
while (1)
{
@@ -1368,8 +1440,8 @@ Args::ParseArgsForCompletion
}
}
- Mutex::Locker options_locker(NULL);
- OptionParser::Prepare(options_locker);
+ std::unique_lock<std::mutex> lock;
+ OptionParser::Prepare(lock);
OptionParser::EnableError(false);
int val;
diff --git a/source/Interpreter/CMakeLists.txt b/source/Interpreter/CMakeLists.txt
index b92128cd3011..76d046f7d802 100644
--- a/source/Interpreter/CMakeLists.txt
+++ b/source/Interpreter/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lldb_library(lldbInterpreter
Args.cpp
+ CommandAlias.cpp
CommandHistory.cpp
CommandInterpreter.cpp
CommandObject.cpp
diff --git a/source/Interpreter/CommandAlias.cpp b/source/Interpreter/CommandAlias.cpp
new file mode 100644
index 000000000000..a915d63e6541
--- /dev/null
+++ b/source/Interpreter/CommandAlias.cpp
@@ -0,0 +1,307 @@
+//===-- CommandAlias.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Interpreter/CommandAlias.h"
+
+#include "llvm/Support/ErrorHandling.h"
+
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Options.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
+ const char *options_args,
+ OptionArgVectorSP &option_arg_vector_sp)
+{
+ bool success = true;
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ if (!options_args || (strlen (options_args) < 1))
+ return true;
+
+ std::string options_string (options_args);
+ Args args (options_args);
+ CommandReturnObject result;
+ // Check to see if the command being aliased can take any command options.
+ Options *options = cmd_obj_sp->GetOptions ();
+ if (options)
+ {
+ // See if any options were specified as part of the alias; if so, handle them appropriately.
+ options->NotifyOptionParsingStarting ();
+ args.Unshift ("dummy_arg");
+ args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
+ args.Shift ();
+ if (result.Succeeded())
+ options->VerifyPartialOptions (result);
+ if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
+ {
+ result.AppendError ("Unable to create requested alias.\n");
+ return false;
+ }
+ }
+
+ if (!options_string.empty())
+ {
+ if (cmd_obj_sp->WantsRawCommandString ())
+ option_arg_vector->push_back (OptionArgPair ("<argument>",
+ OptionArgValue (-1,
+ options_string)));
+ else
+ {
+ const size_t argc = args.GetArgumentCount();
+ for (size_t i = 0; i < argc; ++i)
+ if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
+ option_arg_vector->push_back
+ (OptionArgPair ("<argument>",
+ OptionArgValue (-1,
+ std::string (args.GetArgumentAtIndex (i)))));
+ }
+ }
+
+ return success;
+}
+
+CommandAlias::CommandAlias (CommandInterpreter &interpreter,
+ lldb::CommandObjectSP cmd_sp,
+ const char *options_args,
+ const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags) :
+ CommandObject(interpreter,
+ name,
+ help,
+ syntax,
+ flags),
+m_underlying_command_sp(),
+m_option_string(options_args ? options_args : ""),
+m_option_args_sp(new OptionArgVector),
+m_is_dashdash_alias(eLazyBoolCalculate),
+m_did_set_help(false),
+m_did_set_help_long(false)
+{
+ if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp))
+ {
+ m_underlying_command_sp = cmd_sp;
+ for (int i = 0;
+ auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
+ i++)
+ {
+ m_arguments.push_back(*cmd_entry);
+ }
+ if (!help || !help[0])
+ {
+ StreamString sstr;
+ StreamString translation_and_help;
+ GetAliasExpansion(sstr);
+
+ translation_and_help.Printf ("(%s) %s", sstr.GetData(), GetUnderlyingCommand()->GetHelp());
+ SetHelp(translation_and_help.GetData());
+ }
+ }
+}
+
+bool
+CommandAlias::WantsRawCommandString()
+{
+ if (IsValid())
+ return m_underlying_command_sp->WantsRawCommandString();
+ return false;
+}
+
+bool
+CommandAlias::WantsCompletion()
+{
+ if (IsValid())
+ return m_underlying_command_sp->WantsCompletion();
+ return false;
+}
+
+int
+CommandAlias::HandleCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ if (IsValid())
+ return m_underlying_command_sp->HandleCompletion(input,
+ cursor_index,
+ cursor_char_position,
+ match_start_point,
+ max_return_elements,
+ word_complete,
+ matches);
+ return -1;
+}
+
+int
+CommandAlias::HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ if (IsValid())
+ return m_underlying_command_sp->HandleArgumentCompletion(input,
+ cursor_index,
+ cursor_char_position,
+ opt_element_vector,
+ match_start_point,
+ max_return_elements,
+ word_complete,
+ matches);
+ return -1;
+}
+
+Options*
+CommandAlias::GetOptions()
+{
+ if (IsValid())
+ return m_underlying_command_sp->GetOptions();
+ return nullptr;
+}
+
+bool
+CommandAlias::Execute(const char *args_string, CommandReturnObject &result)
+{
+ llvm_unreachable("CommandAlias::Execute is not to be called");
+}
+
+void
+CommandAlias::GetAliasExpansion (StreamString &help_string)
+{
+ const char* command_name = m_underlying_command_sp->GetCommandName();
+ help_string.Printf ("'%s", command_name);
+
+ if (m_option_args_sp)
+ {
+ OptionArgVector *options = m_option_args_sp.get();
+ for (size_t i = 0; i < options->size(); ++i)
+ {
+ OptionArgPair cur_option = (*options)[i];
+ std::string opt = cur_option.first;
+ OptionArgValue value_pair = cur_option.second;
+ std::string value = value_pair.second;
+ if (opt.compare("<argument>") == 0)
+ {
+ help_string.Printf (" %s", value.c_str());
+ }
+ else
+ {
+ help_string.Printf (" %s", opt.c_str());
+ if ((value.compare ("<no-argument>") != 0)
+ && (value.compare ("<need-argument") != 0))
+ {
+ help_string.Printf (" %s", value.c_str());
+ }
+ }
+ }
+ }
+
+ help_string.Printf ("'");
+}
+
+bool
+CommandAlias::IsDashDashCommand ()
+{
+ if (m_is_dashdash_alias == eLazyBoolCalculate)
+ {
+ m_is_dashdash_alias = eLazyBoolNo;
+ if (IsValid())
+ {
+ for (const OptionArgPair& opt_arg : *GetOptionArguments())
+ {
+ if (opt_arg.first == "<argument>" &&
+ !opt_arg.second.second.empty() &&
+ llvm::StringRef(opt_arg.second.second).endswith("--"))
+ {
+ m_is_dashdash_alias = eLazyBoolYes;
+ break;
+ }
+ }
+ // if this is a nested alias, it may be adding arguments on top of an already dash-dash alias
+ if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
+ m_is_dashdash_alias = (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes : eLazyBoolNo);
+ }
+ }
+ return (m_is_dashdash_alias == eLazyBoolYes);
+}
+
+bool
+CommandAlias::IsNestedAlias ()
+{
+ if (GetUnderlyingCommand())
+ return GetUnderlyingCommand()->IsAlias();
+ return false;
+}
+
+std::pair<lldb::CommandObjectSP, OptionArgVectorSP>
+CommandAlias::Desugar ()
+{
+ auto underlying = GetUnderlyingCommand();
+ if (!underlying)
+ return {nullptr,nullptr};
+
+ if (underlying->IsAlias())
+ {
+ auto desugared = ((CommandAlias*)underlying.get())->Desugar();
+ auto options = GetOptionArguments();
+ options->insert(options->begin(), desugared.second->begin(), desugared.second->end());
+ return {desugared.first,options};
+ }
+
+ return {underlying,GetOptionArguments()};
+}
+
+// allow CommandAlias objects to provide their own help, but fallback to the info
+// for the underlying command if no customization has been provided
+void
+CommandAlias::SetHelp (const char * str)
+{
+ this->CommandObject::SetHelp(str);
+ m_did_set_help = true;
+}
+
+void
+CommandAlias::SetHelpLong (const char * str)
+{
+ this->CommandObject::SetHelpLong(str);
+ m_did_set_help_long = true;
+}
+
+const char*
+CommandAlias::GetHelp ()
+{
+ if (!m_cmd_help_short.empty() || m_did_set_help)
+ return m_cmd_help_short.c_str();
+ if (IsValid())
+ return m_underlying_command_sp->GetHelp();
+ return nullptr;
+}
+
+const char*
+CommandAlias::GetHelpLong ()
+{
+ if (!m_cmd_help_long.empty() || m_did_set_help_long)
+ return m_cmd_help_long.c_str();
+ if (IsValid())
+ return m_underlying_command_sp->GetHelpLong();
+ return nullptr;
+}
diff --git a/source/Interpreter/CommandHistory.cpp b/source/Interpreter/CommandHistory.cpp
index 9d3c814697b0..ff87e528d36f 100644
--- a/source/Interpreter/CommandHistory.cpp
+++ b/source/Interpreter/CommandHistory.cpp
@@ -15,10 +15,7 @@
using namespace lldb;
using namespace lldb_private;
-
-CommandHistory::CommandHistory () :
- m_mutex(Mutex::eMutexTypeRecursive),
- m_history()
+CommandHistory::CommandHistory() : m_mutex(), m_history()
{}
CommandHistory::~CommandHistory ()
@@ -27,21 +24,21 @@ CommandHistory::~CommandHistory ()
size_t
CommandHistory::GetSize () const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_history.size();
}
bool
CommandHistory::IsEmpty () const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_history.empty();
}
const char*
CommandHistory::FindString (const char* input_str) const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!input_str)
return nullptr;
if (input_str[0] != g_repeat_char)
@@ -80,7 +77,7 @@ CommandHistory::FindString (const char* input_str) const
const char*
CommandHistory::GetStringAtIndex (size_t idx) const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (idx < m_history.size())
return m_history[idx].c_str();
return nullptr;
@@ -95,7 +92,7 @@ CommandHistory::operator [] (size_t idx) const
const char*
CommandHistory::GetRecentmostString () const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (m_history.empty())
return nullptr;
return m_history.back().c_str();
@@ -105,7 +102,7 @@ void
CommandHistory::AppendString (const std::string& str,
bool reject_if_dupe)
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (reject_if_dupe)
{
if (!m_history.empty())
@@ -120,7 +117,7 @@ CommandHistory::AppendString (const std::string& str,
void
CommandHistory::Clear ()
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
m_history.clear();
}
@@ -129,7 +126,7 @@ CommandHistory::Dump (Stream& stream,
size_t start_idx,
size_t stop_idx) const
{
- Mutex::Locker locker(m_mutex);
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
stop_idx = std::min(stop_idx + 1, m_history.size());
for (size_t counter = start_idx;
counter < stop_idx;
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index fd88f0d6b4be..5d5669f73cbc 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -105,7 +105,7 @@ CommandInterpreter::GetStaticBroadcasterClass ()
}
CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution)
- : Broadcaster(&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
+ : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
m_debugger(debugger),
@@ -185,6 +185,9 @@ CommandInterpreter::Initialize ()
LoadCommandDictionary ();
+ // An alias arguments vector to reuse - reset it before use...
+ OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
+
// Set up some initial aliases.
CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
if (cmd_obj_sp)
@@ -195,9 +198,7 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
if (cmd_obj_sp)
- {
- AddAlias ("attach", cmd_obj_sp);
- }
+ AddAlias ("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("process detach",false);
if (cmd_obj_sp)
@@ -214,11 +215,11 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
if (cmd_obj_sp)
- AddAlias ("b", cmd_obj_sp);
+ AddAlias ("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
if (cmd_obj_sp)
- AddAlias ("tbreak", cmd_obj_sp);
+ AddAlias ("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
if (cmd_obj_sp)
@@ -239,6 +240,13 @@ CommandInterpreter::Initialize ()
{
AddAlias ("s", cmd_obj_sp);
AddAlias ("step", cmd_obj_sp);
+ CommandAlias *sif_alias = AddAlias ("sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
+ if (sif_alias)
+ {
+ sif_alias->SetHelp("Step through the current block, stopping if you step "
+ "directly into a function whose name matches the TargetFunctionName.");
+ sif_alias->SetSyntax("sif <TargetFunctionName>");
+ }
}
cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
@@ -269,22 +277,20 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
if (cmd_obj_sp)
{
- AddAlias ("j", cmd_obj_sp);
- AddAlias ("jump", cmd_obj_sp);
+ AddAlias ("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ AddAlias ("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
}
cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
if (cmd_obj_sp)
{
- AddAlias ("l", cmd_obj_sp);
- AddAlias ("list", cmd_obj_sp);
+ AddAlias ("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
+ AddAlias ("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
}
cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
if (cmd_obj_sp)
- {
- AddAlias ("env", cmd_obj_sp);
- }
+ AddAlias ("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("memory read", false);
if (cmd_obj_sp)
@@ -292,15 +298,15 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
if (cmd_obj_sp)
- AddAlias ("up", cmd_obj_sp);
+ AddAlias ("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
if (cmd_obj_sp)
- AddAlias ("down", cmd_obj_sp);
+ AddAlias ("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
if (cmd_obj_sp)
- AddAlias ("display", cmd_obj_sp);
+ AddAlias ("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("disassemble", false);
if (cmd_obj_sp)
@@ -314,11 +320,11 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
if (cmd_obj_sp)
- AddAlias ("undisplay", cmd_obj_sp);
+ AddAlias ("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
if (cmd_obj_sp)
- AddAlias ("bt", cmd_obj_sp);
+ AddAlias ("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
cmd_obj_sp = GetCommandSPExact ("target create", false);
if (cmd_obj_sp)
@@ -329,23 +335,22 @@ CommandInterpreter::Initialize ()
AddAlias ("image", cmd_obj_sp);
- OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
-
+ alias_arguments_vector_sp.reset(new OptionArgVector);
+
cmd_obj_sp = GetCommandSPExact ("expression", false);
if (cmd_obj_sp)
{
- ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
- AddAlias ("p", cmd_obj_sp);
- AddAlias ("print", cmd_obj_sp);
- AddAlias ("call", cmd_obj_sp);
- AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
- AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
- AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
-
- alias_arguments_vector_sp.reset (new OptionArgVector);
- ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
- AddAlias ("po", cmd_obj_sp);
- AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
+ AddAlias ("p", cmd_obj_sp, "--")->SetHelpLong("");
+ AddAlias ("print", cmd_obj_sp, "--")->SetHelpLong("");
+ AddAlias ("call", cmd_obj_sp, "--")->SetHelpLong("");
+ if (auto po = AddAlias ("po", cmd_obj_sp, "-O --"))
+ {
+ po->SetHelp("Evaluate an expression on the current thread. Displays any returned value with formatting "
+ "controlled by the type's author.");
+ po->SetHelpLong("");
+ }
+ AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
+ AddAlias("poarray", cmd_obj_sp, "--object-description --element-count %1 --")->SetHelpLong("");
}
cmd_obj_sp = GetCommandSPExact ("process kill", false);
@@ -359,26 +364,23 @@ CommandInterpreter::Initialize ()
{
alias_arguments_vector_sp.reset (new OptionArgVector);
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
- ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
+ AddAlias ("r", cmd_obj_sp, "--");
+ AddAlias ("run", cmd_obj_sp, "--");
#else
#if defined(__APPLE__)
std::string shell_option;
shell_option.append("--shell-expand-args");
shell_option.append(" true");
shell_option.append(" --");
- ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp);
+ AddAlias ("r", cmd_obj_sp, "--shell-expand-args true --");
+ AddAlias ("run", cmd_obj_sp, "--shell-expand-args true --");
#else
- std::string shell_option;
- shell_option.append("--shell=");
- shell_option.append(HostInfo::GetDefaultShell().GetPath());
- shell_option.append(" --");
- ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp);
+ StreamString defaultshell;
+ defaultshell.Printf("--shell=%s --", HostInfo::GetDefaultShell().GetPath().c_str());
+ AddAlias ("r", cmd_obj_sp, defaultshell.GetData());
+ AddAlias ("run", cmd_obj_sp, defaultshell.GetData());
#endif
#endif
- AddAlias ("r", cmd_obj_sp);
- AddAlias ("run", cmd_obj_sp);
- AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
- AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
}
cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
@@ -390,10 +392,7 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
if (cmd_obj_sp)
{
- alias_arguments_vector_sp.reset (new OptionArgVector);
- ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
- AddAlias ("rbreak", cmd_obj_sp);
- AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
+ AddAlias ("rbreak", cmd_obj_sp, "--func-regex %1");
}
}
@@ -466,22 +465,26 @@ CommandInterpreter::LoadCommandDictionary ()
{"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}};
size_t num_regexes = llvm::array_lengthof(break_regexes);
-
- std::unique_ptr<CommandObjectRegexCommand>
- break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-break",
- "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n",
- "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12 // Break on line 12 of main.c\n"
- "_regexp-break <linenum> # _regexp-break 12 // Break on line 12 of current file\n"
- "_regexp-break <address> # _regexp-break 0x1234000 // Break on address 0x1234000\n"
- "_regexp-break <name> # _regexp-break main // Break in 'main' after the prologue\n"
- "_regexp-break &<name> # _regexp-break &main // Break on the first instruction in 'main'\n"
- "_regexp-break <module>`<name> # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n"
- "_regexp-break /<source-regex>/ # _regexp-break /break here/ // Break on all lines that match the regular expression 'break here' in the current file.\n",
- 2,
- CommandCompletions::eSymbolCompletion |
- CommandCompletions::eSourceFileCompletion,
- false));
+
+ std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-break", "Set a breakpoint using one of several shorthand formats.\n",
+ "\n"
+ "_regexp-break <filename>:<linenum>\n"
+ " main.c:12 // Break at line 12 of main.c\n\n"
+ "_regexp-break <linenum>\n"
+ " 12 // Break at line 12 of current file\n\n"
+ "_regexp-break 0x<address>\n"
+ " 0x1234000 // Break at address 0x1234000\n\n"
+ "_regexp-break <name>\n"
+ " main // Break in 'main' after the prologue\n\n"
+ "_regexp-break &<name>\n"
+ " &main // Break at first instruction in 'main'\n\n"
+ "_regexp-break <module>`<name>\n"
+ " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n"
+ "_regexp-break /<source-regex>/\n"
+ " /break here/ // Break on source lines in current file\n"
+ " // containing text 'break here'.\n",
+ 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));
if (break_regex_cmd_ap.get())
{
@@ -501,15 +504,25 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-tbreak",
- "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
- "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
- 2,
- CommandCompletions::eSymbolCompletion |
- CommandCompletions::eSourceFileCompletion,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-tbreak", "Set a one-shot breakpoint using one of several shorthand formats.\n",
+ "\n"
+ "_regexp-break <filename>:<linenum>\n"
+ " main.c:12 // Break at line 12 of main.c\n\n"
+ "_regexp-break <linenum>\n"
+ " 12 // Break at line 12 of current file\n\n"
+ "_regexp-break 0x<address>\n"
+ " 0x1234000 // Break at address 0x1234000\n\n"
+ "_regexp-break <name>\n"
+ " main // Break in 'main' after the prologue\n\n"
+ "_regexp-break &<name>\n"
+ " &main // Break at first instruction in 'main'\n\n"
+ "_regexp-break <module>`<name>\n"
+ " libc.so`malloc // Break in 'malloc' from 'libc.so'\n\n"
+ "_regexp-break /<source-regex>/\n"
+ " /break here/ // Break on source lines in current file\n"
+ " // containing text 'break here'.\n",
+ 2, CommandCompletions::eSymbolCompletion | CommandCompletions::eSourceFileCompletion, false));
if (tbreak_regex_cmd_ap.get())
{
@@ -534,14 +547,9 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-attach",
- "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
- "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_ap(
+ new CommandObjectRegexCommand(*this, "_regexp-attach", "Attach to process by ID or name.",
+ "_regexp-attach <pid> | <process-name>", 2, 0, false));
if (attach_regex_cmd_ap.get())
{
if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
@@ -553,15 +561,11 @@ CommandInterpreter::LoadCommandDictionary ()
m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
}
}
-
- std::unique_ptr<CommandObjectRegexCommand>
- down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-down",
- "Go down \"n\" frames in the stack (1 frame by default).",
- "_regexp-down [n]",
- 2,
- 0,
- false));
+
+ std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-down", "Select a newer stack frame. Defaults to moving one frame, a numeric argument can "
+ "specify an arbitrary number.",
+ "_regexp-down [<count>]", 2, 0, false));
if (down_regex_cmd_ap.get())
{
if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
@@ -571,15 +575,11 @@ CommandInterpreter::LoadCommandDictionary ()
m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
}
}
-
- std::unique_ptr<CommandObjectRegexCommand>
- up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-up",
- "Go up \"n\" frames in the stack (1 frame by default).",
- "_regexp-up [n]",
- 2,
- 0,
- false));
+
+ std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_ap(
+ new CommandObjectRegexCommand(*this, "_regexp-up", "Select an older stack frame. Defaults to moving one "
+ "frame, a numeric argument can specify an arbitrary number.",
+ "_regexp-up [<count>]", 2, 0, false));
if (up_regex_cmd_ap.get())
{
if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
@@ -590,14 +590,9 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-display",
- "Add an expression evaluation stop-hook.",
- "_regexp-display expression",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-display", "Evaluate an expression at every stop (see 'help target stop-hook'.)",
+ "_regexp-display expression", 2, 0, false));
if (display_regex_cmd_ap.get())
{
if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
@@ -607,14 +602,9 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-undisplay",
- "Remove an expression evaluation stop-hook.",
- "_regexp-undisplay stop-hook-number",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-undisplay", "Stop displaying expression at every stop (specified by stop-hook index.)",
+ "_regexp-undisplay stop-hook-number", 2, 0, false));
if (undisplay_regex_cmd_ap.get())
{
if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
@@ -624,14 +614,10 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
- "gdb-remote",
- "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
- "gdb-remote [<hostname>:]<portnum>",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand(
+ *this, "gdb-remote",
+ "Connect to a process via remote GDB server. If no host is specifed, localhost is assumed.",
+ "gdb-remote [<hostname>:]<portnum>", 2, 0, false));
if (connect_gdb_remote_cmd_ap.get())
{
if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
@@ -642,14 +628,10 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
- "kdp-remote",
- "Connect to a remote KDP server. udp port 41139 is the default port number.",
- "kdp-remote <hostname>[:<portnum>]",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand(
+ *this, "kdp-remote",
+ "Connect to a process via remote KDP server. If no UDP port is specified, port 41139 is assumed.",
+ "kdp-remote <hostname>[:<portnum>]", 2, 0, false));
if (connect_kdp_remote_cmd_ap.get())
{
if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
@@ -660,14 +642,10 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-bt",
- "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.",
- "bt [<digit>|all]",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-bt", "Show the current thread's call stack. Any numeric argument displays at most that many "
+ "frames. The argument 'all' displays all threads.",
+ "bt [<digit> | all]", 2, 0, false));
if (bt_regex_cmd_ap.get())
{
// accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
@@ -683,14 +661,16 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-list",
- "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
- "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
- 2,
- CommandCompletions::eSourceFileCompletion,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_ap(new CommandObjectRegexCommand(
+ *this, "_regexp-list", "List relevant source code using one of several shorthand formats.",
+ "\n"
+ "_regexp-list <file>:<line> // List around specific file/line\n"
+ "_regexp-list <line> // List current file around specified line\n"
+ "_regexp-list <function-name> // List specified function\n"
+ "_regexp-list 0x<address> // List around specified address\n"
+ "_regexp-list -[<count>] // List previous <count> lines\n"
+ "_regexp-list // List subsequent lines",
+ 2, CommandCompletions::eSourceFileCompletion, false));
if (list_regex_cmd_ap.get())
{
if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
@@ -706,14 +686,12 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-env",
- "Implements a shortcut to viewing and setting environment variables.",
- "_regexp-env\n_regexp-env FOO=BAR",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_ap(
+ new CommandObjectRegexCommand(*this, "_regexp-env", "Shorthand for viewing and setting environment variables.",
+ "\n"
+ "_regexp-env // Show enrivonment\n"
+ "_regexp-env <name>=<value> // Set an environment variable",
+ 2, 0, false));
if (env_regex_cmd_ap.get())
{
if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
@@ -724,17 +702,14 @@ CommandInterpreter::LoadCommandDictionary ()
}
}
- std::unique_ptr<CommandObjectRegexCommand>
- jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-jump",
- "Sets the program counter to a new address.",
- "_regexp-jump [<line>]\n"
- "_regexp-jump [<+-lineoffset>]\n"
- "_regexp-jump [<file>:<line>]\n"
- "_regexp-jump [*<addr>]\n",
- 2,
- 0,
- false));
+ std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_ap(
+ new CommandObjectRegexCommand(*this, "_regexp-jump", "Set the program counter to a new address.",
+ "\n"
+ "_regexp-jump <line>\n"
+ "_regexp-jump +<line-offset> | -<line-offset>\n"
+ "_regexp-jump <file>:<line>\n"
+ "_regexp-jump *<addr>\n",
+ 2, 0, false));
if (jump_regex_cmd_ap.get())
{
if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
@@ -753,11 +728,11 @@ int
CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
StringList &matches)
{
- CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
+ AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
if (include_aliases)
{
- CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
+ AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
}
return matches.GetSize();
@@ -780,9 +755,9 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
if (include_aliases && HasAliases())
{
- pos = m_alias_dict.find(cmd);
- if (pos != m_alias_dict.end())
- command_sp = pos->second;
+ auto alias_pos = m_alias_dict.find(cmd);
+ if (alias_pos != m_alias_dict.end())
+ command_sp = alias_pos->second;
}
if (HasUserCommands())
@@ -811,7 +786,7 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
if (HasCommands())
{
- num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
+ num_cmd_matches = AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
}
if (num_cmd_matches == 1)
@@ -824,21 +799,21 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
if (include_aliases && HasAliases())
{
- num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
+ num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
}
if (num_alias_matches == 1)
{
cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
- pos = m_alias_dict.find(cmd);
- if (pos != m_alias_dict.end())
- alias_match_sp = pos->second;
+ auto alias_pos = m_alias_dict.find(cmd);
+ if (alias_pos != m_alias_dict.end())
+ alias_match_sp = alias_pos->second;
}
if (HasUserCommands())
{
- num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
+ num_user_matches = AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
}
if (num_user_matches == 1)
@@ -874,6 +849,9 @@ CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bo
bool
CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
{
+ if (cmd_sp.get())
+ assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
+
if (name && name[0])
{
std::string name_sstr(name);
@@ -893,9 +871,11 @@ CommandInterpreter::AddUserCommand (std::string name,
const lldb::CommandObjectSP &cmd_sp,
bool can_replace)
{
+ if (cmd_sp.get())
+ assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
+
if (!name.empty())
{
-
const char* name_cstr = name.c_str();
// do not allow replacement of internal commands
@@ -1009,59 +989,6 @@ CommandInterpreter::CommandExists (const char *cmd)
}
bool
-CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
- const char *options_args,
- OptionArgVectorSP &option_arg_vector_sp)
-{
- bool success = true;
- OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
-
- if (!options_args || (strlen (options_args) < 1))
- return true;
-
- std::string options_string (options_args);
- Args args (options_args);
- CommandReturnObject result;
- // Check to see if the command being aliased can take any command options.
- Options *options = cmd_obj_sp->GetOptions ();
- if (options)
- {
- // See if any options were specified as part of the alias; if so, handle them appropriately.
- options->NotifyOptionParsingStarting ();
- args.Unshift ("dummy_arg");
- args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
- args.Shift ();
- if (result.Succeeded())
- options->VerifyPartialOptions (result);
- if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
- {
- result.AppendError ("Unable to create requested alias.\n");
- return false;
- }
- }
-
- if (!options_string.empty())
- {
- if (cmd_obj_sp->WantsRawCommandString ())
- option_arg_vector->push_back (OptionArgPair ("<argument>",
- OptionArgValue (-1,
- options_string)));
- else
- {
- const size_t argc = args.GetArgumentCount();
- for (size_t i = 0; i < argc; ++i)
- if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
- option_arg_vector->push_back
- (OptionArgPair ("<argument>",
- OptionArgValue (-1,
- std::string (args.GetArgumentAtIndex (i)))));
- }
- }
-
- return success;
-}
-
-bool
CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
{
bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
@@ -1074,7 +1001,7 @@ CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
{
StringList matches;
size_t num_alias_matches;
- num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
+ num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
if (num_alias_matches == 1)
{
// Make sure this isn't shadowing a command in the regular command space:
@@ -1107,17 +1034,32 @@ CommandInterpreter::UserCommandExists (const char *cmd)
return m_user_dict.find(cmd) != m_user_dict.end();
}
-void
-CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
+CommandAlias*
+CommandInterpreter::AddAlias (const char *alias_name,
+ lldb::CommandObjectSP& command_obj_sp,
+ const char *args_string)
{
- command_obj_sp->SetIsAlias (true);
- m_alias_dict[alias_name] = command_obj_sp;
+ if (command_obj_sp.get())
+ assert((this == &command_obj_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
+
+ std::unique_ptr<CommandAlias> command_alias_up(new CommandAlias(*this,
+ command_obj_sp,
+ args_string,
+ alias_name));
+
+ if (command_alias_up && command_alias_up->IsValid())
+ {
+ m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get());
+ return command_alias_up.release();
+ }
+
+ return nullptr;
}
bool
CommandInterpreter::RemoveAlias (const char *alias_name)
{
- CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
+ auto pos = m_alias_dict.find(alias_name);
if (pos != m_alias_dict.end())
{
m_alias_dict.erase(pos);
@@ -1154,56 +1096,6 @@ CommandInterpreter::RemoveUser (const char *alias_name)
}
void
-CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
-{
- help_string.Printf ("'%s", command_name);
- OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
-
- if (option_arg_vector_sp)
- {
- OptionArgVector *options = option_arg_vector_sp.get();
- for (size_t i = 0; i < options->size(); ++i)
- {
- OptionArgPair cur_option = (*options)[i];
- std::string opt = cur_option.first;
- OptionArgValue value_pair = cur_option.second;
- std::string value = value_pair.second;
- if (opt.compare("<argument>") == 0)
- {
- help_string.Printf (" %s", value.c_str());
- }
- else
- {
- help_string.Printf (" %s", opt.c_str());
- if ((value.compare ("<no-argument>") != 0)
- && (value.compare ("<need-argument") != 0))
- {
- help_string.Printf (" %s", value.c_str());
- }
- }
- }
- }
-
- help_string.Printf ("'");
-}
-
-size_t
-CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
-{
- CommandObject::CommandMap::const_iterator pos;
- CommandObject::CommandMap::const_iterator end = dict.end();
- size_t max_len = 0;
-
- for (pos = dict.begin(); pos != end; ++pos)
- {
- size_t len = pos->first.size();
- if (max_len < len)
- max_len = len;
- }
- return max_len;
-}
-
-void
CommandInterpreter::GetHelp (CommandReturnObject &result,
uint32_t cmd_types)
{
@@ -1241,17 +1133,10 @@ CommandInterpreter::GetHelp (CommandReturnObject &result,
result.AppendMessage("");
max_len = FindLongestCommandWord (m_alias_dict);
- for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
+ for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); ++alias_pos)
{
- StreamString sstr;
- StreamString translation_and_help;
- std::string entry_name = pos->first;
- std::string second_entry = pos->second.get()->GetCommandName();
- GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
-
- translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp());
- OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
- translation_and_help.GetData(), max_len);
+ OutputFormattedHelpText (result.GetOutputStream(), alias_pos->first.c_str(), "--", alias_pos->second->GetHelp(),
+ max_len);
}
result.AppendMessage("");
}
@@ -1451,15 +1336,17 @@ CommandInterpreter::BuildAliasResult (const char *alias_name,
alias_cmd_obj = GetCommandObject (alias_name);
StreamString result_str;
- if (alias_cmd_obj)
+ if (alias_cmd_obj && alias_cmd_obj->IsAlias())
{
+ std::pair<CommandObjectSP, OptionArgVectorSP> desugared = ((CommandAlias*)alias_cmd_obj)->Desugar();
+ OptionArgVectorSP option_arg_vector_sp = desugared.second;
+ 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))
cmd_args.Unshift (alias_name);
result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
- OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
if (option_arg_vector_sp.get())
{
@@ -1617,6 +1504,7 @@ CommandInterpreter::PreprocessCommand (std::string &command)
break;
case eExpressionResultUnavailable:
error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str());
+ break;
case eExpressionCompleted:
break;
case eExpressionDiscarded:
@@ -2085,38 +1973,18 @@ CommandInterpreter::Confirm (const char *message, bool default_answer)
return confirm->GetResponse();
}
-OptionArgVectorSP
-CommandInterpreter::GetAliasOptions (const char *alias_name)
+CommandAlias*
+CommandInterpreter::GetAlias (const char *alias_name)
{
- OptionArgMap::iterator pos;
OptionArgVectorSP ret_val;
std::string alias (alias_name);
- if (HasAliasOptions())
- {
- pos = m_alias_options.find (alias);
- if (pos != m_alias_options.end())
- ret_val = pos->second;
- }
-
- return ret_val;
-}
-
-void
-CommandInterpreter::RemoveAliasOptions (const char *alias_name)
-{
- OptionArgMap::iterator pos = m_alias_options.find(alias_name);
- if (pos != m_alias_options.end())
- {
- m_alias_options.erase (pos);
- }
-}
-
-void
-CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
-{
- m_alias_options[alias_name] = option_arg_vector_sp;
+ auto pos = m_alias_dict.find(alias);
+ if (pos != m_alias_dict.end())
+ return (CommandAlias*)pos->second.get();
+
+ return nullptr;
}
bool
@@ -2140,7 +2008,7 @@ CommandInterpreter::HasUserCommands ()
bool
CommandInterpreter::HasAliasOptions ()
{
- return (!m_alias_options.empty());
+ return HasAliases();
}
void
@@ -2150,7 +2018,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
std::string &raw_input_string,
CommandReturnObject &result)
{
- OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
+ OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments();
bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
@@ -2311,12 +2179,44 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
FileSpec init_file;
if (in_cwd)
{
- // In the current working directory we don't load any program specific
- // .lldbinit files, we only look for a "./.lldbinit" file.
- if (m_skip_lldbinit_files)
- return;
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ // In the current working directory we don't load any program specific
+ // .lldbinit files, we only look for a ".lldbinit" file.
+ if (m_skip_lldbinit_files)
+ return;
- init_file.SetFile ("./.lldbinit", true);
+ LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile ();
+ if (should_load == eLoadCWDlldbinitWarn)
+ {
+ FileSpec dot_lldb (".lldbinit", true);
+ llvm::SmallString<64> home_dir_path;
+ llvm::sys::path::home_directory (home_dir_path);
+ FileSpec homedir_dot_lldb (home_dir_path.c_str(), false);
+ homedir_dot_lldb.AppendPathComponent (".lldbinit");
+ homedir_dot_lldb.ResolvePath ();
+ if (dot_lldb.Exists ()
+ && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory())
+ {
+ result.AppendErrorWithFormat (
+ "There is a .lldbinit file in the current directory which is not being read.\n"
+ "To silence this warning without sourcing in the local .lldbinit,\n"
+ "add the following to the lldbinit file in your home directory:\n"
+ " settings set target.load-cwd-lldbinit false\n"
+ "To allow lldb to source .lldbinit files in the current working directory,\n"
+ "set the value of this variable to true. Only do so if you understand and\n"
+ "accept the security risk.");
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ }
+ else if (should_load == eLoadCWDlldbinitTrue)
+ {
+ init_file.SetFile ("./.lldbinit", true);
+ }
+ }
}
else
{
@@ -2856,54 +2756,63 @@ CommandInterpreter::OutputHelpText (Stream &strm,
}
void
-CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
- StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
+CommandInterpreter::FindCommandsForApropos (const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help,
+ CommandObject::CommandMap &command_map)
{
CommandObject::CommandMap::const_iterator pos;
-
- if (search_builtin_commands)
+
+ for (pos = command_map.begin(); pos != command_map.end(); ++pos)
{
- for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+ const char *command_name = pos->first.c_str();
+ CommandObject *cmd_obj = pos->second.get();
+
+ const bool search_short_help = true;
+ const bool search_long_help = false;
+ const bool search_syntax = false;
+ const bool search_options = false;
+ if (strcasestr(command_name, search_word) ||
+ cmd_obj->HelpTextContainsWord (search_word,
+ search_short_help,
+ search_long_help,
+ search_syntax,
+ search_options))
+ {
+ commands_found.AppendString (cmd_obj->GetCommandName());
+ commands_help.AppendString (cmd_obj->GetHelp());
+ }
+
+ if (cmd_obj->IsMultiwordObject())
{
- const char *command_name = pos->first.c_str();
- CommandObject *cmd_obj = pos->second.get();
-
- if (cmd_obj->HelpTextContainsWord (search_word))
- {
- commands_found.AppendString (command_name);
- commands_help.AppendString (cmd_obj->GetHelp());
- }
-
- if (cmd_obj->IsMultiwordObject())
- cmd_obj->AproposAllSubCommands (command_name,
- search_word,
- commands_found,
- commands_help);
-
+ CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand();
+ FindCommandsForApropos(search_word,
+ commands_found,
+ commands_help,
+ cmd_multiword->GetSubcommandDictionary());
}
}
+}
+
+
+void
+CommandInterpreter::FindCommandsForApropos (const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help,
+ bool search_builtin_commands,
+ bool search_user_commands,
+ bool search_alias_commands)
+{
+ CommandObject::CommandMap::const_iterator pos;
+
+ if (search_builtin_commands)
+ FindCommandsForApropos(search_word, commands_found, commands_help, m_command_dict);
if (search_user_commands)
- {
- for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
- {
- const char *command_name = pos->first.c_str();
- CommandObject *cmd_obj = pos->second.get();
-
- if (cmd_obj->HelpTextContainsWord (search_word))
- {
- commands_found.AppendString (command_name);
- commands_help.AppendString (cmd_obj->GetHelp());
- }
+ FindCommandsForApropos(search_word, commands_found, commands_help, m_user_dict);
- if (cmd_obj->IsMultiwordObject())
- cmd_obj->AproposAllSubCommands (command_name,
- search_word,
- commands_found,
- commands_help);
-
- }
- }
+ if (search_alias_commands)
+ FindCommandsForApropos(search_word, commands_found, commands_help, m_alias_dict);
}
void
@@ -3240,8 +3149,12 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnO
if (cmd_obj == nullptr)
{
std::string full_name;
- if (GetAliasFullName(next_word.c_str(), full_name))
+ bool is_alias = GetAliasFullName(next_word.c_str(), full_name);
+ cmd_obj = GetCommandObject(next_word.c_str(), &matches);
+ bool is_real_command = (is_alias == false) || (cmd_obj != nullptr && cmd_obj->IsAlias() == false);
+ if (!is_real_command)
{
+ matches.Clear();
std::string alias_result;
cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result);
revised_command_line.Printf("%s", alias_result.c_str());
@@ -3253,7 +3166,8 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnO
}
else
{
- cmd_obj = GetCommandObject(next_word.c_str(), &matches);
+ if (!cmd_obj)
+ cmd_obj = GetCommandObject(next_word.c_str(), &matches);
if (cmd_obj)
{
actual_cmd_name_len += strlen(cmd_obj->GetCommandName());
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index 616d3e38acbb..75e42925406b 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -53,7 +53,6 @@ CommandObject::CommandObject
m_cmd_help_short (),
m_cmd_help_long (),
m_cmd_syntax (),
- m_is_alias (false),
m_flags (flags),
m_arguments(),
m_deprecated_command_override_callback (nullptr),
@@ -89,12 +88,12 @@ CommandObject::GetSyntax ()
{
StreamString syntax_str;
syntax_str.Printf ("%s", GetCommandName());
- if (GetOptions() != nullptr)
+ if (!IsDashDashCommand() && GetOptions() != nullptr)
syntax_str.Printf (" <cmd-options>");
if (m_arguments.size() > 0)
{
syntax_str.Printf (" ");
- if (WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
+ if (!IsDashDashCommand() && WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
syntax_str.Printf("-- ");
GetFormattedCommandArguments (syntax_str);
}
@@ -119,25 +118,19 @@ CommandObject::SetCommandName (const char *name)
void
CommandObject::SetHelp (const char *cstr)
{
- m_cmd_help_short = cstr;
-}
-
-void
-CommandObject::SetHelp (std::string str)
-{
- m_cmd_help_short = str;
+ if (cstr)
+ m_cmd_help_short = cstr;
+ else
+ m_cmd_help_short.assign("");
}
void
CommandObject::SetHelpLong (const char *cstr)
{
- m_cmd_help_long = cstr;
-}
-
-void
-CommandObject::SetHelpLong (std::string str)
-{
- m_cmd_help_long = str;
+ if (cstr)
+ m_cmd_help_long = cstr;
+ else
+ m_cmd_help_long.assign("");
}
void
@@ -283,7 +276,7 @@ CommandObject::CheckRequirements (CommandReturnObject &result)
{
Target *target = m_exe_ctx.GetTargetPtr();
if (target)
- m_api_locker.Lock (target->GetAPIMutex());
+ m_api_locker = std::unique_lock<std::recursive_mutex>(target->GetAPIMutex());
}
}
@@ -343,46 +336,8 @@ void
CommandObject::Cleanup ()
{
m_exe_ctx.Clear();
- m_api_locker.Unlock();
-}
-
-
-class CommandDictCommandPartialMatch
-{
- public:
- CommandDictCommandPartialMatch (const char *match_str)
- {
- m_match_str = match_str;
- }
- bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
- {
- // A NULL or empty string matches everything.
- if (m_match_str == nullptr || *m_match_str == '\0')
- return true;
-
- return map_element.first.find (m_match_str, 0) == 0;
- }
-
- private:
- const char *m_match_str;
-};
-
-int
-CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
- StringList &matches)
-{
- int number_added = 0;
- CommandDictCommandPartialMatch matcher(cmd_str);
-
- CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
-
- while (matching_cmds != in_map.end())
- {
- ++number_added;
- matches.AppendString((*matching_cmds).first.c_str());
- matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
- }
- return number_added;
+ if (m_api_locker.owns_lock())
+ m_api_locker.unlock();
}
int
@@ -457,7 +412,11 @@ CommandObject::HandleCompletion
}
bool
-CommandObject::HelpTextContainsWord (const char *search_word)
+CommandObject::HelpTextContainsWord (const char *search_word,
+ bool search_short_help,
+ bool search_long_help,
+ bool search_syntax,
+ bool search_options)
{
std::string options_usage_help;
@@ -467,14 +426,15 @@ CommandObject::HelpTextContainsWord (const char *search_word)
const char *long_help = GetHelpLong();
const char *syntax_help = GetSyntax();
- if (short_help && strcasestr (short_help, search_word))
+ if (search_short_help && short_help && strcasestr (short_help, search_word))
found_word = true;
- else if (long_help && strcasestr (long_help, search_word))
+ else if (search_long_help && long_help && strcasestr (long_help, search_word))
found_word = true;
- else if (syntax_help && strcasestr (syntax_help, search_word))
+ else if (search_syntax && syntax_help && strcasestr (syntax_help, search_word))
found_word = true;
if (!found_word
+ && search_options
&& GetOptions() != nullptr)
{
StreamString usage_help;
@@ -727,46 +687,47 @@ RegisterNameHelpTextCallback ()
static const char *
BreakpointIDHelpTextCallback ()
{
- return "Breakpoint ID's consist major and minor numbers; the major number "
- "corresponds to the single entity that was created with a 'breakpoint set' "
- "command; the minor numbers correspond to all the locations that were actually "
- "found/set based on the major breakpoint. A full breakpoint ID might look like "
- "3.14, meaning the 14th location set for the 3rd breakpoint. You can specify "
- "all the locations of a breakpoint by just indicating the major breakpoint "
- "number. A valid breakpoint id consists either of just the major id number, "
- "or the major number, a dot, and the location number (e.g. 3 or 3.2 could "
- "both be valid breakpoint ids).";
+ return "Breakpoints are identified using major and minor numbers; the major "
+ "number corresponds to the single entity that was created with a 'breakpoint "
+ "set' command; the minor numbers correspond to all the locations that were "
+ "actually found/set based on the major breakpoint. A full breakpoint ID might "
+ "look like 3.14, meaning the 14th location set for the 3rd breakpoint. You "
+ "can specify all the locations of a breakpoint by just indicating the major "
+ "breakpoint number. A valid breakpoint ID consists either of just the major "
+ "number, or the major number followed by a dot and the location number (e.g. "
+ "3 or 3.2 could both be valid breakpoint IDs.)";
}
static const char *
BreakpointIDRangeHelpTextCallback ()
{
- return "A 'breakpoint id list' is a manner of specifying multiple breakpoints. "
- "This can be done through several mechanisms. The easiest way is to just "
- "enter a space-separated list of breakpoint ids. To specify all the "
- "breakpoint locations under a major breakpoint, you can use the major "
- "breakpoint number followed by '.*', eg. '5.*' means all the locations under "
- "breakpoint 5. You can also indicate a range of breakpoints by using "
- "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a range can "
- "be any valid breakpoint ids. It is not legal, however, to specify a range "
- "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7"
- " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
+ return "A 'breakpoint ID list' is a manner of specifying multiple breakpoints. "
+ "This can be done through several mechanisms. The easiest way is to just "
+ "enter a space-separated list of breakpoint IDs. To specify all the "
+ "breakpoint locations under a major breakpoint, you can use the major "
+ "breakpoint number followed by '.*', eg. '5.*' means all the locations under "
+ "breakpoint 5. You can also indicate a range of breakpoints by using "
+ "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a range can "
+ "be any valid breakpoint IDs. It is not legal, however, to specify a range "
+ "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7"
+ " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
}
static const char *
BreakpointNameHelpTextCallback ()
{
return "A name that can be added to a breakpoint when it is created, or later "
- "on with the \"breakpoint name add\" command. "
- "Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's "
- "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, "
- "and to operate on breakpoints you create without having to track the breakpoint number. "
- "Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
- "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name. Future breakpoints "
- "tagged with that name will not pick up the attributes previously given using that name. "
- "In order to distinguish breakpoint names from breakpoint ID's and ranges, "
- "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". "
- "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
+ "on with the \"breakpoint name add\" command. "
+ "Breakpoint names can be used to specify breakpoints in all the places breakpoint IDs "
+ "and breakpoint ID ranges can be used. As such they provide a convenient way to group breakpoints, "
+ "and to operate on breakpoints you create without having to track the breakpoint number. "
+ "Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
+ "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that "
+ "name. Future breakpoints "
+ "tagged with that name will not pick up the attributes previously given using that name. "
+ "In order to distinguish breakpoint names from breakpoint IDs and ranges, "
+ "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\". "
+ "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
}
static const char *
@@ -956,68 +917,46 @@ void
CommandObject::GenerateHelpText (Stream &output_strm)
{
CommandInterpreter& interpreter = GetCommandInterpreter();
- if (GetOptions() != nullptr)
+ if (WantsRawCommandString())
+ {
+ std::string help_text(GetHelp());
+ help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
+ interpreter.OutputFormattedHelpText(output_strm, "", "", help_text.c_str(), 1);
+ }
+ else
+ interpreter.OutputFormattedHelpText(output_strm, "", "", GetHelp(), 1);
+ output_strm.Printf("\nSyntax: %s\n", GetSyntax());
+ Options *options = GetOptions();
+ if (options != nullptr)
+ {
+ options->GenerateOptionUsage(output_strm, this);
+ }
+ const char *long_help = GetHelpLong();
+ if ((long_help != nullptr) && (strlen(long_help) > 0))
+ {
+ FormatLongHelpText(output_strm, long_help);
+ }
+ if (!IsDashDashCommand() && options && options->NumCommandOptions() > 0)
{
- if (WantsRawCommandString())
- {
- std::string help_text (GetHelp());
- help_text.append (" This command takes 'raw' input (no need to quote stuff).");
- interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
- }
- else
- interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
- output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
- GetOptions()->GenerateOptionUsage (output_strm, this);
- const char *long_help = GetHelpLong();
- if ((long_help != nullptr)
- && (strlen (long_help) > 0))
- FormatLongHelpText (output_strm, long_help);
if (WantsRawCommandString() && !WantsCompletion())
{
// Emit the message about using ' -- ' between the end of the command options and the raw input
// conditionally, i.e., only if the command object does not want completion.
- interpreter.OutputFormattedHelpText (output_strm, "", "",
- "\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options"
- " you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1);
+ interpreter.OutputFormattedHelpText(
+ output_strm, "", "",
+ "\nImportant Note: Because this command takes 'raw' input, if you use any command options"
+ " you must use ' -- ' between the end of the command options and the beginning of the raw input.",
+ 1);
}
- else if (GetNumArgumentEntries() > 0
- && GetOptions()
- && GetOptions()->NumCommandOptions() > 0)
+ else if (GetNumArgumentEntries() > 0)
{
// Also emit a warning about using "--" in case you are using a command that takes options and arguments.
- interpreter.OutputFormattedHelpText (output_strm, "", "",
- "\nThis command takes options and free-form arguments. If your arguments resemble"
- " option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
- " the end of the command options and the beginning of the arguments.", 1);
- }
- }
- else if (IsMultiwordObject())
- {
- if (WantsRawCommandString())
- {
- std::string help_text (GetHelp());
- help_text.append (" This command takes 'raw' input (no need to quote stuff).");
- interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
- }
- else
- interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
- GenerateHelpText (output_strm);
- }
- else
- {
- const char *long_help = GetHelpLong();
- if ((long_help != nullptr)
- && (strlen (long_help) > 0))
- FormatLongHelpText (output_strm, long_help);
- else if (WantsRawCommandString())
- {
- std::string help_text (GetHelp());
- help_text.append (" This command takes 'raw' input (no need to quote stuff).");
- interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
+ interpreter.OutputFormattedHelpText(
+ output_strm, "", "", "\nThis command takes options and free-form arguments. If your arguments resemble"
+ " option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
+ " the end of the command options and the beginning of the arguments.",
+ 1);
}
- else
- interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
- output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
}
}
@@ -1067,6 +1006,31 @@ CommandObject::GetSelectedOrDummyTarget(bool prefer_dummy)
return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
}
+Thread *
+CommandObject::GetDefaultThread()
+{
+ Thread *thread_to_use = m_exe_ctx.GetThreadPtr();
+ if (thread_to_use)
+ return thread_to_use;
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ if (!process)
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (!target)
+ {
+ target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ }
+ if (target)
+ process = target->GetProcessSP().get();
+ }
+
+ if (process)
+ return process->GetThreadList().GetSelectedThread().get();
+ else
+ return nullptr;
+}
+
bool
CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result)
{
@@ -1138,9 +1102,8 @@ const char *arch_helper()
return g_archs_help.GetData();
}
-CommandObject::ArgumentTableEntry
-CommandObject::g_arguments_data[] =
-{
+CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
+ // clang-format off
{ eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid address in the target program's execution space." },
{ eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "An expression that resolves to an address." },
{ eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." },
@@ -1170,7 +1133,7 @@ CommandObject::g_arguments_data[] =
{ eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr },
{ eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" },
{ eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." },
- { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr },
+ { eArgTypeLanguage, "source-language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr },
{ eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." },
{ eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
{ eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
@@ -1198,7 +1161,7 @@ CommandObject::g_arguments_data[] =
{ eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
{ eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
{ eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { nullptr, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." },
- { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "The word for which you wish to search for information about." },
+ { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "Any word of interest for search purposes." },
{ eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { nullptr, false }, "An Objective-C selector name." },
{ eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
{ eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
@@ -1223,7 +1186,9 @@ CommandObject::g_arguments_data[] =
{ eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
{ eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." },
{ eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." },
- { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }
+ { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." },
+ { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }
+ // clang-format on
};
const CommandObject::ArgumentTableEntry*
diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp
index 31e5311ab441..e7de490878fd 100644
--- a/source/Interpreter/CommandObjectScript.cpp
+++ b/source/Interpreter/CommandObjectScript.cpp
@@ -30,11 +30,10 @@ using namespace lldb_private;
// CommandObjectScript
//-------------------------------------------------------------------------
-CommandObjectScript::CommandObjectScript (CommandInterpreter &interpreter, ScriptLanguage script_lang) :
- CommandObjectRaw (interpreter,
- "script",
- "Pass an expression to the script interpreter for evaluation and return the results. Drop into the interactive interpreter if no expression is given.",
- "script [<script-expression-for-evaluation>]")
+CommandObjectScript::CommandObjectScript(CommandInterpreter &interpreter, ScriptLanguage script_lang)
+ : CommandObjectRaw(interpreter, "script", "Invoke the script interpreter with provided code and display any "
+ "results. Start the interactive interpreter if no code is supplied.",
+ "script [<script-code>]")
{
}
diff --git a/source/Interpreter/Makefile b/source/Interpreter/Makefile
deleted file mode 100644
index 2f25e6796604..000000000000
--- a/source/Interpreter/Makefile
+++ /dev/null
@@ -1,51 +0,0 @@
-##===- source/Interpreter/Makefile ------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLDB_LEVEL := ../..
-LIBRARYNAME := lldbInterpreter
-BUILD_ARCHIVE = 1
-include $(LLDB_LEVEL)/../../Makefile.config
-
-ifneq ($(HOST_OS),MingW)
-ifeq (,$(findstring -DLLDB_DISABLE_PYTHON,$(CXXFLAGS)))
-DO_BUILD_LLDBWrapPython = 1
-BUILT_SOURCES := LLDBWrapPython.cpp
-endif
-endif
-
-include $(LLDB_LEVEL)/Makefile
--include $(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.d
-
-ifeq ($(DO_BUILD_LLDBWrapPython),1)
-# Drop -Wfour-char-constants, which we are not currently clean with.
-EXTRA_OPTIONS += -Wno-four-char-constants
-
-# Drop -Wself-assign, -Wmissing-field-initializers, -Wsometimes-uninitialized,
-# -Wcast-qual, and -Wdeprecated-register which we are not clean with due to SWIG
-# generated cpp source.
-EXTRA_OPTIONS += -Wno-missing-field-initializers -Wno-self-assign -Wno-sometimes-uninitialized -Wno-cast-qual -Wno-deprecated-register
-
-PYTHON_DIR := $(PROJ_OBJ_ROOT)/$(BuildMode)
-
-SWIG_SOURCES := $(shell find $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts -type f -name '*.swig' -print)
-
-LLDBWrapPython.cpp lldb.py: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py \
- $(wildcard $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/interface/*.i) \
- ${SWIG_SOURCES}
- $(Echo) Generating LLDBWrapPython.cpp
- $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/prepare_bindings.py" "--src-root=$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "--target-dir=$(PROJ_OBJ_DIR)" "--config-build-dir=$(PROJ_OBJ_DIR)" "--prefix=$(PYTHON_DIR)" $(if $(DISABLE_AUTO_DEPENDENCIES),,-M) --find-swig
- $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/finish-swig-wrapper-classes.sh" "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "$(PROJ_OBJ_DIR)" "$(PROJ_OBJ_DIR)" "$(PYTHON_DIR)" -m
-
-install-local:: lldb.py
- $(Echo) Installing $(BuildMode) LLDB python modules
- $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/prepare_bindings.py" "--src-root=$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "--target-dir=$(PROJ_OBJ_DIR)" "--config-build-dir=$(PROJ_OBJ_DIR)" "--prefix=$(DESTDIR)$(prefix)" --find-swig
-
-clean-local::
- $(Verb) $(RM) -f LLDBWrapPython.cpp lldb.py
-endif
diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index bbd966859c34..c30a978d9577 100644
--- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -44,7 +44,8 @@ g_option_table[] =
{ LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
{ LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."},
{ LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
- { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."},
+ { LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument, nullptr, nullptr,0, eArgTypeBoolean, "Show results of type validators."},
+ { LLDB_OPT_SET_1, false, "element-count", 'Z', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Treat the result of the expression as if its type is an array of this many values."},
{ 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
};
@@ -92,6 +93,12 @@ OptionGroupValueObjectDisplay::SetOptionValue (CommandInterpreter &interpreter,
if (!success)
error.SetErrorStringWithFormat("invalid max depth '%s'", option_arg);
break;
+
+ case 'Z':
+ elem_count = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid element count '%s'", option_arg);
+ break;
case 'P':
ptr_depth = StringConvert::ToUInt32 (option_arg, 0, 0, &success);
@@ -141,6 +148,7 @@ OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interp
use_objc = false;
max_depth = UINT32_MAX;
ptr_depth = 0;
+ elem_count = 0;
use_synth = true;
be_raw = false;
ignore_cap = false;
@@ -187,6 +195,8 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl
options.SetRawDisplay();
options.SetRunValidator(run_validator);
+
+ options.SetElementCount(elem_count);
return options;
}
diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp
index aabe457534d6..348414f432c9 100644
--- a/source/Interpreter/OptionValueArray.cpp
+++ b/source/Interpreter/OptionValueArray.cpp
@@ -316,6 +316,7 @@ OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
case eVarSetOperationAssign:
m_values.clear();
// Fall through to append case
+ LLVM_FALLTHROUGH;
case eVarSetOperationAppend:
for (size_t i=0; i<argc; ++i)
{
diff --git a/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecLIst.cpp
index 669d3ee33acc..6a0ba11b676c 100644
--- a/source/Interpreter/OptionValueFileSpecLIst.cpp
+++ b/source/Interpreter/OptionValueFileSpecLIst.cpp
@@ -88,6 +88,7 @@ OptionValueFileSpecList::SetValueFromString (llvm::StringRef value, VarSetOperat
case eVarSetOperationAssign:
m_current_value.Clear();
// Fall through to append case
+ LLVM_FALLTHROUGH;
case eVarSetOperationAppend:
if (argc > 0)
{
diff --git a/source/Interpreter/OptionValuePathMappings.cpp b/source/Interpreter/OptionValuePathMappings.cpp
index 722d6a144279..f3f146f1f8c6 100644
--- a/source/Interpreter/OptionValuePathMappings.cpp
+++ b/source/Interpreter/OptionValuePathMappings.cpp
@@ -14,11 +14,24 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Stream.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/Args.h"
using namespace lldb;
using namespace lldb_private;
+namespace
+{
+ static bool
+ VerifyPathExists(const char *path)
+ {
+ if (path && path[0])
+ return FileSpec(path, false).Exists();
+ else
+ return false;
+ }
+}
+
void
OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
@@ -59,14 +72,27 @@ OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperat
}
else
{
+ bool changed = false;
for (size_t i=1; i<argc; i += 2, ++idx)
{
- ConstString a(args.GetArgumentAtIndex(i));
- ConstString b(args.GetArgumentAtIndex(i+1));
- if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
- m_path_mappings.Append(a, b, m_notify_changes);
+ const char *orginal_path = args.GetArgumentAtIndex(i);
+ const char *replace_path = args.GetArgumentAtIndex(i+1);
+ if (VerifyPathExists(replace_path))
+ {
+ ConstString a(orginal_path);
+ ConstString b(replace_path);
+ if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
+ m_path_mappings.Append(a, b, m_notify_changes);
+ changed = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("the replacement path doesn't exist: \"%s\"", replace_path);
+ break;
+ }
}
- NotifyValueChanged();
+ if (changed)
+ NotifyValueChanged();
}
}
else
@@ -85,6 +111,7 @@ OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperat
}
m_path_mappings.Clear(m_notify_changes);
// Fall through to append case
+ LLVM_FALLTHROUGH;
case eVarSetOperationAppend:
if (argc < 2 || (argc & 1))
{
@@ -93,14 +120,27 @@ OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperat
}
else
{
+ bool changed = false;
for (size_t i=0; i<argc; i += 2)
{
- ConstString a(args.GetArgumentAtIndex(i));
- ConstString b(args.GetArgumentAtIndex(i+1));
- m_path_mappings.Append(a, b, m_notify_changes);
- m_value_was_set = true;
+ const char *orginal_path = args.GetArgumentAtIndex(i);
+ const char *replace_path = args.GetArgumentAtIndex(i+1);
+ if (VerifyPathExists(replace_path))
+ {
+ ConstString a(orginal_path);
+ ConstString b(replace_path);
+ m_path_mappings.Append(a, b, m_notify_changes);
+ m_value_was_set = true;
+ changed = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("the replacement path doesn't exist: \"%s\"", replace_path);
+ break;
+ }
}
- NotifyValueChanged();
+ if (changed)
+ NotifyValueChanged();
}
break;
@@ -117,15 +157,28 @@ OptionValuePathMappings::SetValueFromString (llvm::StringRef value, VarSetOperat
}
else
{
+ bool changed = false;
if (op == eVarSetOperationInsertAfter)
++idx;
for (size_t i=1; i<argc; i += 2, ++idx)
{
- ConstString a(args.GetArgumentAtIndex(i));
- ConstString b(args.GetArgumentAtIndex(i+1));
- m_path_mappings.Insert (a, b, idx, m_notify_changes);
+ const char *orginal_path = args.GetArgumentAtIndex(i);
+ const char *replace_path = args.GetArgumentAtIndex(i+1);
+ if (VerifyPathExists(replace_path))
+ {
+ ConstString a(orginal_path);
+ ConstString b(replace_path);
+ m_path_mappings.Insert (a, b, idx, m_notify_changes);
+ changed = true;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("the replacement path doesn't exist: \"%s\"", replace_path);
+ break;
+ }
}
- NotifyValueChanged();
+ if (changed)
+ NotifyValueChanged();
}
}
else
diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp
index a3c28f70270f..7024c3601d9f 100644
--- a/source/Interpreter/OptionValueProperties.cpp
+++ b/source/Interpreter/OptionValueProperties.cpp
@@ -164,8 +164,23 @@ OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx,
switch (sub_name[0])
{
case '.':
- return value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error);
-
+ {
+ lldb::OptionValueSP return_val_sp;
+ return_val_sp = value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error);
+ if (!return_val_sp)
+ {
+ if (Properties::IsSettingExperimental(sub_name + 1))
+ {
+ size_t experimental_len = strlen(Properties::GetExperimentalSettingsName());
+ if (*(sub_name + experimental_len + 1) == '.')
+ return_val_sp = value_sp->GetSubValue(exe_ctx, sub_name + experimental_len + 2, will_modify, error);
+ // It isn't an error if an experimental setting is not present.
+ if (!return_val_sp)
+ error.Clear();
+ }
+ }
+ return return_val_sp;
+ }
case '{':
// Predicate matching for predicates like
// "<setting-name>{<predicate>}"
diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp
index 7f0e0abc03ea..70f532ed75de 100644
--- a/source/Interpreter/Options.cpp
+++ b/source/Interpreter/Options.cpp
@@ -14,6 +14,7 @@
#include <algorithm>
#include <bitset>
#include <map>
+#include <set>
// Other libraries and framework includes
// Project includes
@@ -477,6 +478,7 @@ Options::GenerateOptionUsage
CommandObject *cmd
)
{
+ const bool only_print_args = cmd->IsDashDashCommand();
const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
const OptionDefinition *opt_defs = GetDefinitions();
@@ -509,203 +511,211 @@ Options::GenerateOptionUsage
uint32_t i;
- for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
+ if (!only_print_args)
{
- uint32_t opt_set_mask;
-
- opt_set_mask = 1 << opt_set;
- if (opt_set > 0)
- strm.Printf ("\n");
- strm.Indent (name);
-
- // Different option sets may require different args.
- StreamString args_str;
- if (cmd)
- cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
-
- // First go through and print all options that take no arguments as
- // a single string. If a command has "-a" "-b" and "-c", this will show
- // up as [-abc]
-
- std::set<int> options;
- std::set<int>::const_iterator options_pos, options_end;
- for (i = 0; i < num_options; ++i)
+ for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
{
- if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ uint32_t opt_set_mask;
+
+ opt_set_mask = 1 << opt_set;
+ if (opt_set > 0)
+ strm.Printf ("\n");
+ strm.Indent (name);
+
+ // Different option sets may require different args.
+ StreamString args_str;
+ if (cmd)
+ cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
+
+ // First go through and print all options that take no arguments as
+ // a single string. If a command has "-a" "-b" and "-c", this will show
+ // up as [-abc]
+
+ std::set<int> options;
+ std::set<int>::const_iterator options_pos, options_end;
+ for (i = 0; i < num_options; ++i)
{
- // Add current option to the end of out_stream.
-
- if (opt_defs[i].required == true &&
- opt_defs[i].option_has_arg == OptionParser::eNoArgument)
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
- options.insert (opt_defs[i].short_option);
- }
- }
- }
+ // Add current option to the end of out_stream.
- if (options.empty() == false)
- {
- // We have some required options with no arguments
- strm.PutCString(" -");
- for (i=0; i<2; ++i)
- for (options_pos = options.begin(), options_end = options.end();
- options_pos != options_end;
- ++options_pos)
- {
- if (i==0 && ::islower (*options_pos))
- continue;
- if (i==1 && ::isupper (*options_pos))
- continue;
- strm << (char)*options_pos;
+ if (opt_defs[i].required == true &&
+ opt_defs[i].option_has_arg == OptionParser::eNoArgument)
+ {
+ options.insert (opt_defs[i].short_option);
+ }
}
- }
+ }
- for (i = 0, options.clear(); i < num_options; ++i)
- {
- if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ if (options.empty() == false)
{
- // Add current option to the end of out_stream.
+ // We have some required options with no arguments
+ strm.PutCString(" -");
+ for (i=0; i<2; ++i)
+ for (options_pos = options.begin(), options_end = options.end();
+ options_pos != options_end;
+ ++options_pos)
+ {
+ if (i==0 && ::islower (*options_pos))
+ continue;
+ if (i==1 && ::isupper (*options_pos))
+ continue;
+ strm << (char)*options_pos;
+ }
+ }
- if (opt_defs[i].required == false &&
- opt_defs[i].option_has_arg == OptionParser::eNoArgument)
+ for (i = 0, options.clear(); i < num_options; ++i)
+ {
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
- options.insert (opt_defs[i].short_option);
+ // Add current option to the end of out_stream.
+
+ if (opt_defs[i].required == false &&
+ opt_defs[i].option_has_arg == OptionParser::eNoArgument)
+ {
+ options.insert (opt_defs[i].short_option);
+ }
}
}
- }
- if (options.empty() == false)
- {
- // We have some required options with no arguments
- strm.PutCString(" [-");
- for (i=0; i<2; ++i)
- for (options_pos = options.begin(), options_end = options.end();
- options_pos != options_end;
- ++options_pos)
- {
- if (i==0 && ::islower (*options_pos))
- continue;
- if (i==1 && ::isupper (*options_pos))
- continue;
- strm << (char)*options_pos;
- }
- strm.PutChar(']');
- }
+ if (options.empty() == false)
+ {
+ // We have some required options with no arguments
+ strm.PutCString(" [-");
+ for (i=0; i<2; ++i)
+ for (options_pos = options.begin(), options_end = options.end();
+ options_pos != options_end;
+ ++options_pos)
+ {
+ if (i==0 && ::islower (*options_pos))
+ continue;
+ if (i==1 && ::isupper (*options_pos))
+ continue;
+ strm << (char)*options_pos;
+ }
+ strm.PutChar(']');
+ }
- // First go through and print the required options (list them up front).
-
- for (i = 0; i < num_options; ++i)
- {
- if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ // First go through and print the required options (list them up front).
+
+ for (i = 0; i < num_options; ++i)
{
- if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
- PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
+ {
+ if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
+ }
}
- }
- // Now go through again, and this time only print the optional options.
+ // Now go through again, and this time only print the optional options.
- for (i = 0; i < num_options; ++i)
- {
- if (opt_defs[i].usage_mask & opt_set_mask)
+ for (i = 0; i < num_options; ++i)
{
- // Add current option to the end of out_stream.
+ if (opt_defs[i].usage_mask & opt_set_mask)
+ {
+ // Add current option to the end of out_stream.
- if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
- PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
+ if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", nullptr, true, strm);
+ }
}
- }
-
- if (args_str.GetSize() > 0)
- {
- if (cmd->WantsRawCommandString())
- strm.Printf(" --");
- strm.Printf (" %s", args_str.GetData());
+ if (args_str.GetSize() > 0)
+ {
+ if (cmd->WantsRawCommandString() && !only_print_args)
+ strm.Printf(" --");
+
+ strm.Printf (" %s", args_str.GetData());
+ if (only_print_args)
+ break;
+ }
}
}
if (cmd &&
- cmd->WantsRawCommandString() &&
+ (only_print_args || cmd->WantsRawCommandString()) &&
arguments_str.GetSize() > 0)
{
- strm.PutChar('\n');
+ if (!only_print_args) strm.PutChar('\n');
strm.Indent(name);
strm.Printf(" %s", arguments_str.GetData());
}
strm.Printf ("\n\n");
- // Now print out all the detailed information about the various options: long form, short form and help text:
- // -short <argument> ( --long_name <argument> )
- // help text
+ if (!only_print_args)
+ {
+ // Now print out all the detailed information about the various options: long form, short form and help text:
+ // -short <argument> ( --long_name <argument> )
+ // help text
- // This variable is used to keep track of which options' info we've printed out, because some options can be in
- // more than one usage level, but we only want to print the long form of its information once.
+ // This variable is used to keep track of which options' info we've printed out, because some options can be in
+ // more than one usage level, but we only want to print the long form of its information once.
- std::multimap<int, uint32_t> options_seen;
- strm.IndentMore (5);
+ std::multimap<int, uint32_t> options_seen;
+ strm.IndentMore (5);
- // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
- // when writing out detailed help for each option.
+ // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
+ // when writing out detailed help for each option.
- for (i = 0; i < num_options; ++i)
- options_seen.insert(std::make_pair(opt_defs[i].short_option, i));
+ for (i = 0; i < num_options; ++i)
+ options_seen.insert(std::make_pair(opt_defs[i].short_option, i));
- // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
- // and write out the detailed help information for that option.
+ // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
+ // and write out the detailed help information for that option.
- bool first_option_printed = false;;
+ bool first_option_printed = false;;
- for (auto pos : options_seen)
- {
- i = pos.second;
- //Print out the help information for this option.
+ for (auto pos : options_seen)
+ {
+ i = pos.second;
+ //Print out the help information for this option.
- // Put a newline separation between arguments
- if (first_option_printed)
- strm.EOL();
- else
- first_option_printed = true;
-
- CommandArgumentType arg_type = opt_defs[i].argument_type;
-
- StreamString arg_name_str;
- arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
+ // Put a newline separation between arguments
+ if (first_option_printed)
+ strm.EOL();
+ else
+ first_option_printed = true;
+
+ CommandArgumentType arg_type = opt_defs[i].argument_type;
+
+ StreamString arg_name_str;
+ arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
- strm.Indent ();
- if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
- {
- PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm);
- PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
- }
- else
- {
- // Short option is not printable, just print long option
- PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm);
- }
- strm.EOL();
-
- strm.IndentMore (5);
-
- if (opt_defs[i].usage_text)
- OutputFormattedUsageText (strm,
- opt_defs[i],
- screen_width);
- if (opt_defs[i].enum_values != nullptr)
- {
strm.Indent ();
- strm.Printf("Values: ");
- for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++)
+ if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
{
- if (k == 0)
- strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
- else
- strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
+ PrintOption (opt_defs[i], eDisplayShortOption, nullptr, nullptr, false, strm);
+ PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
+ }
+ else
+ {
+ // Short option is not printable, just print long option
+ PrintOption (opt_defs[i], eDisplayLongOption, nullptr, nullptr, false, strm);
}
strm.EOL();
+
+ strm.IndentMore (5);
+
+ if (opt_defs[i].usage_text)
+ OutputFormattedUsageText (strm,
+ opt_defs[i],
+ screen_width);
+ if (opt_defs[i].enum_values != nullptr)
+ {
+ strm.Indent ();
+ strm.Printf("Values: ");
+ for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr; k++)
+ {
+ if (k == 0)
+ strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
+ else
+ strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
+ }
+ strm.EOL();
+ }
+ strm.IndentLess (5);
}
- strm.IndentLess (5);
}
// Restore the indent level
@@ -954,6 +964,13 @@ Options::HandleOptionArgumentCompletion
for (size_t i = 0; i < opt_element_vector.size(); i++)
{
int cur_defs_index = opt_element_vector[i].opt_defs_index;
+
+ // trying to use <0 indices will definitely cause problems
+ if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
+ cur_defs_index == OptionArgElement::eBareDash ||
+ cur_defs_index == OptionArgElement::eBareDoubleDash)
+ continue;
+
int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
const char *cur_opt_name = opt_defs[cur_defs_index].long_option;