xref: /freebsd-src/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp (revision 9dba64be9536c28e4800e06512b7f29b43ade345)
1*9dba64beSDimitry Andric //===-- OptionValueFileSpecList.cpp ---------------------------------------===//
2*9dba64beSDimitry Andric //
3*9dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*9dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*9dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*9dba64beSDimitry Andric //
7*9dba64beSDimitry Andric //===----------------------------------------------------------------------===//
8*9dba64beSDimitry Andric 
9*9dba64beSDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h"
10*9dba64beSDimitry Andric 
11*9dba64beSDimitry Andric #include "lldb/Host/StringConvert.h"
12*9dba64beSDimitry Andric #include "lldb/Utility/Args.h"
13*9dba64beSDimitry Andric #include "lldb/Utility/Stream.h"
14*9dba64beSDimitry Andric 
15*9dba64beSDimitry Andric using namespace lldb;
16*9dba64beSDimitry Andric using namespace lldb_private;
17*9dba64beSDimitry Andric 
18*9dba64beSDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
19*9dba64beSDimitry Andric                                         Stream &strm, uint32_t dump_mask) {
20*9dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
21*9dba64beSDimitry Andric   if (dump_mask & eDumpOptionType)
22*9dba64beSDimitry Andric     strm.Printf("(%s)", GetTypeAsCString());
23*9dba64beSDimitry Andric   if (dump_mask & eDumpOptionValue) {
24*9dba64beSDimitry Andric     const bool one_line = dump_mask & eDumpOptionCommand;
25*9dba64beSDimitry Andric     const uint32_t size = m_current_value.GetSize();
26*9dba64beSDimitry Andric     if (dump_mask & eDumpOptionType)
27*9dba64beSDimitry Andric       strm.Printf(" =%s",
28*9dba64beSDimitry Andric                   (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
29*9dba64beSDimitry Andric     if (!one_line)
30*9dba64beSDimitry Andric       strm.IndentMore();
31*9dba64beSDimitry Andric     for (uint32_t i = 0; i < size; ++i) {
32*9dba64beSDimitry Andric       if (!one_line) {
33*9dba64beSDimitry Andric         strm.Indent();
34*9dba64beSDimitry Andric         strm.Printf("[%u]: ", i);
35*9dba64beSDimitry Andric       }
36*9dba64beSDimitry Andric       m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
37*9dba64beSDimitry Andric       if (one_line)
38*9dba64beSDimitry Andric         strm << ' ';
39*9dba64beSDimitry Andric     }
40*9dba64beSDimitry Andric     if (!one_line)
41*9dba64beSDimitry Andric       strm.IndentLess();
42*9dba64beSDimitry Andric   }
43*9dba64beSDimitry Andric }
44*9dba64beSDimitry Andric 
45*9dba64beSDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
46*9dba64beSDimitry Andric                                                    VarSetOperationType op) {
47*9dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
48*9dba64beSDimitry Andric   Status error;
49*9dba64beSDimitry Andric   Args args(value.str());
50*9dba64beSDimitry Andric   const size_t argc = args.GetArgumentCount();
51*9dba64beSDimitry Andric 
52*9dba64beSDimitry Andric   switch (op) {
53*9dba64beSDimitry Andric   case eVarSetOperationClear:
54*9dba64beSDimitry Andric     Clear();
55*9dba64beSDimitry Andric     NotifyValueChanged();
56*9dba64beSDimitry Andric     break;
57*9dba64beSDimitry Andric 
58*9dba64beSDimitry Andric   case eVarSetOperationReplace:
59*9dba64beSDimitry Andric     if (argc > 1) {
60*9dba64beSDimitry Andric       uint32_t idx =
61*9dba64beSDimitry Andric           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
62*9dba64beSDimitry Andric       const uint32_t count = m_current_value.GetSize();
63*9dba64beSDimitry Andric       if (idx > count) {
64*9dba64beSDimitry Andric         error.SetErrorStringWithFormat(
65*9dba64beSDimitry Andric             "invalid file list index %u, index must be 0 through %u", idx,
66*9dba64beSDimitry Andric             count);
67*9dba64beSDimitry Andric       } else {
68*9dba64beSDimitry Andric         for (size_t i = 1; i < argc; ++i, ++idx) {
69*9dba64beSDimitry Andric           FileSpec file(args.GetArgumentAtIndex(i));
70*9dba64beSDimitry Andric           if (idx < count)
71*9dba64beSDimitry Andric             m_current_value.Replace(idx, file);
72*9dba64beSDimitry Andric           else
73*9dba64beSDimitry Andric             m_current_value.Append(file);
74*9dba64beSDimitry Andric         }
75*9dba64beSDimitry Andric         NotifyValueChanged();
76*9dba64beSDimitry Andric       }
77*9dba64beSDimitry Andric     } else {
78*9dba64beSDimitry Andric       error.SetErrorString("replace operation takes an array index followed by "
79*9dba64beSDimitry Andric                            "one or more values");
80*9dba64beSDimitry Andric     }
81*9dba64beSDimitry Andric     break;
82*9dba64beSDimitry Andric 
83*9dba64beSDimitry Andric   case eVarSetOperationAssign:
84*9dba64beSDimitry Andric     m_current_value.Clear();
85*9dba64beSDimitry Andric     // Fall through to append case
86*9dba64beSDimitry Andric     LLVM_FALLTHROUGH;
87*9dba64beSDimitry Andric   case eVarSetOperationAppend:
88*9dba64beSDimitry Andric     if (argc > 0) {
89*9dba64beSDimitry Andric       m_value_was_set = true;
90*9dba64beSDimitry Andric       for (size_t i = 0; i < argc; ++i) {
91*9dba64beSDimitry Andric         FileSpec file(args.GetArgumentAtIndex(i));
92*9dba64beSDimitry Andric         m_current_value.Append(file);
93*9dba64beSDimitry Andric       }
94*9dba64beSDimitry Andric       NotifyValueChanged();
95*9dba64beSDimitry Andric     } else {
96*9dba64beSDimitry Andric       error.SetErrorString(
97*9dba64beSDimitry Andric           "assign operation takes at least one file path argument");
98*9dba64beSDimitry Andric     }
99*9dba64beSDimitry Andric     break;
100*9dba64beSDimitry Andric 
101*9dba64beSDimitry Andric   case eVarSetOperationInsertBefore:
102*9dba64beSDimitry Andric   case eVarSetOperationInsertAfter:
103*9dba64beSDimitry Andric     if (argc > 1) {
104*9dba64beSDimitry Andric       uint32_t idx =
105*9dba64beSDimitry Andric           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
106*9dba64beSDimitry Andric       const uint32_t count = m_current_value.GetSize();
107*9dba64beSDimitry Andric       if (idx > count) {
108*9dba64beSDimitry Andric         error.SetErrorStringWithFormat(
109*9dba64beSDimitry Andric             "invalid insert file list index %u, index must be 0 through %u",
110*9dba64beSDimitry Andric             idx, count);
111*9dba64beSDimitry Andric       } else {
112*9dba64beSDimitry Andric         if (op == eVarSetOperationInsertAfter)
113*9dba64beSDimitry Andric           ++idx;
114*9dba64beSDimitry Andric         for (size_t i = 1; i < argc; ++i, ++idx) {
115*9dba64beSDimitry Andric           FileSpec file(args.GetArgumentAtIndex(i));
116*9dba64beSDimitry Andric           m_current_value.Insert(idx, file);
117*9dba64beSDimitry Andric         }
118*9dba64beSDimitry Andric         NotifyValueChanged();
119*9dba64beSDimitry Andric       }
120*9dba64beSDimitry Andric     } else {
121*9dba64beSDimitry Andric       error.SetErrorString("insert operation takes an array index followed by "
122*9dba64beSDimitry Andric                            "one or more values");
123*9dba64beSDimitry Andric     }
124*9dba64beSDimitry Andric     break;
125*9dba64beSDimitry Andric 
126*9dba64beSDimitry Andric   case eVarSetOperationRemove:
127*9dba64beSDimitry Andric     if (argc > 0) {
128*9dba64beSDimitry Andric       std::vector<int> remove_indexes;
129*9dba64beSDimitry Andric       bool all_indexes_valid = true;
130*9dba64beSDimitry Andric       size_t i;
131*9dba64beSDimitry Andric       for (i = 0; all_indexes_valid && i < argc; ++i) {
132*9dba64beSDimitry Andric         const int idx =
133*9dba64beSDimitry Andric             StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
134*9dba64beSDimitry Andric         if (idx == INT32_MAX)
135*9dba64beSDimitry Andric           all_indexes_valid = false;
136*9dba64beSDimitry Andric         else
137*9dba64beSDimitry Andric           remove_indexes.push_back(idx);
138*9dba64beSDimitry Andric       }
139*9dba64beSDimitry Andric 
140*9dba64beSDimitry Andric       if (all_indexes_valid) {
141*9dba64beSDimitry Andric         size_t num_remove_indexes = remove_indexes.size();
142*9dba64beSDimitry Andric         if (num_remove_indexes) {
143*9dba64beSDimitry Andric           // Sort and then erase in reverse so indexes are always valid
144*9dba64beSDimitry Andric           llvm::sort(remove_indexes.begin(), remove_indexes.end());
145*9dba64beSDimitry Andric           for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
146*9dba64beSDimitry Andric             m_current_value.Remove(j);
147*9dba64beSDimitry Andric           }
148*9dba64beSDimitry Andric         }
149*9dba64beSDimitry Andric         NotifyValueChanged();
150*9dba64beSDimitry Andric       } else {
151*9dba64beSDimitry Andric         error.SetErrorStringWithFormat(
152*9dba64beSDimitry Andric             "invalid array index '%s', aborting remove operation",
153*9dba64beSDimitry Andric             args.GetArgumentAtIndex(i));
154*9dba64beSDimitry Andric       }
155*9dba64beSDimitry Andric     } else {
156*9dba64beSDimitry Andric       error.SetErrorString("remove operation takes one or more array index");
157*9dba64beSDimitry Andric     }
158*9dba64beSDimitry Andric     break;
159*9dba64beSDimitry Andric 
160*9dba64beSDimitry Andric   case eVarSetOperationInvalid:
161*9dba64beSDimitry Andric     error = OptionValue::SetValueFromString(value, op);
162*9dba64beSDimitry Andric     break;
163*9dba64beSDimitry Andric   }
164*9dba64beSDimitry Andric   return error;
165*9dba64beSDimitry Andric }
166*9dba64beSDimitry Andric 
167*9dba64beSDimitry Andric lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const {
168*9dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
169*9dba64beSDimitry Andric   return OptionValueSP(new OptionValueFileSpecList(m_current_value));
170*9dba64beSDimitry Andric }
171