19dba64beSDimitry Andric //===-- OptionValueFileSpecList.cpp ---------------------------------------===// 29dba64beSDimitry Andric // 39dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 59dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69dba64beSDimitry Andric // 79dba64beSDimitry Andric //===----------------------------------------------------------------------===// 89dba64beSDimitry Andric 99dba64beSDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h" 109dba64beSDimitry Andric 119dba64beSDimitry Andric #include "lldb/Host/StringConvert.h" 129dba64beSDimitry Andric #include "lldb/Utility/Args.h" 139dba64beSDimitry Andric #include "lldb/Utility/Stream.h" 149dba64beSDimitry Andric 159dba64beSDimitry Andric using namespace lldb; 169dba64beSDimitry Andric using namespace lldb_private; 179dba64beSDimitry Andric 189dba64beSDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx, 199dba64beSDimitry Andric Stream &strm, uint32_t dump_mask) { 209dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 219dba64beSDimitry Andric if (dump_mask & eDumpOptionType) 229dba64beSDimitry Andric strm.Printf("(%s)", GetTypeAsCString()); 239dba64beSDimitry Andric if (dump_mask & eDumpOptionValue) { 249dba64beSDimitry Andric const bool one_line = dump_mask & eDumpOptionCommand; 259dba64beSDimitry Andric const uint32_t size = m_current_value.GetSize(); 269dba64beSDimitry Andric if (dump_mask & eDumpOptionType) 279dba64beSDimitry Andric strm.Printf(" =%s", 289dba64beSDimitry Andric (m_current_value.GetSize() > 0 && !one_line) ? "\n" : ""); 299dba64beSDimitry Andric if (!one_line) 309dba64beSDimitry Andric strm.IndentMore(); 319dba64beSDimitry Andric for (uint32_t i = 0; i < size; ++i) { 329dba64beSDimitry Andric if (!one_line) { 339dba64beSDimitry Andric strm.Indent(); 349dba64beSDimitry Andric strm.Printf("[%u]: ", i); 359dba64beSDimitry Andric } 36*480093f4SDimitry Andric m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream()); 379dba64beSDimitry Andric if (one_line) 389dba64beSDimitry Andric strm << ' '; 399dba64beSDimitry Andric } 409dba64beSDimitry Andric if (!one_line) 419dba64beSDimitry Andric strm.IndentLess(); 429dba64beSDimitry Andric } 439dba64beSDimitry Andric } 449dba64beSDimitry Andric 459dba64beSDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value, 469dba64beSDimitry Andric VarSetOperationType op) { 479dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 489dba64beSDimitry Andric Status error; 499dba64beSDimitry Andric Args args(value.str()); 509dba64beSDimitry Andric const size_t argc = args.GetArgumentCount(); 519dba64beSDimitry Andric 529dba64beSDimitry Andric switch (op) { 539dba64beSDimitry Andric case eVarSetOperationClear: 549dba64beSDimitry Andric Clear(); 559dba64beSDimitry Andric NotifyValueChanged(); 569dba64beSDimitry Andric break; 579dba64beSDimitry Andric 589dba64beSDimitry Andric case eVarSetOperationReplace: 599dba64beSDimitry Andric if (argc > 1) { 609dba64beSDimitry Andric uint32_t idx = 619dba64beSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 629dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize(); 639dba64beSDimitry Andric if (idx > count) { 649dba64beSDimitry Andric error.SetErrorStringWithFormat( 659dba64beSDimitry Andric "invalid file list index %u, index must be 0 through %u", idx, 669dba64beSDimitry Andric count); 679dba64beSDimitry Andric } else { 689dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) { 699dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 709dba64beSDimitry Andric if (idx < count) 719dba64beSDimitry Andric m_current_value.Replace(idx, file); 729dba64beSDimitry Andric else 739dba64beSDimitry Andric m_current_value.Append(file); 749dba64beSDimitry Andric } 759dba64beSDimitry Andric NotifyValueChanged(); 769dba64beSDimitry Andric } 779dba64beSDimitry Andric } else { 789dba64beSDimitry Andric error.SetErrorString("replace operation takes an array index followed by " 799dba64beSDimitry Andric "one or more values"); 809dba64beSDimitry Andric } 819dba64beSDimitry Andric break; 829dba64beSDimitry Andric 839dba64beSDimitry Andric case eVarSetOperationAssign: 849dba64beSDimitry Andric m_current_value.Clear(); 859dba64beSDimitry Andric // Fall through to append case 869dba64beSDimitry Andric LLVM_FALLTHROUGH; 879dba64beSDimitry Andric case eVarSetOperationAppend: 889dba64beSDimitry Andric if (argc > 0) { 899dba64beSDimitry Andric m_value_was_set = true; 909dba64beSDimitry Andric for (size_t i = 0; i < argc; ++i) { 919dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 929dba64beSDimitry Andric m_current_value.Append(file); 939dba64beSDimitry Andric } 949dba64beSDimitry Andric NotifyValueChanged(); 959dba64beSDimitry Andric } else { 969dba64beSDimitry Andric error.SetErrorString( 979dba64beSDimitry Andric "assign operation takes at least one file path argument"); 989dba64beSDimitry Andric } 999dba64beSDimitry Andric break; 1009dba64beSDimitry Andric 1019dba64beSDimitry Andric case eVarSetOperationInsertBefore: 1029dba64beSDimitry Andric case eVarSetOperationInsertAfter: 1039dba64beSDimitry Andric if (argc > 1) { 1049dba64beSDimitry Andric uint32_t idx = 1059dba64beSDimitry Andric StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX); 1069dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize(); 1079dba64beSDimitry Andric if (idx > count) { 1089dba64beSDimitry Andric error.SetErrorStringWithFormat( 1099dba64beSDimitry Andric "invalid insert file list index %u, index must be 0 through %u", 1109dba64beSDimitry Andric idx, count); 1119dba64beSDimitry Andric } else { 1129dba64beSDimitry Andric if (op == eVarSetOperationInsertAfter) 1139dba64beSDimitry Andric ++idx; 1149dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) { 1159dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 1169dba64beSDimitry Andric m_current_value.Insert(idx, file); 1179dba64beSDimitry Andric } 1189dba64beSDimitry Andric NotifyValueChanged(); 1199dba64beSDimitry Andric } 1209dba64beSDimitry Andric } else { 1219dba64beSDimitry Andric error.SetErrorString("insert operation takes an array index followed by " 1229dba64beSDimitry Andric "one or more values"); 1239dba64beSDimitry Andric } 1249dba64beSDimitry Andric break; 1259dba64beSDimitry Andric 1269dba64beSDimitry Andric case eVarSetOperationRemove: 1279dba64beSDimitry Andric if (argc > 0) { 1289dba64beSDimitry Andric std::vector<int> remove_indexes; 1299dba64beSDimitry Andric bool all_indexes_valid = true; 1309dba64beSDimitry Andric size_t i; 1319dba64beSDimitry Andric for (i = 0; all_indexes_valid && i < argc; ++i) { 1329dba64beSDimitry Andric const int idx = 1339dba64beSDimitry Andric StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX); 1349dba64beSDimitry Andric if (idx == INT32_MAX) 1359dba64beSDimitry Andric all_indexes_valid = false; 1369dba64beSDimitry Andric else 1379dba64beSDimitry Andric remove_indexes.push_back(idx); 1389dba64beSDimitry Andric } 1399dba64beSDimitry Andric 1409dba64beSDimitry Andric if (all_indexes_valid) { 1419dba64beSDimitry Andric size_t num_remove_indexes = remove_indexes.size(); 1429dba64beSDimitry Andric if (num_remove_indexes) { 1439dba64beSDimitry Andric // Sort and then erase in reverse so indexes are always valid 1449dba64beSDimitry Andric llvm::sort(remove_indexes.begin(), remove_indexes.end()); 1459dba64beSDimitry Andric for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { 1469dba64beSDimitry Andric m_current_value.Remove(j); 1479dba64beSDimitry Andric } 1489dba64beSDimitry Andric } 1499dba64beSDimitry Andric NotifyValueChanged(); 1509dba64beSDimitry Andric } else { 1519dba64beSDimitry Andric error.SetErrorStringWithFormat( 1529dba64beSDimitry Andric "invalid array index '%s', aborting remove operation", 1539dba64beSDimitry Andric args.GetArgumentAtIndex(i)); 1549dba64beSDimitry Andric } 1559dba64beSDimitry Andric } else { 1569dba64beSDimitry Andric error.SetErrorString("remove operation takes one or more array index"); 1579dba64beSDimitry Andric } 1589dba64beSDimitry Andric break; 1599dba64beSDimitry Andric 1609dba64beSDimitry Andric case eVarSetOperationInvalid: 1619dba64beSDimitry Andric error = OptionValue::SetValueFromString(value, op); 1629dba64beSDimitry Andric break; 1639dba64beSDimitry Andric } 1649dba64beSDimitry Andric return error; 1659dba64beSDimitry Andric } 1669dba64beSDimitry Andric 1679dba64beSDimitry Andric lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const { 1689dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 1699dba64beSDimitry Andric return OptionValueSP(new OptionValueFileSpecList(m_current_value)); 1709dba64beSDimitry Andric } 171