1ac7ddfbfSEd Maste //===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionValuePathMappings.h"
11ac7ddfbfSEd Maste
12*b5893f02SDimitry Andric #include "lldb/Host/FileSystem.h"
131c3bbb01SEd Maste #include "lldb/Host/StringConvert.h"
144ba319b5SDimitry Andric #include "lldb/Utility/Args.h"
15f678e45dSDimitry Andric #include "lldb/Utility/FileSpec.h"
16f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
17ac7ddfbfSEd Maste
18ac7ddfbfSEd Maste using namespace lldb;
19ac7ddfbfSEd Maste using namespace lldb_private;
20435933ddSDimitry Andric namespace {
VerifyPathExists(const char * path)21435933ddSDimitry Andric static bool VerifyPathExists(const char *path) {
224bb0738eSEd Maste if (path && path[0])
23*b5893f02SDimitry Andric return FileSystem::Instance().Exists(path);
244bb0738eSEd Maste else
254bb0738eSEd Maste return false;
264bb0738eSEd Maste }
274bb0738eSEd Maste }
284bb0738eSEd Maste
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)29435933ddSDimitry Andric void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx,
30435933ddSDimitry Andric Stream &strm, uint32_t dump_mask) {
31ac7ddfbfSEd Maste if (dump_mask & eDumpOptionType)
32ac7ddfbfSEd Maste strm.Printf("(%s)", GetTypeAsCString());
33435933ddSDimitry Andric if (dump_mask & eDumpOptionValue) {
34ac7ddfbfSEd Maste if (dump_mask & eDumpOptionType)
35ac7ddfbfSEd Maste strm.Printf(" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
36ac7ddfbfSEd Maste m_path_mappings.Dump(&strm);
37ac7ddfbfSEd Maste }
38ac7ddfbfSEd Maste }
39ac7ddfbfSEd Maste
SetValueFromString(llvm::StringRef value,VarSetOperationType op)405517e702SDimitry Andric Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
41435933ddSDimitry Andric VarSetOperationType op) {
425517e702SDimitry Andric Status error;
43435933ddSDimitry Andric Args args(value.str());
44ac7ddfbfSEd Maste const size_t argc = args.GetArgumentCount();
45ac7ddfbfSEd Maste
46435933ddSDimitry Andric switch (op) {
47ac7ddfbfSEd Maste case eVarSetOperationClear:
48ac7ddfbfSEd Maste Clear();
497aa51b79SEd Maste NotifyValueChanged();
50ac7ddfbfSEd Maste break;
51ac7ddfbfSEd Maste
52ac7ddfbfSEd Maste case eVarSetOperationReplace:
53435933ddSDimitry Andric // Must be at least one index + 1 pair of paths, and the pair count must be
54435933ddSDimitry Andric // even
55435933ddSDimitry Andric if (argc >= 3 && (((argc - 1) & 1) == 0)) {
56435933ddSDimitry Andric uint32_t idx =
57435933ddSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
58ac7ddfbfSEd Maste const uint32_t count = m_path_mappings.GetSize();
59435933ddSDimitry Andric if (idx > count) {
60435933ddSDimitry Andric error.SetErrorStringWithFormat(
61435933ddSDimitry Andric "invalid file list index %u, index must be 0 through %u", idx,
62435933ddSDimitry Andric count);
63435933ddSDimitry Andric } else {
644bb0738eSEd Maste bool changed = false;
65435933ddSDimitry Andric for (size_t i = 1; i < argc; i += 2, ++idx) {
664bb0738eSEd Maste const char *orginal_path = args.GetArgumentAtIndex(i);
674bb0738eSEd Maste const char *replace_path = args.GetArgumentAtIndex(i + 1);
68435933ddSDimitry Andric if (VerifyPathExists(replace_path)) {
694bb0738eSEd Maste ConstString a(orginal_path);
704bb0738eSEd Maste ConstString b(replace_path);
71ac7ddfbfSEd Maste if (!m_path_mappings.Replace(a, b, idx, m_notify_changes))
72ac7ddfbfSEd Maste m_path_mappings.Append(a, b, m_notify_changes);
734bb0738eSEd Maste changed = true;
74435933ddSDimitry Andric } else {
75435933ddSDimitry Andric error.SetErrorStringWithFormat(
76435933ddSDimitry Andric "the replacement path doesn't exist: \"%s\"", replace_path);
774bb0738eSEd Maste break;
784bb0738eSEd Maste }
794bb0738eSEd Maste }
804bb0738eSEd Maste if (changed)
817aa51b79SEd Maste NotifyValueChanged();
82ac7ddfbfSEd Maste }
83435933ddSDimitry Andric } else {
84435933ddSDimitry Andric error.SetErrorString("replace operation takes an array index followed by "
85435933ddSDimitry Andric "one or more path pairs");
86ac7ddfbfSEd Maste }
87ac7ddfbfSEd Maste break;
88ac7ddfbfSEd Maste
89ac7ddfbfSEd Maste case eVarSetOperationAssign:
90435933ddSDimitry Andric if (argc < 2 || (argc & 1)) {
91ac7ddfbfSEd Maste error.SetErrorString("assign operation takes one or more path pairs");
92ac7ddfbfSEd Maste break;
93ac7ddfbfSEd Maste }
94ac7ddfbfSEd Maste m_path_mappings.Clear(m_notify_changes);
95ac7ddfbfSEd Maste // Fall through to append case
964bb0738eSEd Maste LLVM_FALLTHROUGH;
97ac7ddfbfSEd Maste case eVarSetOperationAppend:
98435933ddSDimitry Andric if (argc < 2 || (argc & 1)) {
99ac7ddfbfSEd Maste error.SetErrorString("append operation takes one or more path pairs");
100ac7ddfbfSEd Maste break;
101435933ddSDimitry Andric } else {
1024bb0738eSEd Maste bool changed = false;
103435933ddSDimitry Andric for (size_t i = 0; i < argc; i += 2) {
1044bb0738eSEd Maste const char *orginal_path = args.GetArgumentAtIndex(i);
1054bb0738eSEd Maste const char *replace_path = args.GetArgumentAtIndex(i + 1);
106435933ddSDimitry Andric if (VerifyPathExists(replace_path)) {
1074bb0738eSEd Maste ConstString a(orginal_path);
1084bb0738eSEd Maste ConstString b(replace_path);
109ac7ddfbfSEd Maste m_path_mappings.Append(a, b, m_notify_changes);
110ac7ddfbfSEd Maste m_value_was_set = true;
1114bb0738eSEd Maste changed = true;
112435933ddSDimitry Andric } else {
113435933ddSDimitry Andric error.SetErrorStringWithFormat(
114435933ddSDimitry Andric "the replacement path doesn't exist: \"%s\"", replace_path);
1154bb0738eSEd Maste break;
1164bb0738eSEd Maste }
1174bb0738eSEd Maste }
1184bb0738eSEd Maste if (changed)
1197aa51b79SEd Maste NotifyValueChanged();
120ac7ddfbfSEd Maste }
121ac7ddfbfSEd Maste break;
122ac7ddfbfSEd Maste
123ac7ddfbfSEd Maste case eVarSetOperationInsertBefore:
124ac7ddfbfSEd Maste case eVarSetOperationInsertAfter:
125435933ddSDimitry Andric // Must be at least one index + 1 pair of paths, and the pair count must be
126435933ddSDimitry Andric // even
127435933ddSDimitry Andric if (argc >= 3 && (((argc - 1) & 1) == 0)) {
128435933ddSDimitry Andric uint32_t idx =
129435933ddSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
130ac7ddfbfSEd Maste const uint32_t count = m_path_mappings.GetSize();
131435933ddSDimitry Andric if (idx > count) {
132435933ddSDimitry Andric error.SetErrorStringWithFormat(
133435933ddSDimitry Andric "invalid file list index %u, index must be 0 through %u", idx,
134435933ddSDimitry Andric count);
135435933ddSDimitry Andric } else {
1364bb0738eSEd Maste bool changed = false;
137ac7ddfbfSEd Maste if (op == eVarSetOperationInsertAfter)
138ac7ddfbfSEd Maste ++idx;
139435933ddSDimitry Andric for (size_t i = 1; i < argc; i += 2, ++idx) {
1404bb0738eSEd Maste const char *orginal_path = args.GetArgumentAtIndex(i);
1414bb0738eSEd Maste const char *replace_path = args.GetArgumentAtIndex(i + 1);
142435933ddSDimitry Andric if (VerifyPathExists(replace_path)) {
1434bb0738eSEd Maste ConstString a(orginal_path);
1444bb0738eSEd Maste ConstString b(replace_path);
145ac7ddfbfSEd Maste m_path_mappings.Insert(a, b, idx, m_notify_changes);
1464bb0738eSEd Maste changed = true;
147435933ddSDimitry Andric } else {
148435933ddSDimitry Andric error.SetErrorStringWithFormat(
149435933ddSDimitry Andric "the replacement path doesn't exist: \"%s\"", replace_path);
1504bb0738eSEd Maste break;
1514bb0738eSEd Maste }
1524bb0738eSEd Maste }
1534bb0738eSEd Maste if (changed)
1547aa51b79SEd Maste NotifyValueChanged();
155ac7ddfbfSEd Maste }
156435933ddSDimitry Andric } else {
157435933ddSDimitry Andric error.SetErrorString("insert operation takes an array index followed by "
158435933ddSDimitry Andric "one or more path pairs");
159ac7ddfbfSEd Maste }
160ac7ddfbfSEd Maste break;
161ac7ddfbfSEd Maste
162ac7ddfbfSEd Maste case eVarSetOperationRemove:
163435933ddSDimitry Andric if (argc > 0) {
164ac7ddfbfSEd Maste std::vector<int> remove_indexes;
165ac7ddfbfSEd Maste bool all_indexes_valid = true;
166ac7ddfbfSEd Maste size_t i;
167435933ddSDimitry Andric for (i = 0; all_indexes_valid && i < argc; ++i) {
168435933ddSDimitry Andric const int idx =
169435933ddSDimitry Andric StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
170ac7ddfbfSEd Maste if (idx == INT32_MAX)
171ac7ddfbfSEd Maste all_indexes_valid = false;
172ac7ddfbfSEd Maste else
173ac7ddfbfSEd Maste remove_indexes.push_back(idx);
174ac7ddfbfSEd Maste }
175ac7ddfbfSEd Maste
176435933ddSDimitry Andric if (all_indexes_valid) {
177ac7ddfbfSEd Maste size_t num_remove_indexes = remove_indexes.size();
178435933ddSDimitry Andric if (num_remove_indexes) {
179ac7ddfbfSEd Maste // Sort and then erase in reverse so indexes are always valid
180*b5893f02SDimitry Andric llvm::sort(remove_indexes.begin(), remove_indexes.end());
181435933ddSDimitry Andric for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
182ac7ddfbfSEd Maste m_path_mappings.Remove(j, m_notify_changes);
183ac7ddfbfSEd Maste }
184ac7ddfbfSEd Maste }
1857aa51b79SEd Maste NotifyValueChanged();
186435933ddSDimitry Andric } else {
187435933ddSDimitry Andric error.SetErrorStringWithFormat(
188435933ddSDimitry Andric "invalid array index '%s', aborting remove operation",
189435933ddSDimitry Andric args.GetArgumentAtIndex(i));
190ac7ddfbfSEd Maste }
191435933ddSDimitry Andric } else {
192ac7ddfbfSEd Maste error.SetErrorString("remove operation takes one or more array index");
193ac7ddfbfSEd Maste }
194ac7ddfbfSEd Maste break;
195ac7ddfbfSEd Maste
196ac7ddfbfSEd Maste case eVarSetOperationInvalid:
1971c3bbb01SEd Maste error = OptionValue::SetValueFromString(value, op);
198ac7ddfbfSEd Maste break;
199ac7ddfbfSEd Maste }
200ac7ddfbfSEd Maste return error;
201ac7ddfbfSEd Maste }
202ac7ddfbfSEd Maste
DeepCopy() const203435933ddSDimitry Andric lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const {
204ac7ddfbfSEd Maste return OptionValueSP(new OptionValuePathMappings(*this));
205ac7ddfbfSEd Maste }
206