summaryrefslogtreecommitdiffstats
path: root/lldb/source/Interpreter/CommandCompletions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Interpreter/CommandCompletions.cpp')
-rw-r--r--lldb/source/Interpreter/CommandCompletions.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/lldb/source/Interpreter/CommandCompletions.cpp b/lldb/source/Interpreter/CommandCompletions.cpp
new file mode 100644
index 00000000000..a299ffb098f
--- /dev/null
+++ b/lldb/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();
+}
+
+
+
OpenPOWER on IntegriCloud