]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandCompletions.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Commands / CommandCompletions.cpp
1 //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 // C Includes
13 #include <sys/stat.h>
14 #include <dirent.h>
15 #if defined(__APPLE__) || defined(__linux__)
16 #include <pwd.h>
17 #endif
18
19 // C++ Includes
20 // Other libraries and framework includes
21 // Project 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"
33
34 using namespace lldb_private;
35
36 CommandCompletions::CommonCompletionElement
37 CommandCompletions::g_common_completions[] =
38 {
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.
50 };
51
52 bool
53 CommandCompletions::InvokeCommonCompletionCallbacks 
54 (
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,
61     bool &word_complete,
62     StringList &matches
63 )
64 {
65     bool handled = false;
66
67     if (completion_mask & eCustomCompletion)
68         return false;
69
70     for (int i = 0; ; i++)
71     {
72         if (g_common_completions[i].type == eNoCompletion)
73             break;
74          else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
75                    && g_common_completions[i].callback != NULL)
76          {
77             handled = true;
78             g_common_completions[i].callback (interpreter,
79                                               completion_str,
80                                               match_start_point,
81                                               max_return_elements,
82                                               searcher,
83                                               word_complete,
84                                               matches);
85         }
86     }
87     return handled;
88 }
89
90 int
91 CommandCompletions::SourceFiles 
92 (
93     CommandInterpreter &interpreter,
94     const char *partial_file_name,
95     int match_start_point,
96     int max_return_elements,
97     SearchFilter *searcher,
98     bool &word_complete,
99     StringList &matches
100 )
101 {
102     word_complete = true;
103     // Find some way to switch "include support files..."
104     SourceFileCompleter completer (interpreter,
105                                    false, 
106                                    partial_file_name, 
107                                    match_start_point, 
108                                    max_return_elements,
109                                    matches);
110
111     if (searcher == NULL)
112     {
113         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
114         SearchFilter null_searcher (target_sp);
115         completer.DoCompletion (&null_searcher);
116     }
117     else
118     {
119         completer.DoCompletion (searcher);
120     }
121     return matches.GetSize();
122 }
123
124 static int
125 DiskFilesOrDirectories 
126 (
127     const char *partial_file_name,
128     bool only_directories,
129     bool &saw_directory,
130     StringList &matches
131 )
132 {
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...
135     
136     size_t partial_name_len = strlen(partial_file_name);
137     
138     if (partial_name_len >= PATH_MAX)
139         return matches.GetSize();
140     
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.
146     
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';
150     
151     // We'll need to save a copy of the remainder for comparison, which we do here.
152     char remainder[PATH_MAX];
153     
154     // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
155     char *end_ptr;
156     
157     end_ptr = strrchr(partial_name_copy, '/');
158     
159     // This will store the resolved form of the containing directory
160     char containing_part[PATH_MAX];
161     
162     if (end_ptr == NULL)
163     {
164         // There's no directory.  If the thing begins with a "~" then this is a bare
165         // user name.
166         if (*partial_name_copy == '~')
167         {
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));
174                                                           
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)
179             {
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();
187             } 
188             else
189             {   
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();
197             }
198         }
199         else
200         {
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;
206         }
207     }
208     else
209     {
210         if (end_ptr == partial_name_copy)
211         {
212             // We're completing a file or directory in the root volume.
213             containing_part[0] = '/';
214             containing_part[1] = '\0';
215         }
216         else
217         {
218             size_t len = end_ptr - partial_name_copy;
219             memcpy(containing_part, partial_name_copy, len);
220             containing_part[len] = '\0';
221         }
222         // Push end_ptr past the final "/" and set remainder.
223         end_ptr++;
224         strcpy(remainder, end_ptr);
225     }
226     
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:
229
230     if (*partial_name_copy == '~')
231     {
232         size_t resolved_username_len = FileSpec::ResolveUsername(containing_part, 
233                                                                  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();
238     }
239
240     // Okay, containing_part is now the directory we want to open and look for files:
241
242     lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
243     if (!dir_stream.is_valid())
244         return matches.GetSize();
245     
246     struct dirent *dirent_buf;
247     
248     size_t baselen = end_ptr - partial_name_copy;
249     
250     while ((dirent_buf = readdir(dir_stream.get())) != NULL) 
251     {
252         char *name = dirent_buf->d_name;
253         
254         // Omit ".", ".." and any . files if the match string doesn't start with .
255         if (name[0] == '.')
256         {
257             if (name[1] == '\0')
258                 continue;
259             else if (name[1] == '.' && name[2] == '\0')
260                 continue;
261             else if (remainder[0] != '.')
262                 continue;
263         }
264         
265         // If we found a directory, we put a "/" at the end of the name.
266         
267         if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
268         {
269             if (strlen(name) + baselen >= PATH_MAX)
270                 continue;
271                 
272             strcpy(end_ptr, name);
273             
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)
278             { 
279                 struct stat stat_buf;
280                 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
281                     isa_directory = true;
282             }
283             
284             if (isa_directory)
285             {
286                 saw_directory = true;
287                 size_t len = strlen(partial_name_copy);
288                 partial_name_copy[len] = '/';
289                 partial_name_copy[len + 1] = '\0';
290             }
291             if (only_directories && !isa_directory)
292                 continue;
293             matches.AppendString(partial_name_copy);
294         }
295     }
296     
297     return matches.GetSize();
298 }
299
300 int
301 CommandCompletions::DiskFiles 
302 (
303     CommandInterpreter &interpreter,
304     const char *partial_file_name,
305     int match_start_point,
306     int max_return_elements,
307     SearchFilter *searcher,
308     bool &word_complete,
309     StringList &matches
310 )
311 {
312
313     int ret_val = DiskFilesOrDirectories (partial_file_name,
314                                           false,
315                                           word_complete,
316                                           matches);
317     word_complete = !word_complete;
318     return ret_val;
319 }
320
321 int
322 CommandCompletions::DiskDirectories 
323 (
324     CommandInterpreter &interpreter,
325     const char *partial_file_name,
326     int match_start_point,
327     int max_return_elements,
328     SearchFilter *searcher,
329     bool &word_complete,
330     StringList &matches
331 )
332 {
333     int ret_val =  DiskFilesOrDirectories (partial_file_name,
334                                            true,
335                                            word_complete,
336                                            matches); 
337     word_complete = false;
338     return ret_val;
339 }
340
341 int
342 CommandCompletions::Modules 
343 (
344     CommandInterpreter &interpreter,
345     const char *partial_file_name,
346     int match_start_point,
347     int max_return_elements,
348     SearchFilter *searcher,
349     bool &word_complete,
350     StringList &matches
351 )
352 {
353     word_complete = true;
354     ModuleCompleter completer (interpreter,
355                                partial_file_name, 
356                                match_start_point, 
357                                max_return_elements, 
358                                matches);
359     
360     if (searcher == NULL)
361     {
362         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
363         SearchFilter null_searcher (target_sp);
364         completer.DoCompletion (&null_searcher);
365     }
366     else
367     {
368         completer.DoCompletion (searcher);
369     }
370     return matches.GetSize();
371 }
372
373 int
374 CommandCompletions::Symbols 
375 (
376     CommandInterpreter &interpreter,
377     const char *partial_file_name,
378     int match_start_point,
379     int max_return_elements,
380     SearchFilter *searcher,
381     bool &word_complete,
382     StringList &matches)
383 {
384     word_complete = true;
385     SymbolCompleter completer (interpreter,
386                                partial_file_name, 
387                                match_start_point, 
388                                max_return_elements, 
389                                matches);
390
391     if (searcher == NULL)
392     {
393         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
394         SearchFilter null_searcher (target_sp);
395         completer.DoCompletion (&null_searcher);
396     }
397     else
398     {
399         completer.DoCompletion (searcher);
400     }
401     return matches.GetSize();
402 }
403
404 int
405 CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
406                                    const char *partial_setting_name,
407                                    int match_start_point,
408                                    int max_return_elements,
409                                    SearchFilter *searcher,
410                                    bool &word_complete,
411                                    StringList &matches)
412 {
413     // Cache the full setting name list
414     static StringList g_property_names;
415     if (g_property_names.GetSize() == 0)
416     {
417         // Generate the full setting name list on demand
418         lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
419         if (properties_sp)
420         {
421             StreamString strm;
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());
425         }
426     }
427     
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;
431     return num_matches;
432 }
433
434
435 int
436 CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
437                                          const char *partial_name,
438                                          int match_start_point,
439                                          int max_return_elements,
440                                          SearchFilter *searcher,
441                                          bool &word_complete,
442                                          lldb_private::StringList &matches)
443 {
444     const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
445     word_complete = num_matches == 1;
446     return num_matches;
447 }
448
449 int
450 CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
451                                        const char *partial_name,
452                                        int match_start_point,
453                                        int max_return_elements,
454                                        SearchFilter *searcher,
455                                        bool &word_complete,
456                                        lldb_private::StringList &matches)
457 {
458     const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
459     word_complete = num_matches == 1;
460     return num_matches;
461 }
462
463
464 int
465 CommandCompletions::VariablePath (CommandInterpreter &interpreter,
466                                   const char *partial_name,
467                                   int match_start_point,
468                                   int max_return_elements,
469                                   SearchFilter *searcher,
470                                   bool &word_complete,
471                                   lldb_private::StringList &matches)
472 {
473     return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
474 }
475
476
477 CommandCompletions::Completer::Completer 
478 (
479     CommandInterpreter &interpreter,
480     const char *completion_str,
481     int match_start_point,
482     int max_return_elements,
483     StringList &matches
484 ) :
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),
489     m_matches (matches)
490 {
491 }
492
493 CommandCompletions::Completer::~Completer ()
494 {
495
496 }
497
498 //----------------------------------------------------------------------
499 // SourceFileCompleter
500 //----------------------------------------------------------------------
501
502 CommandCompletions::SourceFileCompleter::SourceFileCompleter 
503 (
504     CommandInterpreter &interpreter,
505     bool include_support_files,
506     const char *completion_str,
507     int match_start_point,
508     int max_return_elements,
509     StringList &matches
510 ) :
511     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
512     m_include_support_files (include_support_files),
513     m_matching_files()
514 {
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();
518 }
519
520 Searcher::Depth
521 CommandCompletions::SourceFileCompleter::GetDepth()
522 {
523     return eDepthCompUnit;
524 }
525
526 Searcher::CallbackReturn
527 CommandCompletions::SourceFileCompleter::SearchCallback (
528     SearchFilter &filter,
529     SymbolContext &context,
530     Address *addr,
531     bool complete
532 )
533 {
534     if (context.comp_unit != NULL)
535     {
536         if (m_include_support_files)
537         {
538             FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
539             for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
540             {
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();
544                 bool match = false;
545                 if (m_file_name && sfile_file_name
546                     && strstr (sfile_file_name, m_file_name) == sfile_file_name)
547                     match = true;
548                 if (match && m_dir_name && sfile_dir_name
549                     && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
550                     match = false;
551
552                 if (match)
553                 {
554                     m_matching_files.AppendIfUnique(sfile_spec);
555                 }
556             }
557
558         }
559         else
560         {
561             const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
562             const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
563
564             bool match = false;
565             if (m_file_name && cur_file_name
566                 && strstr (cur_file_name, m_file_name) == cur_file_name)
567                 match = true;
568
569             if (match && m_dir_name && cur_dir_name
570                 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
571                 match = false;
572
573             if (match)
574             {
575                 m_matching_files.AppendIfUnique(context.comp_unit);
576             }
577         }
578     }
579     return Searcher::eCallbackReturnContinue;
580 }
581
582 size_t
583 CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
584 {
585     filter->Search (*this);
586     // Now convert the filelist to completions:
587     for (size_t i = 0; i < m_matching_files.GetSize(); i++)
588     {
589         m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
590     }
591     return m_matches.GetSize();
592
593 }
594
595 //----------------------------------------------------------------------
596 // SymbolCompleter
597 //----------------------------------------------------------------------
598
599 static bool
600 regex_chars (const char comp)
601 {
602     if (comp == '[' || comp == ']' ||
603         comp == '(' || comp == ')' ||
604         comp == '{' || comp == '}' ||
605         comp == '+' ||
606         comp == '.' ||
607         comp == '*' ||
608         comp == '|' ||
609         comp == '^' ||
610         comp == '$' ||
611         comp == '\\' ||
612         comp == '?')
613         return true;
614     else
615         return false;
616 }
617 CommandCompletions::SymbolCompleter::SymbolCompleter 
618 (
619     CommandInterpreter &interpreter,
620     const char *completion_str,
621     int match_start_point,
622     int max_return_elements,
623     StringList &matches
624 ) :
625     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
626 {
627     std::string regex_str;
628     if (completion_str && completion_str[0])
629     {
630         regex_str.append("^");
631         regex_str.append(completion_str);
632     }
633     else
634     {
635         // Match anything since the completion string is empty
636         regex_str.append(".");
637     }
638     std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
639     while (pos < regex_str.end())
640     {
641         pos = regex_str.insert(pos, '\\');
642         pos = find_if(pos + 2, regex_str.end(), regex_chars);
643     }
644     m_regex.Compile(regex_str.c_str());
645 }
646
647 Searcher::Depth
648 CommandCompletions::SymbolCompleter::GetDepth()
649 {
650     return eDepthModule;
651 }
652
653 Searcher::CallbackReturn
654 CommandCompletions::SymbolCompleter::SearchCallback (
655     SearchFilter &filter,
656     SymbolContext &context,
657     Address *addr,
658     bool complete
659 )
660 {
661     if (context.module_sp)
662     {
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);
668
669         SymbolContext sc;
670         // Now add the functions & symbols to the list - only add if unique:
671         for (uint32_t i = 0; i < sc_list.GetSize(); i++)
672         {
673             if (sc_list.GetContextAtIndex(i, sc))
674             {
675                 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
676                 if (!func_name.IsEmpty())
677                     m_match_set.insert (func_name);
678             }
679         }
680     }
681     return Searcher::eCallbackReturnContinue;
682 }
683
684 size_t
685 CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
686 {
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());
691
692     return m_matches.GetSize();
693 }
694
695 //----------------------------------------------------------------------
696 // ModuleCompleter
697 //----------------------------------------------------------------------
698 CommandCompletions::ModuleCompleter::ModuleCompleter 
699 (
700     CommandInterpreter &interpreter,
701     const char *completion_str,
702     int match_start_point,
703     int max_return_elements,
704     StringList &matches
705 ) :
706     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
707 {
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();
711 }
712
713 Searcher::Depth
714 CommandCompletions::ModuleCompleter::GetDepth()
715 {
716     return eDepthModule;
717 }
718
719 Searcher::CallbackReturn
720 CommandCompletions::ModuleCompleter::SearchCallback (
721     SearchFilter &filter,
722     SymbolContext &context,
723     Address *addr,
724     bool complete
725 )
726 {
727     if (context.module_sp)
728     {
729         const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
730         const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
731
732         bool match = false;
733         if (m_file_name && cur_file_name
734             && strstr (cur_file_name, m_file_name) == cur_file_name)
735             match = true;
736
737         if (match && m_dir_name && cur_dir_name
738             && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
739             match = false;
740
741         if (match)
742         {
743             m_matches.AppendString (cur_file_name);
744         }
745     }
746     return Searcher::eCallbackReturnContinue;
747 }
748
749 size_t
750 CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
751 {
752     filter->Search (*this);
753     return m_matches.GetSize();
754 }