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