1ead24645SDimitry Andric //===-- OptionValueFileSpecList.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Interpreter/OptionValueFileSpecList.h"
10f034231aSEd Maste
11f73363f1SDimitry Andric #include "lldb/Utility/Args.h"
1274a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
13f034231aSEd Maste
14f034231aSEd Maste using namespace lldb;
15f034231aSEd Maste using namespace lldb_private;
16f034231aSEd Maste
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)1714f1b3e8SDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
1814f1b3e8SDimitry Andric Stream &strm, uint32_t dump_mask) {
195f29bb8aSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
20f034231aSEd Maste if (dump_mask & eDumpOptionType)
21f034231aSEd Maste strm.Printf("(%s)", GetTypeAsCString());
2214f1b3e8SDimitry Andric if (dump_mask & eDumpOptionValue) {
2394994d37SDimitry Andric const bool one_line = dump_mask & eDumpOptionCommand;
24f034231aSEd Maste const uint32_t size = m_current_value.GetSize();
2594994d37SDimitry Andric if (dump_mask & eDumpOptionType)
2694994d37SDimitry Andric strm.Printf(" =%s",
2794994d37SDimitry Andric (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
2894994d37SDimitry Andric if (!one_line)
2994994d37SDimitry Andric strm.IndentMore();
3014f1b3e8SDimitry Andric for (uint32_t i = 0; i < size; ++i) {
3194994d37SDimitry Andric if (!one_line) {
32f034231aSEd Maste strm.Indent();
33f034231aSEd Maste strm.Printf("[%u]: ", i);
34f034231aSEd Maste }
35706b4fc4SDimitry Andric m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream());
3694994d37SDimitry Andric if (one_line)
3794994d37SDimitry Andric strm << ' ';
3894994d37SDimitry Andric }
3994994d37SDimitry Andric if (!one_line)
40f034231aSEd Maste strm.IndentLess();
41f034231aSEd Maste }
42f034231aSEd Maste }
43f034231aSEd Maste
SetValueFromString(llvm::StringRef value,VarSetOperationType op)44b76161e4SDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
4514f1b3e8SDimitry Andric VarSetOperationType op) {
465f29bb8aSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
47b76161e4SDimitry Andric Status error;
4814f1b3e8SDimitry Andric Args args(value.str());
49f034231aSEd Maste const size_t argc = args.GetArgumentCount();
50f034231aSEd Maste
5114f1b3e8SDimitry Andric switch (op) {
52f034231aSEd Maste case eVarSetOperationClear:
53f034231aSEd Maste Clear();
54205afe67SEd Maste NotifyValueChanged();
55f034231aSEd Maste break;
56f034231aSEd Maste
57f034231aSEd Maste case eVarSetOperationReplace:
5814f1b3e8SDimitry Andric if (argc > 1) {
59c0981da4SDimitry Andric uint32_t idx;
60f034231aSEd Maste const uint32_t count = m_current_value.GetSize();
61c0981da4SDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
6214f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
63c0981da4SDimitry Andric "invalid file list index %s, index must be 0 through %u",
64c0981da4SDimitry Andric args.GetArgumentAtIndex(0), count);
6514f1b3e8SDimitry Andric } else {
6614f1b3e8SDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) {
6794994d37SDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
68f034231aSEd Maste if (idx < count)
69f034231aSEd Maste m_current_value.Replace(idx, file);
70f034231aSEd Maste else
71f034231aSEd Maste m_current_value.Append(file);
72f034231aSEd Maste }
73205afe67SEd Maste NotifyValueChanged();
74f034231aSEd Maste }
7514f1b3e8SDimitry Andric } else {
7614f1b3e8SDimitry Andric error.SetErrorString("replace operation takes an array index followed by "
7714f1b3e8SDimitry Andric "one or more values");
78f034231aSEd Maste }
79f034231aSEd Maste break;
80f034231aSEd Maste
81f034231aSEd Maste case eVarSetOperationAssign:
82f034231aSEd Maste m_current_value.Clear();
83f034231aSEd Maste // Fall through to append case
84e3b55780SDimitry Andric [[fallthrough]];
85f034231aSEd Maste case eVarSetOperationAppend:
8614f1b3e8SDimitry Andric if (argc > 0) {
87f034231aSEd Maste m_value_was_set = true;
8814f1b3e8SDimitry Andric for (size_t i = 0; i < argc; ++i) {
8994994d37SDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
90f034231aSEd Maste m_current_value.Append(file);
91f034231aSEd Maste }
92205afe67SEd Maste NotifyValueChanged();
9314f1b3e8SDimitry Andric } else {
9414f1b3e8SDimitry Andric error.SetErrorString(
9514f1b3e8SDimitry Andric "assign operation takes at least one file path argument");
96f034231aSEd Maste }
97f034231aSEd Maste break;
98f034231aSEd Maste
99f034231aSEd Maste case eVarSetOperationInsertBefore:
100f034231aSEd Maste case eVarSetOperationInsertAfter:
10114f1b3e8SDimitry Andric if (argc > 1) {
102c0981da4SDimitry Andric uint32_t idx;
103f034231aSEd Maste const uint32_t count = m_current_value.GetSize();
104c0981da4SDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
10514f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
106c0981da4SDimitry Andric "invalid insert file list index %s, index must be 0 through %u",
107c0981da4SDimitry Andric args.GetArgumentAtIndex(0), count);
10814f1b3e8SDimitry Andric } else {
109f034231aSEd Maste if (op == eVarSetOperationInsertAfter)
110f034231aSEd Maste ++idx;
11114f1b3e8SDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) {
11294994d37SDimitry Andric FileSpec file(args.GetArgumentAtIndex(i));
113f034231aSEd Maste m_current_value.Insert(idx, file);
114f034231aSEd Maste }
115205afe67SEd Maste NotifyValueChanged();
116f034231aSEd Maste }
11714f1b3e8SDimitry Andric } else {
11814f1b3e8SDimitry Andric error.SetErrorString("insert operation takes an array index followed by "
11914f1b3e8SDimitry Andric "one or more values");
120f034231aSEd Maste }
121f034231aSEd Maste break;
122f034231aSEd Maste
123f034231aSEd Maste case eVarSetOperationRemove:
12414f1b3e8SDimitry Andric if (argc > 0) {
125f034231aSEd Maste std::vector<int> remove_indexes;
126f034231aSEd Maste bool all_indexes_valid = true;
127f034231aSEd Maste size_t i;
12814f1b3e8SDimitry Andric for (i = 0; all_indexes_valid && i < argc; ++i) {
129c0981da4SDimitry Andric int idx;
130c0981da4SDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx))
131f034231aSEd Maste all_indexes_valid = false;
132f034231aSEd Maste else
133f034231aSEd Maste remove_indexes.push_back(idx);
134f034231aSEd Maste }
135f034231aSEd Maste
13614f1b3e8SDimitry Andric if (all_indexes_valid) {
137f034231aSEd Maste size_t num_remove_indexes = remove_indexes.size();
13814f1b3e8SDimitry Andric if (num_remove_indexes) {
139f034231aSEd Maste // Sort and then erase in reverse so indexes are always valid
1404b4fe385SDimitry Andric llvm::sort(remove_indexes);
14114f1b3e8SDimitry Andric for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
142f034231aSEd Maste m_current_value.Remove(j);
143f034231aSEd Maste }
144f034231aSEd Maste }
145205afe67SEd Maste NotifyValueChanged();
14614f1b3e8SDimitry Andric } else {
14714f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
14814f1b3e8SDimitry Andric "invalid array index '%s', aborting remove operation",
14914f1b3e8SDimitry Andric args.GetArgumentAtIndex(i));
150f034231aSEd Maste }
15114f1b3e8SDimitry Andric } else {
152f034231aSEd Maste error.SetErrorString("remove operation takes one or more array index");
153f034231aSEd Maste }
154f034231aSEd Maste break;
155f034231aSEd Maste
156f034231aSEd Maste case eVarSetOperationInvalid:
1575e95aa85SEd Maste error = OptionValue::SetValueFromString(value, op);
158f034231aSEd Maste break;
159f034231aSEd Maste }
160f034231aSEd Maste return error;
161f034231aSEd Maste }
162f034231aSEd Maste
Clone() const163344a3780SDimitry Andric OptionValueSP OptionValueFileSpecList::Clone() const {
1645f29bb8aSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex);
165344a3780SDimitry Andric return Cloneable::Clone();
166f034231aSEd Maste }
167