brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · b45fcca Raw
250 lines · cpp
1//===-- CommandAlias.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Interpreter/CommandAlias.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/Support/ErrorHandling.h"13#include "llvm/Support/FormatAdapters.h"14 15#include "lldb/Interpreter/CommandInterpreter.h"16#include "lldb/Interpreter/CommandObject.h"17#include "lldb/Interpreter/CommandReturnObject.h"18#include "lldb/Interpreter/Options.h"19#include "lldb/Utility/StreamString.h"20 21using namespace lldb;22using namespace lldb_private;23 24static llvm::Error25ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,26                        llvm::StringRef options_args,27                        OptionArgVectorSP &option_arg_vector_sp) {28  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();29 30  if (options_args.size() < 1)31    return llvm::Error::success();32 33  Args args(options_args);34  std::string options_string(options_args);35  // Check to see if the command being aliased can take any command options.36  Options *options = cmd_obj_sp->GetOptions();37  if (options) {38    // See if any options were specified as part of the alias;  if so, handle39    // them appropriately.40    ExecutionContext exe_ctx =41        cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();42    options->NotifyOptionParsingStarting(&exe_ctx);43 44    llvm::Expected<Args> args_or =45        options->ParseAlias(args, option_arg_vector, options_string);46    if (!args_or)47      return llvm::createStringError(48          llvm::formatv("unable to create alias: {0}",49                        llvm::fmt_consume(args_or.takeError())));50    args = std::move(*args_or);51    if (llvm::Error error = options->VerifyPartialOptions())52      return error;53  }54 55  if (!options_string.empty()) {56    if (cmd_obj_sp->WantsRawCommandString()) {57      option_arg_vector->emplace_back(CommandInterpreter::g_argument, -1,58                                      options_string);59    } else {60      for (auto &entry : args.entries()) {61        if (!entry.ref().empty())62          option_arg_vector->emplace_back(63              std::string(CommandInterpreter::g_argument), -1,64              std::string(entry.ref()));65      }66    }67  }68 69  return llvm::Error::success();70}71 72CommandAlias::CommandAlias(CommandInterpreter &interpreter,73                           lldb::CommandObjectSP cmd_sp,74                           llvm::StringRef options_args, llvm::StringRef name,75                           llvm::StringRef help, llvm::StringRef syntax,76                           uint32_t flags)77    : CommandObject(interpreter, name, help, syntax, flags),78      m_option_string(std::string(options_args)),79      m_option_args_sp(new OptionArgVector),80      m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),81      m_did_set_help_long(false) {82  if (llvm::Error error =83          ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {84    // FIXME: Find a way to percolate this error up.85    LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(error),86                   "ProcessAliasOptionsArgs failed: {0}");87  } else {88    m_underlying_command_sp = cmd_sp;89    for (int i = 0;90         auto *cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);91         i++) {92      m_arguments.push_back(*cmd_entry);93    }94    if (!help.empty()) {95      StreamString sstr;96      StreamString translation_and_help;97      GetAliasExpansion(sstr);98 99      translation_and_help.Printf(100          "(%s)  %s", sstr.GetData(),101          GetUnderlyingCommand()->GetHelp().str().c_str());102      SetHelp(translation_and_help.GetString());103    }104  }105}106 107bool CommandAlias::WantsRawCommandString() {108  if (IsValid())109    return m_underlying_command_sp->WantsRawCommandString();110  return false;111}112 113bool CommandAlias::WantsCompletion() {114  if (IsValid())115    return m_underlying_command_sp->WantsCompletion();116  return false;117}118 119void CommandAlias::HandleCompletion(CompletionRequest &request) {120  if (IsValid())121    m_underlying_command_sp->HandleCompletion(request);122}123 124void CommandAlias::HandleArgumentCompletion(125    CompletionRequest &request, OptionElementVector &opt_element_vector) {126  if (IsValid())127    m_underlying_command_sp->HandleArgumentCompletion(request,128                                                      opt_element_vector);129}130 131Options *CommandAlias::GetOptions() {132  if (IsValid())133    return m_underlying_command_sp->GetOptions();134  return nullptr;135}136 137void CommandAlias::Execute(const char *args_string,138                           CommandReturnObject &result) {139  llvm_unreachable("CommandAlias::Execute is not to be called");140}141 142void CommandAlias::GetAliasExpansion(StreamString &help_string) const {143  llvm::StringRef command_name = m_underlying_command_sp->GetCommandName();144  help_string.Printf("'%*s", (int)command_name.size(), command_name.data());145 146  if (!m_option_args_sp) {147    help_string.Printf("'");148    return;149  }150 151  OptionArgVector *options = m_option_args_sp.get();152  std::string opt;153  std::string value;154 155  for (const auto &opt_entry : *options) {156    std::tie(opt, std::ignore, value) = opt_entry;157    if (opt == CommandInterpreter::g_argument) {158      help_string.Printf(" %s", value.c_str());159    } else {160      help_string.Printf(" %s", opt.c_str());161      if ((value != CommandInterpreter::g_no_argument) 162           && (value != CommandInterpreter::g_need_argument)) {163        help_string.Printf(" %s", value.c_str());164      }165    }166  }167 168  help_string.Printf("'");169}170 171bool CommandAlias::IsDashDashCommand() {172  if (m_is_dashdash_alias != eLazyBoolCalculate)173    return (m_is_dashdash_alias == eLazyBoolYes);174  m_is_dashdash_alias = eLazyBoolNo;175  if (!IsValid())176    return false;177 178  std::string opt;179  std::string value;180 181  for (const auto &opt_entry : *GetOptionArguments()) {182    std::tie(opt, std::ignore, value) = opt_entry;183    if (opt == CommandInterpreter::g_argument && !value.empty() &&184        llvm::StringRef(value).ends_with("--")) {185      m_is_dashdash_alias = eLazyBoolYes;186      break;187    }188  }189 190  // if this is a nested alias, it may be adding arguments on top of an already191  // dash-dash alias192  if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())193    m_is_dashdash_alias =194        (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes195                                                     : eLazyBoolNo);196  return (m_is_dashdash_alias == eLazyBoolYes);197}198 199bool CommandAlias::IsNestedAlias() {200  if (GetUnderlyingCommand())201    return GetUnderlyingCommand()->IsAlias();202  return false;203}204 205std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {206  auto underlying = GetUnderlyingCommand();207  if (!underlying)208    return {nullptr, nullptr};209 210  if (underlying->IsAlias()) {211    // FIXME: This doesn't work if the original alias fills a slot in the212    // underlying alias, since this just appends the two lists.213    auto desugared = ((CommandAlias *)underlying.get())->Desugar();214    OptionArgVectorSP options = std::make_shared<OptionArgVector>();215    llvm::append_range(*options, *desugared.second);216    llvm::append_range(*options, *GetOptionArguments());217    return {desugared.first, options};218  }219 220  return {underlying, GetOptionArguments()};221}222 223// allow CommandAlias objects to provide their own help, but fallback to the224// info for the underlying command if no customization has been provided225void CommandAlias::SetHelp(llvm::StringRef str) {226  this->CommandObject::SetHelp(str);227  m_did_set_help = true;228}229 230void CommandAlias::SetHelpLong(llvm::StringRef str) {231  this->CommandObject::SetHelpLong(str);232  m_did_set_help_long = true;233}234 235llvm::StringRef CommandAlias::GetHelp() {236  if (!m_cmd_help_short.empty() || m_did_set_help)237    return m_cmd_help_short;238  if (IsValid())239    return m_underlying_command_sp->GetHelp();240  return llvm::StringRef();241}242 243llvm::StringRef CommandAlias::GetHelpLong() {244  if (!m_cmd_help_long.empty() || m_did_set_help_long)245    return m_cmd_help_long;246  if (IsValid())247    return m_underlying_command_sp->GetHelpLong();248  return llvm::StringRef();249}250