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/Utility/Args.h" 129dba64beSDimitry Andric #include "lldb/Utility/Stream.h" 139dba64beSDimitry Andric 149dba64beSDimitry Andric using namespace lldb; 159dba64beSDimitry Andric using namespace lldb_private; 169dba64beSDimitry Andric 179dba64beSDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx, 189dba64beSDimitry Andric Stream &strm, uint32_t dump_mask) { 199dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 209dba64beSDimitry Andric if (dump_mask & eDumpOptionType) 219dba64beSDimitry Andric strm.Printf("(%s)", GetTypeAsCString()); 229dba64beSDimitry Andric if (dump_mask & eDumpOptionValue) { 239dba64beSDimitry Andric const bool one_line = dump_mask & eDumpOptionCommand; 249dba64beSDimitry Andric const uint32_t size = m_current_value.GetSize(); 259dba64beSDimitry Andric if (dump_mask & eDumpOptionType) 269dba64beSDimitry Andric strm.Printf(" =%s", 279dba64beSDimitry Andric (m_current_value.GetSize() > 0 && !one_line) ? "\n" : ""); 289dba64beSDimitry Andric if (!one_line) 299dba64beSDimitry Andric strm.IndentMore(); 309dba64beSDimitry Andric for (uint32_t i = 0; i < size; ++i) { 319dba64beSDimitry Andric if (!one_line) { 329dba64beSDimitry Andric strm.Indent(); 339dba64beSDimitry Andric strm.Printf("[%u]: ", i); 349dba64beSDimitry Andric } 35480093f4SDimitry Andric m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream()); 369dba64beSDimitry Andric if (one_line) 379dba64beSDimitry Andric strm << ' '; 389dba64beSDimitry Andric } 399dba64beSDimitry Andric if (!one_line) 409dba64beSDimitry Andric strm.IndentLess(); 419dba64beSDimitry Andric } 429dba64beSDimitry Andric } 439dba64beSDimitry Andric 449dba64beSDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value, 459dba64beSDimitry Andric VarSetOperationType op) { 469dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 479dba64beSDimitry Andric Status error; 489dba64beSDimitry Andric Args args(value.str()); 499dba64beSDimitry Andric const size_t argc = args.GetArgumentCount(); 509dba64beSDimitry Andric 519dba64beSDimitry Andric switch (op) { 529dba64beSDimitry Andric case eVarSetOperationClear: 539dba64beSDimitry Andric Clear(); 549dba64beSDimitry Andric NotifyValueChanged(); 559dba64beSDimitry Andric break; 569dba64beSDimitry Andric 579dba64beSDimitry Andric case eVarSetOperationReplace: 589dba64beSDimitry Andric if (argc > 1) { 59*349cc55cSDimitry Andric uint32_t idx; 609dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize(); 61*349cc55cSDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) { 629dba64beSDimitry Andric error.SetErrorStringWithFormat( 63*349cc55cSDimitry Andric "invalid file list index %s, index must be 0 through %u", 64*349cc55cSDimitry Andric args.GetArgumentAtIndex(0), count); 659dba64beSDimitry Andric } else { 669dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) { 679dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 689dba64beSDimitry Andric if (idx < count) 699dba64beSDimitry Andric m_current_value.Replace(idx, file); 709dba64beSDimitry Andric else 719dba64beSDimitry Andric m_current_value.Append(file); 729dba64beSDimitry Andric } 739dba64beSDimitry Andric NotifyValueChanged(); 749dba64beSDimitry Andric } 759dba64beSDimitry Andric } else { 769dba64beSDimitry Andric error.SetErrorString("replace operation takes an array index followed by " 779dba64beSDimitry Andric "one or more values"); 789dba64beSDimitry Andric } 799dba64beSDimitry Andric break; 809dba64beSDimitry Andric 819dba64beSDimitry Andric case eVarSetOperationAssign: 829dba64beSDimitry Andric m_current_value.Clear(); 839dba64beSDimitry Andric // Fall through to append case 849dba64beSDimitry Andric LLVM_FALLTHROUGH; 859dba64beSDimitry Andric case eVarSetOperationAppend: 869dba64beSDimitry Andric if (argc > 0) { 879dba64beSDimitry Andric m_value_was_set = true; 889dba64beSDimitry Andric for (size_t i = 0; i < argc; ++i) { 899dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 909dba64beSDimitry Andric m_current_value.Append(file); 919dba64beSDimitry Andric } 929dba64beSDimitry Andric NotifyValueChanged(); 939dba64beSDimitry Andric } else { 949dba64beSDimitry Andric error.SetErrorString( 959dba64beSDimitry Andric "assign operation takes at least one file path argument"); 969dba64beSDimitry Andric } 979dba64beSDimitry Andric break; 989dba64beSDimitry Andric 999dba64beSDimitry Andric case eVarSetOperationInsertBefore: 1009dba64beSDimitry Andric case eVarSetOperationInsertAfter: 1019dba64beSDimitry Andric if (argc > 1) { 102*349cc55cSDimitry Andric uint32_t idx; 1039dba64beSDimitry Andric const uint32_t count = m_current_value.GetSize(); 104*349cc55cSDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) { 1059dba64beSDimitry Andric error.SetErrorStringWithFormat( 106*349cc55cSDimitry Andric "invalid insert file list index %s, index must be 0 through %u", 107*349cc55cSDimitry Andric args.GetArgumentAtIndex(0), count); 1089dba64beSDimitry Andric } else { 1099dba64beSDimitry Andric if (op == eVarSetOperationInsertAfter) 1109dba64beSDimitry Andric ++idx; 1119dba64beSDimitry Andric for (size_t i = 1; i < argc; ++i, ++idx) { 1129dba64beSDimitry Andric FileSpec file(args.GetArgumentAtIndex(i)); 1139dba64beSDimitry Andric m_current_value.Insert(idx, file); 1149dba64beSDimitry Andric } 1159dba64beSDimitry Andric NotifyValueChanged(); 1169dba64beSDimitry Andric } 1179dba64beSDimitry Andric } else { 1189dba64beSDimitry Andric error.SetErrorString("insert operation takes an array index followed by " 1199dba64beSDimitry Andric "one or more values"); 1209dba64beSDimitry Andric } 1219dba64beSDimitry Andric break; 1229dba64beSDimitry Andric 1239dba64beSDimitry Andric case eVarSetOperationRemove: 1249dba64beSDimitry Andric if (argc > 0) { 1259dba64beSDimitry Andric std::vector<int> remove_indexes; 1269dba64beSDimitry Andric bool all_indexes_valid = true; 1279dba64beSDimitry Andric size_t i; 1289dba64beSDimitry Andric for (i = 0; all_indexes_valid && i < argc; ++i) { 129*349cc55cSDimitry Andric int idx; 130*349cc55cSDimitry Andric if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx)) 1319dba64beSDimitry Andric all_indexes_valid = false; 1329dba64beSDimitry Andric else 1339dba64beSDimitry Andric remove_indexes.push_back(idx); 1349dba64beSDimitry Andric } 1359dba64beSDimitry Andric 1369dba64beSDimitry Andric if (all_indexes_valid) { 1379dba64beSDimitry Andric size_t num_remove_indexes = remove_indexes.size(); 1389dba64beSDimitry Andric if (num_remove_indexes) { 1399dba64beSDimitry Andric // Sort and then erase in reverse so indexes are always valid 1409dba64beSDimitry Andric llvm::sort(remove_indexes.begin(), remove_indexes.end()); 1419dba64beSDimitry Andric for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { 1429dba64beSDimitry Andric m_current_value.Remove(j); 1439dba64beSDimitry Andric } 1449dba64beSDimitry Andric } 1459dba64beSDimitry Andric NotifyValueChanged(); 1469dba64beSDimitry Andric } else { 1479dba64beSDimitry Andric error.SetErrorStringWithFormat( 1489dba64beSDimitry Andric "invalid array index '%s', aborting remove operation", 1499dba64beSDimitry Andric args.GetArgumentAtIndex(i)); 1509dba64beSDimitry Andric } 1519dba64beSDimitry Andric } else { 1529dba64beSDimitry Andric error.SetErrorString("remove operation takes one or more array index"); 1539dba64beSDimitry Andric } 1549dba64beSDimitry Andric break; 1559dba64beSDimitry Andric 1569dba64beSDimitry Andric case eVarSetOperationInvalid: 1579dba64beSDimitry Andric error = OptionValue::SetValueFromString(value, op); 1589dba64beSDimitry Andric break; 1599dba64beSDimitry Andric } 1609dba64beSDimitry Andric return error; 1619dba64beSDimitry Andric } 1629dba64beSDimitry Andric 163fe6060f1SDimitry Andric OptionValueSP OptionValueFileSpecList::Clone() const { 1649dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> lock(m_mutex); 165fe6060f1SDimitry Andric return Cloneable::Clone(); 1669dba64beSDimitry Andric } 167