1c9af18a5SGreg Clayton //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===// 2c9af18a5SGreg Clayton // 3c9af18a5SGreg Clayton // The LLVM Compiler Infrastructure 4c9af18a5SGreg Clayton // 5c9af18a5SGreg Clayton // This file is distributed under the University of Illinois Open Source 6c9af18a5SGreg Clayton // License. See LICENSE.TXT for details. 7c9af18a5SGreg Clayton // 8c9af18a5SGreg Clayton //===----------------------------------------------------------------------===// 9c9af18a5SGreg Clayton 10c9af18a5SGreg Clayton 11c9af18a5SGreg Clayton // C Includes 12558ce124SJim Ingham #include <sys/stat.h> 13558ce124SJim Ingham #include <dirent.h> 14fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__) 157cc478b9SJim Ingham #include <pwd.h> 16fd18426eSGreg Clayton #endif 17558ce124SJim Ingham 18c9af18a5SGreg Clayton // C++ Includes 19c9af18a5SGreg Clayton // Other libraries and framework includes 20c9af18a5SGreg Clayton // Project includes 2153239f00SGreg Clayton #include "lldb/Host/FileSpec.h" 229b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h" 23*ab65b34fSGreg Clayton #include "lldb/Core/PluginManager.h" 249b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h" 259b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 269b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 279b62fd2fSGreg Clayton #include "lldb/Target/Target.h" 289b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h" 29c9af18a5SGreg Clayton 30c9af18a5SGreg Clayton using namespace lldb_private; 31c9af18a5SGreg Clayton 32c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 33c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 34c9af18a5SGreg Clayton { 35c9af18a5SGreg Clayton {eCustomCompletion, NULL}, 36c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 37558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 38558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 39c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 40c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 413df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 42*ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 43*ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 44c9af18a5SGreg Clayton {eNoCompletion, NULL} // This one has to be last in the list. 45c9af18a5SGreg Clayton }; 46c9af18a5SGreg Clayton 47c9af18a5SGreg Clayton bool 486611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks 496611103cSGreg Clayton ( 506611103cSGreg Clayton CommandInterpreter &interpreter, 516611103cSGreg Clayton uint32_t completion_mask, 52c9af18a5SGreg Clayton const char *completion_str, 53c9af18a5SGreg Clayton int match_start_point, 54c9af18a5SGreg Clayton int max_return_elements, 55c9af18a5SGreg Clayton SearchFilter *searcher, 56558ce124SJim Ingham bool &word_complete, 576611103cSGreg Clayton StringList &matches 586611103cSGreg Clayton ) 59c9af18a5SGreg Clayton { 60c9af18a5SGreg Clayton bool handled = false; 61c9af18a5SGreg Clayton 62c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 63c9af18a5SGreg Clayton return false; 64c9af18a5SGreg Clayton 65c9af18a5SGreg Clayton for (int i = 0; ; i++) 66c9af18a5SGreg Clayton { 67c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 68c9af18a5SGreg Clayton break; 69c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 70c9af18a5SGreg Clayton && g_common_completions[i].callback != NULL) 71c9af18a5SGreg Clayton { 72c9af18a5SGreg Clayton handled = true; 736611103cSGreg Clayton g_common_completions[i].callback (interpreter, 746611103cSGreg Clayton completion_str, 75c9af18a5SGreg Clayton match_start_point, 76c9af18a5SGreg Clayton max_return_elements, 77c9af18a5SGreg Clayton searcher, 78558ce124SJim Ingham word_complete, 79c9af18a5SGreg Clayton matches); 80c9af18a5SGreg Clayton } 81c9af18a5SGreg Clayton } 82c9af18a5SGreg Clayton return handled; 83c9af18a5SGreg Clayton } 84c9af18a5SGreg Clayton 85c9af18a5SGreg Clayton int 866611103cSGreg Clayton CommandCompletions::SourceFiles 876611103cSGreg Clayton ( 886611103cSGreg Clayton CommandInterpreter &interpreter, 896611103cSGreg Clayton const char *partial_file_name, 90c9af18a5SGreg Clayton int match_start_point, 91c9af18a5SGreg Clayton int max_return_elements, 92c9af18a5SGreg Clayton SearchFilter *searcher, 93558ce124SJim Ingham bool &word_complete, 946611103cSGreg Clayton StringList &matches 956611103cSGreg Clayton ) 96c9af18a5SGreg Clayton { 97558ce124SJim Ingham word_complete = true; 98c9af18a5SGreg Clayton // Find some way to switch "include support files..." 996611103cSGreg Clayton SourceFileCompleter completer (interpreter, 1006611103cSGreg Clayton false, 1016611103cSGreg Clayton partial_file_name, 1026611103cSGreg Clayton match_start_point, 1036611103cSGreg Clayton max_return_elements, 104c9af18a5SGreg Clayton matches); 105c9af18a5SGreg Clayton 106c9af18a5SGreg Clayton if (searcher == NULL) 107c9af18a5SGreg Clayton { 1082976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 109c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 110c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 111c9af18a5SGreg Clayton } 112c9af18a5SGreg Clayton else 113c9af18a5SGreg Clayton { 114c9af18a5SGreg Clayton completer.DoCompletion (searcher); 115c9af18a5SGreg Clayton } 116c9af18a5SGreg Clayton return matches.GetSize(); 117c9af18a5SGreg Clayton } 118c9af18a5SGreg Clayton 119558ce124SJim Ingham static int 120558ce124SJim Ingham DiskFilesOrDirectories 121558ce124SJim Ingham ( 122558ce124SJim Ingham const char *partial_file_name, 123558ce124SJim Ingham bool only_directories, 124558ce124SJim Ingham bool &saw_directory, 125558ce124SJim Ingham StringList &matches 126558ce124SJim Ingham ) 127558ce124SJim Ingham { 128558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 129558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 130558ce124SJim Ingham 131558ce124SJim Ingham int partial_name_len = strlen(partial_file_name); 132558ce124SJim Ingham 133558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 134558ce124SJim Ingham return matches.GetSize(); 135558ce124SJim Ingham 136558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 137558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 138558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 139558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 140558ce124SJim Ingham // the form the user originally typed. 141558ce124SJim Ingham 142558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 143021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 144558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 145558ce124SJim Ingham 146710dd5aeSGreg Clayton // We'll need to save a copy of the remainder for comparison, which we do here. 147558ce124SJim Ingham char remainder[PATH_MAX]; 148558ce124SJim Ingham 149558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 150558ce124SJim Ingham char *end_ptr; 151558ce124SJim Ingham 152558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 153558ce124SJim Ingham 154558ce124SJim Ingham // This will store the resolved form of the containing directory 155558ce124SJim Ingham char containing_part[PATH_MAX]; 156558ce124SJim Ingham 157558ce124SJim Ingham if (end_ptr == NULL) 158558ce124SJim Ingham { 159558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 160558ce124SJim Ingham // user name. 161558ce124SJim Ingham if (*partial_name_copy == '~') 162558ce124SJim Ingham { 163558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 1647cc478b9SJim Ingham // but for completeness sake we'll resolve the user name and only put a slash 165558ce124SJim Ingham // on the end if it exists. 1667cc478b9SJim Ingham char resolved_username[PATH_MAX]; 167c982c768SGreg Clayton size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username, 1687cc478b9SJim Ingham sizeof (resolved_username)); 1697cc478b9SJim Ingham 1707cc478b9SJim Ingham // Not sure how this would happen, a username longer than PATH_MAX? Still... 1717cc478b9SJim Ingham if (resolved_username_len >= sizeof (resolved_username)) 172558ce124SJim Ingham return matches.GetSize(); 17384363078SJim Ingham else if (resolved_username_len == 0) 1747cc478b9SJim Ingham { 1757cc478b9SJim Ingham // The user name didn't resolve, let's look in the password database for matches. 1767cc478b9SJim Ingham // The user name database contains duplicates, and is not in alphabetical order, so 1777cc478b9SJim Ingham // we'll use a set to manage that for us. 17884363078SJim Ingham FileSpec::ResolvePartialUsername (partial_name_copy, matches); 17984363078SJim Ingham if (matches.GetSize() > 0) 1807cc478b9SJim Ingham saw_directory = true; 1817cc478b9SJim Ingham return matches.GetSize(); 1827cc478b9SJim Ingham } 18384363078SJim Ingham else 18484363078SJim Ingham { 185558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 186558ce124SJim Ingham // FIXME: complete user names here: 187558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 188558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 189558ce124SJim Ingham matches.AppendString(partial_name_copy); 190021b605dSBenjamin Kramer saw_directory = true; 191558ce124SJim Ingham return matches.GetSize(); 192558ce124SJim Ingham } 19384363078SJim Ingham } 194558ce124SJim Ingham else 195558ce124SJim Ingham { 196558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 197558ce124SJim Ingham containing_part[0] = '.'; 198558ce124SJim Ingham containing_part[1] = '\0'; 199558ce124SJim Ingham strcpy(remainder, partial_name_copy); 200558ce124SJim Ingham end_ptr = partial_name_copy; 201558ce124SJim Ingham } 202558ce124SJim Ingham } 203558ce124SJim Ingham else 204558ce124SJim Ingham { 205558ce124SJim Ingham if (end_ptr == partial_name_copy) 206558ce124SJim Ingham { 207558ce124SJim Ingham // We're completing a file or directory in the root volume. 208558ce124SJim Ingham containing_part[0] = '/'; 209558ce124SJim Ingham containing_part[1] = '\0'; 210558ce124SJim Ingham } 211558ce124SJim Ingham else 212558ce124SJim Ingham { 213558ce124SJim Ingham size_t len = end_ptr - partial_name_copy; 214558ce124SJim Ingham memcpy(containing_part, partial_name_copy, len); 215558ce124SJim Ingham containing_part[len] = '\0'; 216558ce124SJim Ingham } 217558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 218558ce124SJim Ingham end_ptr++; 219558ce124SJim Ingham strcpy(remainder, end_ptr); 220558ce124SJim Ingham } 221558ce124SJim Ingham 2227cc478b9SJim Ingham // Look for a user name in the containing part, and if it's there, resolve it and stick the 223558ce124SJim Ingham // result back into the containing_part: 224558ce124SJim Ingham 225558ce124SJim Ingham if (*partial_name_copy == '~') 226558ce124SJim Ingham { 22784363078SJim Ingham size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, 22884363078SJim Ingham containing_part, 22984363078SJim Ingham sizeof (containing_part)); 230558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 231a0807356SGreg Clayton if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part)) 232558ce124SJim Ingham return matches.GetSize(); 233558ce124SJim Ingham } 234558ce124SJim Ingham 235558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 236558ce124SJim Ingham 2379b62fd2fSGreg Clayton lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir); 2389b62fd2fSGreg Clayton if (!dir_stream.is_valid()) 239558ce124SJim Ingham return matches.GetSize(); 240558ce124SJim Ingham 241558ce124SJim Ingham struct dirent *dirent_buf; 242558ce124SJim Ingham 243558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 244558ce124SJim Ingham 2459b62fd2fSGreg Clayton while ((dirent_buf = readdir(dir_stream.get())) != NULL) 246558ce124SJim Ingham { 247558ce124SJim Ingham char *name = dirent_buf->d_name; 248558ce124SJim Ingham 249558ce124SJim Ingham // Omit ".", ".." and any . files if the match string doesn't start with . 250558ce124SJim Ingham if (name[0] == '.') 251558ce124SJim Ingham { 252558ce124SJim Ingham if (name[1] == '\0') 253558ce124SJim Ingham continue; 254558ce124SJim Ingham else if (name[1] == '.' && name[2] == '\0') 255558ce124SJim Ingham continue; 256558ce124SJim Ingham else if (remainder[0] != '.') 257558ce124SJim Ingham continue; 258558ce124SJim Ingham } 259558ce124SJim Ingham 2607cc478b9SJim Ingham // If we found a directory, we put a "/" at the end of the name. 2617cc478b9SJim Ingham 262558ce124SJim Ingham if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name) 263558ce124SJim Ingham { 264558ce124SJim Ingham if (strlen(name) + baselen >= PATH_MAX) 265558ce124SJim Ingham continue; 266558ce124SJim Ingham 267558ce124SJim Ingham strcpy(end_ptr, name); 268558ce124SJim Ingham 269558ce124SJim Ingham bool isa_directory = false; 270558ce124SJim Ingham if (dirent_buf->d_type & DT_DIR) 271558ce124SJim Ingham isa_directory = true; 272558ce124SJim Ingham else if (dirent_buf->d_type & DT_LNK) 273558ce124SJim Ingham { 274558ce124SJim Ingham struct stat stat_buf; 275558ce124SJim Ingham if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR)) 276558ce124SJim Ingham isa_directory = true; 277558ce124SJim Ingham } 278558ce124SJim Ingham 279558ce124SJim Ingham if (isa_directory) 280558ce124SJim Ingham { 281558ce124SJim Ingham saw_directory = true; 282558ce124SJim Ingham size_t len = strlen(partial_name_copy); 283558ce124SJim Ingham partial_name_copy[len] = '/'; 284558ce124SJim Ingham partial_name_copy[len + 1] = '\0'; 285558ce124SJim Ingham } 286558ce124SJim Ingham if (only_directories && !isa_directory) 287558ce124SJim Ingham continue; 288558ce124SJim Ingham matches.AppendString(partial_name_copy); 289558ce124SJim Ingham } 290558ce124SJim Ingham } 291558ce124SJim Ingham 292558ce124SJim Ingham return matches.GetSize(); 293558ce124SJim Ingham } 294558ce124SJim Ingham 295558ce124SJim Ingham int 296558ce124SJim Ingham CommandCompletions::DiskFiles 297558ce124SJim Ingham ( 298558ce124SJim Ingham CommandInterpreter &interpreter, 299558ce124SJim Ingham const char *partial_file_name, 300558ce124SJim Ingham int match_start_point, 301558ce124SJim Ingham int max_return_elements, 302558ce124SJim Ingham SearchFilter *searcher, 303558ce124SJim Ingham bool &word_complete, 304558ce124SJim Ingham StringList &matches 305558ce124SJim Ingham ) 306558ce124SJim Ingham { 307558ce124SJim Ingham 308558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 309558ce124SJim Ingham false, 310558ce124SJim Ingham word_complete, 311558ce124SJim Ingham matches); 312558ce124SJim Ingham word_complete = !word_complete; 313558ce124SJim Ingham return ret_val; 314558ce124SJim Ingham } 315558ce124SJim Ingham 316558ce124SJim Ingham int 317558ce124SJim Ingham CommandCompletions::DiskDirectories 318558ce124SJim Ingham ( 319558ce124SJim Ingham CommandInterpreter &interpreter, 320558ce124SJim Ingham const char *partial_file_name, 321558ce124SJim Ingham int match_start_point, 322558ce124SJim Ingham int max_return_elements, 323558ce124SJim Ingham SearchFilter *searcher, 324558ce124SJim Ingham bool &word_complete, 325558ce124SJim Ingham StringList &matches 326558ce124SJim Ingham ) 327558ce124SJim Ingham { 328558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 329558ce124SJim Ingham true, 330558ce124SJim Ingham word_complete, 331558ce124SJim Ingham matches); 332558ce124SJim Ingham word_complete = false; 333558ce124SJim Ingham return ret_val; 334558ce124SJim Ingham } 335558ce124SJim Ingham 336c9af18a5SGreg Clayton int 3376611103cSGreg Clayton CommandCompletions::Modules 3386611103cSGreg Clayton ( 3396611103cSGreg Clayton CommandInterpreter &interpreter, 3406611103cSGreg Clayton const char *partial_file_name, 341c9af18a5SGreg Clayton int match_start_point, 342c9af18a5SGreg Clayton int max_return_elements, 343c9af18a5SGreg Clayton SearchFilter *searcher, 344558ce124SJim Ingham bool &word_complete, 3456611103cSGreg Clayton StringList &matches 3466611103cSGreg Clayton ) 347c9af18a5SGreg Clayton { 348558ce124SJim Ingham word_complete = true; 3496611103cSGreg Clayton ModuleCompleter completer (interpreter, 3506611103cSGreg Clayton partial_file_name, 3516611103cSGreg Clayton match_start_point, 3526611103cSGreg Clayton max_return_elements, 3536611103cSGreg Clayton matches); 354c9af18a5SGreg Clayton 355c9af18a5SGreg Clayton if (searcher == NULL) 356c9af18a5SGreg Clayton { 3572976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 358c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 359c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 360c9af18a5SGreg Clayton } 361c9af18a5SGreg Clayton else 362c9af18a5SGreg Clayton { 363c9af18a5SGreg Clayton completer.DoCompletion (searcher); 364c9af18a5SGreg Clayton } 365c9af18a5SGreg Clayton return matches.GetSize(); 366c9af18a5SGreg Clayton } 367c9af18a5SGreg Clayton 368c9af18a5SGreg Clayton int 3696611103cSGreg Clayton CommandCompletions::Symbols 3706611103cSGreg Clayton ( 3716611103cSGreg Clayton CommandInterpreter &interpreter, 3726611103cSGreg Clayton const char *partial_file_name, 373c9af18a5SGreg Clayton int match_start_point, 374c9af18a5SGreg Clayton int max_return_elements, 375c9af18a5SGreg Clayton SearchFilter *searcher, 376558ce124SJim Ingham bool &word_complete, 3776611103cSGreg Clayton StringList &matches) 378c9af18a5SGreg Clayton { 379558ce124SJim Ingham word_complete = true; 3806611103cSGreg Clayton SymbolCompleter completer (interpreter, 3816611103cSGreg Clayton partial_file_name, 3826611103cSGreg Clayton match_start_point, 3836611103cSGreg Clayton max_return_elements, 3846611103cSGreg Clayton matches); 385c9af18a5SGreg Clayton 386c9af18a5SGreg Clayton if (searcher == NULL) 387c9af18a5SGreg Clayton { 3882976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 389c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 390c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 391c9af18a5SGreg Clayton } 392c9af18a5SGreg Clayton else 393c9af18a5SGreg Clayton { 394c9af18a5SGreg Clayton completer.DoCompletion (searcher); 395c9af18a5SGreg Clayton } 396c9af18a5SGreg Clayton return matches.GetSize(); 397c9af18a5SGreg Clayton } 398c9af18a5SGreg Clayton 3993df9a8dfSCaroline Tice int 4003df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter, 4013df9a8dfSCaroline Tice const char *partial_setting_name, 4023df9a8dfSCaroline Tice int match_start_point, 4033df9a8dfSCaroline Tice int max_return_elements, 4043df9a8dfSCaroline Tice SearchFilter *searcher, 4053df9a8dfSCaroline Tice bool &word_complete, 4063df9a8dfSCaroline Tice StringList &matches) 4073df9a8dfSCaroline Tice { 4083df9a8dfSCaroline Tice lldb::UserSettingsControllerSP root_settings = Debugger::GetSettingsController(); 4093df9a8dfSCaroline Tice Args partial_setting_name_pieces = UserSettingsController::BreakNameIntoPieces (partial_setting_name); 4103df9a8dfSCaroline Tice 4113df9a8dfSCaroline Tice return UserSettingsController::CompleteSettingsNames (root_settings, 4123df9a8dfSCaroline Tice partial_setting_name_pieces, 4133df9a8dfSCaroline Tice word_complete, 4143df9a8dfSCaroline Tice matches); 4153df9a8dfSCaroline Tice 4163df9a8dfSCaroline Tice //return matches.GetSize(); 4173df9a8dfSCaroline Tice } 4183df9a8dfSCaroline Tice 419*ab65b34fSGreg Clayton 420*ab65b34fSGreg Clayton int 421*ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter, 422*ab65b34fSGreg Clayton const char *partial_name, 423*ab65b34fSGreg Clayton int match_start_point, 424*ab65b34fSGreg Clayton int max_return_elements, 425*ab65b34fSGreg Clayton SearchFilter *searcher, 426*ab65b34fSGreg Clayton bool &word_complete, 427*ab65b34fSGreg Clayton lldb_private::StringList &matches) 428*ab65b34fSGreg Clayton { 429*ab65b34fSGreg Clayton const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches); 430*ab65b34fSGreg Clayton word_complete = num_matches == 1; 431*ab65b34fSGreg Clayton return num_matches; 432*ab65b34fSGreg Clayton } 433*ab65b34fSGreg Clayton 434*ab65b34fSGreg Clayton int 435*ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter, 436*ab65b34fSGreg Clayton const char *partial_name, 437*ab65b34fSGreg Clayton int match_start_point, 438*ab65b34fSGreg Clayton int max_return_elements, 439*ab65b34fSGreg Clayton SearchFilter *searcher, 440*ab65b34fSGreg Clayton bool &word_complete, 441*ab65b34fSGreg Clayton lldb_private::StringList &matches) 442*ab65b34fSGreg Clayton { 443*ab65b34fSGreg Clayton const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches); 444*ab65b34fSGreg Clayton word_complete = num_matches == 1; 445*ab65b34fSGreg Clayton return num_matches; 446*ab65b34fSGreg Clayton } 447*ab65b34fSGreg Clayton 448*ab65b34fSGreg Clayton 4496611103cSGreg Clayton CommandCompletions::Completer::Completer 4506611103cSGreg Clayton ( 4516611103cSGreg Clayton CommandInterpreter &interpreter, 452c9af18a5SGreg Clayton const char *completion_str, 453c9af18a5SGreg Clayton int match_start_point, 454c9af18a5SGreg Clayton int max_return_elements, 455c9af18a5SGreg Clayton StringList &matches 456c9af18a5SGreg Clayton ) : 4576611103cSGreg Clayton m_interpreter (interpreter), 458c9af18a5SGreg Clayton m_completion_str (completion_str), 459c9af18a5SGreg Clayton m_match_start_point (match_start_point), 460c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 461c9af18a5SGreg Clayton m_matches (matches) 462c9af18a5SGreg Clayton { 463c9af18a5SGreg Clayton } 464c9af18a5SGreg Clayton 465c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer () 466c9af18a5SGreg Clayton { 467c9af18a5SGreg Clayton 468c9af18a5SGreg Clayton } 469c9af18a5SGreg Clayton 470c9af18a5SGreg Clayton //---------------------------------------------------------------------- 471c9af18a5SGreg Clayton // SourceFileCompleter 472c9af18a5SGreg Clayton //---------------------------------------------------------------------- 473c9af18a5SGreg Clayton 4746611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter 4756611103cSGreg Clayton ( 4766611103cSGreg Clayton CommandInterpreter &interpreter, 477c9af18a5SGreg Clayton bool include_support_files, 478c9af18a5SGreg Clayton const char *completion_str, 479c9af18a5SGreg Clayton int match_start_point, 480c9af18a5SGreg Clayton int max_return_elements, 481c9af18a5SGreg Clayton StringList &matches 482c9af18a5SGreg Clayton ) : 4836611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 484c9af18a5SGreg Clayton m_include_support_files (include_support_files), 485c9af18a5SGreg Clayton m_matching_files() 486c9af18a5SGreg Clayton { 487274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 488c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 489c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 490c9af18a5SGreg Clayton } 491c9af18a5SGreg Clayton 492c9af18a5SGreg Clayton Searcher::Depth 493c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 494c9af18a5SGreg Clayton { 495c9af18a5SGreg Clayton return eDepthCompUnit; 496c9af18a5SGreg Clayton } 497c9af18a5SGreg Clayton 498c9af18a5SGreg Clayton Searcher::CallbackReturn 499c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback ( 500c9af18a5SGreg Clayton SearchFilter &filter, 501c9af18a5SGreg Clayton SymbolContext &context, 502c9af18a5SGreg Clayton Address *addr, 503c9af18a5SGreg Clayton bool complete 504c9af18a5SGreg Clayton ) 505c9af18a5SGreg Clayton { 506c9af18a5SGreg Clayton if (context.comp_unit != NULL) 507c9af18a5SGreg Clayton { 508c9af18a5SGreg Clayton if (m_include_support_files) 509c9af18a5SGreg Clayton { 510c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 511c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 512c9af18a5SGreg Clayton { 513c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 514c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 515c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 516c9af18a5SGreg Clayton bool match = false; 517c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 518c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 519c9af18a5SGreg Clayton match = true; 520c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 521c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 522c9af18a5SGreg Clayton match = false; 523c9af18a5SGreg Clayton 524c9af18a5SGreg Clayton if (match) 525c9af18a5SGreg Clayton { 526c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 527c9af18a5SGreg Clayton } 528c9af18a5SGreg Clayton } 529c9af18a5SGreg Clayton 530c9af18a5SGreg Clayton } 531c9af18a5SGreg Clayton else 532c9af18a5SGreg Clayton { 533c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 534c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 535c9af18a5SGreg Clayton 536c9af18a5SGreg Clayton bool match = false; 537c9af18a5SGreg Clayton if (m_file_name && cur_file_name 538c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 539c9af18a5SGreg Clayton match = true; 540c9af18a5SGreg Clayton 541c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 542c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 543c9af18a5SGreg Clayton match = false; 544c9af18a5SGreg Clayton 545c9af18a5SGreg Clayton if (match) 546c9af18a5SGreg Clayton { 547c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 548c9af18a5SGreg Clayton } 549c9af18a5SGreg Clayton } 550c9af18a5SGreg Clayton } 551c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 552c9af18a5SGreg Clayton } 553c9af18a5SGreg Clayton 554c9af18a5SGreg Clayton size_t 555c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 556c9af18a5SGreg Clayton { 557c9af18a5SGreg Clayton filter->Search (*this); 558c9af18a5SGreg Clayton // Now convert the filelist to completions: 559c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 560c9af18a5SGreg Clayton { 561c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 562c9af18a5SGreg Clayton } 563c9af18a5SGreg Clayton return m_matches.GetSize(); 564c9af18a5SGreg Clayton 565c9af18a5SGreg Clayton } 566c9af18a5SGreg Clayton 567c9af18a5SGreg Clayton //---------------------------------------------------------------------- 568c9af18a5SGreg Clayton // SymbolCompleter 569c9af18a5SGreg Clayton //---------------------------------------------------------------------- 570c9af18a5SGreg Clayton 571c9af18a5SGreg Clayton static bool 572c9af18a5SGreg Clayton regex_chars (const char comp) 573c9af18a5SGreg Clayton { 574c9af18a5SGreg Clayton if (comp == '[' || comp == ']' || comp == '(' || comp == ')') 575c9af18a5SGreg Clayton return true; 576c9af18a5SGreg Clayton else 577c9af18a5SGreg Clayton return false; 578c9af18a5SGreg Clayton } 5796611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter 5806611103cSGreg Clayton ( 5816611103cSGreg Clayton CommandInterpreter &interpreter, 582c9af18a5SGreg Clayton const char *completion_str, 583c9af18a5SGreg Clayton int match_start_point, 584c9af18a5SGreg Clayton int max_return_elements, 585c9af18a5SGreg Clayton StringList &matches 586c9af18a5SGreg Clayton ) : 5876611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 588c9af18a5SGreg Clayton { 589c9af18a5SGreg Clayton std::string regex_str ("^"); 590c9af18a5SGreg Clayton regex_str.append(completion_str); 591c9af18a5SGreg Clayton regex_str.append(".*"); 592c9af18a5SGreg Clayton std::string::iterator pos; 593c9af18a5SGreg Clayton 594c9af18a5SGreg Clayton pos = find_if(regex_str.begin(), regex_str.end(), regex_chars); 595c9af18a5SGreg Clayton while (pos < regex_str.end()) { 596c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 597c9af18a5SGreg Clayton pos += 2; 598c9af18a5SGreg Clayton pos = find_if(pos, regex_str.end(), regex_chars); 599c9af18a5SGreg Clayton } 600c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 601c9af18a5SGreg Clayton } 602c9af18a5SGreg Clayton 603c9af18a5SGreg Clayton Searcher::Depth 604c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 605c9af18a5SGreg Clayton { 606c9af18a5SGreg Clayton return eDepthModule; 607c9af18a5SGreg Clayton } 608c9af18a5SGreg Clayton 609c9af18a5SGreg Clayton Searcher::CallbackReturn 610c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback ( 611c9af18a5SGreg Clayton SearchFilter &filter, 612c9af18a5SGreg Clayton SymbolContext &context, 613c9af18a5SGreg Clayton Address *addr, 614c9af18a5SGreg Clayton bool complete 615c9af18a5SGreg Clayton ) 616c9af18a5SGreg Clayton { 617c9af18a5SGreg Clayton if (context.module_sp) 618c9af18a5SGreg Clayton { 619931180e6SGreg Clayton SymbolContextList sc_list; 620931180e6SGreg Clayton const bool include_symbols = true; 621931180e6SGreg Clayton const bool append = true; 622931180e6SGreg Clayton context.module_sp->FindFunctions (m_regex, include_symbols, append, sc_list); 623c9af18a5SGreg Clayton 624c9af18a5SGreg Clayton SymbolContext sc; 625c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 626931180e6SGreg Clayton for (uint32_t i = 0; i < sc_list.GetSize(); i++) 627c9af18a5SGreg Clayton { 628931180e6SGreg Clayton if (sc_list.GetContextAtIndex(i, sc)) 629c9af18a5SGreg Clayton { 630c9af18a5SGreg Clayton if (sc.function) 631c9af18a5SGreg Clayton { 632c9af18a5SGreg Clayton m_match_set.insert (sc.function->GetMangled().GetDemangledName()); 633c9af18a5SGreg Clayton } 634931180e6SGreg Clayton else if (sc.symbol && sc.symbol->GetAddressRangePtr()) 635c9af18a5SGreg Clayton { 636c9af18a5SGreg Clayton m_match_set.insert (sc.symbol->GetMangled().GetDemangledName()); 637c9af18a5SGreg Clayton } 638c9af18a5SGreg Clayton } 639c9af18a5SGreg Clayton } 640c9af18a5SGreg Clayton } 641c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 642c9af18a5SGreg Clayton } 643c9af18a5SGreg Clayton 644c9af18a5SGreg Clayton size_t 645c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 646c9af18a5SGreg Clayton { 647c9af18a5SGreg Clayton filter->Search (*this); 648c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 649c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 650c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 651c9af18a5SGreg Clayton 652c9af18a5SGreg Clayton return m_matches.GetSize(); 653c9af18a5SGreg Clayton } 654c9af18a5SGreg Clayton 655c9af18a5SGreg Clayton //---------------------------------------------------------------------- 656c9af18a5SGreg Clayton // ModuleCompleter 657c9af18a5SGreg Clayton //---------------------------------------------------------------------- 6586611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter 6596611103cSGreg Clayton ( 6606611103cSGreg Clayton CommandInterpreter &interpreter, 661c9af18a5SGreg Clayton const char *completion_str, 662c9af18a5SGreg Clayton int match_start_point, 663c9af18a5SGreg Clayton int max_return_elements, 664c9af18a5SGreg Clayton StringList &matches 665c9af18a5SGreg Clayton ) : 6666611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 667c9af18a5SGreg Clayton { 668274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 669c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 670c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 671c9af18a5SGreg Clayton } 672c9af18a5SGreg Clayton 673c9af18a5SGreg Clayton Searcher::Depth 674c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 675c9af18a5SGreg Clayton { 676c9af18a5SGreg Clayton return eDepthModule; 677c9af18a5SGreg Clayton } 678c9af18a5SGreg Clayton 679c9af18a5SGreg Clayton Searcher::CallbackReturn 680c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback ( 681c9af18a5SGreg Clayton SearchFilter &filter, 682c9af18a5SGreg Clayton SymbolContext &context, 683c9af18a5SGreg Clayton Address *addr, 684c9af18a5SGreg Clayton bool complete 685c9af18a5SGreg Clayton ) 686c9af18a5SGreg Clayton { 687c9af18a5SGreg Clayton if (context.module_sp != NULL) 688c9af18a5SGreg Clayton { 689c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 690c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 691c9af18a5SGreg Clayton 692c9af18a5SGreg Clayton bool match = false; 693c9af18a5SGreg Clayton if (m_file_name && cur_file_name 694c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 695c9af18a5SGreg Clayton match = true; 696c9af18a5SGreg Clayton 697c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 698c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 699c9af18a5SGreg Clayton match = false; 700c9af18a5SGreg Clayton 701c9af18a5SGreg Clayton if (match) 702c9af18a5SGreg Clayton { 703c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 704c9af18a5SGreg Clayton } 705c9af18a5SGreg Clayton } 706c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 707c9af18a5SGreg Clayton } 708c9af18a5SGreg Clayton 709c9af18a5SGreg Clayton size_t 710c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 711c9af18a5SGreg Clayton { 712c9af18a5SGreg Clayton filter->Search (*this); 713c9af18a5SGreg Clayton return m_matches.GetSize(); 714c9af18a5SGreg Clayton } 715