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