167cc0636SGreg Clayton //===-- OptionValuePathMappings.cpp -----------------------------*- C++ -*-===//
267cc0636SGreg Clayton //
367cc0636SGreg Clayton //                     The LLVM Compiler Infrastructure
467cc0636SGreg Clayton //
567cc0636SGreg Clayton // This file is distributed under the University of Illinois Open Source
667cc0636SGreg Clayton // License. See LICENSE.TXT for details.
767cc0636SGreg Clayton //
867cc0636SGreg Clayton //===----------------------------------------------------------------------===//
967cc0636SGreg Clayton 
1067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValuePathMappings.h"
1167cc0636SGreg Clayton 
1267cc0636SGreg Clayton // C Includes
1367cc0636SGreg Clayton // C++ Includes
1467cc0636SGreg Clayton // Other libraries and framework includes
1567cc0636SGreg Clayton // Project includes
1667cc0636SGreg Clayton #include "lldb/Core/Stream.h"
1767cc0636SGreg Clayton #include "lldb/Interpreter/Args.h"
1867cc0636SGreg Clayton 
1967cc0636SGreg Clayton using namespace lldb;
2067cc0636SGreg Clayton using namespace lldb_private;
2167cc0636SGreg Clayton 
2267cc0636SGreg Clayton void
2367cc0636SGreg Clayton OptionValuePathMappings::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
2467cc0636SGreg Clayton {
2567cc0636SGreg Clayton     if (dump_mask & eDumpOptionType)
2667cc0636SGreg Clayton         strm.Printf ("(%s)", GetTypeAsCString ());
2767cc0636SGreg Clayton     if (dump_mask & eDumpOptionValue)
2867cc0636SGreg Clayton     {
2967cc0636SGreg Clayton         if (dump_mask & eDumpOptionType)
3067cc0636SGreg Clayton             strm.Printf (" =%s", (m_path_mappings.GetSize() > 0) ? "\n" : "");
3167cc0636SGreg Clayton         m_path_mappings.Dump(&strm);
3267cc0636SGreg Clayton     }
3367cc0636SGreg Clayton }
3467cc0636SGreg Clayton 
3567cc0636SGreg Clayton Error
3667cc0636SGreg Clayton OptionValuePathMappings::SetValueFromCString (const char *value, VarSetOperationType op)
3767cc0636SGreg Clayton {
3867cc0636SGreg Clayton     Error error;
3967cc0636SGreg Clayton     Args args(value);
4067cc0636SGreg Clayton     const size_t argc = args.GetArgumentCount();
4167cc0636SGreg Clayton 
4267cc0636SGreg Clayton     switch (op)
4367cc0636SGreg Clayton     {
4467cc0636SGreg Clayton         case eVarSetOperationClear:
4567cc0636SGreg Clayton             Clear ();
4667cc0636SGreg Clayton             break;
4767cc0636SGreg Clayton 
4867cc0636SGreg Clayton         case eVarSetOperationReplace:
4967cc0636SGreg Clayton             // Must be at least one index + 1 pair of paths, and the pair count must be even
5067cc0636SGreg Clayton             if (argc >= 3 && (((argc - 1) & 1) == 0))
5167cc0636SGreg Clayton             {
5267cc0636SGreg Clayton                 uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
5367cc0636SGreg Clayton                 const uint32_t count = m_path_mappings.GetSize();
5467cc0636SGreg Clayton                 if (idx > count)
5567cc0636SGreg Clayton                 {
5667cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
5767cc0636SGreg Clayton                 }
5867cc0636SGreg Clayton                 else
5967cc0636SGreg Clayton                 {
6067cc0636SGreg Clayton                     for (size_t i=1; i<argc; i += 2, ++idx)
6167cc0636SGreg Clayton                     {
6267cc0636SGreg Clayton                         ConstString a(args.GetArgumentAtIndex(i));
6367cc0636SGreg Clayton                         ConstString b(args.GetArgumentAtIndex(i+1));
6467cc0636SGreg Clayton                         if (!m_path_mappings.Replace (a, b, idx, m_notify_changes))
6567cc0636SGreg Clayton                             m_path_mappings.Append(a, b, m_notify_changes);
6667cc0636SGreg Clayton                     }
6767cc0636SGreg Clayton                 }
6867cc0636SGreg Clayton             }
6967cc0636SGreg Clayton             else
7067cc0636SGreg Clayton             {
7167cc0636SGreg Clayton                 error.SetErrorString("replace operation takes an array index followed by one or more path pairs");
7267cc0636SGreg Clayton             }
7367cc0636SGreg Clayton             break;
7467cc0636SGreg Clayton 
7567cc0636SGreg Clayton 
7667cc0636SGreg Clayton 
7767cc0636SGreg Clayton         case eVarSetOperationAssign:
7867cc0636SGreg Clayton             if (argc < 2 || (argc & 1))
7967cc0636SGreg Clayton             {
8067cc0636SGreg Clayton                 error.SetErrorString("assign operation takes one or more path pairs");
8167cc0636SGreg Clayton                 break;
8267cc0636SGreg Clayton             }
8367cc0636SGreg Clayton             m_path_mappings.Clear(m_notify_changes);
8467cc0636SGreg Clayton             // Fall through to append case
8567cc0636SGreg Clayton         case eVarSetOperationAppend:
8667cc0636SGreg Clayton             if (argc < 2 || (argc & 1))
8767cc0636SGreg Clayton             {
8867cc0636SGreg Clayton                 error.SetErrorString("append operation takes one or more path pairs");
8967cc0636SGreg Clayton                 break;
9067cc0636SGreg Clayton             }
9167cc0636SGreg Clayton             else
9267cc0636SGreg Clayton             {
9367cc0636SGreg Clayton                 for (size_t i=0; i<argc; i += 2)
9467cc0636SGreg Clayton                 {
9567cc0636SGreg Clayton                     ConstString a(args.GetArgumentAtIndex(i));
9667cc0636SGreg Clayton                     ConstString b(args.GetArgumentAtIndex(i+1));
9767cc0636SGreg Clayton                     m_path_mappings.Append(a, b, m_notify_changes);
9867cc0636SGreg Clayton                     m_value_was_set = true;
9967cc0636SGreg Clayton                 }
10067cc0636SGreg Clayton             }
10167cc0636SGreg Clayton             break;
10267cc0636SGreg Clayton 
10367cc0636SGreg Clayton         case eVarSetOperationInsertBefore:
10467cc0636SGreg Clayton         case eVarSetOperationInsertAfter:
10567cc0636SGreg Clayton             // Must be at least one index + 1 pair of paths, and the pair count must be even
10667cc0636SGreg Clayton             if (argc >= 3 && (((argc - 1) & 1) == 0))
10767cc0636SGreg Clayton             {
10867cc0636SGreg Clayton                 uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
10967cc0636SGreg Clayton                 const uint32_t count = m_path_mappings.GetSize();
11067cc0636SGreg Clayton                 if (idx > count)
11167cc0636SGreg Clayton                 {
11267cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
11367cc0636SGreg Clayton                 }
11467cc0636SGreg Clayton                 else
11567cc0636SGreg Clayton                 {
11667cc0636SGreg Clayton                     if (op == eVarSetOperationInsertAfter)
11767cc0636SGreg Clayton                         ++idx;
11867cc0636SGreg Clayton                     for (size_t i=1; i<argc; i += 2, ++idx)
11967cc0636SGreg Clayton                     {
12067cc0636SGreg Clayton                         ConstString a(args.GetArgumentAtIndex(i));
12167cc0636SGreg Clayton                         ConstString b(args.GetArgumentAtIndex(i+1));
12267cc0636SGreg Clayton                         m_path_mappings.Insert (a, b, idx, m_notify_changes);
12367cc0636SGreg Clayton                     }
12467cc0636SGreg Clayton                 }
12567cc0636SGreg Clayton             }
12667cc0636SGreg Clayton             else
12767cc0636SGreg Clayton             {
12867cc0636SGreg Clayton                 error.SetErrorString("insert operation takes an array index followed by one or more path pairs");
12967cc0636SGreg Clayton             }
13067cc0636SGreg Clayton             break;
13167cc0636SGreg Clayton 
13267cc0636SGreg Clayton         case eVarSetOperationRemove:
13367cc0636SGreg Clayton             if (argc > 0)
13467cc0636SGreg Clayton             {
13567cc0636SGreg Clayton                 std::vector<int> remove_indexes;
13667cc0636SGreg Clayton                 bool all_indexes_valid = true;
13767cc0636SGreg Clayton                 size_t i;
13867cc0636SGreg Clayton                 for (i=0; all_indexes_valid && i<argc; ++i)
13967cc0636SGreg Clayton                 {
14067cc0636SGreg Clayton                     const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
14167cc0636SGreg Clayton                     if (idx == INT32_MAX)
14267cc0636SGreg Clayton                         all_indexes_valid = false;
14367cc0636SGreg Clayton                     else
14467cc0636SGreg Clayton                         remove_indexes.push_back(idx);
14567cc0636SGreg Clayton                 }
14667cc0636SGreg Clayton 
14767cc0636SGreg Clayton                 if (all_indexes_valid)
14867cc0636SGreg Clayton                 {
14967cc0636SGreg Clayton                     size_t num_remove_indexes = remove_indexes.size();
15067cc0636SGreg Clayton                     if (num_remove_indexes)
15167cc0636SGreg Clayton                     {
15267cc0636SGreg Clayton                         // Sort and then erase in reverse so indexes are always valid
15367cc0636SGreg Clayton                         std::sort(remove_indexes.begin(), remove_indexes.end());
154*ccd41e55SJason Molenda                         for (int j=num_remove_indexes-1; j<num_remove_indexes; ++j)
15567cc0636SGreg Clayton                         {
156*ccd41e55SJason Molenda                             m_path_mappings.Remove (j, m_notify_changes);
15767cc0636SGreg Clayton                         }
15867cc0636SGreg Clayton                     }
15967cc0636SGreg Clayton                 }
16067cc0636SGreg Clayton                 else
16167cc0636SGreg Clayton                 {
16267cc0636SGreg Clayton                     error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
16367cc0636SGreg Clayton                 }
16467cc0636SGreg Clayton             }
16567cc0636SGreg Clayton             else
16667cc0636SGreg Clayton             {
16767cc0636SGreg Clayton                 error.SetErrorString("remove operation takes one or more array index");
16867cc0636SGreg Clayton             }
16967cc0636SGreg Clayton             break;
17067cc0636SGreg Clayton 
17167cc0636SGreg Clayton         case eVarSetOperationInvalid:
17267cc0636SGreg Clayton             error = OptionValue::SetValueFromCString (value, op);
17367cc0636SGreg Clayton             break;
17467cc0636SGreg Clayton     }
17567cc0636SGreg Clayton     return error;
17667cc0636SGreg Clayton 
17767cc0636SGreg Clayton     m_value_was_set = true;
17867cc0636SGreg Clayton     return Error();
17967cc0636SGreg Clayton }
18067cc0636SGreg Clayton 
18167cc0636SGreg Clayton lldb::OptionValueSP
18267cc0636SGreg Clayton OptionValuePathMappings::DeepCopy () const
18367cc0636SGreg Clayton {
18467cc0636SGreg Clayton     return OptionValueSP(new OptionValuePathMappings(*this));
18567cc0636SGreg Clayton }
186