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 18*c8ecc2a9SEugene Zelenko #include "llvm/ADT/SmallString.h" 19*c8ecc2a9SEugene Zelenko 20c9af18a5SGreg Clayton // Project includes 2153239f00SGreg Clayton #include "lldb/Host/FileSpec.h" 229b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h" 23ab65b34fSGreg Clayton #include "lldb/Core/PluginManager.h" 241f746071SGreg Clayton #include "lldb/Core/Module.h" 259b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h" 269b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 28633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 291f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 30f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 319b62fd2fSGreg Clayton #include "lldb/Target/Target.h" 329b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h" 33c9af18a5SGreg Clayton 34c9af18a5SGreg Clayton using namespace lldb_private; 35c9af18a5SGreg Clayton 36c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 37c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 38c9af18a5SGreg Clayton { 39*c8ecc2a9SEugene Zelenko {eCustomCompletion, nullptr}, 40c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 41558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 42558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 43c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 44c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 453df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 46ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 47ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 48f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 49*c8ecc2a9SEugene Zelenko {eNoCompletion, nullptr} // This one has to be last in the list. 50c9af18a5SGreg Clayton }; 51c9af18a5SGreg Clayton 52c9af18a5SGreg Clayton bool 53*c8ecc2a9SEugene Zelenko CommandCompletions::InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, 546611103cSGreg Clayton uint32_t completion_mask, 55c9af18a5SGreg Clayton const char *completion_str, 56c9af18a5SGreg Clayton int match_start_point, 57c9af18a5SGreg Clayton int max_return_elements, 58c9af18a5SGreg Clayton SearchFilter *searcher, 59558ce124SJim Ingham bool &word_complete, 60*c8ecc2a9SEugene Zelenko StringList &matches) 61c9af18a5SGreg Clayton { 62c9af18a5SGreg Clayton bool handled = false; 63c9af18a5SGreg Clayton 64c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 65c9af18a5SGreg Clayton return false; 66c9af18a5SGreg Clayton 67c9af18a5SGreg Clayton for (int i = 0; ; i++) 68c9af18a5SGreg Clayton { 69c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 70c9af18a5SGreg Clayton break; 71c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 72*c8ecc2a9SEugene Zelenko && g_common_completions[i].callback != nullptr) 73c9af18a5SGreg Clayton { 74c9af18a5SGreg Clayton handled = true; 756611103cSGreg Clayton g_common_completions[i].callback (interpreter, 766611103cSGreg Clayton completion_str, 77c9af18a5SGreg Clayton match_start_point, 78c9af18a5SGreg Clayton max_return_elements, 79c9af18a5SGreg Clayton searcher, 80558ce124SJim Ingham word_complete, 81c9af18a5SGreg Clayton matches); 82c9af18a5SGreg Clayton } 83c9af18a5SGreg Clayton } 84c9af18a5SGreg Clayton return handled; 85c9af18a5SGreg Clayton } 86c9af18a5SGreg Clayton 87c9af18a5SGreg Clayton int 88*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFiles(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, 94*c8ecc2a9SEugene Zelenko StringList &matches) 95c9af18a5SGreg Clayton { 96558ce124SJim Ingham word_complete = true; 97c9af18a5SGreg Clayton // Find some way to switch "include support files..." 986611103cSGreg Clayton SourceFileCompleter completer (interpreter, 996611103cSGreg Clayton false, 1006611103cSGreg Clayton partial_file_name, 1016611103cSGreg Clayton match_start_point, 1026611103cSGreg Clayton max_return_elements, 103c9af18a5SGreg Clayton matches); 104c9af18a5SGreg Clayton 105*c8ecc2a9SEugene Zelenko if (searcher == nullptr) 106c9af18a5SGreg Clayton { 1072976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 10833df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher (target_sp); 109c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 110c9af18a5SGreg Clayton } 111c9af18a5SGreg Clayton else 112c9af18a5SGreg Clayton { 113c9af18a5SGreg Clayton completer.DoCompletion (searcher); 114c9af18a5SGreg Clayton } 115c9af18a5SGreg Clayton return matches.GetSize(); 116c9af18a5SGreg Clayton } 117c9af18a5SGreg Clayton 118b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton 119b2f1fb29SVirgile Bello { 120b2f1fb29SVirgile Bello const char *remainder; 121b2f1fb29SVirgile Bello char *partial_name_copy; 122b2f1fb29SVirgile Bello bool only_directories; 123b2f1fb29SVirgile Bello bool *saw_directory; 124b2f1fb29SVirgile Bello StringList *matches; 125b2f1fb29SVirgile Bello char *end_ptr; 126b2f1fb29SVirgile Bello size_t baselen; 1270b5e5f43SMichael Sartain } DiskFilesOrDirectoriesBaton; 128b2f1fb29SVirgile Bello 129b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec) 130b2f1fb29SVirgile Bello { 131b2f1fb29SVirgile Bello const char *name = spec.GetFilename().AsCString(); 132b2f1fb29SVirgile Bello 133b2f1fb29SVirgile Bello const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton; 134b2f1fb29SVirgile Bello char *end_ptr = parameters->end_ptr; 135b2f1fb29SVirgile Bello char *partial_name_copy = parameters->partial_name_copy; 136b2f1fb29SVirgile Bello const char *remainder = parameters->remainder; 137b2f1fb29SVirgile Bello 138b2f1fb29SVirgile Bello // Omit ".", ".." and any . files if the match string doesn't start with . 139b2f1fb29SVirgile Bello if (name[0] == '.') 140b2f1fb29SVirgile Bello { 141b2f1fb29SVirgile Bello if (name[1] == '\0') 142b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 143b2f1fb29SVirgile Bello else if (name[1] == '.' && name[2] == '\0') 144b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 145b2f1fb29SVirgile Bello else if (remainder[0] != '.') 146b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 147b2f1fb29SVirgile Bello } 148b2f1fb29SVirgile Bello 149b2f1fb29SVirgile Bello // If we found a directory, we put a "/" at the end of the name. 150b2f1fb29SVirgile Bello 151b2f1fb29SVirgile Bello if (remainder[0] == '\0' || strstr(name, remainder) == name) 152b2f1fb29SVirgile Bello { 153b2f1fb29SVirgile Bello if (strlen(name) + parameters->baselen >= PATH_MAX) 154b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 155b2f1fb29SVirgile Bello 156b2f1fb29SVirgile Bello strcpy(end_ptr, name); 157b2f1fb29SVirgile Bello 158b2f1fb29SVirgile Bello bool isa_directory = false; 159b2f1fb29SVirgile Bello if (file_type == FileSpec::eFileTypeDirectory) 160b2f1fb29SVirgile Bello isa_directory = true; 161b2f1fb29SVirgile Bello else if (file_type == FileSpec::eFileTypeSymbolicLink) 162b2f1fb29SVirgile Bello { 163b2f1fb29SVirgile Bello struct stat stat_buf; 164b2f1fb29SVirgile Bello if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) 165b2f1fb29SVirgile Bello isa_directory = true; 166b2f1fb29SVirgile Bello } 167b2f1fb29SVirgile Bello 168b2f1fb29SVirgile Bello if (isa_directory) 169b2f1fb29SVirgile Bello { 170b2f1fb29SVirgile Bello *parameters->saw_directory = true; 171b2f1fb29SVirgile Bello size_t len = strlen(parameters->partial_name_copy); 172b2f1fb29SVirgile Bello partial_name_copy[len] = '/'; 173b2f1fb29SVirgile Bello partial_name_copy[len + 1] = '\0'; 174b2f1fb29SVirgile Bello } 175b2f1fb29SVirgile Bello if (parameters->only_directories && !isa_directory) 176b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 177b2f1fb29SVirgile Bello parameters->matches->AppendString(partial_name_copy); 178b2f1fb29SVirgile Bello } 179b2f1fb29SVirgile Bello 180b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 181b2f1fb29SVirgile Bello } 182b2f1fb29SVirgile Bello 183558ce124SJim Ingham static int 184*c8ecc2a9SEugene Zelenko DiskFilesOrDirectories(const char *partial_file_name, 185558ce124SJim Ingham bool only_directories, 186558ce124SJim Ingham bool &saw_directory, 187*c8ecc2a9SEugene Zelenko StringList &matches) 188558ce124SJim Ingham { 189558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 190558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 191558ce124SJim Ingham 192c7bece56SGreg Clayton size_t partial_name_len = strlen(partial_file_name); 193558ce124SJim Ingham 194558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 195558ce124SJim Ingham return matches.GetSize(); 196558ce124SJim Ingham 197558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 198558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 199558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 200558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 201558ce124SJim Ingham // the form the user originally typed. 202558ce124SJim Ingham 203558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 204021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 205558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 206558ce124SJim Ingham 207710dd5aeSGreg Clayton // We'll need to save a copy of the remainder for comparison, which we do here. 208558ce124SJim Ingham char remainder[PATH_MAX]; 209558ce124SJim Ingham 210558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 211558ce124SJim Ingham char *end_ptr; 212558ce124SJim Ingham 213558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 214558ce124SJim Ingham 215558ce124SJim Ingham // This will store the resolved form of the containing directory 2163f559740SZachary Turner llvm::SmallString<64> containing_part; 217558ce124SJim Ingham 218*c8ecc2a9SEugene Zelenko if (end_ptr == nullptr) 219558ce124SJim Ingham { 220558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 221558ce124SJim Ingham // user name. 222558ce124SJim Ingham if (*partial_name_copy == '~') 223558ce124SJim Ingham { 224558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 2257cc478b9SJim Ingham // but for completeness sake we'll resolve the user name and only put a slash 226558ce124SJim Ingham // on the end if it exists. 2273f559740SZachary Turner llvm::SmallString<64> resolved_username(partial_name_copy); 2283f559740SZachary Turner FileSpec::ResolveUsername (resolved_username); 2297cc478b9SJim Ingham 2307cc478b9SJim Ingham // Not sure how this would happen, a username longer than PATH_MAX? Still... 2313f559740SZachary Turner if (resolved_username.size() == 0) 2327cc478b9SJim Ingham { 2337cc478b9SJim Ingham // The user name didn't resolve, let's look in the password database for matches. 2347cc478b9SJim Ingham // The user name database contains duplicates, and is not in alphabetical order, so 2357cc478b9SJim Ingham // we'll use a set to manage that for us. 23684363078SJim Ingham FileSpec::ResolvePartialUsername (partial_name_copy, matches); 23784363078SJim Ingham if (matches.GetSize() > 0) 2387cc478b9SJim Ingham saw_directory = true; 2397cc478b9SJim Ingham return matches.GetSize(); 2407cc478b9SJim Ingham } 24184363078SJim Ingham else 24284363078SJim Ingham { 243558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 244558ce124SJim Ingham // FIXME: complete user names here: 245558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 246558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 247558ce124SJim Ingham matches.AppendString(partial_name_copy); 248021b605dSBenjamin Kramer saw_directory = true; 249558ce124SJim Ingham return matches.GetSize(); 250558ce124SJim Ingham } 25184363078SJim Ingham } 252558ce124SJim Ingham else 253558ce124SJim Ingham { 254558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 2553f559740SZachary Turner containing_part = "."; 256558ce124SJim Ingham strcpy(remainder, partial_name_copy); 257558ce124SJim Ingham end_ptr = partial_name_copy; 258558ce124SJim Ingham } 259558ce124SJim Ingham } 260558ce124SJim Ingham else 261558ce124SJim Ingham { 262558ce124SJim Ingham if (end_ptr == partial_name_copy) 263558ce124SJim Ingham { 264558ce124SJim Ingham // We're completing a file or directory in the root volume. 2653f559740SZachary Turner containing_part = "/"; 266558ce124SJim Ingham } 267558ce124SJim Ingham else 268558ce124SJim Ingham { 2693f559740SZachary Turner containing_part.append(partial_name_copy, end_ptr); 270558ce124SJim Ingham } 271558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 272558ce124SJim Ingham end_ptr++; 273558ce124SJim Ingham strcpy(remainder, end_ptr); 274558ce124SJim Ingham } 275558ce124SJim Ingham 2767cc478b9SJim Ingham // Look for a user name in the containing part, and if it's there, resolve it and stick the 277558ce124SJim Ingham // result back into the containing_part: 278558ce124SJim Ingham 279558ce124SJim Ingham if (*partial_name_copy == '~') 280558ce124SJim Ingham { 2813f559740SZachary Turner FileSpec::ResolveUsername(containing_part); 282558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 2833f559740SZachary Turner if (containing_part.empty()) 284558ce124SJim Ingham return matches.GetSize(); 285558ce124SJim Ingham } 286558ce124SJim Ingham 287558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 288558ce124SJim Ingham 289558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 290558ce124SJim Ingham 291b2f1fb29SVirgile Bello DiskFilesOrDirectoriesBaton parameters; 292b2f1fb29SVirgile Bello parameters.remainder = remainder; 293b2f1fb29SVirgile Bello parameters.partial_name_copy = partial_name_copy; 294b2f1fb29SVirgile Bello parameters.only_directories = only_directories; 295b2f1fb29SVirgile Bello parameters.saw_directory = &saw_directory; 296b2f1fb29SVirgile Bello parameters.matches = &matches; 297b2f1fb29SVirgile Bello parameters.end_ptr = end_ptr; 298b2f1fb29SVirgile Bello parameters.baselen = baselen; 299558ce124SJim Ingham 3003f559740SZachary Turner FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, ¶meters); 301558ce124SJim Ingham 302558ce124SJim Ingham return matches.GetSize(); 303558ce124SJim Ingham } 304558ce124SJim Ingham 305558ce124SJim Ingham int 306*c8ecc2a9SEugene Zelenko CommandCompletions::DiskFiles(CommandInterpreter &interpreter, 307558ce124SJim Ingham const char *partial_file_name, 308558ce124SJim Ingham int match_start_point, 309558ce124SJim Ingham int max_return_elements, 310558ce124SJim Ingham SearchFilter *searcher, 311558ce124SJim Ingham bool &word_complete, 312*c8ecc2a9SEugene Zelenko StringList &matches) 313558ce124SJim Ingham { 314558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 315558ce124SJim Ingham false, 316558ce124SJim Ingham word_complete, 317558ce124SJim Ingham matches); 318558ce124SJim Ingham word_complete = !word_complete; 319558ce124SJim Ingham return ret_val; 320558ce124SJim Ingham } 321558ce124SJim Ingham 322558ce124SJim Ingham int 323*c8ecc2a9SEugene Zelenko CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, 324558ce124SJim Ingham const char *partial_file_name, 325558ce124SJim Ingham int match_start_point, 326558ce124SJim Ingham int max_return_elements, 327558ce124SJim Ingham SearchFilter *searcher, 328558ce124SJim Ingham bool &word_complete, 329*c8ecc2a9SEugene Zelenko StringList &matches) 330558ce124SJim Ingham { 331558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 332558ce124SJim Ingham true, 333558ce124SJim Ingham word_complete, 334558ce124SJim Ingham matches); 335558ce124SJim Ingham word_complete = false; 336558ce124SJim Ingham return ret_val; 337558ce124SJim Ingham } 338558ce124SJim Ingham 339c9af18a5SGreg Clayton int 340*c8ecc2a9SEugene Zelenko CommandCompletions::Modules(CommandInterpreter &interpreter, 3416611103cSGreg Clayton const char *partial_file_name, 342c9af18a5SGreg Clayton int match_start_point, 343c9af18a5SGreg Clayton int max_return_elements, 344c9af18a5SGreg Clayton SearchFilter *searcher, 345558ce124SJim Ingham bool &word_complete, 346*c8ecc2a9SEugene Zelenko StringList &matches) 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 355*c8ecc2a9SEugene Zelenko if (searcher == nullptr) 356c9af18a5SGreg Clayton { 3572976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 35833df7cd3SJim Ingham SearchFilterForUnconstrainedSearches 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 369*c8ecc2a9SEugene Zelenko CommandCompletions::Symbols(CommandInterpreter &interpreter, 3706611103cSGreg Clayton const char *partial_file_name, 371c9af18a5SGreg Clayton int match_start_point, 372c9af18a5SGreg Clayton int max_return_elements, 373c9af18a5SGreg Clayton SearchFilter *searcher, 374558ce124SJim Ingham bool &word_complete, 3756611103cSGreg Clayton StringList &matches) 376c9af18a5SGreg Clayton { 377558ce124SJim Ingham word_complete = true; 3786611103cSGreg Clayton SymbolCompleter completer (interpreter, 3796611103cSGreg Clayton partial_file_name, 3806611103cSGreg Clayton match_start_point, 3816611103cSGreg Clayton max_return_elements, 3826611103cSGreg Clayton matches); 383c9af18a5SGreg Clayton 384*c8ecc2a9SEugene Zelenko if (searcher == nullptr) 385c9af18a5SGreg Clayton { 3862976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 38733df7cd3SJim Ingham SearchFilterForUnconstrainedSearches null_searcher (target_sp); 388c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 389c9af18a5SGreg Clayton } 390c9af18a5SGreg Clayton else 391c9af18a5SGreg Clayton { 392c9af18a5SGreg Clayton completer.DoCompletion (searcher); 393c9af18a5SGreg Clayton } 394c9af18a5SGreg Clayton return matches.GetSize(); 395c9af18a5SGreg Clayton } 396c9af18a5SGreg Clayton 3973df9a8dfSCaroline Tice int 3983df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter, 3993df9a8dfSCaroline Tice const char *partial_setting_name, 4003df9a8dfSCaroline Tice int match_start_point, 4013df9a8dfSCaroline Tice int max_return_elements, 4023df9a8dfSCaroline Tice SearchFilter *searcher, 4033df9a8dfSCaroline Tice bool &word_complete, 4043df9a8dfSCaroline Tice StringList &matches) 4053df9a8dfSCaroline Tice { 40667cc0636SGreg Clayton // Cache the full setting name list 40767cc0636SGreg Clayton static StringList g_property_names; 40867cc0636SGreg Clayton if (g_property_names.GetSize() == 0) 40967cc0636SGreg Clayton { 41067cc0636SGreg Clayton // Generate the full setting name list on demand 41167cc0636SGreg Clayton lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties()); 41267cc0636SGreg Clayton if (properties_sp) 41367cc0636SGreg Clayton { 41467cc0636SGreg Clayton StreamString strm; 415*c8ecc2a9SEugene Zelenko properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName); 41667cc0636SGreg Clayton const std::string &str = strm.GetString(); 41767cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 41867cc0636SGreg Clayton } 41967cc0636SGreg Clayton } 4203df9a8dfSCaroline Tice 42167cc0636SGreg Clayton size_t exact_matches_idx = SIZE_MAX; 42267cc0636SGreg Clayton const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx); 42367cc0636SGreg Clayton word_complete = exact_matches_idx != SIZE_MAX; 42467cc0636SGreg Clayton return num_matches; 4253df9a8dfSCaroline Tice } 4263df9a8dfSCaroline Tice 427ab65b34fSGreg Clayton int 428ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter, 429ab65b34fSGreg Clayton const char *partial_name, 430ab65b34fSGreg Clayton int match_start_point, 431ab65b34fSGreg Clayton int max_return_elements, 432ab65b34fSGreg Clayton SearchFilter *searcher, 433ab65b34fSGreg Clayton bool &word_complete, 434ab65b34fSGreg Clayton lldb_private::StringList &matches) 435ab65b34fSGreg Clayton { 436ab65b34fSGreg Clayton const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches); 437ab65b34fSGreg Clayton word_complete = num_matches == 1; 438ab65b34fSGreg Clayton return num_matches; 439ab65b34fSGreg Clayton } 440ab65b34fSGreg Clayton 441ab65b34fSGreg Clayton int 442ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter, 443ab65b34fSGreg Clayton const char *partial_name, 444ab65b34fSGreg Clayton int match_start_point, 445ab65b34fSGreg Clayton int max_return_elements, 446ab65b34fSGreg Clayton SearchFilter *searcher, 447ab65b34fSGreg Clayton bool &word_complete, 448ab65b34fSGreg Clayton lldb_private::StringList &matches) 449ab65b34fSGreg Clayton { 450ab65b34fSGreg Clayton const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches); 451ab65b34fSGreg Clayton word_complete = num_matches == 1; 452ab65b34fSGreg Clayton return num_matches; 453ab65b34fSGreg Clayton } 454ab65b34fSGreg Clayton 455f21feadcSGreg Clayton int 456f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter, 457f21feadcSGreg Clayton const char *partial_name, 458f21feadcSGreg Clayton int match_start_point, 459f21feadcSGreg Clayton int max_return_elements, 460f21feadcSGreg Clayton SearchFilter *searcher, 461f21feadcSGreg Clayton bool &word_complete, 462f21feadcSGreg Clayton lldb_private::StringList &matches) 463f21feadcSGreg Clayton { 464f21feadcSGreg Clayton return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete); 465f21feadcSGreg Clayton } 466f21feadcSGreg Clayton 467*c8ecc2a9SEugene Zelenko CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, 468c9af18a5SGreg Clayton const char *completion_str, 469c9af18a5SGreg Clayton int match_start_point, 470c9af18a5SGreg Clayton int max_return_elements, 471*c8ecc2a9SEugene Zelenko StringList &matches) : 4726611103cSGreg Clayton m_interpreter (interpreter), 473c9af18a5SGreg Clayton m_completion_str (completion_str), 474c9af18a5SGreg Clayton m_match_start_point (match_start_point), 475c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 476c9af18a5SGreg Clayton m_matches (matches) 477c9af18a5SGreg Clayton { 478c9af18a5SGreg Clayton } 479c9af18a5SGreg Clayton 480*c8ecc2a9SEugene Zelenko CommandCompletions::Completer::~Completer() = default; 481c9af18a5SGreg Clayton 482c9af18a5SGreg Clayton //---------------------------------------------------------------------- 483c9af18a5SGreg Clayton // SourceFileCompleter 484c9af18a5SGreg Clayton //---------------------------------------------------------------------- 485c9af18a5SGreg Clayton 486*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SourceFileCompleter(CommandInterpreter &interpreter, 487c9af18a5SGreg Clayton bool include_support_files, 488c9af18a5SGreg Clayton const char *completion_str, 489c9af18a5SGreg Clayton int match_start_point, 490c9af18a5SGreg Clayton int max_return_elements, 491*c8ecc2a9SEugene Zelenko StringList &matches) : 4926611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 493c9af18a5SGreg Clayton m_include_support_files (include_support_files), 494c9af18a5SGreg Clayton m_matching_files() 495c9af18a5SGreg Clayton { 496274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 497c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 498c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 499c9af18a5SGreg Clayton } 500c9af18a5SGreg Clayton 501c9af18a5SGreg Clayton Searcher::Depth 502c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 503c9af18a5SGreg Clayton { 504c9af18a5SGreg Clayton return eDepthCompUnit; 505c9af18a5SGreg Clayton } 506c9af18a5SGreg Clayton 507c9af18a5SGreg Clayton Searcher::CallbackReturn 508*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, 509c9af18a5SGreg Clayton SymbolContext &context, 510c9af18a5SGreg Clayton Address *addr, 511*c8ecc2a9SEugene Zelenko bool complete) 512c9af18a5SGreg Clayton { 513*c8ecc2a9SEugene Zelenko if (context.comp_unit != nullptr) 514c9af18a5SGreg Clayton { 515c9af18a5SGreg Clayton if (m_include_support_files) 516c9af18a5SGreg Clayton { 517c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 518c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 519c9af18a5SGreg Clayton { 520c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 521c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 522c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 523c9af18a5SGreg Clayton bool match = false; 524c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 525c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 526c9af18a5SGreg Clayton match = true; 527c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 528c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 529c9af18a5SGreg Clayton match = false; 530c9af18a5SGreg Clayton 531c9af18a5SGreg Clayton if (match) 532c9af18a5SGreg Clayton { 533c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 534c9af18a5SGreg Clayton } 535c9af18a5SGreg Clayton } 536c9af18a5SGreg Clayton } 537c9af18a5SGreg Clayton else 538c9af18a5SGreg Clayton { 539c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 540c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 541c9af18a5SGreg Clayton 542c9af18a5SGreg Clayton bool match = false; 543c9af18a5SGreg Clayton if (m_file_name && cur_file_name 544c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 545c9af18a5SGreg Clayton match = true; 546c9af18a5SGreg Clayton 547c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 548c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 549c9af18a5SGreg Clayton match = false; 550c9af18a5SGreg Clayton 551c9af18a5SGreg Clayton if (match) 552c9af18a5SGreg Clayton { 553c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 554c9af18a5SGreg Clayton } 555c9af18a5SGreg Clayton } 556c9af18a5SGreg Clayton } 557c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 558c9af18a5SGreg Clayton } 559c9af18a5SGreg Clayton 560c9af18a5SGreg Clayton size_t 561c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 562c9af18a5SGreg Clayton { 563c9af18a5SGreg Clayton filter->Search (*this); 564c9af18a5SGreg Clayton // Now convert the filelist to completions: 565c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 566c9af18a5SGreg Clayton { 567c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 568c9af18a5SGreg Clayton } 569c9af18a5SGreg Clayton return m_matches.GetSize(); 570c9af18a5SGreg Clayton } 571c9af18a5SGreg Clayton 572c9af18a5SGreg Clayton //---------------------------------------------------------------------- 573c9af18a5SGreg Clayton // SymbolCompleter 574c9af18a5SGreg Clayton //---------------------------------------------------------------------- 575c9af18a5SGreg Clayton 576c9af18a5SGreg Clayton static bool 577c9af18a5SGreg Clayton regex_chars (const char comp) 578c9af18a5SGreg Clayton { 579*c8ecc2a9SEugene Zelenko return (comp == '[' || comp == ']' || 580649f8b9bSGreg Clayton comp == '(' || comp == ')' || 581649f8b9bSGreg Clayton comp == '{' || comp == '}' || 582649f8b9bSGreg Clayton comp == '+' || 583649f8b9bSGreg Clayton comp == '.' || 584649f8b9bSGreg Clayton comp == '*' || 585649f8b9bSGreg Clayton comp == '|' || 586649f8b9bSGreg Clayton comp == '^' || 587649f8b9bSGreg Clayton comp == '$' || 588649f8b9bSGreg Clayton comp == '\\' || 589*c8ecc2a9SEugene Zelenko comp == '?'); 590c9af18a5SGreg Clayton } 591*c8ecc2a9SEugene Zelenko 592*c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SymbolCompleter(CommandInterpreter &interpreter, 593c9af18a5SGreg Clayton const char *completion_str, 594c9af18a5SGreg Clayton int match_start_point, 595c9af18a5SGreg Clayton int max_return_elements, 596*c8ecc2a9SEugene Zelenko StringList &matches) : 5976611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 598c9af18a5SGreg Clayton { 599649f8b9bSGreg Clayton std::string regex_str; 600649f8b9bSGreg Clayton if (completion_str && completion_str[0]) 601649f8b9bSGreg Clayton { 602649f8b9bSGreg Clayton regex_str.append("^"); 603c9af18a5SGreg Clayton regex_str.append(completion_str); 604649f8b9bSGreg Clayton } 605649f8b9bSGreg Clayton else 606649f8b9bSGreg Clayton { 607649f8b9bSGreg Clayton // Match anything since the completion string is empty 608649f8b9bSGreg Clayton regex_str.append("."); 609649f8b9bSGreg Clayton } 610649f8b9bSGreg Clayton std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 611649f8b9bSGreg Clayton while (pos < regex_str.end()) 612649f8b9bSGreg Clayton { 613c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 614649f8b9bSGreg Clayton pos = find_if(pos + 2, regex_str.end(), regex_chars); 615c9af18a5SGreg Clayton } 616c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 617c9af18a5SGreg Clayton } 618c9af18a5SGreg Clayton 619c9af18a5SGreg Clayton Searcher::Depth 620c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 621c9af18a5SGreg Clayton { 622c9af18a5SGreg Clayton return eDepthModule; 623c9af18a5SGreg Clayton } 624c9af18a5SGreg Clayton 625c9af18a5SGreg Clayton Searcher::CallbackReturn 626*c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter, 627c9af18a5SGreg Clayton SymbolContext &context, 628c9af18a5SGreg Clayton Address *addr, 629*c8ecc2a9SEugene Zelenko bool complete) 630c9af18a5SGreg Clayton { 631c9af18a5SGreg Clayton if (context.module_sp) 632c9af18a5SGreg Clayton { 633931180e6SGreg Clayton SymbolContextList sc_list; 634931180e6SGreg Clayton const bool include_symbols = true; 6359df05fbbSSean Callanan const bool include_inlines = true; 636931180e6SGreg Clayton const bool append = true; 6379df05fbbSSean Callanan context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list); 638c9af18a5SGreg Clayton 639c9af18a5SGreg Clayton SymbolContext sc; 640c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 641931180e6SGreg Clayton for (uint32_t i = 0; i < sc_list.GetSize(); i++) 642c9af18a5SGreg Clayton { 643931180e6SGreg Clayton if (sc_list.GetContextAtIndex(i, sc)) 644c9af18a5SGreg Clayton { 645530a413cSJim Ingham ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 646530a413cSJim Ingham if (!func_name.IsEmpty()) 647530a413cSJim Ingham m_match_set.insert (func_name); 648c9af18a5SGreg Clayton } 649c9af18a5SGreg Clayton } 650c9af18a5SGreg Clayton } 651c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 652c9af18a5SGreg Clayton } 653c9af18a5SGreg Clayton 654c9af18a5SGreg Clayton size_t 655c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 656c9af18a5SGreg Clayton { 657c9af18a5SGreg Clayton filter->Search (*this); 658c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 659c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 660c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 661c9af18a5SGreg Clayton 662c9af18a5SGreg Clayton return m_matches.GetSize(); 663c9af18a5SGreg Clayton } 664c9af18a5SGreg Clayton 665c9af18a5SGreg Clayton //---------------------------------------------------------------------- 666c9af18a5SGreg Clayton // ModuleCompleter 667c9af18a5SGreg Clayton //---------------------------------------------------------------------- 668*c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::ModuleCompleter(CommandInterpreter &interpreter, 669c9af18a5SGreg Clayton const char *completion_str, 670c9af18a5SGreg Clayton int match_start_point, 671c9af18a5SGreg Clayton int max_return_elements, 672*c8ecc2a9SEugene Zelenko StringList &matches) : 6736611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 674c9af18a5SGreg Clayton { 675274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 676c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 677c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 678c9af18a5SGreg Clayton } 679c9af18a5SGreg Clayton 680c9af18a5SGreg Clayton Searcher::Depth 681c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 682c9af18a5SGreg Clayton { 683c9af18a5SGreg Clayton return eDepthModule; 684c9af18a5SGreg Clayton } 685c9af18a5SGreg Clayton 686c9af18a5SGreg Clayton Searcher::CallbackReturn 687*c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::SearchCallback(SearchFilter &filter, 688c9af18a5SGreg Clayton SymbolContext &context, 689c9af18a5SGreg Clayton Address *addr, 690*c8ecc2a9SEugene Zelenko bool complete) 691c9af18a5SGreg Clayton { 692747bcb03SGreg Clayton if (context.module_sp) 693c9af18a5SGreg Clayton { 694c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 695c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 696c9af18a5SGreg Clayton 697c9af18a5SGreg Clayton bool match = false; 698c9af18a5SGreg Clayton if (m_file_name && cur_file_name 699c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 700c9af18a5SGreg Clayton match = true; 701c9af18a5SGreg Clayton 702c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 703c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 704c9af18a5SGreg Clayton match = false; 705c9af18a5SGreg Clayton 706c9af18a5SGreg Clayton if (match) 707c9af18a5SGreg Clayton { 708c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 709c9af18a5SGreg Clayton } 710c9af18a5SGreg Clayton } 711c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 712c9af18a5SGreg Clayton } 713c9af18a5SGreg Clayton 714c9af18a5SGreg Clayton size_t 715c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 716c9af18a5SGreg Clayton { 717c9af18a5SGreg Clayton filter->Search (*this); 718c9af18a5SGreg Clayton return m_matches.GetSize(); 719c9af18a5SGreg Clayton } 720