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 1093a64300SDaniel Malea #include "lldb/lldb-python.h" 11c9af18a5SGreg Clayton 12c9af18a5SGreg Clayton // C Includes 13558ce124SJim Ingham #include <sys/stat.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" 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" 281f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h" 29f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h" 309b62fd2fSGreg Clayton #include "lldb/Target/Target.h" 319b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h" 32c9af18a5SGreg Clayton 33c9af18a5SGreg Clayton using namespace lldb_private; 34c9af18a5SGreg Clayton 35c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 36c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 37c9af18a5SGreg Clayton { 38c9af18a5SGreg Clayton {eCustomCompletion, NULL}, 39c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 40558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 41558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 42c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 43c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 443df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 45ab65b34fSGreg Clayton {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames}, 46ab65b34fSGreg Clayton {eArchitectureCompletion, CommandCompletions::ArchitectureNames}, 47f21feadcSGreg Clayton {eVariablePathCompletion, CommandCompletions::VariablePath}, 48c9af18a5SGreg Clayton {eNoCompletion, NULL} // This one has to be last in the list. 49c9af18a5SGreg Clayton }; 50c9af18a5SGreg Clayton 51c9af18a5SGreg Clayton bool 526611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks 536611103cSGreg Clayton ( 546611103cSGreg Clayton CommandInterpreter &interpreter, 556611103cSGreg Clayton uint32_t completion_mask, 56c9af18a5SGreg Clayton const char *completion_str, 57c9af18a5SGreg Clayton int match_start_point, 58c9af18a5SGreg Clayton int max_return_elements, 59c9af18a5SGreg Clayton SearchFilter *searcher, 60558ce124SJim Ingham bool &word_complete, 616611103cSGreg Clayton StringList &matches 626611103cSGreg Clayton ) 63c9af18a5SGreg Clayton { 64c9af18a5SGreg Clayton bool handled = false; 65c9af18a5SGreg Clayton 66c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 67c9af18a5SGreg Clayton return false; 68c9af18a5SGreg Clayton 69c9af18a5SGreg Clayton for (int i = 0; ; i++) 70c9af18a5SGreg Clayton { 71c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 72c9af18a5SGreg Clayton break; 73c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 74c9af18a5SGreg Clayton && g_common_completions[i].callback != NULL) 75c9af18a5SGreg Clayton { 76c9af18a5SGreg Clayton handled = true; 776611103cSGreg Clayton g_common_completions[i].callback (interpreter, 786611103cSGreg Clayton completion_str, 79c9af18a5SGreg Clayton match_start_point, 80c9af18a5SGreg Clayton max_return_elements, 81c9af18a5SGreg Clayton searcher, 82558ce124SJim Ingham word_complete, 83c9af18a5SGreg Clayton matches); 84c9af18a5SGreg Clayton } 85c9af18a5SGreg Clayton } 86c9af18a5SGreg Clayton return handled; 87c9af18a5SGreg Clayton } 88c9af18a5SGreg Clayton 89c9af18a5SGreg Clayton int 906611103cSGreg Clayton CommandCompletions::SourceFiles 916611103cSGreg Clayton ( 926611103cSGreg Clayton CommandInterpreter &interpreter, 936611103cSGreg Clayton const char *partial_file_name, 94c9af18a5SGreg Clayton int match_start_point, 95c9af18a5SGreg Clayton int max_return_elements, 96c9af18a5SGreg Clayton SearchFilter *searcher, 97558ce124SJim Ingham bool &word_complete, 986611103cSGreg Clayton StringList &matches 996611103cSGreg Clayton ) 100c9af18a5SGreg Clayton { 101558ce124SJim Ingham word_complete = true; 102c9af18a5SGreg Clayton // Find some way to switch "include support files..." 1036611103cSGreg Clayton SourceFileCompleter completer (interpreter, 1046611103cSGreg Clayton false, 1056611103cSGreg Clayton partial_file_name, 1066611103cSGreg Clayton match_start_point, 1076611103cSGreg Clayton max_return_elements, 108c9af18a5SGreg Clayton matches); 109c9af18a5SGreg Clayton 110c9af18a5SGreg Clayton if (searcher == NULL) 111c9af18a5SGreg Clayton { 1122976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 113c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 114c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 115c9af18a5SGreg Clayton } 116c9af18a5SGreg Clayton else 117c9af18a5SGreg Clayton { 118c9af18a5SGreg Clayton completer.DoCompletion (searcher); 119c9af18a5SGreg Clayton } 120c9af18a5SGreg Clayton return matches.GetSize(); 121c9af18a5SGreg Clayton } 122c9af18a5SGreg Clayton 123*b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton 124*b2f1fb29SVirgile Bello { 125*b2f1fb29SVirgile Bello const char *remainder; 126*b2f1fb29SVirgile Bello char *partial_name_copy; 127*b2f1fb29SVirgile Bello bool only_directories; 128*b2f1fb29SVirgile Bello bool *saw_directory; 129*b2f1fb29SVirgile Bello StringList *matches; 130*b2f1fb29SVirgile Bello char *end_ptr; 131*b2f1fb29SVirgile Bello size_t baselen; 132*b2f1fb29SVirgile Bello }; 133*b2f1fb29SVirgile Bello 134*b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec) 135*b2f1fb29SVirgile Bello { 136*b2f1fb29SVirgile Bello const char *name = spec.GetFilename().AsCString(); 137*b2f1fb29SVirgile Bello 138*b2f1fb29SVirgile Bello const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton; 139*b2f1fb29SVirgile Bello char *end_ptr = parameters->end_ptr; 140*b2f1fb29SVirgile Bello char *partial_name_copy = parameters->partial_name_copy; 141*b2f1fb29SVirgile Bello size_t baselen = end_ptr - partial_name_copy; 142*b2f1fb29SVirgile Bello const char *remainder = parameters->remainder; 143*b2f1fb29SVirgile Bello 144*b2f1fb29SVirgile Bello // Omit ".", ".." and any . files if the match string doesn't start with . 145*b2f1fb29SVirgile Bello if (name[0] == '.') 146*b2f1fb29SVirgile Bello { 147*b2f1fb29SVirgile Bello if (name[1] == '\0') 148*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 149*b2f1fb29SVirgile Bello else if (name[1] == '.' && name[2] == '\0') 150*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 151*b2f1fb29SVirgile Bello else if (remainder[0] != '.') 152*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 153*b2f1fb29SVirgile Bello } 154*b2f1fb29SVirgile Bello 155*b2f1fb29SVirgile Bello // If we found a directory, we put a "/" at the end of the name. 156*b2f1fb29SVirgile Bello 157*b2f1fb29SVirgile Bello if (remainder[0] == '\0' || strstr(name, remainder) == name) 158*b2f1fb29SVirgile Bello { 159*b2f1fb29SVirgile Bello if (strlen(name) + parameters->baselen >= PATH_MAX) 160*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 161*b2f1fb29SVirgile Bello 162*b2f1fb29SVirgile Bello strcpy(end_ptr, name); 163*b2f1fb29SVirgile Bello 164*b2f1fb29SVirgile Bello bool isa_directory = false; 165*b2f1fb29SVirgile Bello if (file_type == FileSpec::eFileTypeDirectory) 166*b2f1fb29SVirgile Bello isa_directory = true; 167*b2f1fb29SVirgile Bello else if (file_type == FileSpec::eFileTypeSymbolicLink) 168*b2f1fb29SVirgile Bello { 169*b2f1fb29SVirgile Bello struct stat stat_buf; 170*b2f1fb29SVirgile Bello if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) 171*b2f1fb29SVirgile Bello isa_directory = true; 172*b2f1fb29SVirgile Bello } 173*b2f1fb29SVirgile Bello 174*b2f1fb29SVirgile Bello if (isa_directory) 175*b2f1fb29SVirgile Bello { 176*b2f1fb29SVirgile Bello *parameters->saw_directory = true; 177*b2f1fb29SVirgile Bello size_t len = strlen(parameters->partial_name_copy); 178*b2f1fb29SVirgile Bello partial_name_copy[len] = '/'; 179*b2f1fb29SVirgile Bello partial_name_copy[len + 1] = '\0'; 180*b2f1fb29SVirgile Bello } 181*b2f1fb29SVirgile Bello if (parameters->only_directories && !isa_directory) 182*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 183*b2f1fb29SVirgile Bello parameters->matches->AppendString(partial_name_copy); 184*b2f1fb29SVirgile Bello } 185*b2f1fb29SVirgile Bello 186*b2f1fb29SVirgile Bello return FileSpec::eEnumerateDirectoryResultNext; 187*b2f1fb29SVirgile Bello } 188*b2f1fb29SVirgile Bello 189558ce124SJim Ingham static int 190558ce124SJim Ingham DiskFilesOrDirectories 191558ce124SJim Ingham ( 192558ce124SJim Ingham const char *partial_file_name, 193558ce124SJim Ingham bool only_directories, 194558ce124SJim Ingham bool &saw_directory, 195558ce124SJim Ingham StringList &matches 196558ce124SJim Ingham ) 197558ce124SJim Ingham { 198558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 199558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 200558ce124SJim Ingham 201c7bece56SGreg Clayton size_t partial_name_len = strlen(partial_file_name); 202558ce124SJim Ingham 203558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 204558ce124SJim Ingham return matches.GetSize(); 205558ce124SJim Ingham 206558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 207558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 208558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 209558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 210558ce124SJim Ingham // the form the user originally typed. 211558ce124SJim Ingham 212558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 213021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 214558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 215558ce124SJim Ingham 216710dd5aeSGreg Clayton // We'll need to save a copy of the remainder for comparison, which we do here. 217558ce124SJim Ingham char remainder[PATH_MAX]; 218558ce124SJim Ingham 219558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 220558ce124SJim Ingham char *end_ptr; 221558ce124SJim Ingham 222558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 223558ce124SJim Ingham 224558ce124SJim Ingham // This will store the resolved form of the containing directory 225558ce124SJim Ingham char containing_part[PATH_MAX]; 226558ce124SJim Ingham 227558ce124SJim Ingham if (end_ptr == NULL) 228558ce124SJim Ingham { 229558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 230558ce124SJim Ingham // user name. 231558ce124SJim Ingham if (*partial_name_copy == '~') 232558ce124SJim Ingham { 233558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 2347cc478b9SJim Ingham // but for completeness sake we'll resolve the user name and only put a slash 235558ce124SJim Ingham // on the end if it exists. 2367cc478b9SJim Ingham char resolved_username[PATH_MAX]; 237c982c768SGreg Clayton size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username, 2387cc478b9SJim Ingham sizeof (resolved_username)); 2397cc478b9SJim Ingham 2407cc478b9SJim Ingham // Not sure how this would happen, a username longer than PATH_MAX? Still... 2417cc478b9SJim Ingham if (resolved_username_len >= sizeof (resolved_username)) 242558ce124SJim Ingham return matches.GetSize(); 24384363078SJim Ingham else if (resolved_username_len == 0) 2447cc478b9SJim Ingham { 2457cc478b9SJim Ingham // The user name didn't resolve, let's look in the password database for matches. 2467cc478b9SJim Ingham // The user name database contains duplicates, and is not in alphabetical order, so 2477cc478b9SJim Ingham // we'll use a set to manage that for us. 24884363078SJim Ingham FileSpec::ResolvePartialUsername (partial_name_copy, matches); 24984363078SJim Ingham if (matches.GetSize() > 0) 2507cc478b9SJim Ingham saw_directory = true; 2517cc478b9SJim Ingham return matches.GetSize(); 2527cc478b9SJim Ingham } 25384363078SJim Ingham else 25484363078SJim Ingham { 255558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 256558ce124SJim Ingham // FIXME: complete user names here: 257558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 258558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 259558ce124SJim Ingham matches.AppendString(partial_name_copy); 260021b605dSBenjamin Kramer saw_directory = true; 261558ce124SJim Ingham return matches.GetSize(); 262558ce124SJim Ingham } 26384363078SJim Ingham } 264558ce124SJim Ingham else 265558ce124SJim Ingham { 266558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 267558ce124SJim Ingham containing_part[0] = '.'; 268558ce124SJim Ingham containing_part[1] = '\0'; 269558ce124SJim Ingham strcpy(remainder, partial_name_copy); 270558ce124SJim Ingham end_ptr = partial_name_copy; 271558ce124SJim Ingham } 272558ce124SJim Ingham } 273558ce124SJim Ingham else 274558ce124SJim Ingham { 275558ce124SJim Ingham if (end_ptr == partial_name_copy) 276558ce124SJim Ingham { 277558ce124SJim Ingham // We're completing a file or directory in the root volume. 278558ce124SJim Ingham containing_part[0] = '/'; 279558ce124SJim Ingham containing_part[1] = '\0'; 280558ce124SJim Ingham } 281558ce124SJim Ingham else 282558ce124SJim Ingham { 283558ce124SJim Ingham size_t len = end_ptr - partial_name_copy; 284558ce124SJim Ingham memcpy(containing_part, partial_name_copy, len); 285558ce124SJim Ingham containing_part[len] = '\0'; 286558ce124SJim Ingham } 287558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 288558ce124SJim Ingham end_ptr++; 289558ce124SJim Ingham strcpy(remainder, end_ptr); 290558ce124SJim Ingham } 291558ce124SJim Ingham 2927cc478b9SJim Ingham // Look for a user name in the containing part, and if it's there, resolve it and stick the 293558ce124SJim Ingham // result back into the containing_part: 294558ce124SJim Ingham 295558ce124SJim Ingham if (*partial_name_copy == '~') 296558ce124SJim Ingham { 29784363078SJim Ingham size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, 29884363078SJim Ingham containing_part, 29984363078SJim Ingham sizeof (containing_part)); 300558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 301a0807356SGreg Clayton if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part)) 302558ce124SJim Ingham return matches.GetSize(); 303558ce124SJim Ingham } 304558ce124SJim Ingham 305558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 306558ce124SJim Ingham 307558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 308558ce124SJim Ingham 309*b2f1fb29SVirgile Bello DiskFilesOrDirectoriesBaton parameters; 310*b2f1fb29SVirgile Bello parameters.remainder = remainder; 311*b2f1fb29SVirgile Bello parameters.partial_name_copy = partial_name_copy; 312*b2f1fb29SVirgile Bello parameters.only_directories = only_directories; 313*b2f1fb29SVirgile Bello parameters.saw_directory = &saw_directory; 314*b2f1fb29SVirgile Bello parameters.matches = &matches; 315*b2f1fb29SVirgile Bello parameters.end_ptr = end_ptr; 316*b2f1fb29SVirgile Bello parameters.baselen = baselen; 317558ce124SJim Ingham 318*b2f1fb29SVirgile Bello FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, ¶meters); 319558ce124SJim Ingham 320558ce124SJim Ingham return matches.GetSize(); 321558ce124SJim Ingham } 322558ce124SJim Ingham 323558ce124SJim Ingham int 324558ce124SJim Ingham CommandCompletions::DiskFiles 325558ce124SJim Ingham ( 326558ce124SJim Ingham CommandInterpreter &interpreter, 327558ce124SJim Ingham const char *partial_file_name, 328558ce124SJim Ingham int match_start_point, 329558ce124SJim Ingham int max_return_elements, 330558ce124SJim Ingham SearchFilter *searcher, 331558ce124SJim Ingham bool &word_complete, 332558ce124SJim Ingham StringList &matches 333558ce124SJim Ingham ) 334558ce124SJim Ingham { 335558ce124SJim Ingham 336558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 337558ce124SJim Ingham false, 338558ce124SJim Ingham word_complete, 339558ce124SJim Ingham matches); 340558ce124SJim Ingham word_complete = !word_complete; 341558ce124SJim Ingham return ret_val; 342558ce124SJim Ingham } 343558ce124SJim Ingham 344558ce124SJim Ingham int 345558ce124SJim Ingham CommandCompletions::DiskDirectories 346558ce124SJim Ingham ( 347558ce124SJim Ingham CommandInterpreter &interpreter, 348558ce124SJim Ingham const char *partial_file_name, 349558ce124SJim Ingham int match_start_point, 350558ce124SJim Ingham int max_return_elements, 351558ce124SJim Ingham SearchFilter *searcher, 352558ce124SJim Ingham bool &word_complete, 353558ce124SJim Ingham StringList &matches 354558ce124SJim Ingham ) 355558ce124SJim Ingham { 356558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 357558ce124SJim Ingham true, 358558ce124SJim Ingham word_complete, 359558ce124SJim Ingham matches); 360558ce124SJim Ingham word_complete = false; 361558ce124SJim Ingham return ret_val; 362558ce124SJim Ingham } 363558ce124SJim Ingham 364c9af18a5SGreg Clayton int 3656611103cSGreg Clayton CommandCompletions::Modules 3666611103cSGreg Clayton ( 3676611103cSGreg Clayton CommandInterpreter &interpreter, 3686611103cSGreg Clayton const char *partial_file_name, 369c9af18a5SGreg Clayton int match_start_point, 370c9af18a5SGreg Clayton int max_return_elements, 371c9af18a5SGreg Clayton SearchFilter *searcher, 372558ce124SJim Ingham bool &word_complete, 3736611103cSGreg Clayton StringList &matches 3746611103cSGreg Clayton ) 375c9af18a5SGreg Clayton { 376558ce124SJim Ingham word_complete = true; 3776611103cSGreg Clayton ModuleCompleter completer (interpreter, 3786611103cSGreg Clayton partial_file_name, 3796611103cSGreg Clayton match_start_point, 3806611103cSGreg Clayton max_return_elements, 3816611103cSGreg Clayton matches); 382c9af18a5SGreg Clayton 383c9af18a5SGreg Clayton if (searcher == NULL) 384c9af18a5SGreg Clayton { 3852976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 386c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 387c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 388c9af18a5SGreg Clayton } 389c9af18a5SGreg Clayton else 390c9af18a5SGreg Clayton { 391c9af18a5SGreg Clayton completer.DoCompletion (searcher); 392c9af18a5SGreg Clayton } 393c9af18a5SGreg Clayton return matches.GetSize(); 394c9af18a5SGreg Clayton } 395c9af18a5SGreg Clayton 396c9af18a5SGreg Clayton int 3976611103cSGreg Clayton CommandCompletions::Symbols 3986611103cSGreg Clayton ( 3996611103cSGreg Clayton CommandInterpreter &interpreter, 4006611103cSGreg Clayton const char *partial_file_name, 401c9af18a5SGreg Clayton int match_start_point, 402c9af18a5SGreg Clayton int max_return_elements, 403c9af18a5SGreg Clayton SearchFilter *searcher, 404558ce124SJim Ingham bool &word_complete, 4056611103cSGreg Clayton StringList &matches) 406c9af18a5SGreg Clayton { 407558ce124SJim Ingham word_complete = true; 4086611103cSGreg Clayton SymbolCompleter completer (interpreter, 4096611103cSGreg Clayton partial_file_name, 4106611103cSGreg Clayton match_start_point, 4116611103cSGreg Clayton max_return_elements, 4126611103cSGreg Clayton matches); 413c9af18a5SGreg Clayton 414c9af18a5SGreg Clayton if (searcher == NULL) 415c9af18a5SGreg Clayton { 4162976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 417c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 418c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 419c9af18a5SGreg Clayton } 420c9af18a5SGreg Clayton else 421c9af18a5SGreg Clayton { 422c9af18a5SGreg Clayton completer.DoCompletion (searcher); 423c9af18a5SGreg Clayton } 424c9af18a5SGreg Clayton return matches.GetSize(); 425c9af18a5SGreg Clayton } 426c9af18a5SGreg Clayton 4273df9a8dfSCaroline Tice int 4283df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter, 4293df9a8dfSCaroline Tice const char *partial_setting_name, 4303df9a8dfSCaroline Tice int match_start_point, 4313df9a8dfSCaroline Tice int max_return_elements, 4323df9a8dfSCaroline Tice SearchFilter *searcher, 4333df9a8dfSCaroline Tice bool &word_complete, 4343df9a8dfSCaroline Tice StringList &matches) 4353df9a8dfSCaroline Tice { 43667cc0636SGreg Clayton // Cache the full setting name list 43767cc0636SGreg Clayton static StringList g_property_names; 43867cc0636SGreg Clayton if (g_property_names.GetSize() == 0) 43967cc0636SGreg Clayton { 44067cc0636SGreg Clayton // Generate the full setting name list on demand 44167cc0636SGreg Clayton lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties()); 44267cc0636SGreg Clayton if (properties_sp) 44367cc0636SGreg Clayton { 44467cc0636SGreg Clayton StreamString strm; 44567cc0636SGreg Clayton properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName); 44667cc0636SGreg Clayton const std::string &str = strm.GetString(); 44767cc0636SGreg Clayton g_property_names.SplitIntoLines(str.c_str(), str.size()); 44867cc0636SGreg Clayton } 44967cc0636SGreg Clayton } 4503df9a8dfSCaroline Tice 45167cc0636SGreg Clayton size_t exact_matches_idx = SIZE_MAX; 45267cc0636SGreg Clayton const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx); 45367cc0636SGreg Clayton word_complete = exact_matches_idx != SIZE_MAX; 45467cc0636SGreg Clayton return num_matches; 4553df9a8dfSCaroline Tice } 4563df9a8dfSCaroline Tice 457ab65b34fSGreg Clayton 458ab65b34fSGreg Clayton int 459ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter, 460ab65b34fSGreg Clayton const char *partial_name, 461ab65b34fSGreg Clayton int match_start_point, 462ab65b34fSGreg Clayton int max_return_elements, 463ab65b34fSGreg Clayton SearchFilter *searcher, 464ab65b34fSGreg Clayton bool &word_complete, 465ab65b34fSGreg Clayton lldb_private::StringList &matches) 466ab65b34fSGreg Clayton { 467ab65b34fSGreg Clayton const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches); 468ab65b34fSGreg Clayton word_complete = num_matches == 1; 469ab65b34fSGreg Clayton return num_matches; 470ab65b34fSGreg Clayton } 471ab65b34fSGreg Clayton 472ab65b34fSGreg Clayton int 473ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter, 474ab65b34fSGreg Clayton const char *partial_name, 475ab65b34fSGreg Clayton int match_start_point, 476ab65b34fSGreg Clayton int max_return_elements, 477ab65b34fSGreg Clayton SearchFilter *searcher, 478ab65b34fSGreg Clayton bool &word_complete, 479ab65b34fSGreg Clayton lldb_private::StringList &matches) 480ab65b34fSGreg Clayton { 481ab65b34fSGreg Clayton const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches); 482ab65b34fSGreg Clayton word_complete = num_matches == 1; 483ab65b34fSGreg Clayton return num_matches; 484ab65b34fSGreg Clayton } 485ab65b34fSGreg Clayton 486ab65b34fSGreg Clayton 487f21feadcSGreg Clayton int 488f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter, 489f21feadcSGreg Clayton const char *partial_name, 490f21feadcSGreg Clayton int match_start_point, 491f21feadcSGreg Clayton int max_return_elements, 492f21feadcSGreg Clayton SearchFilter *searcher, 493f21feadcSGreg Clayton bool &word_complete, 494f21feadcSGreg Clayton lldb_private::StringList &matches) 495f21feadcSGreg Clayton { 496f21feadcSGreg Clayton return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete); 497f21feadcSGreg Clayton } 498f21feadcSGreg Clayton 499f21feadcSGreg Clayton 5006611103cSGreg Clayton CommandCompletions::Completer::Completer 5016611103cSGreg Clayton ( 5026611103cSGreg Clayton CommandInterpreter &interpreter, 503c9af18a5SGreg Clayton const char *completion_str, 504c9af18a5SGreg Clayton int match_start_point, 505c9af18a5SGreg Clayton int max_return_elements, 506c9af18a5SGreg Clayton StringList &matches 507c9af18a5SGreg Clayton ) : 5086611103cSGreg Clayton m_interpreter (interpreter), 509c9af18a5SGreg Clayton m_completion_str (completion_str), 510c9af18a5SGreg Clayton m_match_start_point (match_start_point), 511c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 512c9af18a5SGreg Clayton m_matches (matches) 513c9af18a5SGreg Clayton { 514c9af18a5SGreg Clayton } 515c9af18a5SGreg Clayton 516c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer () 517c9af18a5SGreg Clayton { 518c9af18a5SGreg Clayton 519c9af18a5SGreg Clayton } 520c9af18a5SGreg Clayton 521c9af18a5SGreg Clayton //---------------------------------------------------------------------- 522c9af18a5SGreg Clayton // SourceFileCompleter 523c9af18a5SGreg Clayton //---------------------------------------------------------------------- 524c9af18a5SGreg Clayton 5256611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter 5266611103cSGreg Clayton ( 5276611103cSGreg Clayton CommandInterpreter &interpreter, 528c9af18a5SGreg Clayton bool include_support_files, 529c9af18a5SGreg Clayton const char *completion_str, 530c9af18a5SGreg Clayton int match_start_point, 531c9af18a5SGreg Clayton int max_return_elements, 532c9af18a5SGreg Clayton StringList &matches 533c9af18a5SGreg Clayton ) : 5346611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 535c9af18a5SGreg Clayton m_include_support_files (include_support_files), 536c9af18a5SGreg Clayton m_matching_files() 537c9af18a5SGreg Clayton { 538274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 539c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 540c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 541c9af18a5SGreg Clayton } 542c9af18a5SGreg Clayton 543c9af18a5SGreg Clayton Searcher::Depth 544c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 545c9af18a5SGreg Clayton { 546c9af18a5SGreg Clayton return eDepthCompUnit; 547c9af18a5SGreg Clayton } 548c9af18a5SGreg Clayton 549c9af18a5SGreg Clayton Searcher::CallbackReturn 550c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback ( 551c9af18a5SGreg Clayton SearchFilter &filter, 552c9af18a5SGreg Clayton SymbolContext &context, 553c9af18a5SGreg Clayton Address *addr, 554c9af18a5SGreg Clayton bool complete 555c9af18a5SGreg Clayton ) 556c9af18a5SGreg Clayton { 557c9af18a5SGreg Clayton if (context.comp_unit != NULL) 558c9af18a5SGreg Clayton { 559c9af18a5SGreg Clayton if (m_include_support_files) 560c9af18a5SGreg Clayton { 561c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 562c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 563c9af18a5SGreg Clayton { 564c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 565c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 566c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 567c9af18a5SGreg Clayton bool match = false; 568c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 569c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 570c9af18a5SGreg Clayton match = true; 571c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 572c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 573c9af18a5SGreg Clayton match = false; 574c9af18a5SGreg Clayton 575c9af18a5SGreg Clayton if (match) 576c9af18a5SGreg Clayton { 577c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 578c9af18a5SGreg Clayton } 579c9af18a5SGreg Clayton } 580c9af18a5SGreg Clayton 581c9af18a5SGreg Clayton } 582c9af18a5SGreg Clayton else 583c9af18a5SGreg Clayton { 584c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 585c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 586c9af18a5SGreg Clayton 587c9af18a5SGreg Clayton bool match = false; 588c9af18a5SGreg Clayton if (m_file_name && cur_file_name 589c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 590c9af18a5SGreg Clayton match = true; 591c9af18a5SGreg Clayton 592c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 593c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 594c9af18a5SGreg Clayton match = false; 595c9af18a5SGreg Clayton 596c9af18a5SGreg Clayton if (match) 597c9af18a5SGreg Clayton { 598c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 599c9af18a5SGreg Clayton } 600c9af18a5SGreg Clayton } 601c9af18a5SGreg Clayton } 602c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 603c9af18a5SGreg Clayton } 604c9af18a5SGreg Clayton 605c9af18a5SGreg Clayton size_t 606c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 607c9af18a5SGreg Clayton { 608c9af18a5SGreg Clayton filter->Search (*this); 609c9af18a5SGreg Clayton // Now convert the filelist to completions: 610c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 611c9af18a5SGreg Clayton { 612c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 613c9af18a5SGreg Clayton } 614c9af18a5SGreg Clayton return m_matches.GetSize(); 615c9af18a5SGreg Clayton 616c9af18a5SGreg Clayton } 617c9af18a5SGreg Clayton 618c9af18a5SGreg Clayton //---------------------------------------------------------------------- 619c9af18a5SGreg Clayton // SymbolCompleter 620c9af18a5SGreg Clayton //---------------------------------------------------------------------- 621c9af18a5SGreg Clayton 622c9af18a5SGreg Clayton static bool 623c9af18a5SGreg Clayton regex_chars (const char comp) 624c9af18a5SGreg Clayton { 625649f8b9bSGreg Clayton if (comp == '[' || comp == ']' || 626649f8b9bSGreg Clayton comp == '(' || comp == ')' || 627649f8b9bSGreg Clayton comp == '{' || comp == '}' || 628649f8b9bSGreg Clayton comp == '+' || 629649f8b9bSGreg Clayton comp == '.' || 630649f8b9bSGreg Clayton comp == '*' || 631649f8b9bSGreg Clayton comp == '|' || 632649f8b9bSGreg Clayton comp == '^' || 633649f8b9bSGreg Clayton comp == '$' || 634649f8b9bSGreg Clayton comp == '\\' || 635649f8b9bSGreg Clayton comp == '?') 636c9af18a5SGreg Clayton return true; 637c9af18a5SGreg Clayton else 638c9af18a5SGreg Clayton return false; 639c9af18a5SGreg Clayton } 6406611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter 6416611103cSGreg Clayton ( 6426611103cSGreg Clayton CommandInterpreter &interpreter, 643c9af18a5SGreg Clayton const char *completion_str, 644c9af18a5SGreg Clayton int match_start_point, 645c9af18a5SGreg Clayton int max_return_elements, 646c9af18a5SGreg Clayton StringList &matches 647c9af18a5SGreg Clayton ) : 6486611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 649c9af18a5SGreg Clayton { 650649f8b9bSGreg Clayton std::string regex_str; 651649f8b9bSGreg Clayton if (completion_str && completion_str[0]) 652649f8b9bSGreg Clayton { 653649f8b9bSGreg Clayton regex_str.append("^"); 654c9af18a5SGreg Clayton regex_str.append(completion_str); 655649f8b9bSGreg Clayton } 656649f8b9bSGreg Clayton else 657649f8b9bSGreg Clayton { 658649f8b9bSGreg Clayton // Match anything since the completion string is empty 659649f8b9bSGreg Clayton regex_str.append("."); 660649f8b9bSGreg Clayton } 661649f8b9bSGreg Clayton std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars); 662649f8b9bSGreg Clayton while (pos < regex_str.end()) 663649f8b9bSGreg Clayton { 664c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 665649f8b9bSGreg Clayton pos = find_if(pos + 2, regex_str.end(), regex_chars); 666c9af18a5SGreg Clayton } 667c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 668c9af18a5SGreg Clayton } 669c9af18a5SGreg Clayton 670c9af18a5SGreg Clayton Searcher::Depth 671c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 672c9af18a5SGreg Clayton { 673c9af18a5SGreg Clayton return eDepthModule; 674c9af18a5SGreg Clayton } 675c9af18a5SGreg Clayton 676c9af18a5SGreg Clayton Searcher::CallbackReturn 677c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback ( 678c9af18a5SGreg Clayton SearchFilter &filter, 679c9af18a5SGreg Clayton SymbolContext &context, 680c9af18a5SGreg Clayton Address *addr, 681c9af18a5SGreg Clayton bool complete 682c9af18a5SGreg Clayton ) 683c9af18a5SGreg Clayton { 684c9af18a5SGreg Clayton if (context.module_sp) 685c9af18a5SGreg Clayton { 686931180e6SGreg Clayton SymbolContextList sc_list; 687931180e6SGreg Clayton const bool include_symbols = true; 6889df05fbbSSean Callanan const bool include_inlines = true; 689931180e6SGreg Clayton const bool append = true; 6909df05fbbSSean Callanan context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list); 691c9af18a5SGreg Clayton 692c9af18a5SGreg Clayton SymbolContext sc; 693c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 694931180e6SGreg Clayton for (uint32_t i = 0; i < sc_list.GetSize(); i++) 695c9af18a5SGreg Clayton { 696931180e6SGreg Clayton if (sc_list.GetContextAtIndex(i, sc)) 697c9af18a5SGreg Clayton { 698530a413cSJim Ingham ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); 699530a413cSJim Ingham if (!func_name.IsEmpty()) 700530a413cSJim Ingham m_match_set.insert (func_name); 701c9af18a5SGreg Clayton } 702c9af18a5SGreg Clayton } 703c9af18a5SGreg Clayton } 704c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 705c9af18a5SGreg Clayton } 706c9af18a5SGreg Clayton 707c9af18a5SGreg Clayton size_t 708c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 709c9af18a5SGreg Clayton { 710c9af18a5SGreg Clayton filter->Search (*this); 711c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 712c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 713c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 714c9af18a5SGreg Clayton 715c9af18a5SGreg Clayton return m_matches.GetSize(); 716c9af18a5SGreg Clayton } 717c9af18a5SGreg Clayton 718c9af18a5SGreg Clayton //---------------------------------------------------------------------- 719c9af18a5SGreg Clayton // ModuleCompleter 720c9af18a5SGreg Clayton //---------------------------------------------------------------------- 7216611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter 7226611103cSGreg Clayton ( 7236611103cSGreg Clayton CommandInterpreter &interpreter, 724c9af18a5SGreg Clayton const char *completion_str, 725c9af18a5SGreg Clayton int match_start_point, 726c9af18a5SGreg Clayton int max_return_elements, 727c9af18a5SGreg Clayton StringList &matches 728c9af18a5SGreg Clayton ) : 7296611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 730c9af18a5SGreg Clayton { 731274060b6SGreg Clayton FileSpec partial_spec (m_completion_str.c_str(), false); 732c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 733c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 734c9af18a5SGreg Clayton } 735c9af18a5SGreg Clayton 736c9af18a5SGreg Clayton Searcher::Depth 737c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 738c9af18a5SGreg Clayton { 739c9af18a5SGreg Clayton return eDepthModule; 740c9af18a5SGreg Clayton } 741c9af18a5SGreg Clayton 742c9af18a5SGreg Clayton Searcher::CallbackReturn 743c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback ( 744c9af18a5SGreg Clayton SearchFilter &filter, 745c9af18a5SGreg Clayton SymbolContext &context, 746c9af18a5SGreg Clayton Address *addr, 747c9af18a5SGreg Clayton bool complete 748c9af18a5SGreg Clayton ) 749c9af18a5SGreg Clayton { 750747bcb03SGreg Clayton if (context.module_sp) 751c9af18a5SGreg Clayton { 752c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 753c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 754c9af18a5SGreg Clayton 755c9af18a5SGreg Clayton bool match = false; 756c9af18a5SGreg Clayton if (m_file_name && cur_file_name 757c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 758c9af18a5SGreg Clayton match = true; 759c9af18a5SGreg Clayton 760c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 761c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 762c9af18a5SGreg Clayton match = false; 763c9af18a5SGreg Clayton 764c9af18a5SGreg Clayton if (match) 765c9af18a5SGreg Clayton { 766c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 767c9af18a5SGreg Clayton } 768c9af18a5SGreg Clayton } 769c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 770c9af18a5SGreg Clayton } 771c9af18a5SGreg Clayton 772c9af18a5SGreg Clayton size_t 773c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 774c9af18a5SGreg Clayton { 775c9af18a5SGreg Clayton filter->Search (*this); 776c9af18a5SGreg Clayton return m_matches.GetSize(); 777c9af18a5SGreg Clayton } 778