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