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 // C Includes
11558ce124SJim Ingham #include <sys/stat.h>
12fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__)
137cc478b9SJim Ingham #include <pwd.h>
14fd18426eSGreg Clayton #endif
15558ce124SJim Ingham 
16c9af18a5SGreg Clayton // C++ Includes
17c9af18a5SGreg Clayton // Other libraries and framework includes
18*c8ecc2a9SEugene Zelenko #include "llvm/ADT/SmallString.h"
19*c8ecc2a9SEugene Zelenko 
20c9af18a5SGreg Clayton // Project includes
2153239f00SGreg Clayton #include "lldb/Host/FileSpec.h"
229b62fd2fSGreg Clayton #include "lldb/Core/FileSpecList.h"
23ab65b34fSGreg Clayton #include "lldb/Core/PluginManager.h"
241f746071SGreg Clayton #include "lldb/Core/Module.h"
259b62fd2fSGreg Clayton #include "lldb/Interpreter/Args.h"
269b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandCompletions.h"
279b62fd2fSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
28633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
291f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
30f21feadcSGreg 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 {
39*c8ecc2a9SEugene Zelenko     {eCustomCompletion,          nullptr},
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},
48f21feadcSGreg Clayton     {eVariablePathCompletion,    CommandCompletions::VariablePath},
49*c8ecc2a9SEugene Zelenko     {eNoCompletion,              nullptr}      // This one has to be last in the list.
50c9af18a5SGreg Clayton };
51c9af18a5SGreg Clayton 
52c9af18a5SGreg Clayton bool
53*c8ecc2a9SEugene Zelenko CommandCompletions::InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter,
546611103cSGreg Clayton                                                     uint32_t completion_mask,
55c9af18a5SGreg Clayton                                                     const char *completion_str,
56c9af18a5SGreg Clayton                                                     int match_start_point,
57c9af18a5SGreg Clayton                                                     int max_return_elements,
58c9af18a5SGreg Clayton                                                     SearchFilter *searcher,
59558ce124SJim Ingham                                                     bool &word_complete,
60*c8ecc2a9SEugene Zelenko                                                     StringList &matches)
61c9af18a5SGreg Clayton {
62c9af18a5SGreg Clayton     bool handled = false;
63c9af18a5SGreg Clayton 
64c9af18a5SGreg Clayton     if (completion_mask & eCustomCompletion)
65c9af18a5SGreg Clayton         return false;
66c9af18a5SGreg Clayton 
67c9af18a5SGreg Clayton     for (int i = 0; ; i++)
68c9af18a5SGreg Clayton     {
69c9af18a5SGreg Clayton         if (g_common_completions[i].type == eNoCompletion)
70c9af18a5SGreg Clayton             break;
71c9af18a5SGreg Clayton          else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
72*c8ecc2a9SEugene Zelenko                    && g_common_completions[i].callback != nullptr)
73c9af18a5SGreg Clayton          {
74c9af18a5SGreg Clayton             handled = true;
756611103cSGreg Clayton             g_common_completions[i].callback (interpreter,
766611103cSGreg Clayton                                               completion_str,
77c9af18a5SGreg Clayton                                               match_start_point,
78c9af18a5SGreg Clayton                                               max_return_elements,
79c9af18a5SGreg Clayton                                               searcher,
80558ce124SJim Ingham                                               word_complete,
81c9af18a5SGreg Clayton                                               matches);
82c9af18a5SGreg Clayton         }
83c9af18a5SGreg Clayton     }
84c9af18a5SGreg Clayton     return handled;
85c9af18a5SGreg Clayton }
86c9af18a5SGreg Clayton 
87c9af18a5SGreg Clayton int
88*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
896611103cSGreg Clayton                                 const char *partial_file_name,
90c9af18a5SGreg Clayton                                 int match_start_point,
91c9af18a5SGreg Clayton                                 int max_return_elements,
92c9af18a5SGreg Clayton                                 SearchFilter *searcher,
93558ce124SJim Ingham                                 bool &word_complete,
94*c8ecc2a9SEugene Zelenko                                 StringList &matches)
95c9af18a5SGreg Clayton {
96558ce124SJim Ingham     word_complete = true;
97c9af18a5SGreg Clayton     // Find some way to switch "include support files..."
986611103cSGreg Clayton     SourceFileCompleter completer (interpreter,
996611103cSGreg Clayton                                    false,
1006611103cSGreg Clayton                                    partial_file_name,
1016611103cSGreg Clayton                                    match_start_point,
1026611103cSGreg Clayton                                    max_return_elements,
103c9af18a5SGreg Clayton                                    matches);
104c9af18a5SGreg Clayton 
105*c8ecc2a9SEugene Zelenko     if (searcher == nullptr)
106c9af18a5SGreg Clayton     {
1072976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
10833df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
109c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
110c9af18a5SGreg Clayton     }
111c9af18a5SGreg Clayton     else
112c9af18a5SGreg Clayton     {
113c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
114c9af18a5SGreg Clayton     }
115c9af18a5SGreg Clayton     return matches.GetSize();
116c9af18a5SGreg Clayton }
117c9af18a5SGreg Clayton 
118b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton
119b2f1fb29SVirgile Bello {
120b2f1fb29SVirgile Bello     const char *remainder;
121b2f1fb29SVirgile Bello     char *partial_name_copy;
122b2f1fb29SVirgile Bello     bool only_directories;
123b2f1fb29SVirgile Bello     bool *saw_directory;
124b2f1fb29SVirgile Bello     StringList *matches;
125b2f1fb29SVirgile Bello     char *end_ptr;
126b2f1fb29SVirgile Bello     size_t baselen;
1270b5e5f43SMichael Sartain } DiskFilesOrDirectoriesBaton;
128b2f1fb29SVirgile Bello 
129b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
130b2f1fb29SVirgile Bello {
131b2f1fb29SVirgile Bello     const char *name = spec.GetFilename().AsCString();
132b2f1fb29SVirgile Bello 
133b2f1fb29SVirgile Bello     const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
134b2f1fb29SVirgile Bello     char *end_ptr = parameters->end_ptr;
135b2f1fb29SVirgile Bello     char *partial_name_copy = parameters->partial_name_copy;
136b2f1fb29SVirgile Bello     const char *remainder = parameters->remainder;
137b2f1fb29SVirgile Bello 
138b2f1fb29SVirgile Bello     // Omit ".", ".." and any . files if the match string doesn't start with .
139b2f1fb29SVirgile Bello     if (name[0] == '.')
140b2f1fb29SVirgile Bello     {
141b2f1fb29SVirgile Bello         if (name[1] == '\0')
142b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
143b2f1fb29SVirgile Bello         else if (name[1] == '.' && name[2] == '\0')
144b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
145b2f1fb29SVirgile Bello         else if (remainder[0] != '.')
146b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
147b2f1fb29SVirgile Bello     }
148b2f1fb29SVirgile Bello 
149b2f1fb29SVirgile Bello     // If we found a directory, we put a "/" at the end of the name.
150b2f1fb29SVirgile Bello 
151b2f1fb29SVirgile Bello     if (remainder[0] == '\0' || strstr(name, remainder) == name)
152b2f1fb29SVirgile Bello     {
153b2f1fb29SVirgile Bello         if (strlen(name) + parameters->baselen >= PATH_MAX)
154b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
155b2f1fb29SVirgile Bello 
156b2f1fb29SVirgile Bello         strcpy(end_ptr, name);
157b2f1fb29SVirgile Bello 
158b2f1fb29SVirgile Bello         bool isa_directory = false;
159b2f1fb29SVirgile Bello         if (file_type == FileSpec::eFileTypeDirectory)
160b2f1fb29SVirgile Bello             isa_directory = true;
161b2f1fb29SVirgile Bello         else if (file_type == FileSpec::eFileTypeSymbolicLink)
162b2f1fb29SVirgile Bello         {
163b2f1fb29SVirgile Bello             struct stat stat_buf;
164b2f1fb29SVirgile Bello             if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
165b2f1fb29SVirgile Bello                 isa_directory = true;
166b2f1fb29SVirgile Bello         }
167b2f1fb29SVirgile Bello 
168b2f1fb29SVirgile Bello         if (isa_directory)
169b2f1fb29SVirgile Bello         {
170b2f1fb29SVirgile Bello             *parameters->saw_directory = true;
171b2f1fb29SVirgile Bello             size_t len = strlen(parameters->partial_name_copy);
172b2f1fb29SVirgile Bello             partial_name_copy[len] = '/';
173b2f1fb29SVirgile Bello             partial_name_copy[len + 1] = '\0';
174b2f1fb29SVirgile Bello         }
175b2f1fb29SVirgile Bello         if (parameters->only_directories && !isa_directory)
176b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
177b2f1fb29SVirgile Bello         parameters->matches->AppendString(partial_name_copy);
178b2f1fb29SVirgile Bello     }
179b2f1fb29SVirgile Bello 
180b2f1fb29SVirgile Bello     return FileSpec::eEnumerateDirectoryResultNext;
181b2f1fb29SVirgile Bello }
182b2f1fb29SVirgile Bello 
183558ce124SJim Ingham static int
184*c8ecc2a9SEugene Zelenko DiskFilesOrDirectories(const char *partial_file_name,
185558ce124SJim Ingham                        bool only_directories,
186558ce124SJim Ingham                        bool &saw_directory,
187*c8ecc2a9SEugene Zelenko                        StringList &matches)
188558ce124SJim Ingham {
189558ce124SJim Ingham     // I'm going to  use the "glob" function with GLOB_TILDE for user directory expansion.
190558ce124SJim Ingham     // If it is not defined on your host system, you'll need to implement it yourself...
191558ce124SJim Ingham 
192c7bece56SGreg Clayton     size_t partial_name_len = strlen(partial_file_name);
193558ce124SJim Ingham 
194558ce124SJim Ingham     if (partial_name_len >= PATH_MAX)
195558ce124SJim Ingham         return matches.GetSize();
196558ce124SJim Ingham 
197558ce124SJim Ingham     // This copy of the string will be cut up into the directory part, and the remainder.  end_ptr
198558ce124SJim Ingham     // below will point to the place of the remainder in this string.  Then when we've resolved the
199558ce124SJim Ingham     // containing directory, and opened it, we'll read the directory contents and overwrite the
200558ce124SJim Ingham     // partial_name_copy starting from end_ptr with each of the matches.  Thus we will preserve
201558ce124SJim Ingham     // the form the user originally typed.
202558ce124SJim Ingham 
203558ce124SJim Ingham     char partial_name_copy[PATH_MAX];
204021b605dSBenjamin Kramer     memcpy(partial_name_copy, partial_file_name, partial_name_len);
205558ce124SJim Ingham     partial_name_copy[partial_name_len] = '\0';
206558ce124SJim Ingham 
207710dd5aeSGreg Clayton     // We'll need to save a copy of the remainder for comparison, which we do here.
208558ce124SJim Ingham     char remainder[PATH_MAX];
209558ce124SJim Ingham 
210558ce124SJim Ingham     // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
211558ce124SJim Ingham     char *end_ptr;
212558ce124SJim Ingham 
213558ce124SJim Ingham     end_ptr = strrchr(partial_name_copy, '/');
214558ce124SJim Ingham 
215558ce124SJim Ingham     // This will store the resolved form of the containing directory
2163f559740SZachary Turner     llvm::SmallString<64> containing_part;
217558ce124SJim Ingham 
218*c8ecc2a9SEugene Zelenko     if (end_ptr == nullptr)
219558ce124SJim Ingham     {
220558ce124SJim Ingham         // There's no directory.  If the thing begins with a "~" then this is a bare
221558ce124SJim Ingham         // user name.
222558ce124SJim Ingham         if (*partial_name_copy == '~')
223558ce124SJim Ingham         {
224558ce124SJim Ingham             // Nothing here but the user name.  We could just put a slash on the end,
2257cc478b9SJim Ingham             // but for completeness sake we'll resolve the user name and only put a slash
226558ce124SJim Ingham             // on the end if it exists.
2273f559740SZachary Turner             llvm::SmallString<64> resolved_username(partial_name_copy);
2283f559740SZachary Turner             FileSpec::ResolveUsername (resolved_username);
2297cc478b9SJim Ingham 
2307cc478b9SJim Ingham            // Not sure how this would happen, a username longer than PATH_MAX?  Still...
2313f559740SZachary Turner             if (resolved_username.size() == 0)
2327cc478b9SJim Ingham             {
2337cc478b9SJim Ingham                 // The user name didn't resolve, let's look in the password database for matches.
2347cc478b9SJim Ingham                 // The user name database contains duplicates, and is not in alphabetical order, so
2357cc478b9SJim Ingham                 // we'll use a set to manage that for us.
23684363078SJim Ingham                 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
23784363078SJim Ingham                 if (matches.GetSize() > 0)
2387cc478b9SJim Ingham                     saw_directory = true;
2397cc478b9SJim Ingham                 return matches.GetSize();
2407cc478b9SJim Ingham             }
24184363078SJim Ingham             else
24284363078SJim Ingham             {
243558ce124SJim Ingham                 //The thing exists, put a '/' on the end, and return it...
244558ce124SJim Ingham                 // FIXME: complete user names here:
245558ce124SJim Ingham                 partial_name_copy[partial_name_len] = '/';
246558ce124SJim Ingham                 partial_name_copy[partial_name_len+1] = '\0';
247558ce124SJim Ingham                 matches.AppendString(partial_name_copy);
248021b605dSBenjamin Kramer                 saw_directory = true;
249558ce124SJim Ingham                 return matches.GetSize();
250558ce124SJim Ingham             }
25184363078SJim Ingham         }
252558ce124SJim Ingham         else
253558ce124SJim Ingham         {
254558ce124SJim Ingham             // The containing part is the CWD, and the whole string is the remainder.
2553f559740SZachary Turner             containing_part = ".";
256558ce124SJim Ingham             strcpy(remainder, partial_name_copy);
257558ce124SJim Ingham             end_ptr = partial_name_copy;
258558ce124SJim Ingham         }
259558ce124SJim Ingham     }
260558ce124SJim Ingham     else
261558ce124SJim Ingham     {
262558ce124SJim Ingham         if (end_ptr == partial_name_copy)
263558ce124SJim Ingham         {
264558ce124SJim Ingham             // We're completing a file or directory in the root volume.
2653f559740SZachary Turner             containing_part = "/";
266558ce124SJim Ingham         }
267558ce124SJim Ingham         else
268558ce124SJim Ingham         {
2693f559740SZachary Turner             containing_part.append(partial_name_copy, end_ptr);
270558ce124SJim Ingham         }
271558ce124SJim Ingham         // Push end_ptr past the final "/" and set remainder.
272558ce124SJim Ingham         end_ptr++;
273558ce124SJim Ingham         strcpy(remainder, end_ptr);
274558ce124SJim Ingham     }
275558ce124SJim Ingham 
2767cc478b9SJim Ingham     // Look for a user name in the containing part, and if it's there, resolve it and stick the
277558ce124SJim Ingham     // result back into the containing_part:
278558ce124SJim Ingham 
279558ce124SJim Ingham     if (*partial_name_copy == '~')
280558ce124SJim Ingham     {
2813f559740SZachary Turner         FileSpec::ResolveUsername(containing_part);
282558ce124SJim Ingham         // User name doesn't exist, we're not getting any further...
2833f559740SZachary Turner         if (containing_part.empty())
284558ce124SJim Ingham             return matches.GetSize();
285558ce124SJim Ingham     }
286558ce124SJim Ingham 
287558ce124SJim Ingham     // Okay, containing_part is now the directory we want to open and look for files:
288558ce124SJim Ingham 
289558ce124SJim Ingham     size_t baselen = end_ptr - partial_name_copy;
290558ce124SJim Ingham 
291b2f1fb29SVirgile Bello     DiskFilesOrDirectoriesBaton parameters;
292b2f1fb29SVirgile Bello     parameters.remainder = remainder;
293b2f1fb29SVirgile Bello     parameters.partial_name_copy = partial_name_copy;
294b2f1fb29SVirgile Bello     parameters.only_directories = only_directories;
295b2f1fb29SVirgile Bello     parameters.saw_directory = &saw_directory;
296b2f1fb29SVirgile Bello     parameters.matches = &matches;
297b2f1fb29SVirgile Bello     parameters.end_ptr = end_ptr;
298b2f1fb29SVirgile Bello     parameters.baselen = baselen;
299558ce124SJim Ingham 
3003f559740SZachary Turner     FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
301558ce124SJim Ingham 
302558ce124SJim Ingham     return matches.GetSize();
303558ce124SJim Ingham }
304558ce124SJim Ingham 
305558ce124SJim Ingham int
306*c8ecc2a9SEugene Zelenko CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
307558ce124SJim Ingham                               const char *partial_file_name,
308558ce124SJim Ingham                               int match_start_point,
309558ce124SJim Ingham                               int max_return_elements,
310558ce124SJim Ingham                               SearchFilter *searcher,
311558ce124SJim Ingham                               bool &word_complete,
312*c8ecc2a9SEugene Zelenko                               StringList &matches)
313558ce124SJim Ingham {
314558ce124SJim Ingham     int ret_val = DiskFilesOrDirectories (partial_file_name,
315558ce124SJim Ingham                                           false,
316558ce124SJim Ingham                                           word_complete,
317558ce124SJim Ingham                                           matches);
318558ce124SJim Ingham     word_complete = !word_complete;
319558ce124SJim Ingham     return ret_val;
320558ce124SJim Ingham }
321558ce124SJim Ingham 
322558ce124SJim Ingham int
323*c8ecc2a9SEugene Zelenko CommandCompletions::DiskDirectories(CommandInterpreter &interpreter,
324558ce124SJim Ingham                                     const char *partial_file_name,
325558ce124SJim Ingham                                     int match_start_point,
326558ce124SJim Ingham                                     int max_return_elements,
327558ce124SJim Ingham                                     SearchFilter *searcher,
328558ce124SJim Ingham                                     bool &word_complete,
329*c8ecc2a9SEugene Zelenko                                     StringList &matches)
330558ce124SJim Ingham {
331558ce124SJim Ingham     int ret_val =  DiskFilesOrDirectories (partial_file_name,
332558ce124SJim Ingham                                            true,
333558ce124SJim Ingham                                            word_complete,
334558ce124SJim Ingham                                            matches);
335558ce124SJim Ingham     word_complete = false;
336558ce124SJim Ingham     return ret_val;
337558ce124SJim Ingham }
338558ce124SJim Ingham 
339c9af18a5SGreg Clayton int
340*c8ecc2a9SEugene Zelenko CommandCompletions::Modules(CommandInterpreter &interpreter,
3416611103cSGreg Clayton                             const char *partial_file_name,
342c9af18a5SGreg Clayton                             int match_start_point,
343c9af18a5SGreg Clayton                             int max_return_elements,
344c9af18a5SGreg Clayton                             SearchFilter *searcher,
345558ce124SJim Ingham                             bool &word_complete,
346*c8ecc2a9SEugene Zelenko                             StringList &matches)
347c9af18a5SGreg Clayton {
348558ce124SJim Ingham     word_complete = true;
3496611103cSGreg Clayton     ModuleCompleter completer (interpreter,
3506611103cSGreg Clayton                                partial_file_name,
3516611103cSGreg Clayton                                match_start_point,
3526611103cSGreg Clayton                                max_return_elements,
3536611103cSGreg Clayton                                matches);
354c9af18a5SGreg Clayton 
355*c8ecc2a9SEugene Zelenko     if (searcher == nullptr)
356c9af18a5SGreg Clayton     {
3572976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
35833df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
359c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
360c9af18a5SGreg Clayton     }
361c9af18a5SGreg Clayton     else
362c9af18a5SGreg Clayton     {
363c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
364c9af18a5SGreg Clayton     }
365c9af18a5SGreg Clayton     return matches.GetSize();
366c9af18a5SGreg Clayton }
367c9af18a5SGreg Clayton 
368c9af18a5SGreg Clayton int
369*c8ecc2a9SEugene Zelenko CommandCompletions::Symbols(CommandInterpreter &interpreter,
3706611103cSGreg Clayton                             const char *partial_file_name,
371c9af18a5SGreg Clayton                             int match_start_point,
372c9af18a5SGreg Clayton                             int max_return_elements,
373c9af18a5SGreg Clayton                             SearchFilter *searcher,
374558ce124SJim Ingham                             bool &word_complete,
3756611103cSGreg Clayton                             StringList &matches)
376c9af18a5SGreg Clayton {
377558ce124SJim Ingham     word_complete = true;
3786611103cSGreg Clayton     SymbolCompleter completer (interpreter,
3796611103cSGreg Clayton                                partial_file_name,
3806611103cSGreg Clayton                                match_start_point,
3816611103cSGreg Clayton                                max_return_elements,
3826611103cSGreg Clayton                                matches);
383c9af18a5SGreg Clayton 
384*c8ecc2a9SEugene Zelenko     if (searcher == nullptr)
385c9af18a5SGreg Clayton     {
3862976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
38733df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
388c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
389c9af18a5SGreg Clayton     }
390c9af18a5SGreg Clayton     else
391c9af18a5SGreg Clayton     {
392c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
393c9af18a5SGreg Clayton     }
394c9af18a5SGreg Clayton     return matches.GetSize();
395c9af18a5SGreg Clayton }
396c9af18a5SGreg Clayton 
3973df9a8dfSCaroline Tice int
3983df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
3993df9a8dfSCaroline Tice                                    const char *partial_setting_name,
4003df9a8dfSCaroline Tice                                    int match_start_point,
4013df9a8dfSCaroline Tice                                    int max_return_elements,
4023df9a8dfSCaroline Tice                                    SearchFilter *searcher,
4033df9a8dfSCaroline Tice                                    bool &word_complete,
4043df9a8dfSCaroline Tice                                    StringList &matches)
4053df9a8dfSCaroline Tice {
40667cc0636SGreg Clayton     // Cache the full setting name list
40767cc0636SGreg Clayton     static StringList g_property_names;
40867cc0636SGreg Clayton     if (g_property_names.GetSize() == 0)
40967cc0636SGreg Clayton     {
41067cc0636SGreg Clayton         // Generate the full setting name list on demand
41167cc0636SGreg Clayton         lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
41267cc0636SGreg Clayton         if (properties_sp)
41367cc0636SGreg Clayton         {
41467cc0636SGreg Clayton             StreamString strm;
415*c8ecc2a9SEugene Zelenko             properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
41667cc0636SGreg Clayton             const std::string &str = strm.GetString();
41767cc0636SGreg Clayton             g_property_names.SplitIntoLines(str.c_str(), str.size());
41867cc0636SGreg Clayton         }
41967cc0636SGreg Clayton     }
4203df9a8dfSCaroline Tice 
42167cc0636SGreg Clayton     size_t exact_matches_idx = SIZE_MAX;
42267cc0636SGreg Clayton     const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
42367cc0636SGreg Clayton     word_complete = exact_matches_idx != SIZE_MAX;
42467cc0636SGreg Clayton     return num_matches;
4253df9a8dfSCaroline Tice }
4263df9a8dfSCaroline Tice 
427ab65b34fSGreg Clayton int
428ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
429ab65b34fSGreg Clayton                                          const char *partial_name,
430ab65b34fSGreg Clayton                                          int match_start_point,
431ab65b34fSGreg Clayton                                          int max_return_elements,
432ab65b34fSGreg Clayton                                          SearchFilter *searcher,
433ab65b34fSGreg Clayton                                          bool &word_complete,
434ab65b34fSGreg Clayton                                          lldb_private::StringList &matches)
435ab65b34fSGreg Clayton {
436ab65b34fSGreg Clayton     const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
437ab65b34fSGreg Clayton     word_complete = num_matches == 1;
438ab65b34fSGreg Clayton     return num_matches;
439ab65b34fSGreg Clayton }
440ab65b34fSGreg Clayton 
441ab65b34fSGreg Clayton int
442ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
443ab65b34fSGreg Clayton                                        const char *partial_name,
444ab65b34fSGreg Clayton                                        int match_start_point,
445ab65b34fSGreg Clayton                                        int max_return_elements,
446ab65b34fSGreg Clayton                                        SearchFilter *searcher,
447ab65b34fSGreg Clayton                                        bool &word_complete,
448ab65b34fSGreg Clayton                                        lldb_private::StringList &matches)
449ab65b34fSGreg Clayton {
450ab65b34fSGreg Clayton     const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
451ab65b34fSGreg Clayton     word_complete = num_matches == 1;
452ab65b34fSGreg Clayton     return num_matches;
453ab65b34fSGreg Clayton }
454ab65b34fSGreg Clayton 
455f21feadcSGreg Clayton int
456f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter,
457f21feadcSGreg Clayton                                   const char *partial_name,
458f21feadcSGreg Clayton                                   int match_start_point,
459f21feadcSGreg Clayton                                   int max_return_elements,
460f21feadcSGreg Clayton                                   SearchFilter *searcher,
461f21feadcSGreg Clayton                                   bool &word_complete,
462f21feadcSGreg Clayton                                   lldb_private::StringList &matches)
463f21feadcSGreg Clayton {
464f21feadcSGreg Clayton     return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
465f21feadcSGreg Clayton }
466f21feadcSGreg Clayton 
467*c8ecc2a9SEugene Zelenko CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
468c9af18a5SGreg Clayton                                          const char *completion_str,
469c9af18a5SGreg Clayton                                          int match_start_point,
470c9af18a5SGreg Clayton                                          int max_return_elements,
471*c8ecc2a9SEugene Zelenko                                          StringList &matches) :
4726611103cSGreg Clayton     m_interpreter (interpreter),
473c9af18a5SGreg Clayton     m_completion_str (completion_str),
474c9af18a5SGreg Clayton     m_match_start_point (match_start_point),
475c9af18a5SGreg Clayton     m_max_return_elements (max_return_elements),
476c9af18a5SGreg Clayton     m_matches (matches)
477c9af18a5SGreg Clayton {
478c9af18a5SGreg Clayton }
479c9af18a5SGreg Clayton 
480*c8ecc2a9SEugene Zelenko CommandCompletions::Completer::~Completer() = default;
481c9af18a5SGreg Clayton 
482c9af18a5SGreg Clayton //----------------------------------------------------------------------
483c9af18a5SGreg Clayton // SourceFileCompleter
484c9af18a5SGreg Clayton //----------------------------------------------------------------------
485c9af18a5SGreg Clayton 
486*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SourceFileCompleter(CommandInterpreter &interpreter,
487c9af18a5SGreg Clayton                                                              bool include_support_files,
488c9af18a5SGreg Clayton                                                              const char *completion_str,
489c9af18a5SGreg Clayton                                                              int match_start_point,
490c9af18a5SGreg Clayton                                                              int max_return_elements,
491*c8ecc2a9SEugene Zelenko                                                              StringList &matches) :
4926611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
493c9af18a5SGreg Clayton     m_include_support_files (include_support_files),
494c9af18a5SGreg Clayton     m_matching_files()
495c9af18a5SGreg Clayton {
496274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
497c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
498c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
499c9af18a5SGreg Clayton }
500c9af18a5SGreg Clayton 
501c9af18a5SGreg Clayton Searcher::Depth
502c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth()
503c9af18a5SGreg Clayton {
504c9af18a5SGreg Clayton     return eDepthCompUnit;
505c9af18a5SGreg Clayton }
506c9af18a5SGreg Clayton 
507c9af18a5SGreg Clayton Searcher::CallbackReturn
508*c8ecc2a9SEugene Zelenko CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
509c9af18a5SGreg Clayton                                                         SymbolContext &context,
510c9af18a5SGreg Clayton                                                         Address *addr,
511*c8ecc2a9SEugene Zelenko                                                         bool complete)
512c9af18a5SGreg Clayton {
513*c8ecc2a9SEugene Zelenko     if (context.comp_unit != nullptr)
514c9af18a5SGreg Clayton     {
515c9af18a5SGreg Clayton         if (m_include_support_files)
516c9af18a5SGreg Clayton         {
517c9af18a5SGreg Clayton             FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
518c9af18a5SGreg Clayton             for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
519c9af18a5SGreg Clayton             {
520c9af18a5SGreg Clayton                 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
521c9af18a5SGreg Clayton                 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
522c9af18a5SGreg Clayton                 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
523c9af18a5SGreg Clayton                 bool match = false;
524c9af18a5SGreg Clayton                 if (m_file_name && sfile_file_name
525c9af18a5SGreg Clayton                     && strstr (sfile_file_name, m_file_name) == sfile_file_name)
526c9af18a5SGreg Clayton                     match = true;
527c9af18a5SGreg Clayton                 if (match && m_dir_name && sfile_dir_name
528c9af18a5SGreg Clayton                     && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
529c9af18a5SGreg Clayton                     match = false;
530c9af18a5SGreg Clayton 
531c9af18a5SGreg Clayton                 if (match)
532c9af18a5SGreg Clayton                 {
533c9af18a5SGreg Clayton                     m_matching_files.AppendIfUnique(sfile_spec);
534c9af18a5SGreg Clayton                 }
535c9af18a5SGreg Clayton             }
536c9af18a5SGreg Clayton         }
537c9af18a5SGreg Clayton         else
538c9af18a5SGreg Clayton         {
539c9af18a5SGreg Clayton             const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
540c9af18a5SGreg Clayton             const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
541c9af18a5SGreg Clayton 
542c9af18a5SGreg Clayton             bool match = false;
543c9af18a5SGreg Clayton             if (m_file_name && cur_file_name
544c9af18a5SGreg Clayton                 && strstr (cur_file_name, m_file_name) == cur_file_name)
545c9af18a5SGreg Clayton                 match = true;
546c9af18a5SGreg Clayton 
547c9af18a5SGreg Clayton             if (match && m_dir_name && cur_dir_name
548c9af18a5SGreg Clayton                 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
549c9af18a5SGreg Clayton                 match = false;
550c9af18a5SGreg Clayton 
551c9af18a5SGreg Clayton             if (match)
552c9af18a5SGreg Clayton             {
553c9af18a5SGreg Clayton                 m_matching_files.AppendIfUnique(context.comp_unit);
554c9af18a5SGreg Clayton             }
555c9af18a5SGreg Clayton         }
556c9af18a5SGreg Clayton     }
557c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
558c9af18a5SGreg Clayton }
559c9af18a5SGreg Clayton 
560c9af18a5SGreg Clayton size_t
561c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
562c9af18a5SGreg Clayton {
563c9af18a5SGreg Clayton     filter->Search (*this);
564c9af18a5SGreg Clayton     // Now convert the filelist to completions:
565c9af18a5SGreg Clayton     for (size_t i = 0; i < m_matching_files.GetSize(); i++)
566c9af18a5SGreg Clayton     {
567c9af18a5SGreg Clayton         m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
568c9af18a5SGreg Clayton     }
569c9af18a5SGreg Clayton     return m_matches.GetSize();
570c9af18a5SGreg Clayton }
571c9af18a5SGreg Clayton 
572c9af18a5SGreg Clayton //----------------------------------------------------------------------
573c9af18a5SGreg Clayton // SymbolCompleter
574c9af18a5SGreg Clayton //----------------------------------------------------------------------
575c9af18a5SGreg Clayton 
576c9af18a5SGreg Clayton static bool
577c9af18a5SGreg Clayton regex_chars (const char comp)
578c9af18a5SGreg Clayton {
579*c8ecc2a9SEugene Zelenko     return (comp == '[' || comp == ']' ||
580649f8b9bSGreg Clayton             comp == '(' || comp == ')' ||
581649f8b9bSGreg Clayton             comp == '{' || comp == '}' ||
582649f8b9bSGreg Clayton             comp == '+' ||
583649f8b9bSGreg Clayton             comp == '.' ||
584649f8b9bSGreg Clayton             comp == '*' ||
585649f8b9bSGreg Clayton             comp == '|' ||
586649f8b9bSGreg Clayton             comp == '^' ||
587649f8b9bSGreg Clayton             comp == '$' ||
588649f8b9bSGreg Clayton             comp == '\\' ||
589*c8ecc2a9SEugene Zelenko             comp == '?');
590c9af18a5SGreg Clayton }
591*c8ecc2a9SEugene Zelenko 
592*c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SymbolCompleter(CommandInterpreter &interpreter,
593c9af18a5SGreg Clayton                                                      const char *completion_str,
594c9af18a5SGreg Clayton                                                      int match_start_point,
595c9af18a5SGreg Clayton                                                      int max_return_elements,
596*c8ecc2a9SEugene Zelenko                                                      StringList &matches) :
5976611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
598c9af18a5SGreg Clayton {
599649f8b9bSGreg Clayton     std::string regex_str;
600649f8b9bSGreg Clayton     if (completion_str && completion_str[0])
601649f8b9bSGreg Clayton     {
602649f8b9bSGreg Clayton         regex_str.append("^");
603c9af18a5SGreg Clayton         regex_str.append(completion_str);
604649f8b9bSGreg Clayton     }
605649f8b9bSGreg Clayton     else
606649f8b9bSGreg Clayton     {
607649f8b9bSGreg Clayton         // Match anything since the completion string is empty
608649f8b9bSGreg Clayton         regex_str.append(".");
609649f8b9bSGreg Clayton     }
610649f8b9bSGreg Clayton     std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
611649f8b9bSGreg Clayton     while (pos < regex_str.end())
612649f8b9bSGreg Clayton     {
613c9af18a5SGreg Clayton         pos = regex_str.insert(pos, '\\');
614649f8b9bSGreg Clayton         pos = find_if(pos + 2, regex_str.end(), regex_chars);
615c9af18a5SGreg Clayton     }
616c9af18a5SGreg Clayton     m_regex.Compile(regex_str.c_str());
617c9af18a5SGreg Clayton }
618c9af18a5SGreg Clayton 
619c9af18a5SGreg Clayton Searcher::Depth
620c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth()
621c9af18a5SGreg Clayton {
622c9af18a5SGreg Clayton     return eDepthModule;
623c9af18a5SGreg Clayton }
624c9af18a5SGreg Clayton 
625c9af18a5SGreg Clayton Searcher::CallbackReturn
626*c8ecc2a9SEugene Zelenko CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter,
627c9af18a5SGreg Clayton                                                     SymbolContext &context,
628c9af18a5SGreg Clayton                                                     Address *addr,
629*c8ecc2a9SEugene Zelenko                                                     bool complete)
630c9af18a5SGreg Clayton {
631c9af18a5SGreg Clayton     if (context.module_sp)
632c9af18a5SGreg Clayton     {
633931180e6SGreg Clayton         SymbolContextList sc_list;
634931180e6SGreg Clayton         const bool include_symbols = true;
6359df05fbbSSean Callanan         const bool include_inlines = true;
636931180e6SGreg Clayton         const bool append = true;
6379df05fbbSSean Callanan         context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
638c9af18a5SGreg Clayton 
639c9af18a5SGreg Clayton         SymbolContext sc;
640c9af18a5SGreg Clayton         // Now add the functions & symbols to the list - only add if unique:
641931180e6SGreg Clayton         for (uint32_t i = 0; i < sc_list.GetSize(); i++)
642c9af18a5SGreg Clayton         {
643931180e6SGreg Clayton             if (sc_list.GetContextAtIndex(i, sc))
644c9af18a5SGreg Clayton             {
645530a413cSJim Ingham                 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
646530a413cSJim Ingham                 if (!func_name.IsEmpty())
647530a413cSJim Ingham                     m_match_set.insert (func_name);
648c9af18a5SGreg Clayton             }
649c9af18a5SGreg Clayton         }
650c9af18a5SGreg Clayton     }
651c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
652c9af18a5SGreg Clayton }
653c9af18a5SGreg Clayton 
654c9af18a5SGreg Clayton size_t
655c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
656c9af18a5SGreg Clayton {
657c9af18a5SGreg Clayton     filter->Search (*this);
658c9af18a5SGreg Clayton     collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
659c9af18a5SGreg Clayton     for (pos = m_match_set.begin(); pos != end; pos++)
660c9af18a5SGreg Clayton         m_matches.AppendString((*pos).GetCString());
661c9af18a5SGreg Clayton 
662c9af18a5SGreg Clayton     return m_matches.GetSize();
663c9af18a5SGreg Clayton }
664c9af18a5SGreg Clayton 
665c9af18a5SGreg Clayton //----------------------------------------------------------------------
666c9af18a5SGreg Clayton // ModuleCompleter
667c9af18a5SGreg Clayton //----------------------------------------------------------------------
668*c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::ModuleCompleter(CommandInterpreter &interpreter,
669c9af18a5SGreg Clayton                                                      const char *completion_str,
670c9af18a5SGreg Clayton                                                      int match_start_point,
671c9af18a5SGreg Clayton                                                      int max_return_elements,
672*c8ecc2a9SEugene Zelenko                                                      StringList &matches) :
6736611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
674c9af18a5SGreg Clayton {
675274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
676c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
677c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
678c9af18a5SGreg Clayton }
679c9af18a5SGreg Clayton 
680c9af18a5SGreg Clayton Searcher::Depth
681c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth()
682c9af18a5SGreg Clayton {
683c9af18a5SGreg Clayton     return eDepthModule;
684c9af18a5SGreg Clayton }
685c9af18a5SGreg Clayton 
686c9af18a5SGreg Clayton Searcher::CallbackReturn
687*c8ecc2a9SEugene Zelenko CommandCompletions::ModuleCompleter::SearchCallback(SearchFilter &filter,
688c9af18a5SGreg Clayton                                                     SymbolContext &context,
689c9af18a5SGreg Clayton                                                     Address *addr,
690*c8ecc2a9SEugene Zelenko                                                     bool complete)
691c9af18a5SGreg Clayton {
692747bcb03SGreg Clayton     if (context.module_sp)
693c9af18a5SGreg Clayton     {
694c9af18a5SGreg Clayton         const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
695c9af18a5SGreg Clayton         const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
696c9af18a5SGreg Clayton 
697c9af18a5SGreg Clayton         bool match = false;
698c9af18a5SGreg Clayton         if (m_file_name && cur_file_name
699c9af18a5SGreg Clayton             && strstr (cur_file_name, m_file_name) == cur_file_name)
700c9af18a5SGreg Clayton             match = true;
701c9af18a5SGreg Clayton 
702c9af18a5SGreg Clayton         if (match && m_dir_name && cur_dir_name
703c9af18a5SGreg Clayton             && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
704c9af18a5SGreg Clayton             match = false;
705c9af18a5SGreg Clayton 
706c9af18a5SGreg Clayton         if (match)
707c9af18a5SGreg Clayton         {
708c9af18a5SGreg Clayton             m_matches.AppendString (cur_file_name);
709c9af18a5SGreg Clayton         }
710c9af18a5SGreg Clayton     }
711c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
712c9af18a5SGreg Clayton }
713c9af18a5SGreg Clayton 
714c9af18a5SGreg Clayton size_t
715c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
716c9af18a5SGreg Clayton {
717c9af18a5SGreg Clayton     filter->Search (*this);
718c9af18a5SGreg Clayton     return m_matches.GetSize();
719c9af18a5SGreg Clayton }
720