1 //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
15 #if defined(__APPLE__) || defined(__linux__)
20 // Other libraries and framework includes
22 #include "lldb/Host/FileSpec.h"
23 #include "lldb/Core/FileSpecList.h"
24 #include "lldb/Core/PluginManager.h"
25 #include "lldb/Core/Module.h"
26 #include "lldb/Interpreter/Args.h"
27 #include "lldb/Interpreter/CommandCompletions.h"
28 #include "lldb/Interpreter/CommandInterpreter.h"
29 #include "lldb/Symbol/CompileUnit.h"
30 #include "lldb/Symbol/Variable.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Utility/CleanUp.h"
34 using namespace lldb_private;
36 CommandCompletions::CommonCompletionElement
37 CommandCompletions::g_common_completions[] =
39 {eCustomCompletion, NULL},
40 {eSourceFileCompletion, CommandCompletions::SourceFiles},
41 {eDiskFileCompletion, CommandCompletions::DiskFiles},
42 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
43 {eSymbolCompletion, CommandCompletions::Symbols},
44 {eModuleCompletion, CommandCompletions::Modules},
45 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
46 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
47 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
48 {eVariablePathCompletion, CommandCompletions::VariablePath},
49 {eNoCompletion, NULL} // This one has to be last in the list.
53 CommandCompletions::InvokeCommonCompletionCallbacks
55 CommandInterpreter &interpreter,
56 uint32_t completion_mask,
57 const char *completion_str,
58 int match_start_point,
59 int max_return_elements,
60 SearchFilter *searcher,
67 if (completion_mask & eCustomCompletion)
70 for (int i = 0; ; i++)
72 if (g_common_completions[i].type == eNoCompletion)
74 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
75 && g_common_completions[i].callback != NULL)
78 g_common_completions[i].callback (interpreter,
91 CommandCompletions::SourceFiles
93 CommandInterpreter &interpreter,
94 const char *partial_file_name,
95 int match_start_point,
96 int max_return_elements,
97 SearchFilter *searcher,
102 word_complete = true;
103 // Find some way to switch "include support files..."
104 SourceFileCompleter completer (interpreter,
111 if (searcher == NULL)
113 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
114 SearchFilter null_searcher (target_sp);
115 completer.DoCompletion (&null_searcher);
119 completer.DoCompletion (searcher);
121 return matches.GetSize();
125 DiskFilesOrDirectories
127 const char *partial_file_name,
128 bool only_directories,
133 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
134 // If it is not defined on your host system, you'll need to implement it yourself...
136 size_t partial_name_len = strlen(partial_file_name);
138 if (partial_name_len >= PATH_MAX)
139 return matches.GetSize();
141 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
142 // below will point to the place of the remainder in this string. Then when we've resolved the
143 // containing directory, and opened it, we'll read the directory contents and overwrite the
144 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
145 // the form the user originally typed.
147 char partial_name_copy[PATH_MAX];
148 memcpy(partial_name_copy, partial_file_name, partial_name_len);
149 partial_name_copy[partial_name_len] = '\0';
151 // We'll need to save a copy of the remainder for comparison, which we do here.
152 char remainder[PATH_MAX];
154 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
157 end_ptr = strrchr(partial_name_copy, '/');
159 // This will store the resolved form of the containing directory
160 char containing_part[PATH_MAX];
164 // There's no directory. If the thing begins with a "~" then this is a bare
166 if (*partial_name_copy == '~')
168 // Nothing here but the user name. We could just put a slash on the end,
169 // but for completeness sake we'll resolve the user name and only put a slash
170 // on the end if it exists.
171 char resolved_username[PATH_MAX];
172 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
173 sizeof (resolved_username));
175 // Not sure how this would happen, a username longer than PATH_MAX? Still...
176 if (resolved_username_len >= sizeof (resolved_username))
177 return matches.GetSize();
178 else if (resolved_username_len == 0)
180 // The user name didn't resolve, let's look in the password database for matches.
181 // The user name database contains duplicates, and is not in alphabetical order, so
182 // we'll use a set to manage that for us.
183 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
184 if (matches.GetSize() > 0)
185 saw_directory = true;
186 return matches.GetSize();
190 //The thing exists, put a '/' on the end, and return it...
191 // FIXME: complete user names here:
192 partial_name_copy[partial_name_len] = '/';
193 partial_name_copy[partial_name_len+1] = '\0';
194 matches.AppendString(partial_name_copy);
195 saw_directory = true;
196 return matches.GetSize();
201 // The containing part is the CWD, and the whole string is the remainder.
202 containing_part[0] = '.';
203 containing_part[1] = '\0';
204 strcpy(remainder, partial_name_copy);
205 end_ptr = partial_name_copy;
210 if (end_ptr == partial_name_copy)
212 // We're completing a file or directory in the root volume.
213 containing_part[0] = '/';
214 containing_part[1] = '\0';
218 size_t len = end_ptr - partial_name_copy;
219 memcpy(containing_part, partial_name_copy, len);
220 containing_part[len] = '\0';
222 // Push end_ptr past the final "/" and set remainder.
224 strcpy(remainder, end_ptr);
227 // Look for a user name in the containing part, and if it's there, resolve it and stick the
228 // result back into the containing_part:
230 if (*partial_name_copy == '~')
232 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
234 sizeof (containing_part));
235 // User name doesn't exist, we're not getting any further...
236 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
237 return matches.GetSize();
240 // Okay, containing_part is now the directory we want to open and look for files:
242 lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
243 if (!dir_stream.is_valid())
244 return matches.GetSize();
246 struct dirent *dirent_buf;
248 size_t baselen = end_ptr - partial_name_copy;
250 while ((dirent_buf = readdir(dir_stream.get())) != NULL)
252 char *name = dirent_buf->d_name;
254 // Omit ".", ".." and any . files if the match string doesn't start with .
259 else if (name[1] == '.' && name[2] == '\0')
261 else if (remainder[0] != '.')
265 // If we found a directory, we put a "/" at the end of the name.
267 if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
269 if (strlen(name) + baselen >= PATH_MAX)
272 strcpy(end_ptr, name);
274 bool isa_directory = false;
275 if (dirent_buf->d_type & DT_DIR)
276 isa_directory = true;
277 else if (dirent_buf->d_type & DT_LNK)
279 struct stat stat_buf;
280 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
281 isa_directory = true;
286 saw_directory = true;
287 size_t len = strlen(partial_name_copy);
288 partial_name_copy[len] = '/';
289 partial_name_copy[len + 1] = '\0';
291 if (only_directories && !isa_directory)
293 matches.AppendString(partial_name_copy);
297 return matches.GetSize();
301 CommandCompletions::DiskFiles
303 CommandInterpreter &interpreter,
304 const char *partial_file_name,
305 int match_start_point,
306 int max_return_elements,
307 SearchFilter *searcher,
313 int ret_val = DiskFilesOrDirectories (partial_file_name,
317 word_complete = !word_complete;
322 CommandCompletions::DiskDirectories
324 CommandInterpreter &interpreter,
325 const char *partial_file_name,
326 int match_start_point,
327 int max_return_elements,
328 SearchFilter *searcher,
333 int ret_val = DiskFilesOrDirectories (partial_file_name,
337 word_complete = false;
342 CommandCompletions::Modules
344 CommandInterpreter &interpreter,
345 const char *partial_file_name,
346 int match_start_point,
347 int max_return_elements,
348 SearchFilter *searcher,
353 word_complete = true;
354 ModuleCompleter completer (interpreter,
360 if (searcher == NULL)
362 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
363 SearchFilter null_searcher (target_sp);
364 completer.DoCompletion (&null_searcher);
368 completer.DoCompletion (searcher);
370 return matches.GetSize();
374 CommandCompletions::Symbols
376 CommandInterpreter &interpreter,
377 const char *partial_file_name,
378 int match_start_point,
379 int max_return_elements,
380 SearchFilter *searcher,
384 word_complete = true;
385 SymbolCompleter completer (interpreter,
391 if (searcher == NULL)
393 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
394 SearchFilter null_searcher (target_sp);
395 completer.DoCompletion (&null_searcher);
399 completer.DoCompletion (searcher);
401 return matches.GetSize();
405 CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
406 const char *partial_setting_name,
407 int match_start_point,
408 int max_return_elements,
409 SearchFilter *searcher,
413 // Cache the full setting name list
414 static StringList g_property_names;
415 if (g_property_names.GetSize() == 0)
417 // Generate the full setting name list on demand
418 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
422 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
423 const std::string &str = strm.GetString();
424 g_property_names.SplitIntoLines(str.c_str(), str.size());
428 size_t exact_matches_idx = SIZE_MAX;
429 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
430 word_complete = exact_matches_idx != SIZE_MAX;
436 CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
437 const char *partial_name,
438 int match_start_point,
439 int max_return_elements,
440 SearchFilter *searcher,
442 lldb_private::StringList &matches)
444 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
445 word_complete = num_matches == 1;
450 CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
451 const char *partial_name,
452 int match_start_point,
453 int max_return_elements,
454 SearchFilter *searcher,
456 lldb_private::StringList &matches)
458 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
459 word_complete = num_matches == 1;
465 CommandCompletions::VariablePath (CommandInterpreter &interpreter,
466 const char *partial_name,
467 int match_start_point,
468 int max_return_elements,
469 SearchFilter *searcher,
471 lldb_private::StringList &matches)
473 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
477 CommandCompletions::Completer::Completer
479 CommandInterpreter &interpreter,
480 const char *completion_str,
481 int match_start_point,
482 int max_return_elements,
485 m_interpreter (interpreter),
486 m_completion_str (completion_str),
487 m_match_start_point (match_start_point),
488 m_max_return_elements (max_return_elements),
493 CommandCompletions::Completer::~Completer ()
498 //----------------------------------------------------------------------
499 // SourceFileCompleter
500 //----------------------------------------------------------------------
502 CommandCompletions::SourceFileCompleter::SourceFileCompleter
504 CommandInterpreter &interpreter,
505 bool include_support_files,
506 const char *completion_str,
507 int match_start_point,
508 int max_return_elements,
511 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
512 m_include_support_files (include_support_files),
515 FileSpec partial_spec (m_completion_str.c_str(), false);
516 m_file_name = partial_spec.GetFilename().GetCString();
517 m_dir_name = partial_spec.GetDirectory().GetCString();
521 CommandCompletions::SourceFileCompleter::GetDepth()
523 return eDepthCompUnit;
526 Searcher::CallbackReturn
527 CommandCompletions::SourceFileCompleter::SearchCallback (
528 SearchFilter &filter,
529 SymbolContext &context,
534 if (context.comp_unit != NULL)
536 if (m_include_support_files)
538 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
539 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
541 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
542 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
543 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
545 if (m_file_name && sfile_file_name
546 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
548 if (match && m_dir_name && sfile_dir_name
549 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
554 m_matching_files.AppendIfUnique(sfile_spec);
561 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
562 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
565 if (m_file_name && cur_file_name
566 && strstr (cur_file_name, m_file_name) == cur_file_name)
569 if (match && m_dir_name && cur_dir_name
570 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
575 m_matching_files.AppendIfUnique(context.comp_unit);
579 return Searcher::eCallbackReturnContinue;
583 CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
585 filter->Search (*this);
586 // Now convert the filelist to completions:
587 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
589 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
591 return m_matches.GetSize();
595 //----------------------------------------------------------------------
597 //----------------------------------------------------------------------
600 regex_chars (const char comp)
602 if (comp == '[' || comp == ']' ||
603 comp == '(' || comp == ')' ||
604 comp == '{' || comp == '}' ||
617 CommandCompletions::SymbolCompleter::SymbolCompleter
619 CommandInterpreter &interpreter,
620 const char *completion_str,
621 int match_start_point,
622 int max_return_elements,
625 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
627 std::string regex_str;
628 if (completion_str && completion_str[0])
630 regex_str.append("^");
631 regex_str.append(completion_str);
635 // Match anything since the completion string is empty
636 regex_str.append(".");
638 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
639 while (pos < regex_str.end())
641 pos = regex_str.insert(pos, '\\');
642 pos = find_if(pos + 2, regex_str.end(), regex_chars);
644 m_regex.Compile(regex_str.c_str());
648 CommandCompletions::SymbolCompleter::GetDepth()
653 Searcher::CallbackReturn
654 CommandCompletions::SymbolCompleter::SearchCallback (
655 SearchFilter &filter,
656 SymbolContext &context,
661 if (context.module_sp)
663 SymbolContextList sc_list;
664 const bool include_symbols = true;
665 const bool include_inlines = true;
666 const bool append = true;
667 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
670 // Now add the functions & symbols to the list - only add if unique:
671 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
673 if (sc_list.GetContextAtIndex(i, sc))
675 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
676 if (!func_name.IsEmpty())
677 m_match_set.insert (func_name);
681 return Searcher::eCallbackReturnContinue;
685 CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
687 filter->Search (*this);
688 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
689 for (pos = m_match_set.begin(); pos != end; pos++)
690 m_matches.AppendString((*pos).GetCString());
692 return m_matches.GetSize();
695 //----------------------------------------------------------------------
697 //----------------------------------------------------------------------
698 CommandCompletions::ModuleCompleter::ModuleCompleter
700 CommandInterpreter &interpreter,
701 const char *completion_str,
702 int match_start_point,
703 int max_return_elements,
706 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
708 FileSpec partial_spec (m_completion_str.c_str(), false);
709 m_file_name = partial_spec.GetFilename().GetCString();
710 m_dir_name = partial_spec.GetDirectory().GetCString();
714 CommandCompletions::ModuleCompleter::GetDepth()
719 Searcher::CallbackReturn
720 CommandCompletions::ModuleCompleter::SearchCallback (
721 SearchFilter &filter,
722 SymbolContext &context,
727 if (context.module_sp)
729 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
730 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
733 if (m_file_name && cur_file_name
734 && strstr (cur_file_name, m_file_name) == cur_file_name)
737 if (match && m_dir_name && cur_dir_name
738 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
743 m_matches.AppendString (cur_file_name);
746 return Searcher::eCallbackReturnContinue;
750 CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
752 filter->Search (*this);
753 return m_matches.GetSize();