brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · abf4d42 Raw
210 lines · cpp
1//===-- OptionValuePathMappings.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/OptionValuePathMappings.h"10 11#include "lldb/Host/FileSystem.h"12#include "lldb/Interpreter/OptionValue.h"13#include "lldb/Utility/Args.h"14#include "lldb/Utility/FileSpec.h"15#include "lldb/Utility/Stream.h"16 17using namespace lldb;18using namespace lldb_private;19 20static bool VerifyPathExists(const char *path) {21  if (path && path[0])22    return FileSystem::Instance().Exists(path);23  else24    return false;25}26 27void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx,28                                        Stream &strm, uint32_t dump_mask) {29  if (dump_mask & eDumpOptionType)30    strm.Printf("(%s)", GetTypeAsCString());31  if (dump_mask & eDumpOptionValue) {32    if (dump_mask & (eDumpOptionType | eDumpOptionDefaultValue)) {33      strm.Printf(" =");34      if (dump_mask & eDumpOptionDefaultValue && !m_path_mappings.IsEmpty()) {35        DefaultValueFormat label(strm);36        strm.PutCString("empty");37      }38      if (!m_path_mappings.IsEmpty())39        strm.PutCString("\n");40    }41    m_path_mappings.Dump(&strm);42  }43}44 45llvm::json::Value46OptionValuePathMappings::ToJSON(const ExecutionContext *exe_ctx) const {47  return m_path_mappings.ToJSON();48}49 50Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,51                                                   VarSetOperationType op) {52  Status error;53  Args args(value.str());54  const size_t argc = args.GetArgumentCount();55 56  switch (op) {57  case eVarSetOperationClear:58    Clear();59    NotifyValueChanged();60    break;61 62  case eVarSetOperationReplace:63    // Must be at least one index + 1 pair of paths, and the pair count must be64    // even65    if (argc >= 3 && (((argc - 1) & 1) == 0)) {66      uint32_t idx;67      const uint32_t count = m_path_mappings.GetSize();68      if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {69        error = Status::FromErrorStringWithFormat(70            "invalid file list index %s, index must be 0 through %u",71            args.GetArgumentAtIndex(0), count);72      } else {73        bool changed = false;74        for (size_t i = 1; i < argc; idx++, i += 2) {75          const char *orginal_path = args.GetArgumentAtIndex(i);76          const char *replace_path = args.GetArgumentAtIndex(i + 1);77          if (VerifyPathExists(replace_path)) {78            if (!m_path_mappings.Replace(orginal_path, replace_path, idx,79                                         m_notify_changes))80              m_path_mappings.Append(orginal_path, replace_path,81                                     m_notify_changes);82            changed = true;83          } else {84            std::string previousError =85                error.Fail() ? std::string(error.AsCString()) + "\n" : "";86            error = Status::FromErrorStringWithFormat(87                "%sthe replacement path doesn't exist: \"%s\"",88                previousError.c_str(), replace_path);89          }90        }91        if (changed)92          NotifyValueChanged();93      }94    } else {95      error = Status::FromErrorString(96          "replace operation takes an array index followed by "97          "one or more path pairs");98    }99    break;100 101  case eVarSetOperationAssign:102    if (argc < 2 || (argc & 1)) {103      error = Status::FromErrorString(104          "assign operation takes one or more path pairs");105      break;106    }107    m_path_mappings.Clear(m_notify_changes);108    // Fall through to append case109    [[fallthrough]];110  case eVarSetOperationAppend:111    if (argc < 2 || (argc & 1)) {112      error = Status::FromErrorString(113          "append operation takes one or more path pairs");114      break;115    } else {116      bool changed = false;117      for (size_t i = 0; i < argc; i += 2) {118        const char *orginal_path = args.GetArgumentAtIndex(i);119        const char *replace_path = args.GetArgumentAtIndex(i + 1);120        if (VerifyPathExists(replace_path)) {121          m_path_mappings.Append(orginal_path, replace_path, m_notify_changes);122          m_value_was_set = true;123          changed = true;124        } else {125          std::string previousError =126              error.Fail() ? std::string(error.AsCString()) + "\n" : "";127          error = Status::FromErrorStringWithFormat(128              "%sthe replacement path doesn't exist: \"%s\"",129              previousError.c_str(), replace_path);130        }131      }132      if (changed)133        NotifyValueChanged();134    }135    break;136 137  case eVarSetOperationInsertBefore:138  case eVarSetOperationInsertAfter:139    // Must be at least one index + 1 pair of paths, and the pair count must be140    // even141    if (argc >= 3 && (((argc - 1) & 1) == 0)) {142      uint32_t idx;143      const uint32_t count = m_path_mappings.GetSize();144      if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {145        error = Status::FromErrorStringWithFormat(146            "invalid file list index %s, index must be 0 through %u",147            args.GetArgumentAtIndex(0), count);148      } else {149        bool changed = false;150        if (op == eVarSetOperationInsertAfter)151          ++idx;152        for (size_t i = 1; i < argc; i += 2) {153          const char *orginal_path = args.GetArgumentAtIndex(i);154          const char *replace_path = args.GetArgumentAtIndex(i + 1);155          if (VerifyPathExists(replace_path)) {156            m_path_mappings.Insert(orginal_path, replace_path, idx,157                                   m_notify_changes);158            changed = true;159            idx++;160          } else {161            std::string previousError =162                error.Fail() ? std::string(error.AsCString()) + "\n" : "";163            error = Status::FromErrorStringWithFormat(164                "%sthe replacement path doesn't exist: \"%s\"",165                previousError.c_str(), replace_path);166          }167        }168        if (changed)169          NotifyValueChanged();170      }171    } else {172      error = Status::FromErrorString(173          "insert operation takes an array index followed by "174          "one or more path pairs");175    }176    break;177 178  case eVarSetOperationRemove:179    if (argc > 0) {180      std::vector<int> remove_indexes;181      for (size_t i = 0; i < argc; ++i) {182        int idx;183        if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx) || idx < 0 ||184            idx >= (int)m_path_mappings.GetSize()) {185          error = Status::FromErrorStringWithFormat(186              "invalid array index '%s', aborting remove operation",187              args.GetArgumentAtIndex(i));188          break;189        } else190          remove_indexes.push_back(idx);191      }192 193      // Sort and then erase in reverse so indexes are always valid194      llvm::sort(remove_indexes);195      for (auto index : llvm::reverse(remove_indexes))196        m_path_mappings.Remove(index, m_notify_changes);197      NotifyValueChanged();198    } else {199      error = Status::FromErrorString(200          "remove operation takes one or more array index");201    }202    break;203 204  case eVarSetOperationInvalid:205    error = OptionValue::SetValueFromString(value, op);206    break;207  }208  return error;209}210