183108e75SAdrian Prantl //===-- OptionValueFileSpecList.cpp ---------------------------------------===//
283108e75SAdrian Prantl //
383108e75SAdrian Prantl // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
483108e75SAdrian Prantl // See https://llvm.org/LICENSE.txt for license information.
583108e75SAdrian Prantl // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
683108e75SAdrian Prantl //
783108e75SAdrian Prantl //===----------------------------------------------------------------------===//
883108e75SAdrian Prantl 
983108e75SAdrian Prantl #include "lldb/Interpreter/OptionValueFileSpecList.h"
1083108e75SAdrian Prantl 
1183108e75SAdrian Prantl #include "lldb/Utility/Args.h"
1283108e75SAdrian Prantl #include "lldb/Utility/Stream.h"
1383108e75SAdrian Prantl 
1483108e75SAdrian Prantl using namespace lldb;
1583108e75SAdrian Prantl using namespace lldb_private;
1683108e75SAdrian Prantl 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)1783108e75SAdrian Prantl void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
1883108e75SAdrian Prantl                                         Stream &strm, uint32_t dump_mask) {
1983108e75SAdrian Prantl   std::lock_guard<std::recursive_mutex> lock(m_mutex);
2083108e75SAdrian Prantl   if (dump_mask & eDumpOptionType)
2183108e75SAdrian Prantl     strm.Printf("(%s)", GetTypeAsCString());
2283108e75SAdrian Prantl   if (dump_mask & eDumpOptionValue) {
2383108e75SAdrian Prantl     const bool one_line = dump_mask & eDumpOptionCommand;
2483108e75SAdrian Prantl     const uint32_t size = m_current_value.GetSize();
2583108e75SAdrian Prantl     if (dump_mask & eDumpOptionType)
2683108e75SAdrian Prantl       strm.Printf(" =%s",
2783108e75SAdrian Prantl                   (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
2883108e75SAdrian Prantl     if (!one_line)
2983108e75SAdrian Prantl       strm.IndentMore();
3083108e75SAdrian Prantl     for (uint32_t i = 0; i < size; ++i) {
3183108e75SAdrian Prantl       if (!one_line) {
3283108e75SAdrian Prantl         strm.Indent();
3383108e75SAdrian Prantl         strm.Printf("[%u]: ", i);
3483108e75SAdrian Prantl       }
354dac97ebSRaphael Isemann       m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream());
3683108e75SAdrian Prantl       if (one_line)
3783108e75SAdrian Prantl         strm << ' ';
3883108e75SAdrian Prantl     }
3983108e75SAdrian Prantl     if (!one_line)
4083108e75SAdrian Prantl       strm.IndentLess();
4183108e75SAdrian Prantl   }
4283108e75SAdrian Prantl }
4383108e75SAdrian Prantl 
SetValueFromString(llvm::StringRef value,VarSetOperationType op)4483108e75SAdrian Prantl Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
4583108e75SAdrian Prantl                                                    VarSetOperationType op) {
4683108e75SAdrian Prantl   std::lock_guard<std::recursive_mutex> lock(m_mutex);
4783108e75SAdrian Prantl   Status error;
4883108e75SAdrian Prantl   Args args(value.str());
4983108e75SAdrian Prantl   const size_t argc = args.GetArgumentCount();
5083108e75SAdrian Prantl 
5183108e75SAdrian Prantl   switch (op) {
5283108e75SAdrian Prantl   case eVarSetOperationClear:
5383108e75SAdrian Prantl     Clear();
5483108e75SAdrian Prantl     NotifyValueChanged();
5583108e75SAdrian Prantl     break;
5683108e75SAdrian Prantl 
5783108e75SAdrian Prantl   case eVarSetOperationReplace:
5883108e75SAdrian Prantl     if (argc > 1) {
593a6ba367SMichał Górny       uint32_t idx;
6083108e75SAdrian Prantl       const uint32_t count = m_current_value.GetSize();
613a6ba367SMichał Górny       if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
6283108e75SAdrian Prantl         error.SetErrorStringWithFormat(
633a6ba367SMichał Górny             "invalid file list index %s, index must be 0 through %u",
643a6ba367SMichał Górny             args.GetArgumentAtIndex(0), count);
6583108e75SAdrian Prantl       } else {
6683108e75SAdrian Prantl         for (size_t i = 1; i < argc; ++i, ++idx) {
6783108e75SAdrian Prantl           FileSpec file(args.GetArgumentAtIndex(i));
6883108e75SAdrian Prantl           if (idx < count)
6983108e75SAdrian Prantl             m_current_value.Replace(idx, file);
7083108e75SAdrian Prantl           else
7183108e75SAdrian Prantl             m_current_value.Append(file);
7283108e75SAdrian Prantl         }
7383108e75SAdrian Prantl         NotifyValueChanged();
7483108e75SAdrian Prantl       }
7583108e75SAdrian Prantl     } else {
7683108e75SAdrian Prantl       error.SetErrorString("replace operation takes an array index followed by "
7783108e75SAdrian Prantl                            "one or more values");
7883108e75SAdrian Prantl     }
7983108e75SAdrian Prantl     break;
8083108e75SAdrian Prantl 
8183108e75SAdrian Prantl   case eVarSetOperationAssign:
8283108e75SAdrian Prantl     m_current_value.Clear();
8383108e75SAdrian Prantl     // Fall through to append case
8483108e75SAdrian Prantl     LLVM_FALLTHROUGH;
8583108e75SAdrian Prantl   case eVarSetOperationAppend:
8683108e75SAdrian Prantl     if (argc > 0) {
8783108e75SAdrian Prantl       m_value_was_set = true;
8883108e75SAdrian Prantl       for (size_t i = 0; i < argc; ++i) {
8983108e75SAdrian Prantl         FileSpec file(args.GetArgumentAtIndex(i));
9083108e75SAdrian Prantl         m_current_value.Append(file);
9183108e75SAdrian Prantl       }
9283108e75SAdrian Prantl       NotifyValueChanged();
9383108e75SAdrian Prantl     } else {
9483108e75SAdrian Prantl       error.SetErrorString(
9583108e75SAdrian Prantl           "assign operation takes at least one file path argument");
9683108e75SAdrian Prantl     }
9783108e75SAdrian Prantl     break;
9883108e75SAdrian Prantl 
9983108e75SAdrian Prantl   case eVarSetOperationInsertBefore:
10083108e75SAdrian Prantl   case eVarSetOperationInsertAfter:
10183108e75SAdrian Prantl     if (argc > 1) {
1023a6ba367SMichał Górny       uint32_t idx;
10383108e75SAdrian Prantl       const uint32_t count = m_current_value.GetSize();
1043a6ba367SMichał Górny       if (!llvm::to_integer(args.GetArgumentAtIndex(0), idx) || idx > count) {
10583108e75SAdrian Prantl         error.SetErrorStringWithFormat(
1063a6ba367SMichał Górny             "invalid insert file list index %s, index must be 0 through %u",
1073a6ba367SMichał Górny             args.GetArgumentAtIndex(0), count);
10883108e75SAdrian Prantl       } else {
10983108e75SAdrian Prantl         if (op == eVarSetOperationInsertAfter)
11083108e75SAdrian Prantl           ++idx;
11183108e75SAdrian Prantl         for (size_t i = 1; i < argc; ++i, ++idx) {
11283108e75SAdrian Prantl           FileSpec file(args.GetArgumentAtIndex(i));
11383108e75SAdrian Prantl           m_current_value.Insert(idx, file);
11483108e75SAdrian Prantl         }
11583108e75SAdrian Prantl         NotifyValueChanged();
11683108e75SAdrian Prantl       }
11783108e75SAdrian Prantl     } else {
11883108e75SAdrian Prantl       error.SetErrorString("insert operation takes an array index followed by "
11983108e75SAdrian Prantl                            "one or more values");
12083108e75SAdrian Prantl     }
12183108e75SAdrian Prantl     break;
12283108e75SAdrian Prantl 
12383108e75SAdrian Prantl   case eVarSetOperationRemove:
12483108e75SAdrian Prantl     if (argc > 0) {
12583108e75SAdrian Prantl       std::vector<int> remove_indexes;
12683108e75SAdrian Prantl       bool all_indexes_valid = true;
12783108e75SAdrian Prantl       size_t i;
12883108e75SAdrian Prantl       for (i = 0; all_indexes_valid && i < argc; ++i) {
1293a6ba367SMichał Górny         int idx;
1303a6ba367SMichał Górny         if (!llvm::to_integer(args.GetArgumentAtIndex(i), idx))
13183108e75SAdrian Prantl           all_indexes_valid = false;
13283108e75SAdrian Prantl         else
13383108e75SAdrian Prantl           remove_indexes.push_back(idx);
13483108e75SAdrian Prantl       }
13583108e75SAdrian Prantl 
13683108e75SAdrian Prantl       if (all_indexes_valid) {
13783108e75SAdrian Prantl         size_t num_remove_indexes = remove_indexes.size();
13883108e75SAdrian Prantl         if (num_remove_indexes) {
13983108e75SAdrian Prantl           // Sort and then erase in reverse so indexes are always valid
140*cd9a5cfdSDmitri Gribenko           llvm::sort(remove_indexes);
14183108e75SAdrian Prantl           for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
14283108e75SAdrian Prantl             m_current_value.Remove(j);
14383108e75SAdrian Prantl           }
14483108e75SAdrian Prantl         }
14583108e75SAdrian Prantl         NotifyValueChanged();
14683108e75SAdrian Prantl       } else {
14783108e75SAdrian Prantl         error.SetErrorStringWithFormat(
14883108e75SAdrian Prantl             "invalid array index '%s', aborting remove operation",
14983108e75SAdrian Prantl             args.GetArgumentAtIndex(i));
15083108e75SAdrian Prantl       }
15183108e75SAdrian Prantl     } else {
15283108e75SAdrian Prantl       error.SetErrorString("remove operation takes one or more array index");
15383108e75SAdrian Prantl     }
15483108e75SAdrian Prantl     break;
15583108e75SAdrian Prantl 
15683108e75SAdrian Prantl   case eVarSetOperationInvalid:
15783108e75SAdrian Prantl     error = OptionValue::SetValueFromString(value, op);
15883108e75SAdrian Prantl     break;
15983108e75SAdrian Prantl   }
16083108e75SAdrian Prantl   return error;
16183108e75SAdrian Prantl }
16283108e75SAdrian Prantl 
Clone() const163f0f183eeSTatyana Krasnukha OptionValueSP OptionValueFileSpecList::Clone() const {
16483108e75SAdrian Prantl   std::lock_guard<std::recursive_mutex> lock(m_mutex);
165f0f183eeSTatyana Krasnukha   return Cloneable::Clone();
16683108e75SAdrian Prantl }
167