xref: /src/contrib/llvm-project/lldb/source/Interpreter/OptionValuePathMappings.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1cfca06d7SDimitry Andric //===-- OptionValuePathMappings.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Interpreter/OptionValuePathMappings.h"
10f034231aSEd Maste 
1194994d37SDimitry Andric #include "lldb/Host/FileSystem.h"
12f73363f1SDimitry Andric #include "lldb/Utility/Args.h"
1374a628f7SDimitry Andric #include "lldb/Utility/FileSpec.h"
1474a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
15f034231aSEd Maste 
16f034231aSEd Maste using namespace lldb;
17f034231aSEd Maste using namespace lldb_private;
18c0981da4SDimitry Andric 
VerifyPathExists(const char * path)1914f1b3e8SDimitry Andric static bool VerifyPathExists(const char *path) {
20f3fbd1c0SDimitry Andric   if (path && path[0])
2194994d37SDimitry Andric     return FileSystem::Instance().Exists(path);
22f3fbd1c0SDimitry Andric   else
23f3fbd1c0SDimitry Andric     return false;
24f3fbd1c0SDimitry Andric }
25f3fbd1c0SDimitry Andric 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)2614f1b3e8SDimitry Andric void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx,
2714f1b3e8SDimitry Andric                                         Stream &strm, uint32_t dump_mask) {
28f034231aSEd Maste   if (dump_mask & eDumpOptionType)
29f034231aSEd Maste     strm.Printf("(%s)", GetTypeAsCString());
3014f1b3e8SDimitry Andric   if (dump_mask & eDumpOptionValue) {
31f034231aSEd Maste     if (dump_mask & eDumpOptionType)
32f034231aSEd Maste       strm.Printf(" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
33f034231aSEd Maste     m_path_mappings.Dump(&strm);
34f034231aSEd Maste   }
35f034231aSEd Maste }
36f034231aSEd Maste 
37e3b55780SDimitry Andric llvm::json::Value
ToJSON(const ExecutionContext * exe_ctx)38e3b55780SDimitry Andric OptionValuePathMappings::ToJSON(const ExecutionContext *exe_ctx) {
39e3b55780SDimitry Andric   return m_path_mappings.ToJSON();
40e3b55780SDimitry Andric }
41e3b55780SDimitry Andric 
SetValueFromString(llvm::StringRef value,VarSetOperationType op)42b76161e4SDimitry Andric Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
4314f1b3e8SDimitry Andric                                                    VarSetOperationType op) {
44b76161e4SDimitry Andric   Status error;
4514f1b3e8SDimitry Andric   Args args(value.str());
46f034231aSEd Maste   const size_t argc = args.GetArgumentCount();
47f034231aSEd Maste 
4814f1b3e8SDimitry Andric   switch (op) {
49f034231aSEd Maste   case eVarSetOperationClear:
50f034231aSEd Maste     Clear();
51205afe67SEd Maste     NotifyValueChanged();
52f034231aSEd Maste     break;
53f034231aSEd Maste 
54f034231aSEd Maste   case eVarSetOperationReplace:
5514f1b3e8SDimitry Andric     // Must be at least one index + 1 pair of paths, and the pair count must be
5614f1b3e8SDimitry Andric     // even
5714f1b3e8SDimitry Andric     if (argc >= 3 && (((argc - 1) & 1) == 0)) {
58c0981da4SDimitry Andric       uint32_t idx;
59f034231aSEd Maste       const uint32_t count = m_path_mappings.GetSize();
60c0981da4SDimitry Andric       if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
6114f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
62c0981da4SDimitry Andric             "invalid file list index %s, index must be 0 through %u",
63c0981da4SDimitry Andric             args.GetArgumentAtIndex(0), count);
6414f1b3e8SDimitry Andric       } else {
65f3fbd1c0SDimitry Andric         bool changed = false;
66cfca06d7SDimitry Andric         for (size_t i = 1; i < argc; idx++, i += 2) {
67f3fbd1c0SDimitry Andric           const char *orginal_path = args.GetArgumentAtIndex(i);
68f3fbd1c0SDimitry Andric           const char *replace_path = args.GetArgumentAtIndex(i + 1);
6914f1b3e8SDimitry Andric           if (VerifyPathExists(replace_path)) {
70c0981da4SDimitry Andric             if (!m_path_mappings.Replace(orginal_path, replace_path, idx,
71c0981da4SDimitry Andric                                          m_notify_changes))
72c0981da4SDimitry Andric               m_path_mappings.Append(orginal_path, replace_path,
73c0981da4SDimitry Andric                                      m_notify_changes);
74f3fbd1c0SDimitry Andric             changed = true;
7514f1b3e8SDimitry Andric           } else {
76cfca06d7SDimitry Andric             std::string previousError =
77cfca06d7SDimitry Andric                 error.Fail() ? std::string(error.AsCString()) + "\n" : "";
7814f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
79cfca06d7SDimitry Andric                 "%sthe replacement path doesn't exist: \"%s\"",
80cfca06d7SDimitry Andric                 previousError.c_str(), replace_path);
81f3fbd1c0SDimitry Andric           }
82f3fbd1c0SDimitry Andric         }
83f3fbd1c0SDimitry Andric         if (changed)
84205afe67SEd Maste           NotifyValueChanged();
85f034231aSEd Maste       }
8614f1b3e8SDimitry Andric     } else {
8714f1b3e8SDimitry Andric       error.SetErrorString("replace operation takes an array index followed by "
8814f1b3e8SDimitry Andric                            "one or more path pairs");
89f034231aSEd Maste     }
90f034231aSEd Maste     break;
91f034231aSEd Maste 
92f034231aSEd Maste   case eVarSetOperationAssign:
9314f1b3e8SDimitry Andric     if (argc < 2 || (argc & 1)) {
94f034231aSEd Maste       error.SetErrorString("assign operation takes one or more path pairs");
95f034231aSEd Maste       break;
96f034231aSEd Maste     }
97f034231aSEd Maste     m_path_mappings.Clear(m_notify_changes);
98f034231aSEd Maste     // Fall through to append case
99e3b55780SDimitry Andric     [[fallthrough]];
100f034231aSEd Maste   case eVarSetOperationAppend:
10114f1b3e8SDimitry Andric     if (argc < 2 || (argc & 1)) {
102f034231aSEd Maste       error.SetErrorString("append operation takes one or more path pairs");
103f034231aSEd Maste       break;
10414f1b3e8SDimitry Andric     } else {
105f3fbd1c0SDimitry Andric       bool changed = false;
10614f1b3e8SDimitry Andric       for (size_t i = 0; i < argc; i += 2) {
107f3fbd1c0SDimitry Andric         const char *orginal_path = args.GetArgumentAtIndex(i);
108f3fbd1c0SDimitry Andric         const char *replace_path = args.GetArgumentAtIndex(i + 1);
10914f1b3e8SDimitry Andric         if (VerifyPathExists(replace_path)) {
110c0981da4SDimitry Andric           m_path_mappings.Append(orginal_path, replace_path, m_notify_changes);
111f034231aSEd Maste           m_value_was_set = true;
112f3fbd1c0SDimitry Andric           changed = true;
11314f1b3e8SDimitry Andric         } else {
114cfca06d7SDimitry Andric           std::string previousError =
115cfca06d7SDimitry Andric               error.Fail() ? std::string(error.AsCString()) + "\n" : "";
11614f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
117cfca06d7SDimitry Andric               "%sthe replacement path doesn't exist: \"%s\"",
118cfca06d7SDimitry Andric               previousError.c_str(), replace_path);
119f3fbd1c0SDimitry Andric         }
120f3fbd1c0SDimitry Andric       }
121f3fbd1c0SDimitry Andric       if (changed)
122205afe67SEd Maste         NotifyValueChanged();
123f034231aSEd Maste     }
124f034231aSEd Maste     break;
125f034231aSEd Maste 
126f034231aSEd Maste   case eVarSetOperationInsertBefore:
127f034231aSEd Maste   case eVarSetOperationInsertAfter:
12814f1b3e8SDimitry Andric     // Must be at least one index + 1 pair of paths, and the pair count must be
12914f1b3e8SDimitry Andric     // even
13014f1b3e8SDimitry Andric     if (argc >= 3 && (((argc - 1) & 1) == 0)) {
131c0981da4SDimitry Andric       uint32_t idx;
132f034231aSEd Maste       const uint32_t count = m_path_mappings.GetSize();
133c0981da4SDimitry Andric       if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
13414f1b3e8SDimitry Andric         error.SetErrorStringWithFormat(
135c0981da4SDimitry Andric             "invalid file list index %s, index must be 0 through %u",
136c0981da4SDimitry Andric             args.GetArgumentAtIndex(0), count);
13714f1b3e8SDimitry Andric       } else {
138f3fbd1c0SDimitry Andric         bool changed = false;
139f034231aSEd Maste         if (op == eVarSetOperationInsertAfter)
140f034231aSEd Maste           ++idx;
141cfca06d7SDimitry Andric         for (size_t i = 1; i < argc; i += 2) {
142f3fbd1c0SDimitry Andric           const char *orginal_path = args.GetArgumentAtIndex(i);
143f3fbd1c0SDimitry Andric           const char *replace_path = args.GetArgumentAtIndex(i + 1);
14414f1b3e8SDimitry Andric           if (VerifyPathExists(replace_path)) {
145c0981da4SDimitry Andric             m_path_mappings.Insert(orginal_path, replace_path, idx,
146c0981da4SDimitry Andric                                    m_notify_changes);
147f3fbd1c0SDimitry Andric             changed = true;
148cfca06d7SDimitry Andric             idx++;
14914f1b3e8SDimitry Andric           } else {
150cfca06d7SDimitry Andric             std::string previousError =
151cfca06d7SDimitry Andric                 error.Fail() ? std::string(error.AsCString()) + "\n" : "";
15214f1b3e8SDimitry Andric             error.SetErrorStringWithFormat(
153cfca06d7SDimitry Andric                 "%sthe replacement path doesn't exist: \"%s\"",
154cfca06d7SDimitry Andric                 previousError.c_str(), replace_path);
155f3fbd1c0SDimitry Andric           }
156f3fbd1c0SDimitry Andric         }
157f3fbd1c0SDimitry Andric         if (changed)
158205afe67SEd Maste           NotifyValueChanged();
159f034231aSEd Maste       }
16014f1b3e8SDimitry Andric     } else {
16114f1b3e8SDimitry Andric       error.SetErrorString("insert operation takes an array index followed by "
16214f1b3e8SDimitry Andric                            "one or more path pairs");
163f034231aSEd Maste     }
164f034231aSEd Maste     break;
165f034231aSEd Maste 
166f034231aSEd Maste   case eVarSetOperationRemove:
16714f1b3e8SDimitry Andric     if (argc > 0) {
168f034231aSEd Maste       std::vector<int> remove_indexes;
169cfca06d7SDimitry Andric       for (size_t i = 0; i < argc; ++i) {
170c0981da4SDimitry Andric         int idx;
171c0981da4SDimitry Andric         if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx) || idx < 0 ||
172c0981da4SDimitry Andric             idx >= (int)m_path_mappings.GetSize()) {
17314f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
17414f1b3e8SDimitry Andric               "invalid array index '%s', aborting remove operation",
17514f1b3e8SDimitry Andric               args.GetArgumentAtIndex(i));
176cfca06d7SDimitry Andric           break;
177cfca06d7SDimitry Andric         } else
178cfca06d7SDimitry Andric           remove_indexes.push_back(idx);
179f034231aSEd Maste       }
180cfca06d7SDimitry Andric 
181cfca06d7SDimitry Andric       // Sort and then erase in reverse so indexes are always valid
1824b4fe385SDimitry Andric       llvm::sort(remove_indexes);
183cfca06d7SDimitry Andric       for (auto index : llvm::reverse(remove_indexes))
184cfca06d7SDimitry Andric         m_path_mappings.Remove(index, m_notify_changes);
185cfca06d7SDimitry Andric       NotifyValueChanged();
18614f1b3e8SDimitry Andric     } else {
187f034231aSEd Maste       error.SetErrorString("remove operation takes one or more array index");
188f034231aSEd Maste     }
189f034231aSEd Maste     break;
190f034231aSEd Maste 
191f034231aSEd Maste   case eVarSetOperationInvalid:
1925e95aa85SEd Maste     error = OptionValue::SetValueFromString(value, op);
193f034231aSEd Maste     break;
194f034231aSEd Maste   }
195f034231aSEd Maste   return error;
196f034231aSEd Maste }
197