xref: /freebsd-src/contrib/llvm-project/lldb/source/Interpreter/OptionValueFileSpecList.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
19dba64beSDimitry Andric //===-- OptionValueFileSpecList.cpp ---------------------------------------===//
29dba64beSDimitry Andric //
39dba64beSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49dba64beSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
59dba64beSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69dba64beSDimitry Andric //
79dba64beSDimitry Andric //===----------------------------------------------------------------------===//
89dba64beSDimitry Andric 
99dba64beSDimitry Andric #include "lldb/Interpreter/OptionValueFileSpecList.h"
109dba64beSDimitry Andric 
119dba64beSDimitry Andric #include "lldb/Host/StringConvert.h"
129dba64beSDimitry Andric #include "lldb/Utility/Args.h"
139dba64beSDimitry Andric #include "lldb/Utility/Stream.h"
149dba64beSDimitry Andric 
159dba64beSDimitry Andric using namespace lldb;
169dba64beSDimitry Andric using namespace lldb_private;
179dba64beSDimitry Andric 
189dba64beSDimitry Andric void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
199dba64beSDimitry Andric                                         Stream &strm, uint32_t dump_mask) {
209dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
219dba64beSDimitry Andric   if (dump_mask & eDumpOptionType)
229dba64beSDimitry Andric     strm.Printf("(%s)", GetTypeAsCString());
239dba64beSDimitry Andric   if (dump_mask & eDumpOptionValue) {
249dba64beSDimitry Andric     const bool one_line = dump_mask & eDumpOptionCommand;
259dba64beSDimitry Andric     const uint32_t size = m_current_value.GetSize();
269dba64beSDimitry Andric     if (dump_mask & eDumpOptionType)
279dba64beSDimitry Andric       strm.Printf(" =%s",
289dba64beSDimitry Andric                   (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
299dba64beSDimitry Andric     if (!one_line)
309dba64beSDimitry Andric       strm.IndentMore();
319dba64beSDimitry Andric     for (uint32_t i = 0; i < size; ++i) {
329dba64beSDimitry Andric       if (!one_line) {
339dba64beSDimitry Andric         strm.Indent();
349dba64beSDimitry Andric         strm.Printf("[%u]: ", i);
359dba64beSDimitry Andric       }
36*480093f4SDimitry Andric       m_current_value.GetFileSpecAtIndex(i).Dump(strm.AsRawOstream());
379dba64beSDimitry Andric       if (one_line)
389dba64beSDimitry Andric         strm << ' ';
399dba64beSDimitry Andric     }
409dba64beSDimitry Andric     if (!one_line)
419dba64beSDimitry Andric       strm.IndentLess();
429dba64beSDimitry Andric   }
439dba64beSDimitry Andric }
449dba64beSDimitry Andric 
459dba64beSDimitry Andric Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
469dba64beSDimitry Andric                                                    VarSetOperationType op) {
479dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
489dba64beSDimitry Andric   Status error;
499dba64beSDimitry Andric   Args args(value.str());
509dba64beSDimitry Andric   const size_t argc = args.GetArgumentCount();
519dba64beSDimitry Andric 
529dba64beSDimitry Andric   switch (op) {
539dba64beSDimitry Andric   case eVarSetOperationClear:
549dba64beSDimitry Andric     Clear();
559dba64beSDimitry Andric     NotifyValueChanged();
569dba64beSDimitry Andric     break;
579dba64beSDimitry Andric 
589dba64beSDimitry Andric   case eVarSetOperationReplace:
599dba64beSDimitry Andric     if (argc > 1) {
609dba64beSDimitry Andric       uint32_t idx =
619dba64beSDimitry Andric           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
629dba64beSDimitry Andric       const uint32_t count = m_current_value.GetSize();
639dba64beSDimitry Andric       if (idx > count) {
649dba64beSDimitry Andric         error.SetErrorStringWithFormat(
659dba64beSDimitry Andric             "invalid file list index %u, index must be 0 through %u", idx,
669dba64beSDimitry Andric             count);
679dba64beSDimitry Andric       } else {
689dba64beSDimitry Andric         for (size_t i = 1; i < argc; ++i, ++idx) {
699dba64beSDimitry Andric           FileSpec file(args.GetArgumentAtIndex(i));
709dba64beSDimitry Andric           if (idx < count)
719dba64beSDimitry Andric             m_current_value.Replace(idx, file);
729dba64beSDimitry Andric           else
739dba64beSDimitry Andric             m_current_value.Append(file);
749dba64beSDimitry Andric         }
759dba64beSDimitry Andric         NotifyValueChanged();
769dba64beSDimitry Andric       }
779dba64beSDimitry Andric     } else {
789dba64beSDimitry Andric       error.SetErrorString("replace operation takes an array index followed by "
799dba64beSDimitry Andric                            "one or more values");
809dba64beSDimitry Andric     }
819dba64beSDimitry Andric     break;
829dba64beSDimitry Andric 
839dba64beSDimitry Andric   case eVarSetOperationAssign:
849dba64beSDimitry Andric     m_current_value.Clear();
859dba64beSDimitry Andric     // Fall through to append case
869dba64beSDimitry Andric     LLVM_FALLTHROUGH;
879dba64beSDimitry Andric   case eVarSetOperationAppend:
889dba64beSDimitry Andric     if (argc > 0) {
899dba64beSDimitry Andric       m_value_was_set = true;
909dba64beSDimitry Andric       for (size_t i = 0; i < argc; ++i) {
919dba64beSDimitry Andric         FileSpec file(args.GetArgumentAtIndex(i));
929dba64beSDimitry Andric         m_current_value.Append(file);
939dba64beSDimitry Andric       }
949dba64beSDimitry Andric       NotifyValueChanged();
959dba64beSDimitry Andric     } else {
969dba64beSDimitry Andric       error.SetErrorString(
979dba64beSDimitry Andric           "assign operation takes at least one file path argument");
989dba64beSDimitry Andric     }
999dba64beSDimitry Andric     break;
1009dba64beSDimitry Andric 
1019dba64beSDimitry Andric   case eVarSetOperationInsertBefore:
1029dba64beSDimitry Andric   case eVarSetOperationInsertAfter:
1039dba64beSDimitry Andric     if (argc > 1) {
1049dba64beSDimitry Andric       uint32_t idx =
1059dba64beSDimitry Andric           StringConvert::ToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
1069dba64beSDimitry Andric       const uint32_t count = m_current_value.GetSize();
1079dba64beSDimitry Andric       if (idx > count) {
1089dba64beSDimitry Andric         error.SetErrorStringWithFormat(
1099dba64beSDimitry Andric             "invalid insert file list index %u, index must be 0 through %u",
1109dba64beSDimitry Andric             idx, count);
1119dba64beSDimitry Andric       } else {
1129dba64beSDimitry Andric         if (op == eVarSetOperationInsertAfter)
1139dba64beSDimitry Andric           ++idx;
1149dba64beSDimitry Andric         for (size_t i = 1; i < argc; ++i, ++idx) {
1159dba64beSDimitry Andric           FileSpec file(args.GetArgumentAtIndex(i));
1169dba64beSDimitry Andric           m_current_value.Insert(idx, file);
1179dba64beSDimitry Andric         }
1189dba64beSDimitry Andric         NotifyValueChanged();
1199dba64beSDimitry Andric       }
1209dba64beSDimitry Andric     } else {
1219dba64beSDimitry Andric       error.SetErrorString("insert operation takes an array index followed by "
1229dba64beSDimitry Andric                            "one or more values");
1239dba64beSDimitry Andric     }
1249dba64beSDimitry Andric     break;
1259dba64beSDimitry Andric 
1269dba64beSDimitry Andric   case eVarSetOperationRemove:
1279dba64beSDimitry Andric     if (argc > 0) {
1289dba64beSDimitry Andric       std::vector<int> remove_indexes;
1299dba64beSDimitry Andric       bool all_indexes_valid = true;
1309dba64beSDimitry Andric       size_t i;
1319dba64beSDimitry Andric       for (i = 0; all_indexes_valid && i < argc; ++i) {
1329dba64beSDimitry Andric         const int idx =
1339dba64beSDimitry Andric             StringConvert::ToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
1349dba64beSDimitry Andric         if (idx == INT32_MAX)
1359dba64beSDimitry Andric           all_indexes_valid = false;
1369dba64beSDimitry Andric         else
1379dba64beSDimitry Andric           remove_indexes.push_back(idx);
1389dba64beSDimitry Andric       }
1399dba64beSDimitry Andric 
1409dba64beSDimitry Andric       if (all_indexes_valid) {
1419dba64beSDimitry Andric         size_t num_remove_indexes = remove_indexes.size();
1429dba64beSDimitry Andric         if (num_remove_indexes) {
1439dba64beSDimitry Andric           // Sort and then erase in reverse so indexes are always valid
1449dba64beSDimitry Andric           llvm::sort(remove_indexes.begin(), remove_indexes.end());
1459dba64beSDimitry Andric           for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
1469dba64beSDimitry Andric             m_current_value.Remove(j);
1479dba64beSDimitry Andric           }
1489dba64beSDimitry Andric         }
1499dba64beSDimitry Andric         NotifyValueChanged();
1509dba64beSDimitry Andric       } else {
1519dba64beSDimitry Andric         error.SetErrorStringWithFormat(
1529dba64beSDimitry Andric             "invalid array index '%s', aborting remove operation",
1539dba64beSDimitry Andric             args.GetArgumentAtIndex(i));
1549dba64beSDimitry Andric       }
1559dba64beSDimitry Andric     } else {
1569dba64beSDimitry Andric       error.SetErrorString("remove operation takes one or more array index");
1579dba64beSDimitry Andric     }
1589dba64beSDimitry Andric     break;
1599dba64beSDimitry Andric 
1609dba64beSDimitry Andric   case eVarSetOperationInvalid:
1619dba64beSDimitry Andric     error = OptionValue::SetValueFromString(value, op);
1629dba64beSDimitry Andric     break;
1639dba64beSDimitry Andric   }
1649dba64beSDimitry Andric   return error;
1659dba64beSDimitry Andric }
1669dba64beSDimitry Andric 
1679dba64beSDimitry Andric lldb::OptionValueSP OptionValueFileSpecList::DeepCopy() const {
1689dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> lock(m_mutex);
1699dba64beSDimitry Andric   return OptionValueSP(new OptionValueFileSpecList(m_current_value));
1709dba64beSDimitry Andric }
171