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