1c9af18a5SGreg Clayton //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===// 2c9af18a5SGreg Clayton // 3c9af18a5SGreg Clayton // The LLVM Compiler Infrastructure 4c9af18a5SGreg Clayton // 5c9af18a5SGreg Clayton // This file is distributed under the University of Illinois Open Source 6c9af18a5SGreg Clayton // License. See LICENSE.TXT for details. 7c9af18a5SGreg Clayton // 8c9af18a5SGreg Clayton //===----------------------------------------------------------------------===// 9c9af18a5SGreg Clayton 10c9af18a5SGreg Clayton 11c9af18a5SGreg Clayton // C Includes 12558ce124SJim Ingham #include <sys/stat.h> 13558ce124SJim Ingham #include <dirent.h> 14558ce124SJim Ingham #include <libgen.h> 15558ce124SJim Ingham #include <glob.h> 167cc478b9SJim Ingham #include <pwd.h> 177cc478b9SJim Ingham #include <sys/types.h> 18558ce124SJim Ingham 19c9af18a5SGreg Clayton // C++ Includes 20c9af18a5SGreg Clayton // Other libraries and framework includes 21c9af18a5SGreg Clayton // Project includes 2240af72e1SJim Ingham #include "lldb/Interpreter/Args.h" 23c9af18a5SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 24c9af18a5SGreg Clayton #include "lldb/Core/FileSpecList.h" 25c9af18a5SGreg Clayton #include "lldb/Target/Target.h" 26c9af18a5SGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 277cc478b9SJim Ingham #include "lldb/Core/FileSpec.h" 28c9af18a5SGreg Clayton 29c9af18a5SGreg Clayton 30c9af18a5SGreg Clayton using namespace lldb_private; 31c9af18a5SGreg Clayton 32c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 33c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 34c9af18a5SGreg Clayton { 35c9af18a5SGreg Clayton {eCustomCompletion, NULL}, 36c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 37558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 38558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 39c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 40c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 41*3df9a8dfSCaroline Tice {eSettingsNameCompletion, CommandCompletions::SettingsNames}, 42c9af18a5SGreg Clayton {eNoCompletion, NULL} // This one has to be last in the list. 43c9af18a5SGreg Clayton }; 44c9af18a5SGreg Clayton 45c9af18a5SGreg Clayton bool 466611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks 476611103cSGreg Clayton ( 486611103cSGreg Clayton CommandInterpreter &interpreter, 496611103cSGreg Clayton uint32_t completion_mask, 50c9af18a5SGreg Clayton const char *completion_str, 51c9af18a5SGreg Clayton int match_start_point, 52c9af18a5SGreg Clayton int max_return_elements, 53c9af18a5SGreg Clayton SearchFilter *searcher, 54558ce124SJim Ingham bool &word_complete, 556611103cSGreg Clayton StringList &matches 566611103cSGreg Clayton ) 57c9af18a5SGreg Clayton { 58c9af18a5SGreg Clayton bool handled = false; 59c9af18a5SGreg Clayton 60c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 61c9af18a5SGreg Clayton return false; 62c9af18a5SGreg Clayton 63c9af18a5SGreg Clayton for (int i = 0; ; i++) 64c9af18a5SGreg Clayton { 65c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 66c9af18a5SGreg Clayton break; 67c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 68c9af18a5SGreg Clayton && g_common_completions[i].callback != NULL) 69c9af18a5SGreg Clayton { 70c9af18a5SGreg Clayton handled = true; 716611103cSGreg Clayton g_common_completions[i].callback (interpreter, 726611103cSGreg Clayton completion_str, 73c9af18a5SGreg Clayton match_start_point, 74c9af18a5SGreg Clayton max_return_elements, 75c9af18a5SGreg Clayton searcher, 76558ce124SJim Ingham word_complete, 77c9af18a5SGreg Clayton matches); 78c9af18a5SGreg Clayton } 79c9af18a5SGreg Clayton } 80c9af18a5SGreg Clayton return handled; 81c9af18a5SGreg Clayton } 82c9af18a5SGreg Clayton 83c9af18a5SGreg Clayton int 846611103cSGreg Clayton CommandCompletions::SourceFiles 856611103cSGreg Clayton ( 866611103cSGreg Clayton CommandInterpreter &interpreter, 876611103cSGreg Clayton const char *partial_file_name, 88c9af18a5SGreg Clayton int match_start_point, 89c9af18a5SGreg Clayton int max_return_elements, 90c9af18a5SGreg Clayton SearchFilter *searcher, 91558ce124SJim Ingham bool &word_complete, 926611103cSGreg Clayton StringList &matches 936611103cSGreg Clayton ) 94c9af18a5SGreg Clayton { 95558ce124SJim Ingham word_complete = true; 96c9af18a5SGreg Clayton // Find some way to switch "include support files..." 976611103cSGreg Clayton SourceFileCompleter completer (interpreter, 986611103cSGreg Clayton false, 996611103cSGreg Clayton partial_file_name, 1006611103cSGreg Clayton match_start_point, 1016611103cSGreg Clayton max_return_elements, 102c9af18a5SGreg Clayton matches); 103c9af18a5SGreg Clayton 104c9af18a5SGreg Clayton if (searcher == NULL) 105c9af18a5SGreg Clayton { 1062976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 107c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 108c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 109c9af18a5SGreg Clayton } 110c9af18a5SGreg Clayton else 111c9af18a5SGreg Clayton { 112c9af18a5SGreg Clayton completer.DoCompletion (searcher); 113c9af18a5SGreg Clayton } 114c9af18a5SGreg Clayton return matches.GetSize(); 115c9af18a5SGreg Clayton } 116c9af18a5SGreg Clayton 117558ce124SJim Ingham static int 118558ce124SJim Ingham DiskFilesOrDirectories 119558ce124SJim Ingham ( 120558ce124SJim Ingham const char *partial_file_name, 121558ce124SJim Ingham bool only_directories, 122558ce124SJim Ingham bool &saw_directory, 123558ce124SJim Ingham StringList &matches 124558ce124SJim Ingham ) 125558ce124SJim Ingham { 126558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 127558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 128558ce124SJim Ingham 129558ce124SJim Ingham int partial_name_len = strlen(partial_file_name); 130558ce124SJim Ingham 131558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 132558ce124SJim Ingham return matches.GetSize(); 133558ce124SJim Ingham 134558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 135558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 136558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 137558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 138558ce124SJim Ingham // the form the user originally typed. 139558ce124SJim Ingham 140558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 141021b605dSBenjamin Kramer memcpy(partial_name_copy, partial_file_name, partial_name_len); 142558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 143558ce124SJim Ingham 144558ce124SJim Ingham // We'll need to save a copy of the remainder for comparision, which we do here. 145558ce124SJim Ingham char remainder[PATH_MAX]; 146558ce124SJim Ingham 147558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 148558ce124SJim Ingham char *end_ptr; 149558ce124SJim Ingham 150558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 151558ce124SJim Ingham 152558ce124SJim Ingham // This will store the resolved form of the containing directory 153558ce124SJim Ingham char containing_part[PATH_MAX]; 154558ce124SJim Ingham 155558ce124SJim Ingham if (end_ptr == NULL) 156558ce124SJim Ingham { 157558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 158558ce124SJim Ingham // user name. 159558ce124SJim Ingham if (*partial_name_copy == '~') 160558ce124SJim Ingham { 161558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 1627cc478b9SJim Ingham // but for completeness sake we'll resolve the user name and only put a slash 163558ce124SJim Ingham // on the end if it exists. 1647cc478b9SJim Ingham char resolved_username[PATH_MAX]; 165c982c768SGreg Clayton size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username, 1667cc478b9SJim Ingham sizeof (resolved_username)); 1677cc478b9SJim Ingham 1687cc478b9SJim Ingham // Not sure how this would happen, a username longer than PATH_MAX? Still... 1697cc478b9SJim Ingham if (resolved_username_len >= sizeof (resolved_username)) 170558ce124SJim Ingham return matches.GetSize(); 1717cc478b9SJim Ingham else if (resolved_username_len == 0) 1727cc478b9SJim Ingham { 1737cc478b9SJim Ingham // The user name didn't resolve, let's look in the password database for matches. 1747cc478b9SJim Ingham // The user name database contains duplicates, and is not in alphabetical order, so 1757cc478b9SJim Ingham // we'll use a set to manage that for us. 1767cc478b9SJim Ingham 1777cc478b9SJim Ingham setpwent(); 1787cc478b9SJim Ingham struct passwd *user_entry; 1797cc478b9SJim Ingham const char *name_start = partial_name_copy + 1; 1807cc478b9SJim Ingham std::set<std::string> name_list; 1817cc478b9SJim Ingham 1827cc478b9SJim Ingham while ((user_entry = getpwent()) != NULL) 1837cc478b9SJim Ingham { 1847cc478b9SJim Ingham if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) 1857cc478b9SJim Ingham { 1867cc478b9SJim Ingham std::string tmp_buf("~"); 1877cc478b9SJim Ingham tmp_buf.append(user_entry->pw_name); 1887cc478b9SJim Ingham tmp_buf.push_back('/'); 1897cc478b9SJim Ingham name_list.insert(tmp_buf); 1907cc478b9SJim Ingham saw_directory = true; 1917cc478b9SJim Ingham } 1927cc478b9SJim Ingham } 1937cc478b9SJim Ingham std::set<std::string>::iterator pos, end = name_list.end(); 1947cc478b9SJim Ingham for (pos = name_list.begin(); pos != end; pos++) 1957cc478b9SJim Ingham { 1967cc478b9SJim Ingham matches.AppendString((*pos).c_str()); 1977cc478b9SJim Ingham } 1987cc478b9SJim Ingham return matches.GetSize(); 1997cc478b9SJim Ingham } 200558ce124SJim Ingham 201558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 202558ce124SJim Ingham // FIXME: complete user names here: 203558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 204558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 205558ce124SJim Ingham matches.AppendString(partial_name_copy); 206021b605dSBenjamin Kramer saw_directory = true; 207558ce124SJim Ingham return matches.GetSize(); 208558ce124SJim Ingham } 209558ce124SJim Ingham else 210558ce124SJim Ingham { 211558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 212558ce124SJim Ingham containing_part[0] = '.'; 213558ce124SJim Ingham containing_part[1] = '\0'; 214558ce124SJim Ingham strcpy(remainder, partial_name_copy); 215558ce124SJim Ingham end_ptr = partial_name_copy; 216558ce124SJim Ingham } 217558ce124SJim Ingham } 218558ce124SJim Ingham else 219558ce124SJim Ingham { 220558ce124SJim Ingham if (end_ptr == partial_name_copy) 221558ce124SJim Ingham { 222558ce124SJim Ingham // We're completing a file or directory in the root volume. 223558ce124SJim Ingham containing_part[0] = '/'; 224558ce124SJim Ingham containing_part[1] = '\0'; 225558ce124SJim Ingham } 226558ce124SJim Ingham else 227558ce124SJim Ingham { 228558ce124SJim Ingham size_t len = end_ptr - partial_name_copy; 229558ce124SJim Ingham memcpy(containing_part, partial_name_copy, len); 230558ce124SJim Ingham containing_part[len] = '\0'; 231558ce124SJim Ingham } 232558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 233558ce124SJim Ingham end_ptr++; 234558ce124SJim Ingham strcpy(remainder, end_ptr); 235558ce124SJim Ingham } 236558ce124SJim Ingham 2377cc478b9SJim Ingham // Look for a user name in the containing part, and if it's there, resolve it and stick the 238558ce124SJim Ingham // result back into the containing_part: 239558ce124SJim Ingham 240558ce124SJim Ingham if (*partial_name_copy == '~') 241558ce124SJim Ingham { 242c982c768SGreg Clayton size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, containing_part, sizeof (containing_part)); 243558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 244a0807356SGreg Clayton if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part)) 245558ce124SJim Ingham return matches.GetSize(); 246558ce124SJim Ingham } 247558ce124SJim Ingham 248558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 249558ce124SJim Ingham 250558ce124SJim Ingham DIR *dir_stream; 251558ce124SJim Ingham 252558ce124SJim Ingham dir_stream = opendir(containing_part); 253558ce124SJim Ingham if (dir_stream == NULL) 254558ce124SJim Ingham return matches.GetSize(); 255558ce124SJim Ingham 256558ce124SJim Ingham struct dirent *dirent_buf; 257558ce124SJim Ingham 258558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 259558ce124SJim Ingham 260558ce124SJim Ingham while ((dirent_buf = readdir(dir_stream)) != NULL) 261558ce124SJim Ingham { 262558ce124SJim Ingham char *name = dirent_buf->d_name; 263558ce124SJim Ingham 264558ce124SJim Ingham // Omit ".", ".." and any . files if the match string doesn't start with . 265558ce124SJim Ingham if (name[0] == '.') 266558ce124SJim Ingham { 267558ce124SJim Ingham if (name[1] == '\0') 268558ce124SJim Ingham continue; 269558ce124SJim Ingham else if (name[1] == '.' && name[2] == '\0') 270558ce124SJim Ingham continue; 271558ce124SJim Ingham else if (remainder[0] != '.') 272558ce124SJim Ingham continue; 273558ce124SJim Ingham } 274558ce124SJim Ingham 2757cc478b9SJim Ingham // If we found a directory, we put a "/" at the end of the name. 2767cc478b9SJim Ingham 277558ce124SJim Ingham if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name) 278558ce124SJim Ingham { 279558ce124SJim Ingham if (strlen(name) + baselen >= PATH_MAX) 280558ce124SJim Ingham continue; 281558ce124SJim Ingham 282558ce124SJim Ingham strcpy(end_ptr, name); 283558ce124SJim Ingham 284558ce124SJim Ingham bool isa_directory = false; 285558ce124SJim Ingham if (dirent_buf->d_type & DT_DIR) 286558ce124SJim Ingham isa_directory = true; 287558ce124SJim Ingham else if (dirent_buf->d_type & DT_LNK) 288558ce124SJim Ingham { 289558ce124SJim Ingham struct stat stat_buf; 290558ce124SJim Ingham if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR)) 291558ce124SJim Ingham isa_directory = true; 292558ce124SJim Ingham } 293558ce124SJim Ingham 294558ce124SJim Ingham if (isa_directory) 295558ce124SJim Ingham { 296558ce124SJim Ingham saw_directory = true; 297558ce124SJim Ingham size_t len = strlen(partial_name_copy); 298558ce124SJim Ingham partial_name_copy[len] = '/'; 299558ce124SJim Ingham partial_name_copy[len + 1] = '\0'; 300558ce124SJim Ingham } 301558ce124SJim Ingham if (only_directories && !isa_directory) 302558ce124SJim Ingham continue; 303558ce124SJim Ingham matches.AppendString(partial_name_copy); 304558ce124SJim Ingham } 305558ce124SJim Ingham } 306558ce124SJim Ingham 307558ce124SJim Ingham return matches.GetSize(); 308558ce124SJim Ingham } 309558ce124SJim Ingham 310558ce124SJim Ingham int 311558ce124SJim Ingham CommandCompletions::DiskFiles 312558ce124SJim Ingham ( 313558ce124SJim Ingham CommandInterpreter &interpreter, 314558ce124SJim Ingham const char *partial_file_name, 315558ce124SJim Ingham int match_start_point, 316558ce124SJim Ingham int max_return_elements, 317558ce124SJim Ingham SearchFilter *searcher, 318558ce124SJim Ingham bool &word_complete, 319558ce124SJim Ingham StringList &matches 320558ce124SJim Ingham ) 321558ce124SJim Ingham { 322558ce124SJim Ingham 323558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 324558ce124SJim Ingham false, 325558ce124SJim Ingham word_complete, 326558ce124SJim Ingham matches); 327558ce124SJim Ingham word_complete = !word_complete; 328558ce124SJim Ingham return ret_val; 329558ce124SJim Ingham } 330558ce124SJim Ingham 331558ce124SJim Ingham int 332558ce124SJim Ingham CommandCompletions::DiskDirectories 333558ce124SJim Ingham ( 334558ce124SJim Ingham CommandInterpreter &interpreter, 335558ce124SJim Ingham const char *partial_file_name, 336558ce124SJim Ingham int match_start_point, 337558ce124SJim Ingham int max_return_elements, 338558ce124SJim Ingham SearchFilter *searcher, 339558ce124SJim Ingham bool &word_complete, 340558ce124SJim Ingham StringList &matches 341558ce124SJim Ingham ) 342558ce124SJim Ingham { 343558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 344558ce124SJim Ingham true, 345558ce124SJim Ingham word_complete, 346558ce124SJim Ingham matches); 347558ce124SJim Ingham word_complete = false; 348558ce124SJim Ingham return ret_val; 349558ce124SJim Ingham } 350558ce124SJim Ingham 351c9af18a5SGreg Clayton int 3526611103cSGreg Clayton CommandCompletions::Modules 3536611103cSGreg Clayton ( 3546611103cSGreg Clayton CommandInterpreter &interpreter, 3556611103cSGreg Clayton const char *partial_file_name, 356c9af18a5SGreg Clayton int match_start_point, 357c9af18a5SGreg Clayton int max_return_elements, 358c9af18a5SGreg Clayton SearchFilter *searcher, 359558ce124SJim Ingham bool &word_complete, 3606611103cSGreg Clayton StringList &matches 3616611103cSGreg Clayton ) 362c9af18a5SGreg Clayton { 363558ce124SJim Ingham word_complete = true; 3646611103cSGreg Clayton ModuleCompleter completer (interpreter, 3656611103cSGreg Clayton partial_file_name, 3666611103cSGreg Clayton match_start_point, 3676611103cSGreg Clayton max_return_elements, 3686611103cSGreg Clayton matches); 369c9af18a5SGreg Clayton 370c9af18a5SGreg Clayton if (searcher == NULL) 371c9af18a5SGreg Clayton { 3722976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 373c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 374c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 375c9af18a5SGreg Clayton } 376c9af18a5SGreg Clayton else 377c9af18a5SGreg Clayton { 378c9af18a5SGreg Clayton completer.DoCompletion (searcher); 379c9af18a5SGreg Clayton } 380c9af18a5SGreg Clayton return matches.GetSize(); 381c9af18a5SGreg Clayton } 382c9af18a5SGreg Clayton 383c9af18a5SGreg Clayton int 3846611103cSGreg Clayton CommandCompletions::Symbols 3856611103cSGreg Clayton ( 3866611103cSGreg Clayton CommandInterpreter &interpreter, 3876611103cSGreg Clayton const char *partial_file_name, 388c9af18a5SGreg Clayton int match_start_point, 389c9af18a5SGreg Clayton int max_return_elements, 390c9af18a5SGreg Clayton SearchFilter *searcher, 391558ce124SJim Ingham bool &word_complete, 3926611103cSGreg Clayton StringList &matches) 393c9af18a5SGreg Clayton { 394558ce124SJim Ingham word_complete = true; 3956611103cSGreg Clayton SymbolCompleter completer (interpreter, 3966611103cSGreg Clayton partial_file_name, 3976611103cSGreg Clayton match_start_point, 3986611103cSGreg Clayton max_return_elements, 3996611103cSGreg Clayton matches); 400c9af18a5SGreg Clayton 401c9af18a5SGreg Clayton if (searcher == NULL) 402c9af18a5SGreg Clayton { 4032976d00aSJim Ingham lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 404c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 405c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 406c9af18a5SGreg Clayton } 407c9af18a5SGreg Clayton else 408c9af18a5SGreg Clayton { 409c9af18a5SGreg Clayton completer.DoCompletion (searcher); 410c9af18a5SGreg Clayton } 411c9af18a5SGreg Clayton return matches.GetSize(); 412c9af18a5SGreg Clayton } 413c9af18a5SGreg Clayton 414*3df9a8dfSCaroline Tice int 415*3df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter, 416*3df9a8dfSCaroline Tice const char *partial_setting_name, 417*3df9a8dfSCaroline Tice int match_start_point, 418*3df9a8dfSCaroline Tice int max_return_elements, 419*3df9a8dfSCaroline Tice SearchFilter *searcher, 420*3df9a8dfSCaroline Tice bool &word_complete, 421*3df9a8dfSCaroline Tice StringList &matches) 422*3df9a8dfSCaroline Tice { 423*3df9a8dfSCaroline Tice lldb::UserSettingsControllerSP root_settings = Debugger::GetSettingsController(); 424*3df9a8dfSCaroline Tice Args partial_setting_name_pieces = UserSettingsController::BreakNameIntoPieces (partial_setting_name); 425*3df9a8dfSCaroline Tice 426*3df9a8dfSCaroline Tice return UserSettingsController::CompleteSettingsNames (root_settings, 427*3df9a8dfSCaroline Tice partial_setting_name_pieces, 428*3df9a8dfSCaroline Tice word_complete, 429*3df9a8dfSCaroline Tice matches); 430*3df9a8dfSCaroline Tice 431*3df9a8dfSCaroline Tice //return matches.GetSize(); 432*3df9a8dfSCaroline Tice } 433*3df9a8dfSCaroline Tice 4346611103cSGreg Clayton CommandCompletions::Completer::Completer 4356611103cSGreg Clayton ( 4366611103cSGreg Clayton CommandInterpreter &interpreter, 437c9af18a5SGreg Clayton const char *completion_str, 438c9af18a5SGreg Clayton int match_start_point, 439c9af18a5SGreg Clayton int max_return_elements, 440c9af18a5SGreg Clayton StringList &matches 441c9af18a5SGreg Clayton ) : 4426611103cSGreg Clayton m_interpreter (interpreter), 443c9af18a5SGreg Clayton m_completion_str (completion_str), 444c9af18a5SGreg Clayton m_match_start_point (match_start_point), 445c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 446c9af18a5SGreg Clayton m_matches (matches) 447c9af18a5SGreg Clayton { 448c9af18a5SGreg Clayton } 449c9af18a5SGreg Clayton 450c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer () 451c9af18a5SGreg Clayton { 452c9af18a5SGreg Clayton 453c9af18a5SGreg Clayton } 454c9af18a5SGreg Clayton 455c9af18a5SGreg Clayton //---------------------------------------------------------------------- 456c9af18a5SGreg Clayton // SourceFileCompleter 457c9af18a5SGreg Clayton //---------------------------------------------------------------------- 458c9af18a5SGreg Clayton 4596611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter 4606611103cSGreg Clayton ( 4616611103cSGreg Clayton CommandInterpreter &interpreter, 462c9af18a5SGreg Clayton bool include_support_files, 463c9af18a5SGreg Clayton const char *completion_str, 464c9af18a5SGreg Clayton int match_start_point, 465c9af18a5SGreg Clayton int max_return_elements, 466c9af18a5SGreg Clayton StringList &matches 467c9af18a5SGreg Clayton ) : 4686611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 469c9af18a5SGreg Clayton m_include_support_files (include_support_files), 470c9af18a5SGreg Clayton m_matching_files() 471c9af18a5SGreg Clayton { 472c9af18a5SGreg Clayton FileSpec partial_spec (m_completion_str.c_str()); 473c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 474c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 475c9af18a5SGreg Clayton } 476c9af18a5SGreg Clayton 477c9af18a5SGreg Clayton Searcher::Depth 478c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 479c9af18a5SGreg Clayton { 480c9af18a5SGreg Clayton return eDepthCompUnit; 481c9af18a5SGreg Clayton } 482c9af18a5SGreg Clayton 483c9af18a5SGreg Clayton Searcher::CallbackReturn 484c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback ( 485c9af18a5SGreg Clayton SearchFilter &filter, 486c9af18a5SGreg Clayton SymbolContext &context, 487c9af18a5SGreg Clayton Address *addr, 488c9af18a5SGreg Clayton bool complete 489c9af18a5SGreg Clayton ) 490c9af18a5SGreg Clayton { 491c9af18a5SGreg Clayton if (context.comp_unit != NULL) 492c9af18a5SGreg Clayton { 493c9af18a5SGreg Clayton if (m_include_support_files) 494c9af18a5SGreg Clayton { 495c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 496c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 497c9af18a5SGreg Clayton { 498c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 499c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 500c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 501c9af18a5SGreg Clayton bool match = false; 502c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 503c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 504c9af18a5SGreg Clayton match = true; 505c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 506c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 507c9af18a5SGreg Clayton match = false; 508c9af18a5SGreg Clayton 509c9af18a5SGreg Clayton if (match) 510c9af18a5SGreg Clayton { 511c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 512c9af18a5SGreg Clayton } 513c9af18a5SGreg Clayton } 514c9af18a5SGreg Clayton 515c9af18a5SGreg Clayton } 516c9af18a5SGreg Clayton else 517c9af18a5SGreg Clayton { 518c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 519c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 520c9af18a5SGreg Clayton 521c9af18a5SGreg Clayton bool match = false; 522c9af18a5SGreg Clayton if (m_file_name && cur_file_name 523c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 524c9af18a5SGreg Clayton match = true; 525c9af18a5SGreg Clayton 526c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 527c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 528c9af18a5SGreg Clayton match = false; 529c9af18a5SGreg Clayton 530c9af18a5SGreg Clayton if (match) 531c9af18a5SGreg Clayton { 532c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 533c9af18a5SGreg Clayton } 534c9af18a5SGreg Clayton } 535c9af18a5SGreg Clayton } 536c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 537c9af18a5SGreg Clayton } 538c9af18a5SGreg Clayton 539c9af18a5SGreg Clayton size_t 540c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 541c9af18a5SGreg Clayton { 542c9af18a5SGreg Clayton filter->Search (*this); 543c9af18a5SGreg Clayton // Now convert the filelist to completions: 544c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 545c9af18a5SGreg Clayton { 546c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 547c9af18a5SGreg Clayton } 548c9af18a5SGreg Clayton return m_matches.GetSize(); 549c9af18a5SGreg Clayton 550c9af18a5SGreg Clayton } 551c9af18a5SGreg Clayton 552c9af18a5SGreg Clayton //---------------------------------------------------------------------- 553c9af18a5SGreg Clayton // SymbolCompleter 554c9af18a5SGreg Clayton //---------------------------------------------------------------------- 555c9af18a5SGreg Clayton 556c9af18a5SGreg Clayton static bool 557c9af18a5SGreg Clayton regex_chars (const char comp) 558c9af18a5SGreg Clayton { 559c9af18a5SGreg Clayton if (comp == '[' || comp == ']' || comp == '(' || comp == ')') 560c9af18a5SGreg Clayton return true; 561c9af18a5SGreg Clayton else 562c9af18a5SGreg Clayton return false; 563c9af18a5SGreg Clayton } 5646611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter 5656611103cSGreg Clayton ( 5666611103cSGreg Clayton CommandInterpreter &interpreter, 567c9af18a5SGreg Clayton const char *completion_str, 568c9af18a5SGreg Clayton int match_start_point, 569c9af18a5SGreg Clayton int max_return_elements, 570c9af18a5SGreg Clayton StringList &matches 571c9af18a5SGreg Clayton ) : 5726611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 573c9af18a5SGreg Clayton { 574c9af18a5SGreg Clayton std::string regex_str ("^"); 575c9af18a5SGreg Clayton regex_str.append(completion_str); 576c9af18a5SGreg Clayton regex_str.append(".*"); 577c9af18a5SGreg Clayton std::string::iterator pos; 578c9af18a5SGreg Clayton 579c9af18a5SGreg Clayton pos = find_if(regex_str.begin(), regex_str.end(), regex_chars); 580c9af18a5SGreg Clayton while (pos < regex_str.end()) { 581c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 582c9af18a5SGreg Clayton pos += 2; 583c9af18a5SGreg Clayton pos = find_if(pos, regex_str.end(), regex_chars); 584c9af18a5SGreg Clayton } 585c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 586c9af18a5SGreg Clayton } 587c9af18a5SGreg Clayton 588c9af18a5SGreg Clayton Searcher::Depth 589c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 590c9af18a5SGreg Clayton { 591c9af18a5SGreg Clayton return eDepthModule; 592c9af18a5SGreg Clayton } 593c9af18a5SGreg Clayton 594c9af18a5SGreg Clayton Searcher::CallbackReturn 595c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback ( 596c9af18a5SGreg Clayton SearchFilter &filter, 597c9af18a5SGreg Clayton SymbolContext &context, 598c9af18a5SGreg Clayton Address *addr, 599c9af18a5SGreg Clayton bool complete 600c9af18a5SGreg Clayton ) 601c9af18a5SGreg Clayton { 602c9af18a5SGreg Clayton SymbolContextList func_list; 603c9af18a5SGreg Clayton SymbolContextList sym_list; 604c9af18a5SGreg Clayton 605c9af18a5SGreg Clayton if (context.module_sp != NULL) 606c9af18a5SGreg Clayton { 607c9af18a5SGreg Clayton if (context.module_sp) 608c9af18a5SGreg Clayton { 609c9af18a5SGreg Clayton context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list); 610c9af18a5SGreg Clayton context.module_sp->FindFunctions (m_regex, true, func_list); 611c9af18a5SGreg Clayton } 612c9af18a5SGreg Clayton 613c9af18a5SGreg Clayton SymbolContext sc; 614c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 615c982c768SGreg Clayton for (uint32_t i = 0; i < func_list.GetSize(); i++) 616c9af18a5SGreg Clayton { 617c9af18a5SGreg Clayton if (func_list.GetContextAtIndex(i, sc)) 618c9af18a5SGreg Clayton { 619c9af18a5SGreg Clayton if (sc.function) 620c9af18a5SGreg Clayton { 621c9af18a5SGreg Clayton m_match_set.insert (sc.function->GetMangled().GetDemangledName()); 622c9af18a5SGreg Clayton } 623c9af18a5SGreg Clayton } 624c9af18a5SGreg Clayton } 625c9af18a5SGreg Clayton 626c982c768SGreg Clayton for (uint32_t i = 0; i < sym_list.GetSize(); i++) 627c9af18a5SGreg Clayton { 628c9af18a5SGreg Clayton if (sym_list.GetContextAtIndex(i, sc)) 629c9af18a5SGreg Clayton { 630c9af18a5SGreg Clayton if (sc.symbol && sc.symbol->GetAddressRangePtr()) 631c9af18a5SGreg Clayton { 632c9af18a5SGreg Clayton m_match_set.insert (sc.symbol->GetMangled().GetDemangledName()); 633c9af18a5SGreg Clayton } 634c9af18a5SGreg Clayton } 635c9af18a5SGreg Clayton } 636c9af18a5SGreg Clayton } 637c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 638c9af18a5SGreg Clayton } 639c9af18a5SGreg Clayton 640c9af18a5SGreg Clayton size_t 641c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 642c9af18a5SGreg Clayton { 643c9af18a5SGreg Clayton filter->Search (*this); 644c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 645c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 646c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 647c9af18a5SGreg Clayton 648c9af18a5SGreg Clayton return m_matches.GetSize(); 649c9af18a5SGreg Clayton } 650c9af18a5SGreg Clayton 651c9af18a5SGreg Clayton //---------------------------------------------------------------------- 652c9af18a5SGreg Clayton // ModuleCompleter 653c9af18a5SGreg Clayton //---------------------------------------------------------------------- 6546611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter 6556611103cSGreg Clayton ( 6566611103cSGreg Clayton CommandInterpreter &interpreter, 657c9af18a5SGreg Clayton const char *completion_str, 658c9af18a5SGreg Clayton int match_start_point, 659c9af18a5SGreg Clayton int max_return_elements, 660c9af18a5SGreg Clayton StringList &matches 661c9af18a5SGreg Clayton ) : 6626611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 663c9af18a5SGreg Clayton { 664c9af18a5SGreg Clayton FileSpec partial_spec (m_completion_str.c_str()); 665c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 666c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 667c9af18a5SGreg Clayton } 668c9af18a5SGreg Clayton 669c9af18a5SGreg Clayton Searcher::Depth 670c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 671c9af18a5SGreg Clayton { 672c9af18a5SGreg Clayton return eDepthModule; 673c9af18a5SGreg Clayton } 674c9af18a5SGreg Clayton 675c9af18a5SGreg Clayton Searcher::CallbackReturn 676c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback ( 677c9af18a5SGreg Clayton SearchFilter &filter, 678c9af18a5SGreg Clayton SymbolContext &context, 679c9af18a5SGreg Clayton Address *addr, 680c9af18a5SGreg Clayton bool complete 681c9af18a5SGreg Clayton ) 682c9af18a5SGreg Clayton { 683c9af18a5SGreg Clayton if (context.module_sp != NULL) 684c9af18a5SGreg Clayton { 685c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 686c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 687c9af18a5SGreg Clayton 688c9af18a5SGreg Clayton bool match = false; 689c9af18a5SGreg Clayton if (m_file_name && cur_file_name 690c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 691c9af18a5SGreg Clayton match = true; 692c9af18a5SGreg Clayton 693c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 694c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 695c9af18a5SGreg Clayton match = false; 696c9af18a5SGreg Clayton 697c9af18a5SGreg Clayton if (match) 698c9af18a5SGreg Clayton { 699c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 700c9af18a5SGreg Clayton } 701c9af18a5SGreg Clayton } 702c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 703c9af18a5SGreg Clayton } 704c9af18a5SGreg Clayton 705c9af18a5SGreg Clayton size_t 706c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 707c9af18a5SGreg Clayton { 708c9af18a5SGreg Clayton filter->Search (*this); 709c9af18a5SGreg Clayton return m_matches.GetSize(); 710c9af18a5SGreg Clayton } 711