Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/CommandCompletions.cpp b/source/Interpreter/CommandCompletions.cpp
new file mode 100644
index 0000000..a299ffb
--- /dev/null
+++ b/source/Interpreter/CommandCompletions.cpp
@@ -0,0 +1,414 @@
+//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+
+using namespace lldb_private;
+
+CommandCompletions::CommonCompletionElement
+CommandCompletions::g_common_completions[] =
+{
+    {eCustomCompletion,     NULL},
+    {eSourceFileCompletion, CommandCompletions::SourceFiles},
+    {eDiskFileCompletion,   NULL},
+    {eSymbolCompletion,     CommandCompletions::Symbols},
+    {eModuleCompletion,     CommandCompletions::Modules},
+    {eNoCompletion,         NULL}      // This one has to be last in the list.
+};
+
+bool
+CommandCompletions::InvokeCommonCompletionCallbacks (uint32_t completion_mask,
+                                                const char *completion_str,
+                                                int match_start_point,
+                                                int max_return_elements,
+                                                lldb_private::CommandInterpreter *interpreter,
+                                                SearchFilter *searcher,
+                                                lldb_private::StringList &matches)
+{
+    bool handled = false;
+
+    if (completion_mask & eCustomCompletion)
+        return false;
+
+    for (int i = 0; ; i++)
+    {
+        if (g_common_completions[i].type == eNoCompletion)
+            break;
+         else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
+                   && g_common_completions[i].callback != NULL)
+         {
+            handled = true;
+            g_common_completions[i].callback (completion_str,
+                                              match_start_point,
+                                              max_return_elements,
+                                              interpreter,
+                                              searcher,
+                                              matches);
+        }
+    }
+    return handled;
+}
+
+int
+CommandCompletions::SourceFiles (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    // Find some way to switch "include support files..."
+    SourceFileCompleter completer (false, partial_file_name, match_start_point, max_return_elements, interpreter,
+                                   matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+int
+CommandCompletions::Modules (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    ModuleCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+int
+CommandCompletions::Symbols (const char *partial_file_name,
+                    int match_start_point,
+                    int max_return_elements,
+                    lldb_private::CommandInterpreter *interpreter,
+                    SearchFilter *searcher,
+                    lldb_private::StringList &matches)
+{
+    SymbolCompleter completer(partial_file_name, match_start_point, max_return_elements, interpreter, matches);
+
+    if (searcher == NULL)
+    {
+        lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
+        SearchFilter null_searcher (target_sp);
+        completer.DoCompletion (&null_searcher);
+    }
+    else
+    {
+        completer.DoCompletion (searcher);
+    }
+    return matches.GetSize();
+}
+
+CommandCompletions::Completer::Completer (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    m_completion_str (completion_str),
+    m_match_start_point (match_start_point),
+    m_max_return_elements (max_return_elements),
+    m_interpreter (interpreter),
+    m_matches (matches)
+{
+}
+
+CommandCompletions::Completer::~Completer ()
+{
+
+}
+
+//----------------------------------------------------------------------
+// SourceFileCompleter
+//----------------------------------------------------------------------
+
+CommandCompletions::SourceFileCompleter::SourceFileCompleter (
+    bool include_support_files,
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches),
+    m_include_support_files (include_support_files),
+    m_matching_files()
+{
+    FileSpec partial_spec (m_completion_str.c_str());
+    m_file_name = partial_spec.GetFilename().GetCString();
+    m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::SourceFileCompleter::GetDepth()
+{
+    return eDepthCompUnit;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SourceFileCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    if (context.comp_unit != NULL)
+    {
+        if (m_include_support_files)
+        {
+            FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
+            for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
+            {
+                const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
+                const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
+                const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
+                bool match = false;
+                if (m_file_name && sfile_file_name
+                    && strstr (sfile_file_name, m_file_name) == sfile_file_name)
+                    match = true;
+                if (match && m_dir_name && sfile_dir_name
+                    && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
+                    match = false;
+
+                if (match)
+                {
+                    m_matching_files.AppendIfUnique(sfile_spec);
+                }
+            }
+
+        }
+        else
+        {
+            const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
+            const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
+
+            bool match = false;
+            if (m_file_name && cur_file_name
+                && strstr (cur_file_name, m_file_name) == cur_file_name)
+                match = true;
+
+            if (match && m_dir_name && cur_dir_name
+                && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+                match = false;
+
+            if (match)
+            {
+                m_matching_files.AppendIfUnique(context.comp_unit);
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    // Now convert the filelist to completions:
+    for (size_t i = 0; i < m_matching_files.GetSize(); i++)
+    {
+        m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
+    }
+    return m_matches.GetSize();
+
+}
+
+//----------------------------------------------------------------------
+// SymbolCompleter
+//----------------------------------------------------------------------
+
+static bool
+regex_chars (const char comp)
+{
+    if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
+        return true;
+    else
+        return false;
+}
+CommandCompletions::SymbolCompleter::SymbolCompleter (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+    std::string regex_str ("^");
+    regex_str.append(completion_str);
+    regex_str.append(".*");
+    std::string::iterator pos;
+
+    pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
+    while (pos < regex_str.end()) {
+        pos = regex_str.insert(pos, '\\');
+        pos += 2;
+        pos = find_if(pos, regex_str.end(), regex_chars);
+    }
+    m_regex.Compile(regex_str.c_str());
+}
+
+Searcher::Depth
+CommandCompletions::SymbolCompleter::GetDepth()
+{
+    return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::SymbolCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    SymbolContextList func_list;
+    SymbolContextList sym_list;
+
+    if (context.module_sp != NULL)
+    {
+        if (context.module_sp)
+        {
+            context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list);
+            context.module_sp->FindFunctions (m_regex, true, func_list);
+        }
+
+        SymbolContext sc;
+        // Now add the functions & symbols to the list - only add if unique:
+        for (int i = 0; i < func_list.GetSize(); i++)
+        {
+            if (func_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.function)
+                {
+                    m_match_set.insert (sc.function->GetMangled().GetDemangledName());
+                }
+            }
+        }
+
+        for (int i = 0; i < sym_list.GetSize(); i++)
+        {
+            if (sym_list.GetContextAtIndex(i, sc))
+            {
+                if (sc.symbol && sc.symbol->GetAddressRangePtr())
+                {
+                    m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
+                }
+            }
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
+    for (pos = m_match_set.begin(); pos != end; pos++)
+        m_matches.AppendString((*pos).GetCString());
+
+    return m_matches.GetSize();
+}
+
+//----------------------------------------------------------------------
+// ModuleCompleter
+//----------------------------------------------------------------------
+CommandCompletions::ModuleCompleter::ModuleCompleter (
+    const char *completion_str,
+    int match_start_point,
+    int max_return_elements,
+    CommandInterpreter *interpreter,
+    StringList &matches
+) :
+    CommandCompletions::Completer (completion_str, match_start_point, max_return_elements, interpreter, matches)
+{
+    FileSpec partial_spec (m_completion_str.c_str());
+    m_file_name = partial_spec.GetFilename().GetCString();
+    m_dir_name = partial_spec.GetDirectory().GetCString();
+}
+
+Searcher::Depth
+CommandCompletions::ModuleCompleter::GetDepth()
+{
+    return eDepthModule;
+}
+
+Searcher::CallbackReturn
+CommandCompletions::ModuleCompleter::SearchCallback (
+    SearchFilter &filter,
+    SymbolContext &context,
+    Address *addr,
+    bool complete
+)
+{
+    if (context.module_sp != NULL)
+    {
+        const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
+        const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
+
+        bool match = false;
+        if (m_file_name && cur_file_name
+            && strstr (cur_file_name, m_file_name) == cur_file_name)
+            match = true;
+
+        if (match && m_dir_name && cur_dir_name
+            && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
+            match = false;
+
+        if (match)
+        {
+            m_matches.AppendString (cur_file_name);
+        }
+    }
+    return Searcher::eCallbackReturnContinue;
+}
+
+size_t
+CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
+{
+    filter->Search (*this);
+    return m_matches.GetSize();
+}
+
+
+