xref: /src/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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