19dba64beSDimitry Andric //===-- OptionValueFileSpecList.cpp ---------------------------------------===//
29dba64beSDimitry Andric //
39dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
59dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69dba64beSDimitry Andric //
79dba64beSDimitry Andric //===----------------------------------------------------------------------===//
89dba64beSDimitry Andric
99dba64beSDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h"
109dba64beSDimitry Andric
119dba64beSDimitry Andric #include "lldb/Host/StringConvert.h"
129dba64beSDimitry Andric #include "lldb/Utility/Args.h"
139dba64beSDimitry Andric #include "lldb/Utility/Stream.h"
149dba64beSDimitry Andric
159dba64beSDimitry Andric using namespace lldb;
169dba64beSDimitry Andric using namespace lldb_private;
179dba64beSDimitry Andric
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)189dba64beSDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
199dba64beSDimitry Andric Stream &strm, uint32_t dump_mask) {
209dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
219dba64beSDimitry Andric if (dump_mask & eDumpOptionType)
229dba64beSDimitry Andric strm.Printf("(%s)", GetTypeAsCString());
239dba64beSDimitry Andric if (dump_mask & eDumpOptionValue) {
249dba64beSDimitry Andric const bool one_line = dump_mask & eDumpOptionCommand;
259dba64beSDimitry Andric const uint32_t size = m_current_value.GetSize();
269dba64beSDimitry Andric if (dump_mask & eDumpOptionType)
279dba64beSDimitry Andric strm.Printf(" =%s",
289dba64beSDimitry Andric (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
299dba64beSDimitry Andric if (!one_line)
309dba64beSDimitry Andric strm.IndentMore();
319dba64beSDimitry Andric for (uint32_t i = 0; i < size; ++i) {
329dba64beSDimitry Andric if (!one_line) {
339dba64beSDimitry Andric strm.Indent();
349dba64beSDimitry Andric strm.Printf("[%u]: ", i);
359dba64beSDimitry Andric }
36480093f4SDimitry Andric m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream());
379dba64beSDimitry Andric if (one_line)
389dba64beSDimitry Andric strm << ' ';
399dba64beSDimitry Andric }
409dba64beSDimitry Andric if (!one_line)
419dba64beSDimitry Andric strm.IndentLess();
429dba64beSDimitry Andric }
439dba64beSDimitry Andric }
449dba64beSDimitry Andric
SetValueFromString(llvm::StringRef value,VarSetOperationType op)459dba64beSDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
469dba64beSDimitry Andric VarSetOperationType op) {
479dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
489dba64beSDimitry Andric Status error;
499dba64beSDimitry Andric Args args(value.str());
509dba64beSDimitry Andric const size_t argc = args.GetArgumentCount();
519dba64beSDimitry Andric
529dba64beSDimitry Andric switch (op) {
539dba64beSDimitry Andric case eVarSetOperationClear:
549dba64beSDimitry Andric Clear();
559dba64beSDimitry Andric NotifyValueChanged();
569dba64beSDimitry Andric break;
579dba64beSDimitry Andric
589dba64beSDimitry Andric case eVarSetOperationReplace:
599dba64beSDimitry Andric if (argc > 1) {
609dba64beSDimitry Andric uint32_t idx =
619dba64beSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
629dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize();
639dba64beSDimitry Andric if (idx > count) {
649dba64beSDimitry Andric error.SetErrorStringWithFormat(
659dba64beSDimitry Andric "invalid file list index %u, index must be 0 through %u", idx,
669dba64beSDimitry Andric count);
679dba64beSDimitry Andric } else {
689dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) {
699dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
709dba64beSDimitry Andric if (idx < count)
719dba64beSDimitry Andric m_current_value.Replace(idx, file);
729dba64beSDimitry Andric else
739dba64beSDimitry Andric m_current_value.Append(file);
749dba64beSDimitry Andric }
759dba64beSDimitry Andric NotifyValueChanged();
769dba64beSDimitry Andric }
779dba64beSDimitry Andric } else {
789dba64beSDimitry Andric error.SetErrorString("replace operation takes an array index followed by "
799dba64beSDimitry Andric "one or more values");
809dba64beSDimitry Andric }
819dba64beSDimitry Andric break;
829dba64beSDimitry Andric
839dba64beSDimitry Andric case eVarSetOperationAssign:
849dba64beSDimitry Andric m_current_value.Clear();
859dba64beSDimitry Andric // Fall through to append case
869dba64beSDimitry Andric LLVM_FALLTHROUGH;
879dba64beSDimitry Andric case eVarSetOperationAppend:
889dba64beSDimitry Andric if (argc > 0) {
899dba64beSDimitry Andric m_value_was_set = true;
909dba64beSDimitry Andric for (size_t i = 0; i < argc; ++i) {
919dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
929dba64beSDimitry Andric m_current_value.Append(file);
939dba64beSDimitry Andric }
949dba64beSDimitry Andric NotifyValueChanged();
959dba64beSDimitry Andric } else {
969dba64beSDimitry Andric error.SetErrorString(
979dba64beSDimitry Andric "assign operation takes at least one file path argument");
989dba64beSDimitry Andric }
999dba64beSDimitry Andric break;
1009dba64beSDimitry Andric
1019dba64beSDimitry Andric case eVarSetOperationInsertBefore:
1029dba64beSDimitry Andric case eVarSetOperationInsertAfter:
1039dba64beSDimitry Andric if (argc > 1) {
1049dba64beSDimitry Andric uint32_t idx =
1059dba64beSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
1069dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize();
1079dba64beSDimitry Andric if (idx > count) {
1089dba64beSDimitry Andric error.SetErrorStringWithFormat(
1099dba64beSDimitry Andric "invalid insert file list index %u, index must be 0 through %u",
1109dba64beSDimitry Andric idx, count);
1119dba64beSDimitry Andric } else {
1129dba64beSDimitry Andric if (op == eVarSetOperationInsertAfter)
1139dba64beSDimitry Andric ++idx;
1149dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) {
1159dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
1169dba64beSDimitry Andric m_current_value.Insert(idx, file);
1179dba64beSDimitry Andric }
1189dba64beSDimitry Andric NotifyValueChanged();
1199dba64beSDimitry Andric }
1209dba64beSDimitry Andric } else {
1219dba64beSDimitry Andric error.SetErrorString("insert operation takes an array index followed by "
1229dba64beSDimitry Andric "one or more values");
1239dba64beSDimitry Andric }
1249dba64beSDimitry Andric break;
1259dba64beSDimitry Andric
1269dba64beSDimitry Andric case eVarSetOperationRemove:
1279dba64beSDimitry Andric if (argc > 0) {
1289dba64beSDimitry Andric std::vector<int> remove_indexes;
1299dba64beSDimitry Andric bool all_indexes_valid = true;
1309dba64beSDimitry Andric size_t i;
1319dba64beSDimitry Andric for (i = 0; all_indexes_valid && i < argc; ++i) {
1329dba64beSDimitry Andric const int idx =
1339dba64beSDimitry Andric StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
1349dba64beSDimitry Andric if (idx == INT32_MAX)
1359dba64beSDimitry Andric all_indexes_valid = false;
1369dba64beSDimitry Andric else
1379dba64beSDimitry Andric remove_indexes.push_back(idx);
1389dba64beSDimitry Andric }
1399dba64beSDimitry Andric
1409dba64beSDimitry Andric if (all_indexes_valid) {
1419dba64beSDimitry Andric size_t num_remove_indexes = remove_indexes.size();
1429dba64beSDimitry Andric if (num_remove_indexes) {
1439dba64beSDimitry Andric // Sort and then erase in reverse so indexes are always valid
1449dba64beSDimitry Andric llvm::sort(remove_indexes.begin(), remove_indexes.end());
1459dba64beSDimitry Andric for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
1469dba64beSDimitry Andric m_current_value.Remove(j);
1479dba64beSDimitry Andric }
1489dba64beSDimitry Andric }
1499dba64beSDimitry Andric NotifyValueChanged();
1509dba64beSDimitry Andric } else {
1519dba64beSDimitry Andric error.SetErrorStringWithFormat(
1529dba64beSDimitry Andric "invalid array index '%s', aborting remove operation",
1539dba64beSDimitry Andric args.GetArgumentAtIndex(i));
1549dba64beSDimitry Andric }
1559dba64beSDimitry Andric } else {
1569dba64beSDimitry Andric error.SetErrorString("remove operation takes one or more array index");
1579dba64beSDimitry Andric }
1589dba64beSDimitry Andric break;
1599dba64beSDimitry Andric
1609dba64beSDimitry Andric case eVarSetOperationInvalid:
1619dba64beSDimitry Andric error = OptionValue::SetValueFromString(value, op);
1629dba64beSDimitry Andric break;
1639dba64beSDimitry Andric }
1649dba64beSDimitry Andric return error;
1659dba64beSDimitry Andric }
1669dba64beSDimitry Andric
Clone() const167*5f7ddb14SDimitry Andric OptionValueSP OptionValueFileSpecList::Clone() const {
1689dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
169*5f7ddb14SDimitry Andric return Cloneable::Clone();
1709dba64beSDimitry Andric }
171