167cc0636SGreg Clayton //===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===// 267cc0636SGreg Clayton // 367cc0636SGreg Clayton // The LLVM Compiler Infrastructure 467cc0636SGreg Clayton // 567cc0636SGreg Clayton // This file is distributed under the University of Illinois Open Source 667cc0636SGreg Clayton // License. See LICENSE.TXT for details. 767cc0636SGreg Clayton // 867cc0636SGreg Clayton //===----------------------------------------------------------------------===// 967cc0636SGreg Clayton 1067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValuePathMappings.h" 1167cc0636SGreg Clayton 1267cc0636SGreg Clayton // C Includes 1367cc0636SGreg Clayton // C++ Includes 1467cc0636SGreg Clayton // Other libraries and framework includes 1567cc0636SGreg Clayton // Project includes 16*dbd7fabaSJonas Devlieghere #include "lldb/Host/FileSystem.h" 175275aaa0SVince Harron #include "lldb/Host/StringConvert.h" 18145d95c9SPavel Labath #include "lldb/Utility/Args.h" 195713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 20bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 2167cc0636SGreg Clayton 2267cc0636SGreg Clayton using namespace lldb; 2367cc0636SGreg Clayton using namespace lldb_private; 24b9c1b51eSKate Stone namespace { 25b9c1b51eSKate Stone static bool VerifyPathExists(const char *path) { 266a311641SGreg Clayton if (path && path[0]) 27*dbd7fabaSJonas Devlieghere return FileSystem::Instance().Exists(path); 286a311641SGreg Clayton else 296a311641SGreg Clayton return false; 306a311641SGreg Clayton } 316a311641SGreg Clayton } 326a311641SGreg Clayton 33b9c1b51eSKate Stone void OptionValuePathMappings::DumpValue(const ExecutionContext *exe_ctx, 34b9c1b51eSKate Stone Stream &strm, uint32_t dump_mask) { 3567cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 3667cc0636SGreg Clayton strm.Printf("(%s)", GetTypeAsCString()); 37b9c1b51eSKate Stone if (dump_mask & eDumpOptionValue) { 3867cc0636SGreg Clayton if (dump_mask & eDumpOptionType) 3967cc0636SGreg Clayton strm.Printf(" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : ""); 4067cc0636SGreg Clayton m_path_mappings.Dump(&strm); 4167cc0636SGreg Clayton } 4267cc0636SGreg Clayton } 4367cc0636SGreg Clayton 4497206d57SZachary Turner Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value, 45b9c1b51eSKate Stone VarSetOperationType op) { 4697206d57SZachary Turner Status error; 47771ef6d4SMalcolm Parsons Args args(value.str()); 4867cc0636SGreg Clayton const size_t argc = args.GetArgumentCount(); 4967cc0636SGreg Clayton 50b9c1b51eSKate Stone switch (op) { 5167cc0636SGreg Clayton case eVarSetOperationClear: 5267cc0636SGreg Clayton Clear(); 53332e8b1cSGreg Clayton NotifyValueChanged(); 5467cc0636SGreg Clayton break; 5567cc0636SGreg Clayton 5667cc0636SGreg Clayton case eVarSetOperationReplace: 57b9c1b51eSKate Stone // Must be at least one index + 1 pair of paths, and the pair count must be 58b9c1b51eSKate Stone // even 59b9c1b51eSKate Stone if (argc >= 3 && (((argc - 1) & 1) == 0)) { 60b9c1b51eSKate Stone uint32_t idx = 61b9c1b51eSKate Stone StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 6267cc0636SGreg Clayton const uint32_t count = m_path_mappings.GetSize(); 63b9c1b51eSKate Stone if (idx > count) { 64b9c1b51eSKate Stone error.SetErrorStringWithFormat( 65b9c1b51eSKate Stone "invalid file list index %u, index must be 0 through %u", idx, 66b9c1b51eSKate Stone count); 67b9c1b51eSKate Stone } else { 686a311641SGreg Clayton bool changed = false; 69b9c1b51eSKate Stone for (size_t i = 1; i < argc; i += 2, ++idx) { 706a311641SGreg Clayton const char *orginal_path = args.GetArgumentAtIndex(i); 716a311641SGreg Clayton const char *replace_path = args.GetArgumentAtIndex(i + 1); 72b9c1b51eSKate Stone if (VerifyPathExists(replace_path)) { 736a311641SGreg Clayton ConstString a(orginal_path); 746a311641SGreg Clayton ConstString b(replace_path); 7567cc0636SGreg Clayton if (!m_path_mappings.Replace(a, b, idx, m_notify_changes)) 7667cc0636SGreg Clayton m_path_mappings.Append(a, b, m_notify_changes); 776a311641SGreg Clayton changed = true; 78b9c1b51eSKate Stone } else { 79b9c1b51eSKate Stone error.SetErrorStringWithFormat( 80b9c1b51eSKate Stone "the replacement path doesn't exist: \"%s\"", replace_path); 816a311641SGreg Clayton break; 826a311641SGreg Clayton } 836a311641SGreg Clayton } 846a311641SGreg Clayton if (changed) 85332e8b1cSGreg Clayton NotifyValueChanged(); 8667cc0636SGreg Clayton } 87b9c1b51eSKate Stone } else { 88b9c1b51eSKate Stone error.SetErrorString("replace operation takes an array index followed by " 89b9c1b51eSKate Stone "one or more path pairs"); 9067cc0636SGreg Clayton } 9167cc0636SGreg Clayton break; 9267cc0636SGreg Clayton 9367cc0636SGreg Clayton case eVarSetOperationAssign: 94b9c1b51eSKate Stone if (argc < 2 || (argc & 1)) { 9567cc0636SGreg Clayton error.SetErrorString("assign operation takes one or more path pairs"); 9667cc0636SGreg Clayton break; 9767cc0636SGreg Clayton } 9867cc0636SGreg Clayton m_path_mappings.Clear(m_notify_changes); 9967cc0636SGreg Clayton // Fall through to append case 10062e0681aSJason Molenda LLVM_FALLTHROUGH; 10167cc0636SGreg Clayton case eVarSetOperationAppend: 102b9c1b51eSKate Stone if (argc < 2 || (argc & 1)) { 10367cc0636SGreg Clayton error.SetErrorString("append operation takes one or more path pairs"); 10467cc0636SGreg Clayton break; 105b9c1b51eSKate Stone } else { 1066a311641SGreg Clayton bool changed = false; 107b9c1b51eSKate Stone for (size_t i = 0; i < argc; i += 2) { 1086a311641SGreg Clayton const char *orginal_path = args.GetArgumentAtIndex(i); 1096a311641SGreg Clayton const char *replace_path = args.GetArgumentAtIndex(i + 1); 110b9c1b51eSKate Stone if (VerifyPathExists(replace_path)) { 1116a311641SGreg Clayton ConstString a(orginal_path); 1126a311641SGreg Clayton ConstString b(replace_path); 11367cc0636SGreg Clayton m_path_mappings.Append(a, b, m_notify_changes); 11467cc0636SGreg Clayton m_value_was_set = true; 1156a311641SGreg Clayton changed = true; 116b9c1b51eSKate Stone } else { 117b9c1b51eSKate Stone error.SetErrorStringWithFormat( 118b9c1b51eSKate Stone "the replacement path doesn't exist: \"%s\"", replace_path); 1196a311641SGreg Clayton break; 1206a311641SGreg Clayton } 1216a311641SGreg Clayton } 1226a311641SGreg Clayton if (changed) 123332e8b1cSGreg Clayton NotifyValueChanged(); 12467cc0636SGreg Clayton } 12567cc0636SGreg Clayton break; 12667cc0636SGreg Clayton 12767cc0636SGreg Clayton case eVarSetOperationInsertBefore: 12867cc0636SGreg Clayton case eVarSetOperationInsertAfter: 129b9c1b51eSKate Stone // Must be at least one index + 1 pair of paths, and the pair count must be 130b9c1b51eSKate Stone // even 131b9c1b51eSKate Stone if (argc >= 3 && (((argc - 1) & 1) == 0)) { 132b9c1b51eSKate Stone uint32_t idx = 133b9c1b51eSKate Stone StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 13467cc0636SGreg Clayton const uint32_t count = m_path_mappings.GetSize(); 135b9c1b51eSKate Stone if (idx > count) { 136b9c1b51eSKate Stone error.SetErrorStringWithFormat( 137b9c1b51eSKate Stone "invalid file list index %u, index must be 0 through %u", idx, 138b9c1b51eSKate Stone count); 139b9c1b51eSKate Stone } else { 1406a311641SGreg Clayton bool changed = false; 14167cc0636SGreg Clayton if (op == eVarSetOperationInsertAfter) 14267cc0636SGreg Clayton ++idx; 143b9c1b51eSKate Stone for (size_t i = 1; i < argc; i += 2, ++idx) { 1446a311641SGreg Clayton const char *orginal_path = args.GetArgumentAtIndex(i); 1456a311641SGreg Clayton const char *replace_path = args.GetArgumentAtIndex(i + 1); 146b9c1b51eSKate Stone if (VerifyPathExists(replace_path)) { 1476a311641SGreg Clayton ConstString a(orginal_path); 1486a311641SGreg Clayton ConstString b(replace_path); 14967cc0636SGreg Clayton m_path_mappings.Insert(a, b, idx, m_notify_changes); 1506a311641SGreg Clayton changed = true; 151b9c1b51eSKate Stone } else { 152b9c1b51eSKate Stone error.SetErrorStringWithFormat( 153b9c1b51eSKate Stone "the replacement path doesn't exist: \"%s\"", replace_path); 1546a311641SGreg Clayton break; 1556a311641SGreg Clayton } 1566a311641SGreg Clayton } 1576a311641SGreg Clayton if (changed) 158332e8b1cSGreg Clayton NotifyValueChanged(); 15967cc0636SGreg Clayton } 160b9c1b51eSKate Stone } else { 161b9c1b51eSKate Stone error.SetErrorString("insert operation takes an array index followed by " 162b9c1b51eSKate Stone "one or more path pairs"); 16367cc0636SGreg Clayton } 16467cc0636SGreg Clayton break; 16567cc0636SGreg Clayton 16667cc0636SGreg Clayton case eVarSetOperationRemove: 167b9c1b51eSKate Stone if (argc > 0) { 16867cc0636SGreg Clayton std::vector<int> remove_indexes; 16967cc0636SGreg Clayton bool all_indexes_valid = true; 17067cc0636SGreg Clayton size_t i; 171b9c1b51eSKate Stone for (i = 0; all_indexes_valid && i < argc; ++i) { 172b9c1b51eSKate Stone const int idx = 173b9c1b51eSKate Stone StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); 17467cc0636SGreg Clayton if (idx == INT32_MAX) 17567cc0636SGreg Clayton all_indexes_valid = false; 17667cc0636SGreg Clayton else 17767cc0636SGreg Clayton remove_indexes.push_back(idx); 17867cc0636SGreg Clayton } 17967cc0636SGreg Clayton 180b9c1b51eSKate Stone if (all_indexes_valid) { 18167cc0636SGreg Clayton size_t num_remove_indexes = remove_indexes.size(); 182b9c1b51eSKate Stone if (num_remove_indexes) { 18367cc0636SGreg Clayton // Sort and then erase in reverse so indexes are always valid 18467cc0636SGreg Clayton std::sort(remove_indexes.begin(), remove_indexes.end()); 185b9c1b51eSKate Stone for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { 186ccd41e55SJason Molenda m_path_mappings.Remove(j, m_notify_changes); 18767cc0636SGreg Clayton } 18867cc0636SGreg Clayton } 189332e8b1cSGreg Clayton NotifyValueChanged(); 190b9c1b51eSKate Stone } else { 191b9c1b51eSKate Stone error.SetErrorStringWithFormat( 192b9c1b51eSKate Stone "invalid array index '%s', aborting remove operation", 193b9c1b51eSKate Stone args.GetArgumentAtIndex(i)); 19467cc0636SGreg Clayton } 195b9c1b51eSKate Stone } else { 19667cc0636SGreg Clayton error.SetErrorString("remove operation takes one or more array index"); 19767cc0636SGreg Clayton } 19867cc0636SGreg Clayton break; 19967cc0636SGreg Clayton 20067cc0636SGreg Clayton case eVarSetOperationInvalid: 201c95f7e2aSPavel Labath error = OptionValue::SetValueFromString(value, op); 20267cc0636SGreg Clayton break; 20367cc0636SGreg Clayton } 20467cc0636SGreg Clayton return error; 20567cc0636SGreg Clayton } 20667cc0636SGreg Clayton 207b9c1b51eSKate Stone lldb::OptionValueSP OptionValuePathMappings::DeepCopy() const { 20867cc0636SGreg Clayton return OptionValueSP(new OptionValuePathMappings(*this)); 20967cc0636SGreg Clayton } 210