diff options
Diffstat (limited to 'source/Interpreter/CommandAlias.cpp')
-rw-r--r-- | source/Interpreter/CommandAlias.cpp | 307 |
1 files changed, 307 insertions, 0 deletions
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; +} |