forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			777 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			777 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- CommandCompletions.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/lldb-python.h"
 | 
						|
 | 
						|
// C Includes
 | 
						|
#include <sys/stat.h>
 | 
						|
#if defined(__APPLE__) || defined(__linux__)
 | 
						|
#include <pwd.h>
 | 
						|
#endif
 | 
						|
 | 
						|
// C++ Includes
 | 
						|
// Other libraries and framework includes
 | 
						|
// Project includes
 | 
						|
#include "lldb/Host/FileSpec.h"
 | 
						|
#include "lldb/Core/FileSpecList.h"
 | 
						|
#include "lldb/Core/PluginManager.h"
 | 
						|
#include "lldb/Core/Module.h"
 | 
						|
#include "lldb/Interpreter/Args.h"
 | 
						|
#include "lldb/Interpreter/CommandCompletions.h"
 | 
						|
#include "lldb/Interpreter/CommandInterpreter.h"
 | 
						|
#include "lldb/Symbol/CompileUnit.h"
 | 
						|
#include "lldb/Symbol/Variable.h"
 | 
						|
#include "lldb/Target/Target.h"
 | 
						|
#include "lldb/Utility/CleanUp.h"
 | 
						|
 | 
						|
using namespace lldb_private;
 | 
						|
 | 
						|
CommandCompletions::CommonCompletionElement
 | 
						|
CommandCompletions::g_common_completions[] =
 | 
						|
{
 | 
						|
    {eCustomCompletion,          NULL},
 | 
						|
    {eSourceFileCompletion,      CommandCompletions::SourceFiles},
 | 
						|
    {eDiskFileCompletion,        CommandCompletions::DiskFiles},
 | 
						|
    {eDiskDirectoryCompletion,   CommandCompletions::DiskDirectories},
 | 
						|
    {eSymbolCompletion,          CommandCompletions::Symbols},
 | 
						|
    {eModuleCompletion,          CommandCompletions::Modules},
 | 
						|
    {eSettingsNameCompletion,    CommandCompletions::SettingsNames},
 | 
						|
    {ePlatformPluginCompletion,  CommandCompletions::PlatformPluginNames},
 | 
						|
    {eArchitectureCompletion,    CommandCompletions::ArchitectureNames},
 | 
						|
    {eVariablePathCompletion,    CommandCompletions::VariablePath},
 | 
						|
    {eNoCompletion,              NULL}      // This one has to be last in the list.
 | 
						|
};
 | 
						|
 | 
						|
bool
 | 
						|
CommandCompletions::InvokeCommonCompletionCallbacks 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    uint32_t completion_mask,
 | 
						|
    const char *completion_str,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    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 (interpreter,
 | 
						|
                                              completion_str,
 | 
						|
                                              match_start_point,
 | 
						|
                                              max_return_elements,
 | 
						|
                                              searcher,
 | 
						|
                                              word_complete,
 | 
						|
                                              matches);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return handled;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::SourceFiles 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *partial_file_name,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    StringList &matches
 | 
						|
)
 | 
						|
{
 | 
						|
    word_complete = true;
 | 
						|
    // Find some way to switch "include support files..."
 | 
						|
    SourceFileCompleter completer (interpreter,
 | 
						|
                                   false, 
 | 
						|
                                   partial_file_name, 
 | 
						|
                                   match_start_point, 
 | 
						|
                                   max_return_elements,
 | 
						|
                                   matches);
 | 
						|
 | 
						|
    if (searcher == NULL)
 | 
						|
    {
 | 
						|
        lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
 | 
						|
        SearchFilter null_searcher (target_sp);
 | 
						|
        completer.DoCompletion (&null_searcher);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        completer.DoCompletion (searcher);
 | 
						|
    }
 | 
						|
    return matches.GetSize();
 | 
						|
}
 | 
						|
 | 
						|
typedef struct DiskFilesOrDirectoriesBaton
 | 
						|
{
 | 
						|
    const char *remainder;
 | 
						|
    char *partial_name_copy;
 | 
						|
    bool only_directories;
 | 
						|
    bool *saw_directory;
 | 
						|
    StringList *matches;
 | 
						|
    char *end_ptr;
 | 
						|
    size_t baselen;
 | 
						|
} DiskFilesOrDirectoriesBaton;
 | 
						|
 | 
						|
FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
 | 
						|
{
 | 
						|
    const char *name = spec.GetFilename().AsCString();
 | 
						|
 | 
						|
    const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
 | 
						|
    char *end_ptr = parameters->end_ptr;
 | 
						|
    char *partial_name_copy = parameters->partial_name_copy;
 | 
						|
    const char *remainder = parameters->remainder;
 | 
						|
 | 
						|
    // Omit ".", ".." and any . files if the match string doesn't start with .
 | 
						|
    if (name[0] == '.')
 | 
						|
    {
 | 
						|
        if (name[1] == '\0')
 | 
						|
            return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
        else if (name[1] == '.' && name[2] == '\0')
 | 
						|
            return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
        else if (remainder[0] != '.')
 | 
						|
            return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
    }
 | 
						|
 | 
						|
    // If we found a directory, we put a "/" at the end of the name.
 | 
						|
 | 
						|
    if (remainder[0] == '\0' || strstr(name, remainder) == name)
 | 
						|
    {
 | 
						|
        if (strlen(name) + parameters->baselen >= PATH_MAX)
 | 
						|
            return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
 | 
						|
        strcpy(end_ptr, name);
 | 
						|
 | 
						|
        bool isa_directory = false;
 | 
						|
        if (file_type == FileSpec::eFileTypeDirectory)
 | 
						|
            isa_directory = true;
 | 
						|
        else if (file_type == FileSpec::eFileTypeSymbolicLink)
 | 
						|
        {
 | 
						|
            struct stat stat_buf;
 | 
						|
            if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
 | 
						|
                isa_directory = true;
 | 
						|
        }
 | 
						|
 | 
						|
        if (isa_directory)
 | 
						|
        {
 | 
						|
            *parameters->saw_directory = true;
 | 
						|
            size_t len = strlen(parameters->partial_name_copy);
 | 
						|
            partial_name_copy[len] = '/';
 | 
						|
            partial_name_copy[len + 1] = '\0';
 | 
						|
        }
 | 
						|
        if (parameters->only_directories && !isa_directory)
 | 
						|
            return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
        parameters->matches->AppendString(partial_name_copy);
 | 
						|
    }
 | 
						|
 | 
						|
    return FileSpec::eEnumerateDirectoryResultNext;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
DiskFilesOrDirectories 
 | 
						|
(
 | 
						|
    const char *partial_file_name,
 | 
						|
    bool only_directories,
 | 
						|
    bool &saw_directory,
 | 
						|
    StringList &matches
 | 
						|
)
 | 
						|
{
 | 
						|
    // I'm going to  use the "glob" function with GLOB_TILDE for user directory expansion.  
 | 
						|
    // If it is not defined on your host system, you'll need to implement it yourself...
 | 
						|
    
 | 
						|
    size_t partial_name_len = strlen(partial_file_name);
 | 
						|
    
 | 
						|
    if (partial_name_len >= PATH_MAX)
 | 
						|
        return matches.GetSize();
 | 
						|
    
 | 
						|
    // This copy of the string will be cut up into the directory part, and the remainder.  end_ptr
 | 
						|
    // below will point to the place of the remainder in this string.  Then when we've resolved the
 | 
						|
    // containing directory, and opened it, we'll read the directory contents and overwrite the
 | 
						|
    // partial_name_copy starting from end_ptr with each of the matches.  Thus we will preserve
 | 
						|
    // the form the user originally typed.
 | 
						|
    
 | 
						|
    char partial_name_copy[PATH_MAX];
 | 
						|
    memcpy(partial_name_copy, partial_file_name, partial_name_len);
 | 
						|
    partial_name_copy[partial_name_len] = '\0';
 | 
						|
    
 | 
						|
    // We'll need to save a copy of the remainder for comparison, which we do here.
 | 
						|
    char remainder[PATH_MAX];
 | 
						|
    
 | 
						|
    // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
 | 
						|
    char *end_ptr;
 | 
						|
    
 | 
						|
    end_ptr = strrchr(partial_name_copy, '/');
 | 
						|
    
 | 
						|
    // This will store the resolved form of the containing directory
 | 
						|
    char containing_part[PATH_MAX];
 | 
						|
    
 | 
						|
    if (end_ptr == NULL)
 | 
						|
    {
 | 
						|
        // There's no directory.  If the thing begins with a "~" then this is a bare
 | 
						|
        // user name.
 | 
						|
        if (*partial_name_copy == '~')
 | 
						|
        {
 | 
						|
            // Nothing here but the user name.  We could just put a slash on the end, 
 | 
						|
            // but for completeness sake we'll resolve the user name and only put a slash
 | 
						|
            // on the end if it exists.
 | 
						|
            char resolved_username[PATH_MAX];
 | 
						|
            size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username, 
 | 
						|
                                                          sizeof (resolved_username));
 | 
						|
                                                          
 | 
						|
           // Not sure how this would happen, a username longer than PATH_MAX?  Still...
 | 
						|
            if (resolved_username_len >= sizeof (resolved_username))
 | 
						|
                return matches.GetSize();
 | 
						|
            else if (resolved_username_len == 0)
 | 
						|
            {
 | 
						|
                // The user name didn't resolve, let's look in the password database for matches.
 | 
						|
                // The user name database contains duplicates, and is not in alphabetical order, so
 | 
						|
                // we'll use a set to manage that for us.
 | 
						|
                FileSpec::ResolvePartialUsername (partial_name_copy, matches);
 | 
						|
                if (matches.GetSize() > 0)
 | 
						|
                    saw_directory = true;
 | 
						|
                return matches.GetSize();
 | 
						|
            } 
 | 
						|
            else
 | 
						|
            {   
 | 
						|
                //The thing exists, put a '/' on the end, and return it...
 | 
						|
                // FIXME: complete user names here:
 | 
						|
                partial_name_copy[partial_name_len] = '/';
 | 
						|
                partial_name_copy[partial_name_len+1] = '\0';
 | 
						|
                matches.AppendString(partial_name_copy);
 | 
						|
                saw_directory = true;
 | 
						|
                return matches.GetSize();
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            // The containing part is the CWD, and the whole string is the remainder.
 | 
						|
            containing_part[0] = '.';
 | 
						|
            containing_part[1] = '\0';
 | 
						|
            strcpy(remainder, partial_name_copy);
 | 
						|
            end_ptr = partial_name_copy;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if (end_ptr == partial_name_copy)
 | 
						|
        {
 | 
						|
            // We're completing a file or directory in the root volume.
 | 
						|
            containing_part[0] = '/';
 | 
						|
            containing_part[1] = '\0';
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            size_t len = end_ptr - partial_name_copy;
 | 
						|
            memcpy(containing_part, partial_name_copy, len);
 | 
						|
            containing_part[len] = '\0';
 | 
						|
        }
 | 
						|
        // Push end_ptr past the final "/" and set remainder.
 | 
						|
        end_ptr++;
 | 
						|
        strcpy(remainder, end_ptr);
 | 
						|
    }
 | 
						|
    
 | 
						|
    // Look for a user name in the containing part, and if it's there, resolve it and stick the
 | 
						|
    // result back into the containing_part:
 | 
						|
 | 
						|
    if (*partial_name_copy == '~')
 | 
						|
    {
 | 
						|
        size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, 
 | 
						|
                                                                 containing_part, 
 | 
						|
                                                                 sizeof (containing_part));
 | 
						|
        // User name doesn't exist, we're not getting any further...
 | 
						|
        if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
 | 
						|
            return matches.GetSize();
 | 
						|
    }
 | 
						|
 | 
						|
    // Okay, containing_part is now the directory we want to open and look for files:
 | 
						|
 | 
						|
    size_t baselen = end_ptr - partial_name_copy;
 | 
						|
    
 | 
						|
    DiskFilesOrDirectoriesBaton parameters;
 | 
						|
    parameters.remainder = remainder;
 | 
						|
    parameters.partial_name_copy = partial_name_copy;
 | 
						|
    parameters.only_directories = only_directories;
 | 
						|
    parameters.saw_directory = &saw_directory;
 | 
						|
    parameters.matches = &matches;
 | 
						|
    parameters.end_ptr = end_ptr;
 | 
						|
    parameters.baselen = baselen;
 | 
						|
 | 
						|
    FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, ¶meters);
 | 
						|
    
 | 
						|
    return matches.GetSize();
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::DiskFiles 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *partial_file_name,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    StringList &matches
 | 
						|
)
 | 
						|
{
 | 
						|
 | 
						|
    int ret_val = DiskFilesOrDirectories (partial_file_name,
 | 
						|
                                          false,
 | 
						|
                                          word_complete,
 | 
						|
                                          matches);
 | 
						|
    word_complete = !word_complete;
 | 
						|
    return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::DiskDirectories 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *partial_file_name,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    StringList &matches
 | 
						|
)
 | 
						|
{
 | 
						|
    int ret_val =  DiskFilesOrDirectories (partial_file_name,
 | 
						|
                                           true,
 | 
						|
                                           word_complete,
 | 
						|
                                           matches); 
 | 
						|
    word_complete = false;
 | 
						|
    return ret_val;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::Modules 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *partial_file_name,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    StringList &matches
 | 
						|
)
 | 
						|
{
 | 
						|
    word_complete = true;
 | 
						|
    ModuleCompleter completer (interpreter,
 | 
						|
                               partial_file_name, 
 | 
						|
                               match_start_point, 
 | 
						|
                               max_return_elements, 
 | 
						|
                               matches);
 | 
						|
    
 | 
						|
    if (searcher == NULL)
 | 
						|
    {
 | 
						|
        lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
 | 
						|
        SearchFilter null_searcher (target_sp);
 | 
						|
        completer.DoCompletion (&null_searcher);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        completer.DoCompletion (searcher);
 | 
						|
    }
 | 
						|
    return matches.GetSize();
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::Symbols 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *partial_file_name,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    SearchFilter *searcher,
 | 
						|
    bool &word_complete,
 | 
						|
    StringList &matches)
 | 
						|
{
 | 
						|
    word_complete = true;
 | 
						|
    SymbolCompleter completer (interpreter,
 | 
						|
                               partial_file_name, 
 | 
						|
                               match_start_point, 
 | 
						|
                               max_return_elements, 
 | 
						|
                               matches);
 | 
						|
 | 
						|
    if (searcher == NULL)
 | 
						|
    {
 | 
						|
        lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
 | 
						|
        SearchFilter null_searcher (target_sp);
 | 
						|
        completer.DoCompletion (&null_searcher);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        completer.DoCompletion (searcher);
 | 
						|
    }
 | 
						|
    return matches.GetSize();
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
 | 
						|
                                   const char *partial_setting_name,
 | 
						|
                                   int match_start_point,
 | 
						|
                                   int max_return_elements,
 | 
						|
                                   SearchFilter *searcher,
 | 
						|
                                   bool &word_complete,
 | 
						|
                                   StringList &matches)
 | 
						|
{
 | 
						|
    // Cache the full setting name list
 | 
						|
    static StringList g_property_names;
 | 
						|
    if (g_property_names.GetSize() == 0)
 | 
						|
    {
 | 
						|
        // Generate the full setting name list on demand
 | 
						|
        lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
 | 
						|
        if (properties_sp)
 | 
						|
        {
 | 
						|
            StreamString strm;
 | 
						|
            properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
 | 
						|
            const std::string &str = strm.GetString();
 | 
						|
            g_property_names.SplitIntoLines(str.c_str(), str.size());
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    size_t exact_matches_idx = SIZE_MAX;
 | 
						|
    const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
 | 
						|
    word_complete = exact_matches_idx != SIZE_MAX;
 | 
						|
    return num_matches;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
 | 
						|
                                         const char *partial_name,
 | 
						|
                                         int match_start_point,
 | 
						|
                                         int max_return_elements,
 | 
						|
                                         SearchFilter *searcher,
 | 
						|
                                         bool &word_complete,
 | 
						|
                                         lldb_private::StringList &matches)
 | 
						|
{
 | 
						|
    const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
 | 
						|
    word_complete = num_matches == 1;
 | 
						|
    return num_matches;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
 | 
						|
                                       const char *partial_name,
 | 
						|
                                       int match_start_point,
 | 
						|
                                       int max_return_elements,
 | 
						|
                                       SearchFilter *searcher,
 | 
						|
                                       bool &word_complete,
 | 
						|
                                       lldb_private::StringList &matches)
 | 
						|
{
 | 
						|
    const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
 | 
						|
    word_complete = num_matches == 1;
 | 
						|
    return num_matches;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
CommandCompletions::VariablePath (CommandInterpreter &interpreter,
 | 
						|
                                  const char *partial_name,
 | 
						|
                                  int match_start_point,
 | 
						|
                                  int max_return_elements,
 | 
						|
                                  SearchFilter *searcher,
 | 
						|
                                  bool &word_complete,
 | 
						|
                                  lldb_private::StringList &matches)
 | 
						|
{
 | 
						|
    return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
CommandCompletions::Completer::Completer 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *completion_str,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    StringList &matches
 | 
						|
) :
 | 
						|
    m_interpreter (interpreter),
 | 
						|
    m_completion_str (completion_str),
 | 
						|
    m_match_start_point (match_start_point),
 | 
						|
    m_max_return_elements (max_return_elements),
 | 
						|
    m_matches (matches)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
CommandCompletions::Completer::~Completer ()
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
//----------------------------------------------------------------------
 | 
						|
// SourceFileCompleter
 | 
						|
//----------------------------------------------------------------------
 | 
						|
 | 
						|
CommandCompletions::SourceFileCompleter::SourceFileCompleter 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    bool include_support_files,
 | 
						|
    const char *completion_str,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    StringList &matches
 | 
						|
) :
 | 
						|
    CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
 | 
						|
    m_include_support_files (include_support_files),
 | 
						|
    m_matching_files()
 | 
						|
{
 | 
						|
    FileSpec partial_spec (m_completion_str.c_str(), false);
 | 
						|
    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 == ')' ||
 | 
						|
        comp == '{' || comp == '}' ||
 | 
						|
        comp == '+' ||
 | 
						|
        comp == '.' ||
 | 
						|
        comp == '*' ||
 | 
						|
        comp == '|' ||
 | 
						|
        comp == '^' ||
 | 
						|
        comp == '$' ||
 | 
						|
        comp == '\\' ||
 | 
						|
        comp == '?')
 | 
						|
        return true;
 | 
						|
    else
 | 
						|
        return false;
 | 
						|
}
 | 
						|
CommandCompletions::SymbolCompleter::SymbolCompleter 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *completion_str,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    StringList &matches
 | 
						|
) :
 | 
						|
    CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
 | 
						|
{
 | 
						|
    std::string regex_str;
 | 
						|
    if (completion_str && completion_str[0])
 | 
						|
    {
 | 
						|
        regex_str.append("^");
 | 
						|
        regex_str.append(completion_str);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        // Match anything since the completion string is empty
 | 
						|
        regex_str.append(".");
 | 
						|
    }
 | 
						|
    std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
 | 
						|
    while (pos < regex_str.end())
 | 
						|
    {
 | 
						|
        pos = regex_str.insert(pos, '\\');
 | 
						|
        pos = find_if(pos + 2, 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
 | 
						|
)
 | 
						|
{
 | 
						|
    if (context.module_sp)
 | 
						|
    {
 | 
						|
        SymbolContextList sc_list;        
 | 
						|
        const bool include_symbols = true;
 | 
						|
        const bool include_inlines = true;
 | 
						|
        const bool append = true;
 | 
						|
        context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
 | 
						|
 | 
						|
        SymbolContext sc;
 | 
						|
        // Now add the functions & symbols to the list - only add if unique:
 | 
						|
        for (uint32_t i = 0; i < sc_list.GetSize(); i++)
 | 
						|
        {
 | 
						|
            if (sc_list.GetContextAtIndex(i, sc))
 | 
						|
            {
 | 
						|
                ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
 | 
						|
                if (!func_name.IsEmpty())
 | 
						|
                    m_match_set.insert (func_name);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    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 
 | 
						|
(
 | 
						|
    CommandInterpreter &interpreter,
 | 
						|
    const char *completion_str,
 | 
						|
    int match_start_point,
 | 
						|
    int max_return_elements,
 | 
						|
    StringList &matches
 | 
						|
) :
 | 
						|
    CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
 | 
						|
{
 | 
						|
    FileSpec partial_spec (m_completion_str.c_str(), false);
 | 
						|
    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)
 | 
						|
    {
 | 
						|
        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();
 | 
						|
}
 |