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 12*558ce124SJim Ingham #include <sys/stat.h> 13*558ce124SJim Ingham #include <dirent.h> 14*558ce124SJim Ingham #include <libgen.h> 15*558ce124SJim Ingham #include <glob.h> 16*558ce124SJim Ingham 17c9af18a5SGreg Clayton // C++ Includes 18c9af18a5SGreg Clayton // Other libraries and framework includes 19c9af18a5SGreg Clayton // Project includes 2040af72e1SJim Ingham #include "lldb/Interpreter/Args.h" 21c9af18a5SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 22c9af18a5SGreg Clayton #include "lldb/Core/FileSpecList.h" 23c9af18a5SGreg Clayton #include "lldb/Target/Target.h" 24c9af18a5SGreg Clayton #include "lldb/Interpreter/CommandCompletions.h" 25c9af18a5SGreg Clayton 26c9af18a5SGreg Clayton 27c9af18a5SGreg Clayton using namespace lldb_private; 28c9af18a5SGreg Clayton 29c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement 30c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] = 31c9af18a5SGreg Clayton { 32c9af18a5SGreg Clayton {eCustomCompletion, NULL}, 33c9af18a5SGreg Clayton {eSourceFileCompletion, CommandCompletions::SourceFiles}, 34*558ce124SJim Ingham {eDiskFileCompletion, CommandCompletions::DiskFiles}, 35*558ce124SJim Ingham {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories}, 36c9af18a5SGreg Clayton {eSymbolCompletion, CommandCompletions::Symbols}, 37c9af18a5SGreg Clayton {eModuleCompletion, CommandCompletions::Modules}, 38c9af18a5SGreg Clayton {eNoCompletion, NULL} // This one has to be last in the list. 39c9af18a5SGreg Clayton }; 40c9af18a5SGreg Clayton 41c9af18a5SGreg Clayton bool 426611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks 436611103cSGreg Clayton ( 446611103cSGreg Clayton CommandInterpreter &interpreter, 456611103cSGreg Clayton uint32_t completion_mask, 46c9af18a5SGreg Clayton const char *completion_str, 47c9af18a5SGreg Clayton int match_start_point, 48c9af18a5SGreg Clayton int max_return_elements, 49c9af18a5SGreg Clayton SearchFilter *searcher, 50*558ce124SJim Ingham bool &word_complete, 516611103cSGreg Clayton StringList &matches 526611103cSGreg Clayton ) 53c9af18a5SGreg Clayton { 54c9af18a5SGreg Clayton bool handled = false; 55c9af18a5SGreg Clayton 56c9af18a5SGreg Clayton if (completion_mask & eCustomCompletion) 57c9af18a5SGreg Clayton return false; 58c9af18a5SGreg Clayton 59c9af18a5SGreg Clayton for (int i = 0; ; i++) 60c9af18a5SGreg Clayton { 61c9af18a5SGreg Clayton if (g_common_completions[i].type == eNoCompletion) 62c9af18a5SGreg Clayton break; 63c9af18a5SGreg Clayton else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type 64c9af18a5SGreg Clayton && g_common_completions[i].callback != NULL) 65c9af18a5SGreg Clayton { 66c9af18a5SGreg Clayton handled = true; 676611103cSGreg Clayton g_common_completions[i].callback (interpreter, 686611103cSGreg Clayton completion_str, 69c9af18a5SGreg Clayton match_start_point, 70c9af18a5SGreg Clayton max_return_elements, 71c9af18a5SGreg Clayton searcher, 72*558ce124SJim Ingham word_complete, 73c9af18a5SGreg Clayton matches); 74c9af18a5SGreg Clayton } 75c9af18a5SGreg Clayton } 76c9af18a5SGreg Clayton return handled; 77c9af18a5SGreg Clayton } 78c9af18a5SGreg Clayton 79c9af18a5SGreg Clayton int 806611103cSGreg Clayton CommandCompletions::SourceFiles 816611103cSGreg Clayton ( 826611103cSGreg Clayton CommandInterpreter &interpreter, 836611103cSGreg Clayton const char *partial_file_name, 84c9af18a5SGreg Clayton int match_start_point, 85c9af18a5SGreg Clayton int max_return_elements, 86c9af18a5SGreg Clayton SearchFilter *searcher, 87*558ce124SJim Ingham bool &word_complete, 886611103cSGreg Clayton StringList &matches 896611103cSGreg Clayton ) 90c9af18a5SGreg Clayton { 91*558ce124SJim Ingham word_complete = true; 92c9af18a5SGreg Clayton // Find some way to switch "include support files..." 936611103cSGreg Clayton SourceFileCompleter completer (interpreter, 946611103cSGreg Clayton false, 956611103cSGreg Clayton partial_file_name, 966611103cSGreg Clayton match_start_point, 976611103cSGreg Clayton max_return_elements, 98c9af18a5SGreg Clayton matches); 99c9af18a5SGreg Clayton 100c9af18a5SGreg Clayton if (searcher == NULL) 101c9af18a5SGreg Clayton { 1026611103cSGreg Clayton lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget(); 103c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 104c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 105c9af18a5SGreg Clayton } 106c9af18a5SGreg Clayton else 107c9af18a5SGreg Clayton { 108c9af18a5SGreg Clayton completer.DoCompletion (searcher); 109c9af18a5SGreg Clayton } 110c9af18a5SGreg Clayton return matches.GetSize(); 111c9af18a5SGreg Clayton } 112c9af18a5SGreg Clayton 113*558ce124SJim Ingham static int 114*558ce124SJim Ingham DiskFilesOrDirectories 115*558ce124SJim Ingham ( 116*558ce124SJim Ingham const char *partial_file_name, 117*558ce124SJim Ingham bool only_directories, 118*558ce124SJim Ingham bool &saw_directory, 119*558ce124SJim Ingham StringList &matches 120*558ce124SJim Ingham ) 121*558ce124SJim Ingham { 122*558ce124SJim Ingham // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion. 123*558ce124SJim Ingham // If it is not defined on your host system, you'll need to implement it yourself... 124*558ce124SJim Ingham 125*558ce124SJim Ingham int partial_name_len = strlen(partial_file_name); 126*558ce124SJim Ingham 127*558ce124SJim Ingham if (partial_name_len >= PATH_MAX) 128*558ce124SJim Ingham return matches.GetSize(); 129*558ce124SJim Ingham 130*558ce124SJim Ingham // This copy of the string will be cut up into the directory part, and the remainder. end_ptr 131*558ce124SJim Ingham // below will point to the place of the remainder in this string. Then when we've resolved the 132*558ce124SJim Ingham // containing directory, and opened it, we'll read the directory contents and overwrite the 133*558ce124SJim Ingham // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve 134*558ce124SJim Ingham // the form the user originally typed. 135*558ce124SJim Ingham 136*558ce124SJim Ingham char partial_name_copy[PATH_MAX]; 137*558ce124SJim Ingham bcopy (partial_file_name, partial_name_copy, partial_name_len); 138*558ce124SJim Ingham partial_name_copy[partial_name_len] = '\0'; 139*558ce124SJim Ingham 140*558ce124SJim Ingham // We'll need to save a copy of the remainder for comparision, which we do here. 141*558ce124SJim Ingham char remainder[PATH_MAX]; 142*558ce124SJim Ingham 143*558ce124SJim Ingham // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string. 144*558ce124SJim Ingham char *end_ptr; 145*558ce124SJim Ingham 146*558ce124SJim Ingham end_ptr = strrchr(partial_name_copy, '/'); 147*558ce124SJim Ingham 148*558ce124SJim Ingham // This will store the resolved form of the containing directory 149*558ce124SJim Ingham char containing_part[PATH_MAX]; 150*558ce124SJim Ingham 151*558ce124SJim Ingham if (end_ptr == NULL) 152*558ce124SJim Ingham { 153*558ce124SJim Ingham // There's no directory. If the thing begins with a "~" then this is a bare 154*558ce124SJim Ingham // user name. 155*558ce124SJim Ingham if (*partial_name_copy == '~') 156*558ce124SJim Ingham { 157*558ce124SJim Ingham // Nothing here but the user name. We could just put a slash on the end, 158*558ce124SJim Ingham // but for completeness sake we'll glob the user name and only put a slash 159*558ce124SJim Ingham // on the end if it exists. 160*558ce124SJim Ingham glob_t glob_buf; 161*558ce124SJim Ingham if (glob (partial_name_copy, GLOB_TILDE, NULL, &glob_buf) != 0) 162*558ce124SJim Ingham return matches.GetSize(); 163*558ce124SJim Ingham 164*558ce124SJim Ingham //The thing exists, put a '/' on the end, and return it... 165*558ce124SJim Ingham // FIXME: complete user names here: 166*558ce124SJim Ingham partial_name_copy[partial_name_len] = '/'; 167*558ce124SJim Ingham partial_name_copy[partial_name_len+1] = '\0'; 168*558ce124SJim Ingham matches.AppendString(partial_name_copy); 169*558ce124SJim Ingham globfree(&glob_buf); 170*558ce124SJim Ingham saw_directory == true; 171*558ce124SJim Ingham return matches.GetSize(); 172*558ce124SJim Ingham } 173*558ce124SJim Ingham else 174*558ce124SJim Ingham { 175*558ce124SJim Ingham // The containing part is the CWD, and the whole string is the remainder. 176*558ce124SJim Ingham containing_part[0] = '.'; 177*558ce124SJim Ingham containing_part[1] = '\0'; 178*558ce124SJim Ingham strcpy(remainder, partial_name_copy); 179*558ce124SJim Ingham end_ptr = partial_name_copy; 180*558ce124SJim Ingham } 181*558ce124SJim Ingham } 182*558ce124SJim Ingham else 183*558ce124SJim Ingham { 184*558ce124SJim Ingham if (end_ptr == partial_name_copy) 185*558ce124SJim Ingham { 186*558ce124SJim Ingham // We're completing a file or directory in the root volume. 187*558ce124SJim Ingham containing_part[0] = '/'; 188*558ce124SJim Ingham containing_part[1] = '\0'; 189*558ce124SJim Ingham } 190*558ce124SJim Ingham else 191*558ce124SJim Ingham { 192*558ce124SJim Ingham size_t len = end_ptr - partial_name_copy; 193*558ce124SJim Ingham memcpy(containing_part, partial_name_copy, len); 194*558ce124SJim Ingham containing_part[len] = '\0'; 195*558ce124SJim Ingham } 196*558ce124SJim Ingham // Push end_ptr past the final "/" and set remainder. 197*558ce124SJim Ingham end_ptr++; 198*558ce124SJim Ingham strcpy(remainder, end_ptr); 199*558ce124SJim Ingham } 200*558ce124SJim Ingham 201*558ce124SJim Ingham // Look for a user name in the containing part, and if it's there, glob containing_part and stick the 202*558ce124SJim Ingham // result back into the containing_part: 203*558ce124SJim Ingham 204*558ce124SJim Ingham if (*partial_name_copy == '~') 205*558ce124SJim Ingham { 206*558ce124SJim Ingham glob_t glob_buf; 207*558ce124SJim Ingham 208*558ce124SJim Ingham // User name doesn't exist, we're not getting any further... 209*558ce124SJim Ingham if (glob (containing_part, GLOB_TILDE, NULL, &glob_buf) != 0) 210*558ce124SJim Ingham return matches.GetSize(); 211*558ce124SJim Ingham 212*558ce124SJim Ingham if (glob_buf.gl_pathc != 1) 213*558ce124SJim Ingham { 214*558ce124SJim Ingham // I'm not really sure how this would happen? 215*558ce124SJim Ingham globfree(&glob_buf); 216*558ce124SJim Ingham return matches.GetSize(); 217*558ce124SJim Ingham } 218*558ce124SJim Ingham strcpy(containing_part, glob_buf.gl_pathv[0]); 219*558ce124SJim Ingham globfree(&glob_buf); 220*558ce124SJim Ingham } 221*558ce124SJim Ingham 222*558ce124SJim Ingham // Okay, containing_part is now the directory we want to open and look for files: 223*558ce124SJim Ingham 224*558ce124SJim Ingham DIR *dir_stream; 225*558ce124SJim Ingham 226*558ce124SJim Ingham dir_stream = opendir(containing_part); 227*558ce124SJim Ingham if (dir_stream == NULL) 228*558ce124SJim Ingham return matches.GetSize(); 229*558ce124SJim Ingham 230*558ce124SJim Ingham struct dirent *dirent_buf; 231*558ce124SJim Ingham 232*558ce124SJim Ingham size_t baselen = end_ptr - partial_name_copy; 233*558ce124SJim Ingham 234*558ce124SJim Ingham while ((dirent_buf = readdir(dir_stream)) != NULL) 235*558ce124SJim Ingham { 236*558ce124SJim Ingham char *name = dirent_buf->d_name; 237*558ce124SJim Ingham 238*558ce124SJim Ingham // Omit ".", ".." and any . files if the match string doesn't start with . 239*558ce124SJim Ingham if (name[0] == '.') 240*558ce124SJim Ingham { 241*558ce124SJim Ingham if (name[1] == '\0') 242*558ce124SJim Ingham continue; 243*558ce124SJim Ingham else if (name[1] == '.' && name[2] == '\0') 244*558ce124SJim Ingham continue; 245*558ce124SJim Ingham else if (remainder[0] != '.') 246*558ce124SJim Ingham continue; 247*558ce124SJim Ingham } 248*558ce124SJim Ingham 249*558ce124SJim Ingham if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name) 250*558ce124SJim Ingham { 251*558ce124SJim Ingham if (strlen(name) + baselen >= PATH_MAX) 252*558ce124SJim Ingham continue; 253*558ce124SJim Ingham 254*558ce124SJim Ingham strcpy(end_ptr, name); 255*558ce124SJim Ingham 256*558ce124SJim Ingham bool isa_directory = false; 257*558ce124SJim Ingham if (dirent_buf->d_type & DT_DIR) 258*558ce124SJim Ingham isa_directory = true; 259*558ce124SJim Ingham else if (dirent_buf->d_type & DT_LNK) 260*558ce124SJim Ingham { 261*558ce124SJim Ingham struct stat stat_buf; 262*558ce124SJim Ingham if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR)) 263*558ce124SJim Ingham isa_directory = true; 264*558ce124SJim Ingham } 265*558ce124SJim Ingham 266*558ce124SJim Ingham if (isa_directory) 267*558ce124SJim Ingham { 268*558ce124SJim Ingham saw_directory = true; 269*558ce124SJim Ingham size_t len = strlen(partial_name_copy); 270*558ce124SJim Ingham partial_name_copy[len] = '/'; 271*558ce124SJim Ingham partial_name_copy[len + 1] = '\0'; 272*558ce124SJim Ingham } 273*558ce124SJim Ingham if (only_directories && !isa_directory) 274*558ce124SJim Ingham continue; 275*558ce124SJim Ingham matches.AppendString(partial_name_copy); 276*558ce124SJim Ingham } 277*558ce124SJim Ingham } 278*558ce124SJim Ingham 279*558ce124SJim Ingham return matches.GetSize(); 280*558ce124SJim Ingham } 281*558ce124SJim Ingham 282*558ce124SJim Ingham int 283*558ce124SJim Ingham CommandCompletions::DiskFiles 284*558ce124SJim Ingham ( 285*558ce124SJim Ingham CommandInterpreter &interpreter, 286*558ce124SJim Ingham const char *partial_file_name, 287*558ce124SJim Ingham int match_start_point, 288*558ce124SJim Ingham int max_return_elements, 289*558ce124SJim Ingham SearchFilter *searcher, 290*558ce124SJim Ingham bool &word_complete, 291*558ce124SJim Ingham StringList &matches 292*558ce124SJim Ingham ) 293*558ce124SJim Ingham { 294*558ce124SJim Ingham 295*558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 296*558ce124SJim Ingham false, 297*558ce124SJim Ingham word_complete, 298*558ce124SJim Ingham matches); 299*558ce124SJim Ingham word_complete = !word_complete; 300*558ce124SJim Ingham return ret_val; 301*558ce124SJim Ingham } 302*558ce124SJim Ingham 303*558ce124SJim Ingham int 304*558ce124SJim Ingham CommandCompletions::DiskDirectories 305*558ce124SJim Ingham ( 306*558ce124SJim Ingham CommandInterpreter &interpreter, 307*558ce124SJim Ingham const char *partial_file_name, 308*558ce124SJim Ingham int match_start_point, 309*558ce124SJim Ingham int max_return_elements, 310*558ce124SJim Ingham SearchFilter *searcher, 311*558ce124SJim Ingham bool &word_complete, 312*558ce124SJim Ingham StringList &matches 313*558ce124SJim Ingham ) 314*558ce124SJim Ingham { 315*558ce124SJim Ingham int ret_val = DiskFilesOrDirectories (partial_file_name, 316*558ce124SJim Ingham true, 317*558ce124SJim Ingham word_complete, 318*558ce124SJim Ingham matches); 319*558ce124SJim Ingham word_complete = false; 320*558ce124SJim Ingham return ret_val; 321*558ce124SJim Ingham } 322*558ce124SJim Ingham 323c9af18a5SGreg Clayton int 3246611103cSGreg Clayton CommandCompletions::Modules 3256611103cSGreg Clayton ( 3266611103cSGreg Clayton CommandInterpreter &interpreter, 3276611103cSGreg Clayton const char *partial_file_name, 328c9af18a5SGreg Clayton int match_start_point, 329c9af18a5SGreg Clayton int max_return_elements, 330c9af18a5SGreg Clayton SearchFilter *searcher, 331*558ce124SJim Ingham bool &word_complete, 3326611103cSGreg Clayton StringList &matches 3336611103cSGreg Clayton ) 334c9af18a5SGreg Clayton { 335*558ce124SJim Ingham word_complete = true; 3366611103cSGreg Clayton ModuleCompleter completer (interpreter, 3376611103cSGreg Clayton partial_file_name, 3386611103cSGreg Clayton match_start_point, 3396611103cSGreg Clayton max_return_elements, 3406611103cSGreg Clayton matches); 341c9af18a5SGreg Clayton 342c9af18a5SGreg Clayton if (searcher == NULL) 343c9af18a5SGreg Clayton { 3446611103cSGreg Clayton lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget(); 345c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 346c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 347c9af18a5SGreg Clayton } 348c9af18a5SGreg Clayton else 349c9af18a5SGreg Clayton { 350c9af18a5SGreg Clayton completer.DoCompletion (searcher); 351c9af18a5SGreg Clayton } 352c9af18a5SGreg Clayton return matches.GetSize(); 353c9af18a5SGreg Clayton } 354c9af18a5SGreg Clayton 355c9af18a5SGreg Clayton int 3566611103cSGreg Clayton CommandCompletions::Symbols 3576611103cSGreg Clayton ( 3586611103cSGreg Clayton CommandInterpreter &interpreter, 3596611103cSGreg Clayton const char *partial_file_name, 360c9af18a5SGreg Clayton int match_start_point, 361c9af18a5SGreg Clayton int max_return_elements, 362c9af18a5SGreg Clayton SearchFilter *searcher, 363*558ce124SJim Ingham bool &word_complete, 3646611103cSGreg Clayton StringList &matches) 365c9af18a5SGreg Clayton { 366*558ce124SJim Ingham word_complete = true; 3676611103cSGreg Clayton SymbolCompleter completer (interpreter, 3686611103cSGreg Clayton partial_file_name, 3696611103cSGreg Clayton match_start_point, 3706611103cSGreg Clayton max_return_elements, 3716611103cSGreg Clayton matches); 372c9af18a5SGreg Clayton 373c9af18a5SGreg Clayton if (searcher == NULL) 374c9af18a5SGreg Clayton { 3756611103cSGreg Clayton lldb::TargetSP target_sp = interpreter.GetDebugger().GetCurrentTarget(); 376c9af18a5SGreg Clayton SearchFilter null_searcher (target_sp); 377c9af18a5SGreg Clayton completer.DoCompletion (&null_searcher); 378c9af18a5SGreg Clayton } 379c9af18a5SGreg Clayton else 380c9af18a5SGreg Clayton { 381c9af18a5SGreg Clayton completer.DoCompletion (searcher); 382c9af18a5SGreg Clayton } 383c9af18a5SGreg Clayton return matches.GetSize(); 384c9af18a5SGreg Clayton } 385c9af18a5SGreg Clayton 3866611103cSGreg Clayton CommandCompletions::Completer::Completer 3876611103cSGreg Clayton ( 3886611103cSGreg Clayton CommandInterpreter &interpreter, 389c9af18a5SGreg Clayton const char *completion_str, 390c9af18a5SGreg Clayton int match_start_point, 391c9af18a5SGreg Clayton int max_return_elements, 392c9af18a5SGreg Clayton StringList &matches 393c9af18a5SGreg Clayton ) : 3946611103cSGreg Clayton m_interpreter (interpreter), 395c9af18a5SGreg Clayton m_completion_str (completion_str), 396c9af18a5SGreg Clayton m_match_start_point (match_start_point), 397c9af18a5SGreg Clayton m_max_return_elements (max_return_elements), 398c9af18a5SGreg Clayton m_matches (matches) 399c9af18a5SGreg Clayton { 400c9af18a5SGreg Clayton } 401c9af18a5SGreg Clayton 402c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer () 403c9af18a5SGreg Clayton { 404c9af18a5SGreg Clayton 405c9af18a5SGreg Clayton } 406c9af18a5SGreg Clayton 407c9af18a5SGreg Clayton //---------------------------------------------------------------------- 408c9af18a5SGreg Clayton // SourceFileCompleter 409c9af18a5SGreg Clayton //---------------------------------------------------------------------- 410c9af18a5SGreg Clayton 4116611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter 4126611103cSGreg Clayton ( 4136611103cSGreg Clayton CommandInterpreter &interpreter, 414c9af18a5SGreg Clayton bool include_support_files, 415c9af18a5SGreg Clayton const char *completion_str, 416c9af18a5SGreg Clayton int match_start_point, 417c9af18a5SGreg Clayton int max_return_elements, 418c9af18a5SGreg Clayton StringList &matches 419c9af18a5SGreg Clayton ) : 4206611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches), 421c9af18a5SGreg Clayton m_include_support_files (include_support_files), 422c9af18a5SGreg Clayton m_matching_files() 423c9af18a5SGreg Clayton { 424c9af18a5SGreg Clayton FileSpec partial_spec (m_completion_str.c_str()); 425c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 426c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 427c9af18a5SGreg Clayton } 428c9af18a5SGreg Clayton 429c9af18a5SGreg Clayton Searcher::Depth 430c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth() 431c9af18a5SGreg Clayton { 432c9af18a5SGreg Clayton return eDepthCompUnit; 433c9af18a5SGreg Clayton } 434c9af18a5SGreg Clayton 435c9af18a5SGreg Clayton Searcher::CallbackReturn 436c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback ( 437c9af18a5SGreg Clayton SearchFilter &filter, 438c9af18a5SGreg Clayton SymbolContext &context, 439c9af18a5SGreg Clayton Address *addr, 440c9af18a5SGreg Clayton bool complete 441c9af18a5SGreg Clayton ) 442c9af18a5SGreg Clayton { 443c9af18a5SGreg Clayton if (context.comp_unit != NULL) 444c9af18a5SGreg Clayton { 445c9af18a5SGreg Clayton if (m_include_support_files) 446c9af18a5SGreg Clayton { 447c9af18a5SGreg Clayton FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); 448c9af18a5SGreg Clayton for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) 449c9af18a5SGreg Clayton { 450c9af18a5SGreg Clayton const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles); 451c9af18a5SGreg Clayton const char *sfile_file_name = sfile_spec.GetFilename().GetCString(); 452c9af18a5SGreg Clayton const char *sfile_dir_name = sfile_spec.GetFilename().GetCString(); 453c9af18a5SGreg Clayton bool match = false; 454c9af18a5SGreg Clayton if (m_file_name && sfile_file_name 455c9af18a5SGreg Clayton && strstr (sfile_file_name, m_file_name) == sfile_file_name) 456c9af18a5SGreg Clayton match = true; 457c9af18a5SGreg Clayton if (match && m_dir_name && sfile_dir_name 458c9af18a5SGreg Clayton && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name) 459c9af18a5SGreg Clayton match = false; 460c9af18a5SGreg Clayton 461c9af18a5SGreg Clayton if (match) 462c9af18a5SGreg Clayton { 463c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(sfile_spec); 464c9af18a5SGreg Clayton } 465c9af18a5SGreg Clayton } 466c9af18a5SGreg Clayton 467c9af18a5SGreg Clayton } 468c9af18a5SGreg Clayton else 469c9af18a5SGreg Clayton { 470c9af18a5SGreg Clayton const char *cur_file_name = context.comp_unit->GetFilename().GetCString(); 471c9af18a5SGreg Clayton const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString(); 472c9af18a5SGreg Clayton 473c9af18a5SGreg Clayton bool match = false; 474c9af18a5SGreg Clayton if (m_file_name && cur_file_name 475c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 476c9af18a5SGreg Clayton match = true; 477c9af18a5SGreg Clayton 478c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 479c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 480c9af18a5SGreg Clayton match = false; 481c9af18a5SGreg Clayton 482c9af18a5SGreg Clayton if (match) 483c9af18a5SGreg Clayton { 484c9af18a5SGreg Clayton m_matching_files.AppendIfUnique(context.comp_unit); 485c9af18a5SGreg Clayton } 486c9af18a5SGreg Clayton } 487c9af18a5SGreg Clayton } 488c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 489c9af18a5SGreg Clayton } 490c9af18a5SGreg Clayton 491c9af18a5SGreg Clayton size_t 492c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter) 493c9af18a5SGreg Clayton { 494c9af18a5SGreg Clayton filter->Search (*this); 495c9af18a5SGreg Clayton // Now convert the filelist to completions: 496c9af18a5SGreg Clayton for (size_t i = 0; i < m_matching_files.GetSize(); i++) 497c9af18a5SGreg Clayton { 498c9af18a5SGreg Clayton m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); 499c9af18a5SGreg Clayton } 500c9af18a5SGreg Clayton return m_matches.GetSize(); 501c9af18a5SGreg Clayton 502c9af18a5SGreg Clayton } 503c9af18a5SGreg Clayton 504c9af18a5SGreg Clayton //---------------------------------------------------------------------- 505c9af18a5SGreg Clayton // SymbolCompleter 506c9af18a5SGreg Clayton //---------------------------------------------------------------------- 507c9af18a5SGreg Clayton 508c9af18a5SGreg Clayton static bool 509c9af18a5SGreg Clayton regex_chars (const char comp) 510c9af18a5SGreg Clayton { 511c9af18a5SGreg Clayton if (comp == '[' || comp == ']' || comp == '(' || comp == ')') 512c9af18a5SGreg Clayton return true; 513c9af18a5SGreg Clayton else 514c9af18a5SGreg Clayton return false; 515c9af18a5SGreg Clayton } 5166611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter 5176611103cSGreg Clayton ( 5186611103cSGreg Clayton CommandInterpreter &interpreter, 519c9af18a5SGreg Clayton const char *completion_str, 520c9af18a5SGreg Clayton int match_start_point, 521c9af18a5SGreg Clayton int max_return_elements, 522c9af18a5SGreg Clayton StringList &matches 523c9af18a5SGreg Clayton ) : 5246611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 525c9af18a5SGreg Clayton { 526c9af18a5SGreg Clayton std::string regex_str ("^"); 527c9af18a5SGreg Clayton regex_str.append(completion_str); 528c9af18a5SGreg Clayton regex_str.append(".*"); 529c9af18a5SGreg Clayton std::string::iterator pos; 530c9af18a5SGreg Clayton 531c9af18a5SGreg Clayton pos = find_if(regex_str.begin(), regex_str.end(), regex_chars); 532c9af18a5SGreg Clayton while (pos < regex_str.end()) { 533c9af18a5SGreg Clayton pos = regex_str.insert(pos, '\\'); 534c9af18a5SGreg Clayton pos += 2; 535c9af18a5SGreg Clayton pos = find_if(pos, regex_str.end(), regex_chars); 536c9af18a5SGreg Clayton } 537c9af18a5SGreg Clayton m_regex.Compile(regex_str.c_str()); 538c9af18a5SGreg Clayton } 539c9af18a5SGreg Clayton 540c9af18a5SGreg Clayton Searcher::Depth 541c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth() 542c9af18a5SGreg Clayton { 543c9af18a5SGreg Clayton return eDepthModule; 544c9af18a5SGreg Clayton } 545c9af18a5SGreg Clayton 546c9af18a5SGreg Clayton Searcher::CallbackReturn 547c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback ( 548c9af18a5SGreg Clayton SearchFilter &filter, 549c9af18a5SGreg Clayton SymbolContext &context, 550c9af18a5SGreg Clayton Address *addr, 551c9af18a5SGreg Clayton bool complete 552c9af18a5SGreg Clayton ) 553c9af18a5SGreg Clayton { 554c9af18a5SGreg Clayton SymbolContextList func_list; 555c9af18a5SGreg Clayton SymbolContextList sym_list; 556c9af18a5SGreg Clayton 557c9af18a5SGreg Clayton if (context.module_sp != NULL) 558c9af18a5SGreg Clayton { 559c9af18a5SGreg Clayton if (context.module_sp) 560c9af18a5SGreg Clayton { 561c9af18a5SGreg Clayton context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, lldb::eSymbolTypeCode, sym_list); 562c9af18a5SGreg Clayton context.module_sp->FindFunctions (m_regex, true, func_list); 563c9af18a5SGreg Clayton } 564c9af18a5SGreg Clayton 565c9af18a5SGreg Clayton SymbolContext sc; 566c9af18a5SGreg Clayton // Now add the functions & symbols to the list - only add if unique: 567c9af18a5SGreg Clayton for (int i = 0; i < func_list.GetSize(); i++) 568c9af18a5SGreg Clayton { 569c9af18a5SGreg Clayton if (func_list.GetContextAtIndex(i, sc)) 570c9af18a5SGreg Clayton { 571c9af18a5SGreg Clayton if (sc.function) 572c9af18a5SGreg Clayton { 573c9af18a5SGreg Clayton m_match_set.insert (sc.function->GetMangled().GetDemangledName()); 574c9af18a5SGreg Clayton } 575c9af18a5SGreg Clayton } 576c9af18a5SGreg Clayton } 577c9af18a5SGreg Clayton 578c9af18a5SGreg Clayton for (int i = 0; i < sym_list.GetSize(); i++) 579c9af18a5SGreg Clayton { 580c9af18a5SGreg Clayton if (sym_list.GetContextAtIndex(i, sc)) 581c9af18a5SGreg Clayton { 582c9af18a5SGreg Clayton if (sc.symbol && sc.symbol->GetAddressRangePtr()) 583c9af18a5SGreg Clayton { 584c9af18a5SGreg Clayton m_match_set.insert (sc.symbol->GetMangled().GetDemangledName()); 585c9af18a5SGreg Clayton } 586c9af18a5SGreg Clayton } 587c9af18a5SGreg Clayton } 588c9af18a5SGreg Clayton } 589c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 590c9af18a5SGreg Clayton } 591c9af18a5SGreg Clayton 592c9af18a5SGreg Clayton size_t 593c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter) 594c9af18a5SGreg Clayton { 595c9af18a5SGreg Clayton filter->Search (*this); 596c9af18a5SGreg Clayton collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); 597c9af18a5SGreg Clayton for (pos = m_match_set.begin(); pos != end; pos++) 598c9af18a5SGreg Clayton m_matches.AppendString((*pos).GetCString()); 599c9af18a5SGreg Clayton 600c9af18a5SGreg Clayton return m_matches.GetSize(); 601c9af18a5SGreg Clayton } 602c9af18a5SGreg Clayton 603c9af18a5SGreg Clayton //---------------------------------------------------------------------- 604c9af18a5SGreg Clayton // ModuleCompleter 605c9af18a5SGreg Clayton //---------------------------------------------------------------------- 6066611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter 6076611103cSGreg Clayton ( 6086611103cSGreg Clayton CommandInterpreter &interpreter, 609c9af18a5SGreg Clayton const char *completion_str, 610c9af18a5SGreg Clayton int match_start_point, 611c9af18a5SGreg Clayton int max_return_elements, 612c9af18a5SGreg Clayton StringList &matches 613c9af18a5SGreg Clayton ) : 6146611103cSGreg Clayton CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches) 615c9af18a5SGreg Clayton { 616c9af18a5SGreg Clayton FileSpec partial_spec (m_completion_str.c_str()); 617c9af18a5SGreg Clayton m_file_name = partial_spec.GetFilename().GetCString(); 618c9af18a5SGreg Clayton m_dir_name = partial_spec.GetDirectory().GetCString(); 619c9af18a5SGreg Clayton } 620c9af18a5SGreg Clayton 621c9af18a5SGreg Clayton Searcher::Depth 622c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth() 623c9af18a5SGreg Clayton { 624c9af18a5SGreg Clayton return eDepthModule; 625c9af18a5SGreg Clayton } 626c9af18a5SGreg Clayton 627c9af18a5SGreg Clayton Searcher::CallbackReturn 628c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback ( 629c9af18a5SGreg Clayton SearchFilter &filter, 630c9af18a5SGreg Clayton SymbolContext &context, 631c9af18a5SGreg Clayton Address *addr, 632c9af18a5SGreg Clayton bool complete 633c9af18a5SGreg Clayton ) 634c9af18a5SGreg Clayton { 635c9af18a5SGreg Clayton if (context.module_sp != NULL) 636c9af18a5SGreg Clayton { 637c9af18a5SGreg Clayton const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); 638c9af18a5SGreg Clayton const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString(); 639c9af18a5SGreg Clayton 640c9af18a5SGreg Clayton bool match = false; 641c9af18a5SGreg Clayton if (m_file_name && cur_file_name 642c9af18a5SGreg Clayton && strstr (cur_file_name, m_file_name) == cur_file_name) 643c9af18a5SGreg Clayton match = true; 644c9af18a5SGreg Clayton 645c9af18a5SGreg Clayton if (match && m_dir_name && cur_dir_name 646c9af18a5SGreg Clayton && strstr (cur_dir_name, m_dir_name) != cur_dir_name) 647c9af18a5SGreg Clayton match = false; 648c9af18a5SGreg Clayton 649c9af18a5SGreg Clayton if (match) 650c9af18a5SGreg Clayton { 651c9af18a5SGreg Clayton m_matches.AppendString (cur_file_name); 652c9af18a5SGreg Clayton } 653c9af18a5SGreg Clayton } 654c9af18a5SGreg Clayton return Searcher::eCallbackReturnContinue; 655c9af18a5SGreg Clayton } 656c9af18a5SGreg Clayton 657c9af18a5SGreg Clayton size_t 658c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter) 659c9af18a5SGreg Clayton { 660c9af18a5SGreg Clayton filter->Search (*this); 661c9af18a5SGreg Clayton return m_matches.GetSize(); 662c9af18a5SGreg Clayton } 663c9af18a5SGreg Clayton 664c9af18a5SGreg Clayton 665c9af18a5SGreg Clayton 666