Initial checkin of lldb code from internal Apple repo.

llvm-svn: 105619
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp
new file mode 100644
index 0000000..895f1b1
--- /dev/null
+++ b/lldb/source/Breakpoint/BreakpointIDList.cpp
@@ -0,0 +1,348 @@
+//===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Breakpoint/BreakpointIDList.h"
+
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// class BreakpointIDList
+//----------------------------------------------------------------------
+
+BreakpointIDList::BreakpointIDList () :
+m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID)
+{
+}
+
+BreakpointIDList::~BreakpointIDList ()
+{
+}
+
+int
+BreakpointIDList::Size()
+{
+    return m_breakpoint_ids.size();
+}
+
+BreakpointID &
+BreakpointIDList::GetBreakpointIDAtIndex (int index)
+{
+    if (index < m_breakpoint_ids.size())
+        return m_breakpoint_ids[index];
+    else
+        return m_invalid_id;
+}
+
+bool
+BreakpointIDList::RemoveBreakpointIDAtIndex (int index)
+{
+    bool success = false;
+    if (index < m_breakpoint_ids.size())
+    {
+        BreakpointIDArray::iterator pos;
+        int i;
+
+        for (pos = m_breakpoint_ids.begin(), i = 0; i != index && pos != m_breakpoint_ids.end(); ++pos, ++i);
+        assert (i == index);
+        if (pos != m_breakpoint_ids.end())
+        {
+            m_breakpoint_ids.erase (pos);
+            success = true;
+        }
+    }
+    return success;
+}
+
+void
+BreakpointIDList::Clear()
+{
+    m_breakpoint_ids.clear ();
+}
+
+bool
+BreakpointIDList::AddBreakpointID (BreakpointID bp_id)
+{
+    m_breakpoint_ids.push_back (bp_id);
+
+    return true;  // We don't do any verification in this function, so always return true.
+}
+
+bool
+BreakpointIDList::AddBreakpointID (const char *bp_id_str)
+{
+    BreakpointID temp_bp_id;
+    break_id_t bp_id;
+    break_id_t loc_id;
+
+    bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id);
+
+    if (success)
+    {
+        temp_bp_id.SetID (bp_id, loc_id);
+        m_breakpoint_ids.push_back (temp_bp_id);
+    }
+
+    return success;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, int *position)
+{
+    bool success = false;
+    BreakpointIDArray::iterator tmp_pos;
+
+    for (int i = 0; i <  m_breakpoint_ids.size(); ++i)
+    {
+        BreakpointID tmp_id = m_breakpoint_ids[i];
+        if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID()
+            && tmp_id.GetLocationID() == bp_id.GetLocationID())
+        {
+            success = true;
+            *position = i;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+BreakpointIDList::FindBreakpointID (const char *bp_id_str, int *position)
+{
+    BreakpointID temp_bp_id;
+    break_id_t bp_id;
+    break_id_t loc_id;
+
+    if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id))
+    {
+        temp_bp_id.SetID (bp_id, loc_id);
+        return FindBreakpointID (temp_bp_id, position);
+    }
+    else
+        return false;
+}
+
+void
+BreakpointIDList::InsertStringArray (const char **string_array, int array_size, CommandReturnObject &result)
+{
+    if (string_array == NULL)
+        return;
+
+    for (int i = 0; i < array_size; ++i)
+    {
+        break_id_t bp_id;
+        break_id_t loc_id;
+
+        if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id))
+        {
+            if (bp_id != LLDB_INVALID_BREAK_ID)
+            {
+                BreakpointID temp_bp_id(bp_id, loc_id);
+                m_breakpoint_ids.push_back (temp_bp_id);
+            }
+            else
+            {
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+        }
+    }
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+}
+
+
+//  This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into
+//  an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers.
+//  Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS.  If any
+//  ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to
+//  all the current breakpoints and locations in the range are added to NEW_ARGS.  When this function is done,
+//  NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range.
+
+void
+BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result,
+                                          Args &new_args)
+{
+    char *range_start;
+    const char *range_end;
+    const char *current_arg;
+    int num_old_args = old_args.GetArgumentCount();
+
+    for (int i = 0; i < num_old_args; ++i)
+    {
+        bool is_range = false;
+        current_arg = old_args.GetArgumentAtIndex (i);
+
+        int range_start_len = 0;
+        int range_end_pos = 0;
+        if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos))
+        {
+            is_range = true;
+            range_start = (char *) malloc (range_start_len + 1);
+            strncpy (range_start, current_arg, range_start_len);
+            range_start[range_start_len] = '\0';
+            range_end = current_arg + range_end_pos;
+        }
+        else if ((i + 2 < num_old_args)
+                 && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1))
+                 && BreakpointID::IsValidIDExpression (current_arg)
+                 && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2)))
+        {
+            range_start = (char *) current_arg;
+            range_end = old_args.GetArgumentAtIndex (i+2);
+            is_range = true;
+            i = i+2;
+        }
+
+        if (is_range)
+        {
+            break_id_t start_bp_id;
+            break_id_t end_bp_id;
+            break_id_t start_loc_id;
+            break_id_t end_loc_id;
+
+            BreakpointID::ParseCanonicalReference (range_start, &start_bp_id, &start_loc_id);
+            BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id);
+
+            if ((start_bp_id == LLDB_INVALID_BREAK_ID)
+                || (! target->GetBreakpointByID (start_bp_id)))
+            {
+                new_args.Clear();
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+
+            if ((end_bp_id == LLDB_INVALID_BREAK_ID)
+                || (! target->GetBreakpointByID (end_bp_id)))
+            {
+                new_args.Clear();
+                result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end);
+                result.SetStatus (eReturnStatusFailed);
+                return;
+            }
+
+            // We have valid range starting & ending breakpoint IDs.  Go through all the breakpoints in the
+            // target and find all the breakpoints that fit into this range, and add them to new_args.
+
+            const BreakpointList& breakpoints = target->GetBreakpointList();
+            size_t num_breakpoints = breakpoints.GetSize();
+            for (int j = 0; j < num_breakpoints; ++j)
+            {
+                Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get();
+                break_id_t cur_bp_id = breakpoint->GetID();
+
+                if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))
+                    continue;
+
+                size_t num_locations = breakpoint->GetNumLocations();
+
+                if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID))
+                {
+                    for (int k = 0; k < num_locations; ++k)
+                    {
+                        BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+                        if (bp_loc->GetID() >= start_loc_id)
+                        {
+                            StreamString canonical_id_str;
+                            BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+                            new_args.AppendArgument (canonical_id_str.GetData());
+                        }
+                    }
+                }
+                else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID))
+                {
+                    for (int k = 0; k < num_locations; ++k)
+                    {
+                        BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get();
+                        if (bp_loc->GetID() <= end_loc_id)
+                        {
+                            StreamString canonical_id_str;
+                            BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID());
+                            new_args.AppendArgument (canonical_id_str.GetData());
+                        }
+                    }
+                }
+                else
+                {
+                    StreamString canonical_id_str;
+                    BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID);
+                    new_args.AppendArgument (canonical_id_str.GetData());
+                }
+            }
+        }
+        else  // else is_range was false
+        {
+            new_args.AppendArgument (current_arg);
+        }
+    }
+
+    result.SetStatus (eReturnStatusSuccessFinishNoResult);
+    return;
+}
+
+//bool
+//BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, const char **range_start,
+//                                                     const **range_end)
+bool
+BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, int *range_start_len, int *range_end_pos)
+{
+    bool is_range_expression = false;
+    std::string arg_str = in_string;
+    std::string::size_type idx;
+    std::string::size_type start_pos = 0;
+
+    //*range_start = NULL;
+    //*range_end = NULL;
+    *range_start_len = 0;
+    *range_end_pos = 0;
+
+    int specifiers_size = 0;
+    for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i)
+        ++specifiers_size;
+
+    for (int i = 0; i < specifiers_size && !is_range_expression; ++i)
+    {
+        const char *specifier_str = BreakpointID::g_range_specifiers[i];
+        int len = strlen (specifier_str);
+        idx = arg_str.find (BreakpointID::g_range_specifiers[i]);
+        if (idx != std::string::npos)
+        {
+            *range_start_len = idx - start_pos;
+            std::string start_str = arg_str.substr (start_pos, *range_start_len);
+            if (idx + len < arg_str.length())
+            {
+                *range_end_pos = idx + len;
+                std::string end_str = arg_str.substr (*range_end_pos);
+                if (BreakpointID::IsValidIDExpression (start_str.c_str())
+                    && BreakpointID::IsValidIDExpression (end_str.c_str()))
+                {
+                    is_range_expression = true;
+                    //*range_start = start_str;
+                    //*range_end = end_str;
+                }
+            }
+        }
+    }
+
+    if (!is_range_expression)
+    {
+        *range_start_len = 0;
+        *range_end_pos = 0;
+    }
+
+    return is_range_expression;
+}