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