diff options
Diffstat (limited to 'lldb/source/Interpreter/CommandCompletions.cpp')
-rw-r--r-- | lldb/source/Interpreter/CommandCompletions.cpp | 414 |
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(); +} + + + |