1c9af18a5SGreg Clayton //===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2c9af18a5SGreg Clayton //
3c9af18a5SGreg Clayton //                     The LLVM Compiler Infrastructure
4c9af18a5SGreg Clayton //
5c9af18a5SGreg Clayton // This file is distributed under the University of Illinois Open Source
6c9af18a5SGreg Clayton // License. See LICENSE.TXT for details.
7c9af18a5SGreg Clayton //
8c9af18a5SGreg Clayton //===----------------------------------------------------------------------===//
9c9af18a5SGreg Clayton 
1093a64300SDaniel Malea #include "lldb/lldb-python.h"
11c9af18a5SGreg Clayton 
12c9af18a5SGreg Clayton // C Includes
13558ce124SJim Ingham #include <sys/stat.h>
14558ce124SJim Ingham #include <dirent.h>
15fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__)
167cc478b9SJim Ingham #include <pwd.h>
17fd18426eSGreg Clayton #endif
18558ce124SJim Ingham 
19c9af18a5SGreg Clayton // C++ Includes
20c9af18a5SGreg Clayton // Other libraries and framework includes
21c9af18a5SGreg Clayton // Project includes
2253239f00SGreg Clayton #include "lldb/Host/FileSpec.h"
239b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h"
24ab65b34fSGreg Clayton #include "lldb/Core/PluginManager.h"
251f746071SGreg Clayton #include "lldb/Core/Module.h"
269b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h"
279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h"
289b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
291f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
30*f21feadcSGreg Clayton #include "lldb/Symbol/Variable.h"
319b62fd2fSGreg Clayton #include "lldb/Target/Target.h"
329b62fd2fSGreg Clayton #include "lldb/Utility/CleanUp.h"
33c9af18a5SGreg Clayton 
34c9af18a5SGreg Clayton using namespace lldb_private;
35c9af18a5SGreg Clayton 
36c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement
37c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] =
38c9af18a5SGreg Clayton {
39c9af18a5SGreg Clayton     {eCustomCompletion,          NULL},
40c9af18a5SGreg Clayton     {eSourceFileCompletion,      CommandCompletions::SourceFiles},
41558ce124SJim Ingham     {eDiskFileCompletion,        CommandCompletions::DiskFiles},
42558ce124SJim Ingham     {eDiskDirectoryCompletion,   CommandCompletions::DiskDirectories},
43c9af18a5SGreg Clayton     {eSymbolCompletion,          CommandCompletions::Symbols},
44c9af18a5SGreg Clayton     {eModuleCompletion,          CommandCompletions::Modules},
453df9a8dfSCaroline Tice     {eSettingsNameCompletion,    CommandCompletions::SettingsNames},
46ab65b34fSGreg Clayton     {ePlatformPluginCompletion,  CommandCompletions::PlatformPluginNames},
47ab65b34fSGreg Clayton     {eArchitectureCompletion,    CommandCompletions::ArchitectureNames},
48*f21feadcSGreg Clayton     {eVariablePathCompletion,    CommandCompletions::VariablePath},
49c9af18a5SGreg Clayton     {eNoCompletion,              NULL}      // This one has to be last in the list.
50c9af18a5SGreg Clayton };
51c9af18a5SGreg Clayton 
52c9af18a5SGreg Clayton bool
536611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks
546611103cSGreg Clayton (
556611103cSGreg Clayton     CommandInterpreter &interpreter,
566611103cSGreg Clayton     uint32_t completion_mask,
57c9af18a5SGreg Clayton     const char *completion_str,
58c9af18a5SGreg Clayton     int match_start_point,
59c9af18a5SGreg Clayton     int max_return_elements,
60c9af18a5SGreg Clayton     SearchFilter *searcher,
61558ce124SJim Ingham     bool &word_complete,
626611103cSGreg Clayton     StringList &matches
636611103cSGreg Clayton )
64c9af18a5SGreg Clayton {
65c9af18a5SGreg Clayton     bool handled = false;
66c9af18a5SGreg Clayton 
67c9af18a5SGreg Clayton     if (completion_mask & eCustomCompletion)
68c9af18a5SGreg Clayton         return false;
69c9af18a5SGreg Clayton 
70c9af18a5SGreg Clayton     for (int i = 0; ; i++)
71c9af18a5SGreg Clayton     {
72c9af18a5SGreg Clayton         if (g_common_completions[i].type == eNoCompletion)
73c9af18a5SGreg Clayton             break;
74c9af18a5SGreg Clayton          else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
75c9af18a5SGreg Clayton                    && g_common_completions[i].callback != NULL)
76c9af18a5SGreg Clayton          {
77c9af18a5SGreg Clayton             handled = true;
786611103cSGreg Clayton             g_common_completions[i].callback (interpreter,
796611103cSGreg Clayton                                               completion_str,
80c9af18a5SGreg Clayton                                               match_start_point,
81c9af18a5SGreg Clayton                                               max_return_elements,
82c9af18a5SGreg Clayton                                               searcher,
83558ce124SJim Ingham                                               word_complete,
84c9af18a5SGreg Clayton                                               matches);
85c9af18a5SGreg Clayton         }
86c9af18a5SGreg Clayton     }
87c9af18a5SGreg Clayton     return handled;
88c9af18a5SGreg Clayton }
89c9af18a5SGreg Clayton 
90c9af18a5SGreg Clayton int
916611103cSGreg Clayton CommandCompletions::SourceFiles
926611103cSGreg Clayton (
936611103cSGreg Clayton     CommandInterpreter &interpreter,
946611103cSGreg Clayton     const char *partial_file_name,
95c9af18a5SGreg Clayton     int match_start_point,
96c9af18a5SGreg Clayton     int max_return_elements,
97c9af18a5SGreg Clayton     SearchFilter *searcher,
98558ce124SJim Ingham     bool &word_complete,
996611103cSGreg Clayton     StringList &matches
1006611103cSGreg Clayton )
101c9af18a5SGreg Clayton {
102558ce124SJim Ingham     word_complete = true;
103c9af18a5SGreg Clayton     // Find some way to switch "include support files..."
1046611103cSGreg Clayton     SourceFileCompleter completer (interpreter,
1056611103cSGreg Clayton                                    false,
1066611103cSGreg Clayton                                    partial_file_name,
1076611103cSGreg Clayton                                    match_start_point,
1086611103cSGreg Clayton                                    max_return_elements,
109c9af18a5SGreg Clayton                                    matches);
110c9af18a5SGreg Clayton 
111c9af18a5SGreg Clayton     if (searcher == NULL)
112c9af18a5SGreg Clayton     {
1132976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
114c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
115c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
116c9af18a5SGreg Clayton     }
117c9af18a5SGreg Clayton     else
118c9af18a5SGreg Clayton     {
119c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
120c9af18a5SGreg Clayton     }
121c9af18a5SGreg Clayton     return matches.GetSize();
122c9af18a5SGreg Clayton }
123c9af18a5SGreg Clayton 
124558ce124SJim Ingham static int
125558ce124SJim Ingham DiskFilesOrDirectories
126558ce124SJim Ingham (
127558ce124SJim Ingham     const char *partial_file_name,
128558ce124SJim Ingham     bool only_directories,
129558ce124SJim Ingham     bool &saw_directory,
130558ce124SJim Ingham     StringList &matches
131558ce124SJim Ingham )
132558ce124SJim Ingham {
133558ce124SJim Ingham     // I'm going to  use the "glob" function with GLOB_TILDE for user directory expansion.
134558ce124SJim Ingham     // If it is not defined on your host system, you'll need to implement it yourself...
135558ce124SJim Ingham 
136c7bece56SGreg Clayton     size_t partial_name_len = strlen(partial_file_name);
137558ce124SJim Ingham 
138558ce124SJim Ingham     if (partial_name_len >= PATH_MAX)
139558ce124SJim Ingham         return matches.GetSize();
140558ce124SJim Ingham 
141558ce124SJim Ingham     // This copy of the string will be cut up into the directory part, and the remainder.  end_ptr
142558ce124SJim Ingham     // below will point to the place of the remainder in this string.  Then when we've resolved the
143558ce124SJim Ingham     // containing directory, and opened it, we'll read the directory contents and overwrite the
144558ce124SJim Ingham     // partial_name_copy starting from end_ptr with each of the matches.  Thus we will preserve
145558ce124SJim Ingham     // the form the user originally typed.
146558ce124SJim Ingham 
147558ce124SJim Ingham     char partial_name_copy[PATH_MAX];
148021b605dSBenjamin Kramer     memcpy(partial_name_copy, partial_file_name, partial_name_len);
149558ce124SJim Ingham     partial_name_copy[partial_name_len] = '\0';
150558ce124SJim Ingham 
151710dd5aeSGreg Clayton     // We'll need to save a copy of the remainder for comparison, which we do here.
152558ce124SJim Ingham     char remainder[PATH_MAX];
153558ce124SJim Ingham 
154558ce124SJim Ingham     // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
155558ce124SJim Ingham     char *end_ptr;
156558ce124SJim Ingham 
157558ce124SJim Ingham     end_ptr = strrchr(partial_name_copy, '/');
158558ce124SJim Ingham 
159558ce124SJim Ingham     // This will store the resolved form of the containing directory
160558ce124SJim Ingham     char containing_part[PATH_MAX];
161558ce124SJim Ingham 
162558ce124SJim Ingham     if (end_ptr == NULL)
163558ce124SJim Ingham     {
164558ce124SJim Ingham         // There's no directory.  If the thing begins with a "~" then this is a bare
165558ce124SJim Ingham         // user name.
166558ce124SJim Ingham         if (*partial_name_copy == '~')
167558ce124SJim Ingham         {
168558ce124SJim Ingham             // Nothing here but the user name.  We could just put a slash on the end,
1697cc478b9SJim Ingham             // but for completeness sake we'll resolve the user name and only put a slash
170558ce124SJim Ingham             // on the end if it exists.
1717cc478b9SJim Ingham             char resolved_username[PATH_MAX];
172c982c768SGreg Clayton             size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
1737cc478b9SJim Ingham                                                           sizeof (resolved_username));
1747cc478b9SJim Ingham 
1757cc478b9SJim Ingham            // Not sure how this would happen, a username longer than PATH_MAX?  Still...
1767cc478b9SJim Ingham             if (resolved_username_len >= sizeof (resolved_username))
177558ce124SJim Ingham                 return matches.GetSize();
17884363078SJim Ingham             else if (resolved_username_len == 0)
1797cc478b9SJim Ingham             {
1807cc478b9SJim Ingham                 // The user name didn't resolve, let's look in the password database for matches.
1817cc478b9SJim Ingham                 // The user name database contains duplicates, and is not in alphabetical order, so
1827cc478b9SJim Ingham                 // we'll use a set to manage that for us.
18384363078SJim Ingham                 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
18484363078SJim Ingham                 if (matches.GetSize() > 0)
1857cc478b9SJim Ingham                     saw_directory = true;
1867cc478b9SJim Ingham                 return matches.GetSize();
1877cc478b9SJim Ingham             }
18884363078SJim Ingham             else
18984363078SJim Ingham             {
190558ce124SJim Ingham                 //The thing exists, put a '/' on the end, and return it...
191558ce124SJim Ingham                 // FIXME: complete user names here:
192558ce124SJim Ingham                 partial_name_copy[partial_name_len] = '/';
193558ce124SJim Ingham                 partial_name_copy[partial_name_len+1] = '\0';
194558ce124SJim Ingham                 matches.AppendString(partial_name_copy);
195021b605dSBenjamin Kramer                 saw_directory = true;
196558ce124SJim Ingham                 return matches.GetSize();
197558ce124SJim Ingham             }
19884363078SJim Ingham         }
199558ce124SJim Ingham         else
200558ce124SJim Ingham         {
201558ce124SJim Ingham             // The containing part is the CWD, and the whole string is the remainder.
202558ce124SJim Ingham             containing_part[0] = '.';
203558ce124SJim Ingham             containing_part[1] = '\0';
204558ce124SJim Ingham             strcpy(remainder, partial_name_copy);
205558ce124SJim Ingham             end_ptr = partial_name_copy;
206558ce124SJim Ingham         }
207558ce124SJim Ingham     }
208558ce124SJim Ingham     else
209558ce124SJim Ingham     {
210558ce124SJim Ingham         if (end_ptr == partial_name_copy)
211558ce124SJim Ingham         {
212558ce124SJim Ingham             // We're completing a file or directory in the root volume.
213558ce124SJim Ingham             containing_part[0] = '/';
214558ce124SJim Ingham             containing_part[1] = '\0';
215558ce124SJim Ingham         }
216558ce124SJim Ingham         else
217558ce124SJim Ingham         {
218558ce124SJim Ingham             size_t len = end_ptr - partial_name_copy;
219558ce124SJim Ingham             memcpy(containing_part, partial_name_copy, len);
220558ce124SJim Ingham             containing_part[len] = '\0';
221558ce124SJim Ingham         }
222558ce124SJim Ingham         // Push end_ptr past the final "/" and set remainder.
223558ce124SJim Ingham         end_ptr++;
224558ce124SJim Ingham         strcpy(remainder, end_ptr);
225558ce124SJim Ingham     }
226558ce124SJim Ingham 
2277cc478b9SJim Ingham     // Look for a user name in the containing part, and if it's there, resolve it and stick the
228558ce124SJim Ingham     // result back into the containing_part:
229558ce124SJim Ingham 
230558ce124SJim Ingham     if (*partial_name_copy == '~')
231558ce124SJim Ingham     {
23284363078SJim Ingham         size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
23384363078SJim Ingham                                                                  containing_part,
23484363078SJim Ingham                                                                  sizeof (containing_part));
235558ce124SJim Ingham         // User name doesn't exist, we're not getting any further...
236a0807356SGreg Clayton         if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
237558ce124SJim Ingham             return matches.GetSize();
238558ce124SJim Ingham     }
239558ce124SJim Ingham 
240558ce124SJim Ingham     // Okay, containing_part is now the directory we want to open and look for files:
241558ce124SJim Ingham 
2429b62fd2fSGreg Clayton     lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
2439b62fd2fSGreg Clayton     if (!dir_stream.is_valid())
244558ce124SJim Ingham         return matches.GetSize();
245558ce124SJim Ingham 
246558ce124SJim Ingham     struct dirent *dirent_buf;
247558ce124SJim Ingham 
248558ce124SJim Ingham     size_t baselen = end_ptr - partial_name_copy;
249558ce124SJim Ingham 
2509b62fd2fSGreg Clayton     while ((dirent_buf = readdir(dir_stream.get())) != NULL)
251558ce124SJim Ingham     {
252558ce124SJim Ingham         char *name = dirent_buf->d_name;
253558ce124SJim Ingham 
254558ce124SJim Ingham         // Omit ".", ".." and any . files if the match string doesn't start with .
255558ce124SJim Ingham         if (name[0] == '.')
256558ce124SJim Ingham         {
257558ce124SJim Ingham             if (name[1] == '\0')
258558ce124SJim Ingham                 continue;
259558ce124SJim Ingham             else if (name[1] == '.' && name[2] == '\0')
260558ce124SJim Ingham                 continue;
261558ce124SJim Ingham             else if (remainder[0] != '.')
262558ce124SJim Ingham                 continue;
263558ce124SJim Ingham         }
264558ce124SJim Ingham 
2657cc478b9SJim Ingham         // If we found a directory, we put a "/" at the end of the name.
2667cc478b9SJim Ingham 
267558ce124SJim Ingham         if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
268558ce124SJim Ingham         {
269558ce124SJim Ingham             if (strlen(name) + baselen >= PATH_MAX)
270558ce124SJim Ingham                 continue;
271558ce124SJim Ingham 
272558ce124SJim Ingham             strcpy(end_ptr, name);
273558ce124SJim Ingham 
274558ce124SJim Ingham             bool isa_directory = false;
275558ce124SJim Ingham             if (dirent_buf->d_type & DT_DIR)
276558ce124SJim Ingham                 isa_directory = true;
277558ce124SJim Ingham             else if (dirent_buf->d_type & DT_LNK)
278558ce124SJim Ingham             {
279558ce124SJim Ingham                 struct stat stat_buf;
280d9761cd4SJason Molenda                 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
281558ce124SJim Ingham                     isa_directory = true;
282558ce124SJim Ingham             }
283558ce124SJim Ingham 
284558ce124SJim Ingham             if (isa_directory)
285558ce124SJim Ingham             {
286558ce124SJim Ingham                 saw_directory = true;
287558ce124SJim Ingham                 size_t len = strlen(partial_name_copy);
288558ce124SJim Ingham                 partial_name_copy[len] = '/';
289558ce124SJim Ingham                 partial_name_copy[len + 1] = '\0';
290558ce124SJim Ingham             }
291558ce124SJim Ingham             if (only_directories && !isa_directory)
292558ce124SJim Ingham                 continue;
293558ce124SJim Ingham             matches.AppendString(partial_name_copy);
294558ce124SJim Ingham         }
295558ce124SJim Ingham     }
296558ce124SJim Ingham 
297558ce124SJim Ingham     return matches.GetSize();
298558ce124SJim Ingham }
299558ce124SJim Ingham 
300558ce124SJim Ingham int
301558ce124SJim Ingham CommandCompletions::DiskFiles
302558ce124SJim Ingham (
303558ce124SJim Ingham     CommandInterpreter &interpreter,
304558ce124SJim Ingham     const char *partial_file_name,
305558ce124SJim Ingham     int match_start_point,
306558ce124SJim Ingham     int max_return_elements,
307558ce124SJim Ingham     SearchFilter *searcher,
308558ce124SJim Ingham     bool &word_complete,
309558ce124SJim Ingham     StringList &matches
310558ce124SJim Ingham )
311558ce124SJim Ingham {
312558ce124SJim Ingham 
313558ce124SJim Ingham     int ret_val = DiskFilesOrDirectories (partial_file_name,
314558ce124SJim Ingham                                           false,
315558ce124SJim Ingham                                           word_complete,
316558ce124SJim Ingham                                           matches);
317558ce124SJim Ingham     word_complete = !word_complete;
318558ce124SJim Ingham     return ret_val;
319558ce124SJim Ingham }
320558ce124SJim Ingham 
321558ce124SJim Ingham int
322558ce124SJim Ingham CommandCompletions::DiskDirectories
323558ce124SJim Ingham (
324558ce124SJim Ingham     CommandInterpreter &interpreter,
325558ce124SJim Ingham     const char *partial_file_name,
326558ce124SJim Ingham     int match_start_point,
327558ce124SJim Ingham     int max_return_elements,
328558ce124SJim Ingham     SearchFilter *searcher,
329558ce124SJim Ingham     bool &word_complete,
330558ce124SJim Ingham     StringList &matches
331558ce124SJim Ingham )
332558ce124SJim Ingham {
333558ce124SJim Ingham     int ret_val =  DiskFilesOrDirectories (partial_file_name,
334558ce124SJim Ingham                                            true,
335558ce124SJim Ingham                                            word_complete,
336558ce124SJim Ingham                                            matches);
337558ce124SJim Ingham     word_complete = false;
338558ce124SJim Ingham     return ret_val;
339558ce124SJim Ingham }
340558ce124SJim Ingham 
341c9af18a5SGreg Clayton int
3426611103cSGreg Clayton CommandCompletions::Modules
3436611103cSGreg Clayton (
3446611103cSGreg Clayton     CommandInterpreter &interpreter,
3456611103cSGreg Clayton     const char *partial_file_name,
346c9af18a5SGreg Clayton     int match_start_point,
347c9af18a5SGreg Clayton     int max_return_elements,
348c9af18a5SGreg Clayton     SearchFilter *searcher,
349558ce124SJim Ingham     bool &word_complete,
3506611103cSGreg Clayton     StringList &matches
3516611103cSGreg Clayton )
352c9af18a5SGreg Clayton {
353558ce124SJim Ingham     word_complete = true;
3546611103cSGreg Clayton     ModuleCompleter completer (interpreter,
3556611103cSGreg Clayton                                partial_file_name,
3566611103cSGreg Clayton                                match_start_point,
3576611103cSGreg Clayton                                max_return_elements,
3586611103cSGreg Clayton                                matches);
359c9af18a5SGreg Clayton 
360c9af18a5SGreg Clayton     if (searcher == NULL)
361c9af18a5SGreg Clayton     {
3622976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
363c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
364c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
365c9af18a5SGreg Clayton     }
366c9af18a5SGreg Clayton     else
367c9af18a5SGreg Clayton     {
368c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
369c9af18a5SGreg Clayton     }
370c9af18a5SGreg Clayton     return matches.GetSize();
371c9af18a5SGreg Clayton }
372c9af18a5SGreg Clayton 
373c9af18a5SGreg Clayton int
3746611103cSGreg Clayton CommandCompletions::Symbols
3756611103cSGreg Clayton (
3766611103cSGreg Clayton     CommandInterpreter &interpreter,
3776611103cSGreg Clayton     const char *partial_file_name,
378c9af18a5SGreg Clayton     int match_start_point,
379c9af18a5SGreg Clayton     int max_return_elements,
380c9af18a5SGreg Clayton     SearchFilter *searcher,
381558ce124SJim Ingham     bool &word_complete,
3826611103cSGreg Clayton     StringList &matches)
383c9af18a5SGreg Clayton {
384558ce124SJim Ingham     word_complete = true;
3856611103cSGreg Clayton     SymbolCompleter completer (interpreter,
3866611103cSGreg Clayton                                partial_file_name,
3876611103cSGreg Clayton                                match_start_point,
3886611103cSGreg Clayton                                max_return_elements,
3896611103cSGreg Clayton                                matches);
390c9af18a5SGreg Clayton 
391c9af18a5SGreg Clayton     if (searcher == NULL)
392c9af18a5SGreg Clayton     {
3932976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
394c9af18a5SGreg Clayton         SearchFilter null_searcher (target_sp);
395c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
396c9af18a5SGreg Clayton     }
397c9af18a5SGreg Clayton     else
398c9af18a5SGreg Clayton     {
399c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
400c9af18a5SGreg Clayton     }
401c9af18a5SGreg Clayton     return matches.GetSize();
402c9af18a5SGreg Clayton }
403c9af18a5SGreg Clayton 
4043df9a8dfSCaroline Tice int
4053df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
4063df9a8dfSCaroline Tice                                    const char *partial_setting_name,
4073df9a8dfSCaroline Tice                                    int match_start_point,
4083df9a8dfSCaroline Tice                                    int max_return_elements,
4093df9a8dfSCaroline Tice                                    SearchFilter *searcher,
4103df9a8dfSCaroline Tice                                    bool &word_complete,
4113df9a8dfSCaroline Tice                                    StringList &matches)
4123df9a8dfSCaroline Tice {
41367cc0636SGreg Clayton     // Cache the full setting name list
41467cc0636SGreg Clayton     static StringList g_property_names;
41567cc0636SGreg Clayton     if (g_property_names.GetSize() == 0)
41667cc0636SGreg Clayton     {
41767cc0636SGreg Clayton         // Generate the full setting name list on demand
41867cc0636SGreg Clayton         lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
41967cc0636SGreg Clayton         if (properties_sp)
42067cc0636SGreg Clayton         {
42167cc0636SGreg Clayton             StreamString strm;
42267cc0636SGreg Clayton             properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
42367cc0636SGreg Clayton             const std::string &str = strm.GetString();
42467cc0636SGreg Clayton             g_property_names.SplitIntoLines(str.c_str(), str.size());
42567cc0636SGreg Clayton         }
42667cc0636SGreg Clayton     }
4273df9a8dfSCaroline Tice 
42867cc0636SGreg Clayton     size_t exact_matches_idx = SIZE_MAX;
42967cc0636SGreg Clayton     const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
43067cc0636SGreg Clayton     word_complete = exact_matches_idx != SIZE_MAX;
43167cc0636SGreg Clayton     return num_matches;
4323df9a8dfSCaroline Tice }
4333df9a8dfSCaroline Tice 
434ab65b34fSGreg Clayton 
435ab65b34fSGreg Clayton int
436ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
437ab65b34fSGreg Clayton                                          const char *partial_name,
438ab65b34fSGreg Clayton                                          int match_start_point,
439ab65b34fSGreg Clayton                                          int max_return_elements,
440ab65b34fSGreg Clayton                                          SearchFilter *searcher,
441ab65b34fSGreg Clayton                                          bool &word_complete,
442ab65b34fSGreg Clayton                                          lldb_private::StringList &matches)
443ab65b34fSGreg Clayton {
444ab65b34fSGreg Clayton     const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
445ab65b34fSGreg Clayton     word_complete = num_matches == 1;
446ab65b34fSGreg Clayton     return num_matches;
447ab65b34fSGreg Clayton }
448ab65b34fSGreg Clayton 
449ab65b34fSGreg Clayton int
450ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
451ab65b34fSGreg Clayton                                        const char *partial_name,
452ab65b34fSGreg Clayton                                        int match_start_point,
453ab65b34fSGreg Clayton                                        int max_return_elements,
454ab65b34fSGreg Clayton                                        SearchFilter *searcher,
455ab65b34fSGreg Clayton                                        bool &word_complete,
456ab65b34fSGreg Clayton                                        lldb_private::StringList &matches)
457ab65b34fSGreg Clayton {
458ab65b34fSGreg Clayton     const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
459ab65b34fSGreg Clayton     word_complete = num_matches == 1;
460ab65b34fSGreg Clayton     return num_matches;
461ab65b34fSGreg Clayton }
462ab65b34fSGreg Clayton 
463ab65b34fSGreg Clayton 
464*f21feadcSGreg Clayton int
465*f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter,
466*f21feadcSGreg Clayton                                   const char *partial_name,
467*f21feadcSGreg Clayton                                   int match_start_point,
468*f21feadcSGreg Clayton                                   int max_return_elements,
469*f21feadcSGreg Clayton                                   SearchFilter *searcher,
470*f21feadcSGreg Clayton                                   bool &word_complete,
471*f21feadcSGreg Clayton                                   lldb_private::StringList &matches)
472*f21feadcSGreg Clayton {
473*f21feadcSGreg Clayton     return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
474*f21feadcSGreg Clayton }
475*f21feadcSGreg Clayton 
476*f21feadcSGreg Clayton 
4776611103cSGreg Clayton CommandCompletions::Completer::Completer
4786611103cSGreg Clayton (
4796611103cSGreg Clayton     CommandInterpreter &interpreter,
480c9af18a5SGreg Clayton     const char *completion_str,
481c9af18a5SGreg Clayton     int match_start_point,
482c9af18a5SGreg Clayton     int max_return_elements,
483c9af18a5SGreg Clayton     StringList &matches
484c9af18a5SGreg Clayton ) :
4856611103cSGreg Clayton     m_interpreter (interpreter),
486c9af18a5SGreg Clayton     m_completion_str (completion_str),
487c9af18a5SGreg Clayton     m_match_start_point (match_start_point),
488c9af18a5SGreg Clayton     m_max_return_elements (max_return_elements),
489c9af18a5SGreg Clayton     m_matches (matches)
490c9af18a5SGreg Clayton {
491c9af18a5SGreg Clayton }
492c9af18a5SGreg Clayton 
493c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer ()
494c9af18a5SGreg Clayton {
495c9af18a5SGreg Clayton 
496c9af18a5SGreg Clayton }
497c9af18a5SGreg Clayton 
498c9af18a5SGreg Clayton //----------------------------------------------------------------------
499c9af18a5SGreg Clayton // SourceFileCompleter
500c9af18a5SGreg Clayton //----------------------------------------------------------------------
501c9af18a5SGreg Clayton 
5026611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter
5036611103cSGreg Clayton (
5046611103cSGreg Clayton     CommandInterpreter &interpreter,
505c9af18a5SGreg Clayton     bool include_support_files,
506c9af18a5SGreg Clayton     const char *completion_str,
507c9af18a5SGreg Clayton     int match_start_point,
508c9af18a5SGreg Clayton     int max_return_elements,
509c9af18a5SGreg Clayton     StringList &matches
510c9af18a5SGreg Clayton ) :
5116611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
512c9af18a5SGreg Clayton     m_include_support_files (include_support_files),
513c9af18a5SGreg Clayton     m_matching_files()
514c9af18a5SGreg Clayton {
515274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
516c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
517c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
518c9af18a5SGreg Clayton }
519c9af18a5SGreg Clayton 
520c9af18a5SGreg Clayton Searcher::Depth
521c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth()
522c9af18a5SGreg Clayton {
523c9af18a5SGreg Clayton     return eDepthCompUnit;
524c9af18a5SGreg Clayton }
525c9af18a5SGreg Clayton 
526c9af18a5SGreg Clayton Searcher::CallbackReturn
527c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback (
528c9af18a5SGreg Clayton     SearchFilter &filter,
529c9af18a5SGreg Clayton     SymbolContext &context,
530c9af18a5SGreg Clayton     Address *addr,
531c9af18a5SGreg Clayton     bool complete
532c9af18a5SGreg Clayton )
533c9af18a5SGreg Clayton {
534c9af18a5SGreg Clayton     if (context.comp_unit != NULL)
535c9af18a5SGreg Clayton     {
536c9af18a5SGreg Clayton         if (m_include_support_files)
537c9af18a5SGreg Clayton         {
538c9af18a5SGreg Clayton             FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
539c9af18a5SGreg Clayton             for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
540c9af18a5SGreg Clayton             {
541c9af18a5SGreg Clayton                 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
542c9af18a5SGreg Clayton                 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
543c9af18a5SGreg Clayton                 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
544c9af18a5SGreg Clayton                 bool match = false;
545c9af18a5SGreg Clayton                 if (m_file_name && sfile_file_name
546c9af18a5SGreg Clayton                     && strstr (sfile_file_name, m_file_name) == sfile_file_name)
547c9af18a5SGreg Clayton                     match = true;
548c9af18a5SGreg Clayton                 if (match && m_dir_name && sfile_dir_name
549c9af18a5SGreg Clayton                     && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
550c9af18a5SGreg Clayton                     match = false;
551c9af18a5SGreg Clayton 
552c9af18a5SGreg Clayton                 if (match)
553c9af18a5SGreg Clayton                 {
554c9af18a5SGreg Clayton                     m_matching_files.AppendIfUnique(sfile_spec);
555c9af18a5SGreg Clayton                 }
556c9af18a5SGreg Clayton             }
557c9af18a5SGreg Clayton 
558c9af18a5SGreg Clayton         }
559c9af18a5SGreg Clayton         else
560c9af18a5SGreg Clayton         {
561c9af18a5SGreg Clayton             const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
562c9af18a5SGreg Clayton             const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
563c9af18a5SGreg Clayton 
564c9af18a5SGreg Clayton             bool match = false;
565c9af18a5SGreg Clayton             if (m_file_name && cur_file_name
566c9af18a5SGreg Clayton                 && strstr (cur_file_name, m_file_name) == cur_file_name)
567c9af18a5SGreg Clayton                 match = true;
568c9af18a5SGreg Clayton 
569c9af18a5SGreg Clayton             if (match && m_dir_name && cur_dir_name
570c9af18a5SGreg Clayton                 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
571c9af18a5SGreg Clayton                 match = false;
572c9af18a5SGreg Clayton 
573c9af18a5SGreg Clayton             if (match)
574c9af18a5SGreg Clayton             {
575c9af18a5SGreg Clayton                 m_matching_files.AppendIfUnique(context.comp_unit);
576c9af18a5SGreg Clayton             }
577c9af18a5SGreg Clayton         }
578c9af18a5SGreg Clayton     }
579c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
580c9af18a5SGreg Clayton }
581c9af18a5SGreg Clayton 
582c9af18a5SGreg Clayton size_t
583c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
584c9af18a5SGreg Clayton {
585c9af18a5SGreg Clayton     filter->Search (*this);
586c9af18a5SGreg Clayton     // Now convert the filelist to completions:
587c9af18a5SGreg Clayton     for (size_t i = 0; i < m_matching_files.GetSize(); i++)
588c9af18a5SGreg Clayton     {
589c9af18a5SGreg Clayton         m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
590c9af18a5SGreg Clayton     }
591c9af18a5SGreg Clayton     return m_matches.GetSize();
592c9af18a5SGreg Clayton 
593c9af18a5SGreg Clayton }
594c9af18a5SGreg Clayton 
595c9af18a5SGreg Clayton //----------------------------------------------------------------------
596c9af18a5SGreg Clayton // SymbolCompleter
597c9af18a5SGreg Clayton //----------------------------------------------------------------------
598c9af18a5SGreg Clayton 
599c9af18a5SGreg Clayton static bool
600c9af18a5SGreg Clayton regex_chars (const char comp)
601c9af18a5SGreg Clayton {
602c9af18a5SGreg Clayton     if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
603c9af18a5SGreg Clayton         return true;
604c9af18a5SGreg Clayton     else
605c9af18a5SGreg Clayton         return false;
606c9af18a5SGreg Clayton }
6076611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter
6086611103cSGreg Clayton (
6096611103cSGreg Clayton     CommandInterpreter &interpreter,
610c9af18a5SGreg Clayton     const char *completion_str,
611c9af18a5SGreg Clayton     int match_start_point,
612c9af18a5SGreg Clayton     int max_return_elements,
613c9af18a5SGreg Clayton     StringList &matches
614c9af18a5SGreg Clayton ) :
6156611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
616c9af18a5SGreg Clayton {
617c9af18a5SGreg Clayton     std::string regex_str ("^");
618c9af18a5SGreg Clayton     regex_str.append(completion_str);
619c9af18a5SGreg Clayton     regex_str.append(".*");
620c9af18a5SGreg Clayton     std::string::iterator pos;
621c9af18a5SGreg Clayton 
622c9af18a5SGreg Clayton     pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
623c9af18a5SGreg Clayton     while (pos < regex_str.end()) {
624c9af18a5SGreg Clayton         pos = regex_str.insert(pos, '\\');
625c9af18a5SGreg Clayton         pos += 2;
626c9af18a5SGreg Clayton         pos = find_if(pos, regex_str.end(), regex_chars);
627c9af18a5SGreg Clayton     }
628c9af18a5SGreg Clayton     m_regex.Compile(regex_str.c_str());
629c9af18a5SGreg Clayton }
630c9af18a5SGreg Clayton 
631c9af18a5SGreg Clayton Searcher::Depth
632c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth()
633c9af18a5SGreg Clayton {
634c9af18a5SGreg Clayton     return eDepthModule;
635c9af18a5SGreg Clayton }
636c9af18a5SGreg Clayton 
637c9af18a5SGreg Clayton Searcher::CallbackReturn
638c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback (
639c9af18a5SGreg Clayton     SearchFilter &filter,
640c9af18a5SGreg Clayton     SymbolContext &context,
641c9af18a5SGreg Clayton     Address *addr,
642c9af18a5SGreg Clayton     bool complete
643c9af18a5SGreg Clayton )
644c9af18a5SGreg Clayton {
645c9af18a5SGreg Clayton     if (context.module_sp)
646c9af18a5SGreg Clayton     {
647931180e6SGreg Clayton         SymbolContextList sc_list;
648931180e6SGreg Clayton         const bool include_symbols = true;
6499df05fbbSSean Callanan         const bool include_inlines = true;
650931180e6SGreg Clayton         const bool append = true;
6519df05fbbSSean Callanan         context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
652c9af18a5SGreg Clayton 
653c9af18a5SGreg Clayton         SymbolContext sc;
654c9af18a5SGreg Clayton         // Now add the functions & symbols to the list - only add if unique:
655931180e6SGreg Clayton         for (uint32_t i = 0; i < sc_list.GetSize(); i++)
656c9af18a5SGreg Clayton         {
657931180e6SGreg Clayton             if (sc_list.GetContextAtIndex(i, sc))
658c9af18a5SGreg Clayton             {
659530a413cSJim Ingham                 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
660530a413cSJim Ingham                 if (!func_name.IsEmpty())
661530a413cSJim Ingham                     m_match_set.insert (func_name);
662c9af18a5SGreg Clayton             }
663c9af18a5SGreg Clayton         }
664c9af18a5SGreg Clayton     }
665c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
666c9af18a5SGreg Clayton }
667c9af18a5SGreg Clayton 
668c9af18a5SGreg Clayton size_t
669c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
670c9af18a5SGreg Clayton {
671c9af18a5SGreg Clayton     filter->Search (*this);
672c9af18a5SGreg Clayton     collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
673c9af18a5SGreg Clayton     for (pos = m_match_set.begin(); pos != end; pos++)
674c9af18a5SGreg Clayton         m_matches.AppendString((*pos).GetCString());
675c9af18a5SGreg Clayton 
676c9af18a5SGreg Clayton     return m_matches.GetSize();
677c9af18a5SGreg Clayton }
678c9af18a5SGreg Clayton 
679c9af18a5SGreg Clayton //----------------------------------------------------------------------
680c9af18a5SGreg Clayton // ModuleCompleter
681c9af18a5SGreg Clayton //----------------------------------------------------------------------
6826611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter
6836611103cSGreg Clayton (
6846611103cSGreg Clayton     CommandInterpreter &interpreter,
685c9af18a5SGreg Clayton     const char *completion_str,
686c9af18a5SGreg Clayton     int match_start_point,
687c9af18a5SGreg Clayton     int max_return_elements,
688c9af18a5SGreg Clayton     StringList &matches
689c9af18a5SGreg Clayton ) :
6906611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
691c9af18a5SGreg Clayton {
692274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
693c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
694c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
695c9af18a5SGreg Clayton }
696c9af18a5SGreg Clayton 
697c9af18a5SGreg Clayton Searcher::Depth
698c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth()
699c9af18a5SGreg Clayton {
700c9af18a5SGreg Clayton     return eDepthModule;
701c9af18a5SGreg Clayton }
702c9af18a5SGreg Clayton 
703c9af18a5SGreg Clayton Searcher::CallbackReturn
704c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback (
705c9af18a5SGreg Clayton     SearchFilter &filter,
706c9af18a5SGreg Clayton     SymbolContext &context,
707c9af18a5SGreg Clayton     Address *addr,
708c9af18a5SGreg Clayton     bool complete
709c9af18a5SGreg Clayton )
710c9af18a5SGreg Clayton {
711747bcb03SGreg Clayton     if (context.module_sp)
712c9af18a5SGreg Clayton     {
713c9af18a5SGreg Clayton         const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
714c9af18a5SGreg Clayton         const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
715c9af18a5SGreg Clayton 
716c9af18a5SGreg Clayton         bool match = false;
717c9af18a5SGreg Clayton         if (m_file_name && cur_file_name
718c9af18a5SGreg Clayton             && strstr (cur_file_name, m_file_name) == cur_file_name)
719c9af18a5SGreg Clayton             match = true;
720c9af18a5SGreg Clayton 
721c9af18a5SGreg Clayton         if (match && m_dir_name && cur_dir_name
722c9af18a5SGreg Clayton             && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
723c9af18a5SGreg Clayton             match = false;
724c9af18a5SGreg Clayton 
725c9af18a5SGreg Clayton         if (match)
726c9af18a5SGreg Clayton         {
727c9af18a5SGreg Clayton             m_matches.AppendString (cur_file_name);
728c9af18a5SGreg Clayton         }
729c9af18a5SGreg Clayton     }
730c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
731c9af18a5SGreg Clayton }
732c9af18a5SGreg Clayton 
733c9af18a5SGreg Clayton size_t
734c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
735c9af18a5SGreg Clayton {
736c9af18a5SGreg Clayton     filter->Search (*this);
737c9af18a5SGreg Clayton     return m_matches.GetSize();
738c9af18a5SGreg Clayton }
739