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