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; +}  | 
