Add a new breakpoint type "break by source regular expression".
Fix the RegularExpression class so it has a real copy constructor.
Fix the breakpoint setting with multiple shared libraries so it makes
  one breakpoint not one per shared library.
Add SBFileSpecList, to be used to expose the above to the SB interface (not done yet.)


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@140225 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index 61d0a99..8a15423 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -136,6 +136,18 @@
     return num_completions;
 }
 
+int
+SBCommandInterpreter::HandleCompletion (const char *current_line,
+                  uint32_t cursor_pos,
+                  int match_start_point,
+                  int max_return_elements,
+                  lldb::SBStringList &matches)
+{
+    const char *cursor = current_line + cursor_pos;
+    const char *last_char = current_line + strlen (current_line);
+    return HandleCompletion (current_line, cursor, last_char, match_start_point, max_return_elements, matches);
+}
+
 bool
 SBCommandInterpreter::HasCommands ()
 {
diff --git a/source/API/SBFileSpecList.cpp b/source/API/SBFileSpecList.cpp
new file mode 100644
index 0000000..3abb4fc
--- /dev/null
+++ b/source/API/SBFileSpecList.cpp
@@ -0,0 +1,139 @@
+//===-- SBFileSpecListList.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <limits.h>
+
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/API/SBFileSpecList.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/FileSpec.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+SBFileSpecList::SBFileSpecList () :
+    m_opaque_ap(new FileSpecList())
+{
+}
+
+SBFileSpecList::SBFileSpecList (const SBFileSpecList &rhs) :
+    m_opaque_ap()
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    if (rhs.m_opaque_ap.get())
+        m_opaque_ap.reset (new FileSpecList (*(rhs.get())));
+
+    if (log)
+    {
+        log->Printf ("SBFileSpecList::SBFileSpecList (const SBFileSpecList rhs.ap=%p) => SBFileSpecList(%p): %s",
+                     rhs.m_opaque_ap.get(), m_opaque_ap.get());
+    }
+}
+
+SBFileSpecList::~SBFileSpecList ()
+{
+}
+
+const SBFileSpecList &
+SBFileSpecList::operator = (const SBFileSpecList &rhs)
+{
+    if (this != &rhs)
+    {
+        m_opaque_ap.reset (new lldb_private::FileSpecList(*(rhs.get())));
+    }
+    return *this;
+}
+
+uint32_t
+SBFileSpecList::GetSize () const
+{
+    return m_opaque_ap->GetSize();
+}
+
+void
+SBFileSpecList::Append (const SBFileSpec &sb_file)
+{
+    m_opaque_ap->Append (sb_file.ref());
+}
+
+bool
+SBFileSpecList::AppendIfUnique (const SBFileSpec &sb_file)
+{
+    return m_opaque_ap->AppendIfUnique (sb_file.ref());
+}
+
+void
+SBFileSpecList::Clear()
+{
+    m_opaque_ap->Clear();
+}
+
+uint32_t
+SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file)
+{
+    return m_opaque_ap->FindFileIndex (idx, sb_file.ref());
+}
+
+const SBFileSpec
+SBFileSpecList::GetFileSpecAtIndex (uint32_t idx) const
+{
+    SBFileSpec new_spec;
+    new_spec.SetFileSpec(m_opaque_ap->GetFileSpecAtIndex(idx));
+    return new_spec;
+}
+
+const lldb_private::FileSpecList *
+SBFileSpecList::operator->() const
+{
+    return m_opaque_ap.get();
+}
+
+const lldb_private::FileSpecList *
+SBFileSpecList::get() const
+{
+    return m_opaque_ap.get();
+}
+
+
+const lldb_private::FileSpecList &
+SBFileSpecList::operator*() const
+{
+    return *m_opaque_ap.get();
+}
+
+const lldb_private::FileSpecList &
+SBFileSpecList::ref() const
+{
+    return *m_opaque_ap.get();
+}
+
+bool
+SBFileSpecList::GetDescription (SBStream &description) const
+{
+    if (m_opaque_ap.get())
+    {
+        uint32_t num_files = m_opaque_ap->GetSize();
+        description.Printf ("%d files: ", num_files);
+        for (uint32_t i = 0; i < num_files; i++)
+        {
+            char path[PATH_MAX];
+            if (m_opaque_ap->GetFileSpecAtIndex(i).GetPath(path, sizeof(path)))
+                description.Printf ("\n    %s", path);
+        }
+    }
+    else
+        description.Printf ("No value");
+    
+    return true;
+}
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 5f3716c..4e0dac4 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -580,8 +580,9 @@
         Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
         if (module_name && module_name[0])
         {
-            FileSpec module_file_spec(module_name, false);
-            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
+            FileSpecList module_spec_list;
+            module_spec_list.Append (FileSpec (module_name, false));
+            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
         }
         else
         {
@@ -611,9 +612,10 @@
         
         if (module_name && module_name[0])
         {
-            FileSpec module_file_spec(module_name, false);
+            FileSpecList module_spec_list;
+            module_spec_list.Append (FileSpec (module_name, false));
             
-            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false);
+            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, regexp, false);
         }
         else
         {
@@ -652,6 +654,42 @@
     return sb_bp;
 }
 
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name)
+{
+    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+    SBBreakpoint sb_bp;
+    if (m_opaque_sp.get() && source_regex && source_regex[0])
+    {
+        Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex());
+        RegularExpression regexp(source_regex);
+        
+        if (module_name && module_name[0])
+        {
+            FileSpecList module_spec_list;
+            module_spec_list.Append (FileSpec (module_name, false));
+            
+            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, source_file.ref(), regexp, false);
+        }
+        else
+        {
+            *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, source_file.ref(), regexp, false);
+        }
+    }
+
+    if (log)
+    {
+        char path[PATH_MAX];
+        source_file->GetPath (path, sizeof(path));
+        log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)", 
+                     m_opaque_sp.get(), source_regex, path, sb_bp.get());
+    }
+
+    return sb_bp;
+}
+
+
 SBBreakpoint
 SBTarget::FindBreakpointByID (break_id_t bp_id)
 {