]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Interpreter/OptionValuePathMappings.cpp
Vendor import of lldb trunk r338150:
[FreeBSD/FreeBSD.git] / source / Interpreter / OptionValuePathMappings.cpp
1 //===-- OptionValuePathMappings.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/OptionValuePathMappings.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Host/StringConvert.h"
17 #include "lldb/Utility/Args.h"
18 #include "lldb/Utility/FileSpec.h"
19 #include "lldb/Utility/Stream.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23 namespace {
24 static bool VerifyPathExists(const char *path) {
25   if (path && path[0])
26     return FileSpec(path, false).Exists();
27   else
28     return false;
29 }
30 }
31
32 void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx,
33                                         Stream &strm, uint32_t dump_mask) {
34   if (dump_mask & eDumpOptionType)
35     strm.Printf("(%s)", GetTypeAsCString());
36   if (dump_mask & eDumpOptionValue) {
37     if (dump_mask & eDumpOptionType)
38       strm.Printf(" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
39     m_path_mappings.Dump(&strm);
40   }
41 }
42
43 Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
44                                                    VarSetOperationType op) {
45   Status error;
46   Args args(value.str());
47   const size_t argc = args.GetArgumentCount();
48
49   switch (op) {
50   case eVarSetOperationClear:
51     Clear();
52     NotifyValueChanged();
53     break;
54
55   case eVarSetOperationReplace:
56     // Must be at least one index + 1 pair of paths, and the pair count must be
57     // even
58     if (argc >= 3 && (((argc - 1) & 1) == 0)) {
59       uint32_t idx =
60           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
61       const uint32_t count = m_path_mappings.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         bool changed = false;
68         for (size_t i = 1; i < argc; i += 2, ++idx) {
69           const char *orginal_path = args.GetArgumentAtIndex(i);
70           const char *replace_path = args.GetArgumentAtIndex(i + 1);
71           if (VerifyPathExists(replace_path)) {
72             ConstString a(orginal_path);
73             ConstString b(replace_path);
74             if (!m_path_mappings.Replace(a, b, idx, m_notify_changes))
75               m_path_mappings.Append(a, b, m_notify_changes);
76             changed = true;
77           } else {
78             error.SetErrorStringWithFormat(
79                 "the replacement path doesn't exist: \"%s\"", replace_path);
80             break;
81           }
82         }
83         if (changed)
84           NotifyValueChanged();
85       }
86     } else {
87       error.SetErrorString("replace operation takes an array index followed by "
88                            "one or more path pairs");
89     }
90     break;
91
92   case eVarSetOperationAssign:
93     if (argc < 2 || (argc & 1)) {
94       error.SetErrorString("assign operation takes one or more path pairs");
95       break;
96     }
97     m_path_mappings.Clear(m_notify_changes);
98     // Fall through to append case
99     LLVM_FALLTHROUGH;
100   case eVarSetOperationAppend:
101     if (argc < 2 || (argc & 1)) {
102       error.SetErrorString("append operation takes one or more path pairs");
103       break;
104     } else {
105       bool changed = false;
106       for (size_t i = 0; i < argc; i += 2) {
107         const char *orginal_path = args.GetArgumentAtIndex(i);
108         const char *replace_path = args.GetArgumentAtIndex(i + 1);
109         if (VerifyPathExists(replace_path)) {
110           ConstString a(orginal_path);
111           ConstString b(replace_path);
112           m_path_mappings.Append(a, b, m_notify_changes);
113           m_value_was_set = true;
114           changed = true;
115         } else {
116           error.SetErrorStringWithFormat(
117               "the replacement path doesn't exist: \"%s\"", replace_path);
118           break;
119         }
120       }
121       if (changed)
122         NotifyValueChanged();
123     }
124     break;
125
126   case eVarSetOperationInsertBefore:
127   case eVarSetOperationInsertAfter:
128     // Must be at least one index + 1 pair of paths, and the pair count must be
129     // even
130     if (argc >= 3 && (((argc - 1) & 1) == 0)) {
131       uint32_t idx =
132           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
133       const uint32_t count = m_path_mappings.GetSize();
134       if (idx > count) {
135         error.SetErrorStringWithFormat(
136             "invalid file list index %u, index must be 0 through %u", idx,
137             count);
138       } else {
139         bool changed = false;
140         if (op == eVarSetOperationInsertAfter)
141           ++idx;
142         for (size_t i = 1; i < argc; i += 2, ++idx) {
143           const char *orginal_path = args.GetArgumentAtIndex(i);
144           const char *replace_path = args.GetArgumentAtIndex(i + 1);
145           if (VerifyPathExists(replace_path)) {
146             ConstString a(orginal_path);
147             ConstString b(replace_path);
148             m_path_mappings.Insert(a, b, idx, m_notify_changes);
149             changed = true;
150           } else {
151             error.SetErrorStringWithFormat(
152                 "the replacement path doesn't exist: \"%s\"", replace_path);
153             break;
154           }
155         }
156         if (changed)
157           NotifyValueChanged();
158       }
159     } else {
160       error.SetErrorString("insert operation takes an array index followed by "
161                            "one or more path pairs");
162     }
163     break;
164
165   case eVarSetOperationRemove:
166     if (argc > 0) {
167       std::vector<int> remove_indexes;
168       bool all_indexes_valid = true;
169       size_t i;
170       for (i = 0; all_indexes_valid && i < argc; ++i) {
171         const int idx =
172             StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
173         if (idx == INT32_MAX)
174           all_indexes_valid = false;
175         else
176           remove_indexes.push_back(idx);
177       }
178
179       if (all_indexes_valid) {
180         size_t num_remove_indexes = remove_indexes.size();
181         if (num_remove_indexes) {
182           // Sort and then erase in reverse so indexes are always valid
183           std::sort(remove_indexes.begin(), remove_indexes.end());
184           for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
185             m_path_mappings.Remove(j, m_notify_changes);
186           }
187         }
188         NotifyValueChanged();
189       } else {
190         error.SetErrorStringWithFormat(
191             "invalid array index '%s', aborting remove operation",
192             args.GetArgumentAtIndex(i));
193       }
194     } else {
195       error.SetErrorString("remove operation takes one or more array index");
196     }
197     break;
198
199   case eVarSetOperationInvalid:
200     error = OptionValue::SetValueFromString(value, op);
201     break;
202   }
203   return error;
204 }
205
206 lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const {
207   return OptionValueSP(new OptionValuePathMappings(*this));
208 }