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