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 // C Includes 11558ce124SJim Ingham #include <sys/stat.h> 12fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__) 137cc478b9SJim Ingham #include <pwd.h> 14fd18426eSGreg Clayton #endif 15558ce124SJim Ingham 16c9af18a5SGreg Clayton // C++ Includes 17c9af18a5SGreg Clayton // Other libraries and framework includes 18c8ecc2a9SEugene Zelenko #include "llvm/ADT/SmallString.h" 19c8ecc2a9SEugene Zelenko 20c9af18a5SGreg Clayton // Project includes 219b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h" 221f746071SGreg Clayton #include "lldb/Core/Module.h" 23*190fadcdSZachary Turner #include "lldb/Core/PluginManager.h" 24*190fadcdSZachary Turner #include "lldb/Host/FileSpec.h" 25*190fadcdSZachary Turner #include "lldb/Host/FileSystem.h" 269b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h" 279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 289b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 29633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 301f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 31f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 329b62fd2fSGreg Clayton #include "lldb/Target/Target.h" 339b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h" 34c9af18a5SGreg Clayton 35*190fadcdSZachary Turner #include "llvm/ADT/SmallString.h" 36*190fadcdSZachary Turner 37c9af18a5SGreg Clayton using namespace lldb_private; 38c9af18a5SGreg Clayton 39c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 40c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 41c9af18a5SGreg Clayton { 42c8ecc2a9SEugene Zelenko {eCustomCompletion, nullptr}, 43c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 44558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 45558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 46c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 47c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 483df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 49ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 50ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 51f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 52c8ecc2a9SEugene Zelenko {eNoCompletion, nullptr} // This one has to be last in the list. 53c9af18a5SGreg Clayton }; 54c9af18a5SGreg Clayton 55c9af18a5SGreg Clayton bool 56c8ecc2a9SEugene Zelenko CommandCompletions::InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, 576611103cSGreg Clayton uint32_t completion_mask, 58c9af18a5SGreg Clayton const char *completion_str, 59c9af18a5SGreg Clayton int match_start_point, 60c9af18a5SGreg Clayton int max_return_elements, 61c9af18a5SGreg Clayton SearchFilter *searcher, 62558ce124SJim Ingham bool &word_complete, 63c8ecc2a9SEugene Zelenko StringList &matches) 64c9af18a5SGreg Clayton { 65c9af18a5SGreg Clayton bool handled = false; 66c9af18a5SGreg Clayton 67c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 68c9af18a5SGreg Clayton return false; 69c9af18a5SGreg Clayton 70c9af18a5SGreg Clayton for (int i = 0; ; i++) 71c9af18a5SGreg Clayton { 72c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 73c9af18a5SGreg Clayton break; 74c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 75c8ecc2a9SEugene Zelenko && g_common_completions[i].callback != nullptr) 76c9af18a5SGreg Clayton { 77c9af18a5SGreg Clayton handled = true; 786611103cSGreg Clayton g_common_completions[i].callback (interpreter, 796611103cSGreg Clayton completion_str, 80c9af18a5SGreg Clayton match_start_point, 81c9af18a5SGreg Clayton max_return_elements, 82c9af18a5SGreg Clayton searcher, 83558ce124SJim Ingham word_complete, 84c9af18a5SGreg Clayton matches); 85c9af18a5SGreg Clayton } 86c9af18a5SGreg Clayton } 87c9af18a5SGreg Clayton return handled; 88c9af18a5SGreg Clayton } 89c9af18a5SGreg Clayton 90c9af18a5SGreg Clayton int 91c8ecc2a9SEugene Zelenko CommandCompletions::SourceFiles(CommandInterpreter &interpreter, 926611103cSGreg Clayton const char *partial_file_name, 93c9af18a5SGreg Clayton int match_start_point, 94c9af18a5SGreg Clayton int max_return_elements, 95c9af18a5SGreg Clayton SearchFilter *searcher, 96558ce124SJim Ingham bool &word_complete, 97c8ecc2a9SEugene Zelenko StringList &matches) 98c9af18a5SGreg Clayton { 99558ce124SJim Ingham word_complete = true; 100c9af18a5SGreg Clayton // Find some way to switch "include support files..." 1016611103cSGreg Clayton SourceFileCompleter completer (interpreter, 1026611103cSGreg Clayton false, 1036611103cSGreg Clayton partial_file_name, 1046611103cSGreg Clayton match_start_point, 1056611103cSGreg Clayton max_return_elements, 106c9af18a5SGreg Clayton matches); 107c9af18a5SGreg Clayton 108c8ecc2a9SEugene Zelenko if (searcher == nullptr) 109c9af18a5SGreg Clayton { 1102976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 11133df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher (target_sp); 112c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 113c9af18a5SGreg Clayton } 114c9af18a5SGreg Clayton else 115c9af18a5SGreg Clayton { 116c9af18a5SGreg Clayton completer.DoCompletion (searcher); 117c9af18a5SGreg Clayton } 118c9af18a5SGreg Clayton return matches.GetSize(); 119c9af18a5SGreg Clayton } 120c9af18a5SGreg Clayton 121b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton 122b2f1fb29SVirgile Bello { 123b2f1fb29SVirgile Bello const char *remainder; 124b2f1fb29SVirgile Bello char *partial_name_copy; 125b2f1fb29SVirgile Bello bool only_directories; 126b2f1fb29SVirgile Bello bool *saw_directory; 127b2f1fb29SVirgile Bello StringList *matches; 128b2f1fb29SVirgile Bello char *end_ptr; 129b2f1fb29SVirgile Bello size_t baselen; 1300b5e5f43SMichael Sartain } DiskFilesOrDirectoriesBaton; 131b2f1fb29SVirgile Bello 132b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec) 133b2f1fb29SVirgile Bello { 134b2f1fb29SVirgile Bello const char *name = spec.GetFilename().AsCString(); 135b2f1fb29SVirgile Bello 136b2f1fb29SVirgile Bello const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton; 137b2f1fb29SVirgile Bello char *end_ptr = parameters->end_ptr; 138b2f1fb29SVirgile Bello char *partial_name_copy = parameters->partial_name_copy; 139b2f1fb29SVirgile Bello const char *remainder = parameters->remainder; 140b2f1fb29SVirgile Bello 141b2f1fb29SVirgile Bello // Omit ".", ".." and any . files if the match string doesn't start with . 142b2f1fb29SVirgile Bello if (name[0] == '.') 143b2f1fb29SVirgile Bello { 144b2f1fb29SVirgile Bello if (name[1] == '\0') 145b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 146b2f1fb29SVirgile Bello else if (name[1] == '.' && name[2] == '\0') 147b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 148b2f1fb29SVirgile Bello else if (remainder[0] != '.') 149b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 150b2f1fb29SVirgile Bello } 151b2f1fb29SVirgile Bello 152b2f1fb29SVirgile Bello // If we found a directory, we put a "/" at the end of the name. 153b2f1fb29SVirgile Bello 154b2f1fb29SVirgile Bello if (remainder[0] == '\0' || strstr(name, remainder) == name) 155b2f1fb29SVirgile Bello { 156b2f1fb29SVirgile Bello if (strlen(name) + parameters->baselen >= PATH_MAX) 157b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 158b2f1fb29SVirgile Bello 159b2f1fb29SVirgile Bello strcpy(end_ptr, name); 160b2f1fb29SVirgile Bello 161b2f1fb29SVirgile Bello bool isa_directory = false; 162b2f1fb29SVirgile Bello if (file_type == FileSpec::eFileTypeDirectory) 163b2f1fb29SVirgile Bello isa_directory = true; 164b2f1fb29SVirgile Bello else if (file_type == FileSpec::eFileTypeSymbolicLink) 165b2f1fb29SVirgile Bello { 166*190fadcdSZachary Turner if (FileSpec(partial_name_copy, false).IsDirectory()) 167b2f1fb29SVirgile Bello isa_directory = true; 168b2f1fb29SVirgile Bello } 169b2f1fb29SVirgile Bello 170b2f1fb29SVirgile Bello if (isa_directory) 171b2f1fb29SVirgile Bello { 172b2f1fb29SVirgile Bello *parameters->saw_directory = true; 173b2f1fb29SVirgile Bello size_t len = strlen(parameters->partial_name_copy); 174b2f1fb29SVirgile Bello partial_name_copy[len] = '/'; 175b2f1fb29SVirgile Bello partial_name_copy[len + 1] = '\0'; 176b2f1fb29SVirgile Bello } 177b2f1fb29SVirgile Bello if (parameters->only_directories && !isa_directory) 178b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 179b2f1fb29SVirgile Bello parameters->matches->AppendString(partial_name_copy); 180b2f1fb29SVirgile Bello } 181b2f1fb29SVirgile Bello 182b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 183b2f1fb29SVirgile Bello } 184b2f1fb29SVirgile Bello 185558ce124SJim Ingham static int 186c8ecc2a9SEugene Zelenko DiskFilesOrDirectories(const char *partial_file_name, 187558ce124SJim Ingham bool only_directories, 188558ce124SJim Ingham bool &saw_directory, 189c8ecc2a9SEugene Zelenko StringList &matches) 190558ce124SJim Ingham { 191558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 192558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 193558ce124SJim Ingham 194c7bece56SGreg Clayton size_t partial_name_len = strlen(partial_file_name); 195558ce124SJim Ingham 196558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 197558ce124SJim Ingham return matches.GetSize(); 198558ce124SJim Ingham 199558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 200558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 201558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 202558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 203558ce124SJim Ingham // the form the user originally typed. 204558ce124SJim Ingham 205558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 206021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 207558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 208558ce124SJim Ingham 209710dd5aeSGreg Clayton // We'll need to save a copy of the remainder for comparison, which we do here. 210558ce124SJim Ingham char remainder[PATH_MAX]; 211558ce124SJim Ingham 212558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 213558ce124SJim Ingham char *end_ptr; 214558ce124SJim Ingham 215558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 216558ce124SJim Ingham 217558ce124SJim Ingham // This will store the resolved form of the containing directory 2183f559740SZachary Turner llvm::SmallString<64> containing_part; 219558ce124SJim Ingham 220c8ecc2a9SEugene Zelenko if (end_ptr == nullptr) 221558ce124SJim Ingham { 222558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 223558ce124SJim Ingham // user name. 224558ce124SJim Ingham if (*partial_name_copy == '~') 225558ce124SJim Ingham { 226558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 2277cc478b9SJim Ingham // but for completeness sake we'll resolve the user name and only put a slash 228558ce124SJim Ingham // on the end if it exists. 2293f559740SZachary Turner llvm::SmallString<64> resolved_username(partial_name_copy); 2303f559740SZachary Turner FileSpec::ResolveUsername (resolved_username); 2317cc478b9SJim Ingham 2327cc478b9SJim Ingham // Not sure how this would happen, a username longer than PATH_MAX? Still... 2333f559740SZachary Turner if (resolved_username.size() == 0) 2347cc478b9SJim Ingham { 2357cc478b9SJim Ingham // The user name didn't resolve, let's look in the password database for matches. 2367cc478b9SJim Ingham // The user name database contains duplicates, and is not in alphabetical order, so 2377cc478b9SJim Ingham // we'll use a set to manage that for us. 23884363078SJim Ingham FileSpec::ResolvePartialUsername (partial_name_copy, matches); 23984363078SJim Ingham if (matches.GetSize() > 0) 2407cc478b9SJim Ingham saw_directory = true; 2417cc478b9SJim Ingham return matches.GetSize(); 2427cc478b9SJim Ingham } 24384363078SJim Ingham else 24484363078SJim Ingham { 245558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 246558ce124SJim Ingham // FIXME: complete user names here: 247558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 248558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 249558ce124SJim Ingham matches.AppendString(partial_name_copy); 250021b605dSBenjamin Kramer saw_directory = true; 251558ce124SJim Ingham return matches.GetSize(); 252558ce124SJim Ingham } 25384363078SJim Ingham } 254558ce124SJim Ingham else 255558ce124SJim Ingham { 256558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 2573f559740SZachary Turner containing_part = "."; 258558ce124SJim Ingham strcpy(remainder, partial_name_copy); 259558ce124SJim Ingham end_ptr = partial_name_copy; 260558ce124SJim Ingham } 261558ce124SJim Ingham } 262558ce124SJim Ingham else 263558ce124SJim Ingham { 264558ce124SJim Ingham if (end_ptr == partial_name_copy) 265558ce124SJim Ingham { 266558ce124SJim Ingham // We're completing a file or directory in the root volume. 2673f559740SZachary Turner containing_part = "/"; 268558ce124SJim Ingham } 269558ce124SJim Ingham else 270558ce124SJim Ingham { 2713f559740SZachary Turner containing_part.append(partial_name_copy, end_ptr); 272558ce124SJim Ingham } 273558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 274558ce124SJim Ingham end_ptr++; 275558ce124SJim Ingham strcpy(remainder, end_ptr); 276558ce124SJim Ingham } 277558ce124SJim Ingham 2787cc478b9SJim Ingham // Look for a user name in the containing part, and if it's there, resolve it and stick the 279558ce124SJim Ingham // result back into the containing_part: 280558ce124SJim Ingham 281558ce124SJim Ingham if (*partial_name_copy == '~') 282558ce124SJim Ingham { 2833f559740SZachary Turner FileSpec::ResolveUsername(containing_part); 284558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 2853f559740SZachary Turner if (containing_part.empty()) 286558ce124SJim Ingham return matches.GetSize(); 287558ce124SJim Ingham } 288558ce124SJim Ingham 289558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 290558ce124SJim Ingham 291558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 292558ce124SJim Ingham 293b2f1fb29SVirgile Bello DiskFilesOrDirectoriesBaton parameters; 294b2f1fb29SVirgile Bello parameters.remainder = remainder; 295b2f1fb29SVirgile Bello parameters.partial_name_copy = partial_name_copy; 296b2f1fb29SVirgile Bello parameters.only_directories = only_directories; 297b2f1fb29SVirgile Bello parameters.saw_directory = &saw_directory; 298b2f1fb29SVirgile Bello parameters.matches = &matches; 299b2f1fb29SVirgile Bello parameters.end_ptr = end_ptr; 300b2f1fb29SVirgile Bello parameters.baselen = baselen; 301558ce124SJim Ingham 3023f559740SZachary Turner FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, ¶meters); 303558ce124SJim Ingham 304558ce124SJim Ingham return matches.GetSize(); 305558ce124SJim Ingham } 306558ce124SJim Ingham 307558ce124SJim Ingham int 308c8ecc2a9SEugene Zelenko CommandCompletions::DiskFiles(CommandInterpreter &interpreter, 309558ce124SJim Ingham const char *partial_file_name, 310558ce124SJim Ingham int match_start_point, 311558ce124SJim Ingham int max_return_elements, 312558ce124SJim Ingham SearchFilter *searcher, 313558ce124SJim Ingham bool &word_complete, 314c8ecc2a9SEugene Zelenko StringList &matches) 315558ce124SJim Ingham { 316558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 317558ce124SJim Ingham false, 318558ce124SJim Ingham word_complete, 319558ce124SJim Ingham matches); 320558ce124SJim Ingham word_complete = !word_complete; 321558ce124SJim Ingham return ret_val; 322558ce124SJim Ingham } 323558ce124SJim Ingham 324558ce124SJim Ingham int 325c8ecc2a9SEugene Zelenko CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, 326558ce124SJim Ingham const char *partial_file_name, 327558ce124SJim Ingham int match_start_point, 328558ce124SJim Ingham int max_return_elements, 329558ce124SJim Ingham SearchFilter *searcher, 330558ce124SJim Ingham bool &word_complete, 331c8ecc2a9SEugene Zelenko StringList &matches) 332558ce124SJim Ingham { 333558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 334558ce124SJim Ingham true, 335558ce124SJim Ingham word_complete, 336558ce124SJim Ingham matches); 337558ce124SJim Ingham word_complete = false; 338558ce124SJim Ingham return ret_val; 339558ce124SJim Ingham } 340558ce124SJim Ingham 341c9af18a5SGreg Clayton int 342c8ecc2a9SEugene Zelenko CommandCompletions::Modules(CommandInterpreter &interpreter, 3436611103cSGreg Clayton const char *partial_file_name, 344c9af18a5SGreg Clayton int match_start_point, 345c9af18a5SGreg Clayton int max_return_elements, 346c9af18a5SGreg Clayton SearchFilter *searcher, 347558ce124SJim Ingham bool &word_complete, 348c8ecc2a9SEugene Zelenko StringList &matches) 349c9af18a5SGreg Clayton { 350558ce124SJim Ingham word_complete = true; 3516611103cSGreg Clayton ModuleCompleter completer (interpreter, 3526611103cSGreg Clayton partial_file_name, 3536611103cSGreg Clayton match_start_point, 3546611103cSGreg Clayton max_return_elements, 3556611103cSGreg Clayton matches); 356c9af18a5SGreg Clayton 357c8ecc2a9SEugene Zelenko if (searcher == nullptr) 358c9af18a5SGreg Clayton { 3592976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 36033df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher (target_sp); 361c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 362c9af18a5SGreg Clayton } 363c9af18a5SGreg Clayton else 364c9af18a5SGreg Clayton { 365c9af18a5SGreg Clayton completer.DoCompletion (searcher); 366c9af18a5SGreg Clayton } 367c9af18a5SGreg Clayton return matches.GetSize(); 368c9af18a5SGreg Clayton } 369c9af18a5SGreg Clayton 370c9af18a5SGreg Clayton int 371c8ecc2a9SEugene Zelenko CommandCompletions::Symbols(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 386c8ecc2a9SEugene Zelenko if (searcher == nullptr) 387c9af18a5SGreg Clayton { 3882976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 38933df7cd3SJim Ingham SearchFilterForUnconstrainedSearches 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 { 40867cc0636SGreg Clayton // Cache the full setting name list 40967cc0636SGreg Clayton static StringList g_property_names; 41067cc0636SGreg Clayton if (g_property_names.GetSize() == 0) 41167cc0636SGreg Clayton { 41267cc0636SGreg Clayton // Generate the full setting name list on demand 41367cc0636SGreg Clayton lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties()); 41467cc0636SGreg Clayton if (properties_sp) 41567cc0636SGreg Clayton { 41667cc0636SGreg Clayton StreamString strm; 417c8ecc2a9SEugene Zelenko properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); 41867cc0636SGreg Clayton const std::string &str = strm.GetString(); 41967cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 42067cc0636SGreg Clayton } 42167cc0636SGreg Clayton } 4223df9a8dfSCaroline Tice 42367cc0636SGreg Clayton size_t exact_matches_idx = SIZE_MAX; 42467cc0636SGreg Clayton const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx); 42567cc0636SGreg Clayton word_complete = exact_matches_idx != SIZE_MAX; 42667cc0636SGreg Clayton return num_matches; 4273df9a8dfSCaroline Tice } 4283df9a8dfSCaroline Tice 429ab65b34fSGreg Clayton int 430ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter, 431ab65b34fSGreg Clayton const char *partial_name, 432ab65b34fSGreg Clayton int match_start_point, 433ab65b34fSGreg Clayton int max_return_elements, 434ab65b34fSGreg Clayton SearchFilter *searcher, 435ab65b34fSGreg Clayton bool &word_complete, 436ab65b34fSGreg Clayton lldb_private::StringList &matches) 437ab65b34fSGreg Clayton { 438ab65b34fSGreg Clayton const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches); 439ab65b34fSGreg Clayton word_complete = num_matches == 1; 440ab65b34fSGreg Clayton return num_matches; 441ab65b34fSGreg Clayton } 442ab65b34fSGreg Clayton 443ab65b34fSGreg Clayton int 444ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter, 445ab65b34fSGreg Clayton const char *partial_name, 446ab65b34fSGreg Clayton int match_start_point, 447ab65b34fSGreg Clayton int max_return_elements, 448ab65b34fSGreg Clayton SearchFilter *searcher, 449ab65b34fSGreg Clayton bool &word_complete, 450ab65b34fSGreg Clayton lldb_private::StringList &matches) 451ab65b34fSGreg Clayton { 452ab65b34fSGreg Clayton const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches); 453ab65b34fSGreg Clayton word_complete = num_matches == 1; 454ab65b34fSGreg Clayton return num_matches; 455ab65b34fSGreg Clayton } 456ab65b34fSGreg Clayton 457f21feadcSGreg Clayton int 458f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter, 459f21feadcSGreg Clayton const char *partial_name, 460f21feadcSGreg Clayton int match_start_point, 461f21feadcSGreg Clayton int max_return_elements, 462f21feadcSGreg Clayton SearchFilter *searcher, 463f21feadcSGreg Clayton bool &word_complete, 464f21feadcSGreg Clayton lldb_private::StringList &matches) 465f21feadcSGreg Clayton { 466f21feadcSGreg Clayton return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete); 467f21feadcSGreg Clayton } 468f21feadcSGreg Clayton 469c8ecc2a9SEugene Zelenko CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, 470c9af18a5SGreg Clayton const char *completion_str, 471c9af18a5SGreg Clayton int match_start_point, 472c9af18a5SGreg Clayton int max_return_elements, 473c8ecc2a9SEugene Zelenko StringList &matches) : 4746611103cSGreg Clayton m_interpreter (interpreter), 475c9af18a5SGreg Clayton m_completion_str (completion_str), 476c9af18a5SGreg Clayton m_match_start_point (match_start_point), 477c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 478c9af18a5SGreg Clayton m_matches (matches) 479c9af18a5SGreg Clayton { 480c9af18a5SGreg Clayton } 481c9af18a5SGreg Clayton 482c8ecc2a9SEugene Zelenko CommandCompletions::Completer::~Completer() = default; 483c9af18a5SGreg Clayton 484c9af18a5SGreg Clayton //---------------------------------------------------------------------- 485c9af18a5SGreg Clayton // SourceFileCompleter 486c9af18a5SGreg Clayton //---------------------------------------------------------------------- 487c9af18a5SGreg Clayton 488c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SourceFileCompleter(CommandInterpreter &interpreter, 489c9af18a5SGreg Clayton bool include_support_files, 490c9af18a5SGreg Clayton const char *completion_str, 491c9af18a5SGreg Clayton int match_start_point, 492c9af18a5SGreg Clayton int max_return_elements, 493c8ecc2a9SEugene Zelenko StringList &matches) : 4946611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 495c9af18a5SGreg Clayton m_include_support_files (include_support_files), 496c9af18a5SGreg Clayton m_matching_files() 497c9af18a5SGreg Clayton { 498274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 499c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 500c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 501c9af18a5SGreg Clayton } 502c9af18a5SGreg Clayton 503c9af18a5SGreg Clayton Searcher::Depth 504c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 505c9af18a5SGreg Clayton { 506c9af18a5SGreg Clayton return eDepthCompUnit; 507c9af18a5SGreg Clayton } 508c9af18a5SGreg Clayton 509c9af18a5SGreg Clayton Searcher::CallbackReturn 510c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, 511c9af18a5SGreg Clayton SymbolContext &context, 512c9af18a5SGreg Clayton Address *addr, 513c8ecc2a9SEugene Zelenko bool complete) 514c9af18a5SGreg Clayton { 515c8ecc2a9SEugene Zelenko if (context.comp_unit != nullptr) 516c9af18a5SGreg Clayton { 517c9af18a5SGreg Clayton if (m_include_support_files) 518c9af18a5SGreg Clayton { 519c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 520c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 521c9af18a5SGreg Clayton { 522c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 523c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 524c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 525c9af18a5SGreg Clayton bool match = false; 526c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 527c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 528c9af18a5SGreg Clayton match = true; 529c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 530c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 531c9af18a5SGreg Clayton match = false; 532c9af18a5SGreg Clayton 533c9af18a5SGreg Clayton if (match) 534c9af18a5SGreg Clayton { 535c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 536c9af18a5SGreg Clayton } 537c9af18a5SGreg Clayton } 538c9af18a5SGreg Clayton } 539c9af18a5SGreg Clayton else 540c9af18a5SGreg Clayton { 541c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 542c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 543c9af18a5SGreg Clayton 544c9af18a5SGreg Clayton bool match = false; 545c9af18a5SGreg Clayton if (m_file_name && cur_file_name 546c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 547c9af18a5SGreg Clayton match = true; 548c9af18a5SGreg Clayton 549c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 550c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 551c9af18a5SGreg Clayton match = false; 552c9af18a5SGreg Clayton 553c9af18a5SGreg Clayton if (match) 554c9af18a5SGreg Clayton { 555c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 556c9af18a5SGreg Clayton } 557c9af18a5SGreg Clayton } 558c9af18a5SGreg Clayton } 559c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 560c9af18a5SGreg Clayton } 561c9af18a5SGreg Clayton 562c9af18a5SGreg Clayton size_t 563c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 564c9af18a5SGreg Clayton { 565c9af18a5SGreg Clayton filter->Search (*this); 566c9af18a5SGreg Clayton // Now convert the filelist to completions: 567c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 568c9af18a5SGreg Clayton { 569c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 570c9af18a5SGreg Clayton } 571c9af18a5SGreg Clayton return m_matches.GetSize(); 572c9af18a5SGreg Clayton } 573c9af18a5SGreg Clayton 574c9af18a5SGreg Clayton //---------------------------------------------------------------------- 575c9af18a5SGreg Clayton // SymbolCompleter 576c9af18a5SGreg Clayton //---------------------------------------------------------------------- 577c9af18a5SGreg Clayton 578c9af18a5SGreg Clayton static bool 579c9af18a5SGreg Clayton regex_chars (const char comp) 580c9af18a5SGreg Clayton { 581c8ecc2a9SEugene Zelenko return (comp == '[' || comp == ']' || 582649f8b9bSGreg Clayton comp == '(' || comp == ')' || 583649f8b9bSGreg Clayton comp == '{' || comp == '}' || 584649f8b9bSGreg Clayton comp == '+' || 585649f8b9bSGreg Clayton comp == '.' || 586649f8b9bSGreg Clayton comp == '*' || 587649f8b9bSGreg Clayton comp == '|' || 588649f8b9bSGreg Clayton comp == '^' || 589649f8b9bSGreg Clayton comp == '$' || 590649f8b9bSGreg Clayton comp == '\\' || 591c8ecc2a9SEugene Zelenko comp == '?'); 592c9af18a5SGreg Clayton } 593c8ecc2a9SEugene Zelenko 594c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SymbolCompleter(CommandInterpreter &interpreter, 595c9af18a5SGreg Clayton const char *completion_str, 596c9af18a5SGreg Clayton int match_start_point, 597c9af18a5SGreg Clayton int max_return_elements, 598c8ecc2a9SEugene Zelenko StringList &matches) : 5996611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 600c9af18a5SGreg Clayton { 601649f8b9bSGreg Clayton std::string regex_str; 602649f8b9bSGreg Clayton if (completion_str && completion_str[0]) 603649f8b9bSGreg Clayton { 604649f8b9bSGreg Clayton regex_str.append("^"); 605c9af18a5SGreg Clayton regex_str.append(completion_str); 606649f8b9bSGreg Clayton } 607649f8b9bSGreg Clayton else 608649f8b9bSGreg Clayton { 609649f8b9bSGreg Clayton // Match anything since the completion string is empty 610649f8b9bSGreg Clayton regex_str.append("."); 611649f8b9bSGreg Clayton } 612649f8b9bSGreg Clayton std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 613649f8b9bSGreg Clayton while (pos < regex_str.end()) 614649f8b9bSGreg Clayton { 615c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 616649f8b9bSGreg Clayton pos = find_if(pos + 2, regex_str.end(), regex_chars); 617c9af18a5SGreg Clayton } 618c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 619c9af18a5SGreg Clayton } 620c9af18a5SGreg Clayton 621c9af18a5SGreg Clayton Searcher::Depth 622c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 623c9af18a5SGreg Clayton { 624c9af18a5SGreg Clayton return eDepthModule; 625c9af18a5SGreg Clayton } 626c9af18a5SGreg Clayton 627c9af18a5SGreg Clayton Searcher::CallbackReturn 628c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter, 629c9af18a5SGreg Clayton SymbolContext &context, 630c9af18a5SGreg Clayton Address *addr, 631c8ecc2a9SEugene Zelenko bool complete) 632c9af18a5SGreg Clayton { 633c9af18a5SGreg Clayton if (context.module_sp) 634c9af18a5SGreg Clayton { 635931180e6SGreg Clayton SymbolContextList sc_list; 636931180e6SGreg Clayton const bool include_symbols = true; 6379df05fbbSSean Callanan const bool include_inlines = true; 638931180e6SGreg Clayton const bool append = true; 6399df05fbbSSean Callanan context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list); 640c9af18a5SGreg Clayton 641c9af18a5SGreg Clayton SymbolContext sc; 642c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 643931180e6SGreg Clayton for (uint32_t i = 0; i < sc_list.GetSize(); i++) 644c9af18a5SGreg Clayton { 645931180e6SGreg Clayton if (sc_list.GetContextAtIndex(i, sc)) 646c9af18a5SGreg Clayton { 647530a413cSJim Ingham ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 648530a413cSJim Ingham if (!func_name.IsEmpty()) 649530a413cSJim Ingham m_match_set.insert (func_name); 650c9af18a5SGreg Clayton } 651c9af18a5SGreg Clayton } 652c9af18a5SGreg Clayton } 653c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 654c9af18a5SGreg Clayton } 655c9af18a5SGreg Clayton 656c9af18a5SGreg Clayton size_t 657c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 658c9af18a5SGreg Clayton { 659c9af18a5SGreg Clayton filter->Search (*this); 660c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 661c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 662c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 663c9af18a5SGreg Clayton 664c9af18a5SGreg Clayton return m_matches.GetSize(); 665c9af18a5SGreg Clayton } 666c9af18a5SGreg Clayton 667c9af18a5SGreg Clayton //---------------------------------------------------------------------- 668c9af18a5SGreg Clayton // ModuleCompleter 669c9af18a5SGreg Clayton //---------------------------------------------------------------------- 670c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::ModuleCompleter(CommandInterpreter &interpreter, 671c9af18a5SGreg Clayton const char *completion_str, 672c9af18a5SGreg Clayton int match_start_point, 673c9af18a5SGreg Clayton int max_return_elements, 674c8ecc2a9SEugene Zelenko StringList &matches) : 6756611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 676c9af18a5SGreg Clayton { 677274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 678c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 679c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 680c9af18a5SGreg Clayton } 681c9af18a5SGreg Clayton 682c9af18a5SGreg Clayton Searcher::Depth 683c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 684c9af18a5SGreg Clayton { 685c9af18a5SGreg Clayton return eDepthModule; 686c9af18a5SGreg Clayton } 687c9af18a5SGreg Clayton 688c9af18a5SGreg Clayton Searcher::CallbackReturn 689c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::SearchCallback(SearchFilter &filter, 690c9af18a5SGreg Clayton SymbolContext &context, 691c9af18a5SGreg Clayton Address *addr, 692c8ecc2a9SEugene Zelenko bool complete) 693c9af18a5SGreg Clayton { 694747bcb03SGreg Clayton if (context.module_sp) 695c9af18a5SGreg Clayton { 696c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 697c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 698c9af18a5SGreg Clayton 699c9af18a5SGreg Clayton bool match = false; 700c9af18a5SGreg Clayton if (m_file_name && cur_file_name 701c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 702c9af18a5SGreg Clayton match = true; 703c9af18a5SGreg Clayton 704c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 705c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 706c9af18a5SGreg Clayton match = false; 707c9af18a5SGreg Clayton 708c9af18a5SGreg Clayton if (match) 709c9af18a5SGreg Clayton { 710c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 711c9af18a5SGreg Clayton } 712c9af18a5SGreg Clayton } 713c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 714c9af18a5SGreg Clayton } 715c9af18a5SGreg Clayton 716c9af18a5SGreg Clayton size_t 717c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 718c9af18a5SGreg Clayton { 719c9af18a5SGreg Clayton filter->Search (*this); 720c9af18a5SGreg Clayton return m_matches.GetSize(); 721c9af18a5SGreg Clayton } 722