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>
14fd18426eSGreg Clayton #if defined(__APPLE__) || defined(__linux__)
157cc478b9SJim Ingham #include <pwd.h>
16fd18426eSGreg Clayton #endif
17558ce124SJim Ingham 
18c9af18a5SGreg Clayton // C++ Includes
19c9af18a5SGreg Clayton // Other libraries and framework includes
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"
28*633a29cfSZachary 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 
343f559740SZachary Turner #include "llvm/ADT/SmallString.h"
353f559740SZachary Turner 
36c9af18a5SGreg Clayton using namespace lldb_private;
37c9af18a5SGreg Clayton 
38c9af18a5SGreg Clayton CommandCompletions::CommonCompletionElement
39c9af18a5SGreg Clayton CommandCompletions::g_common_completions[] =
40c9af18a5SGreg Clayton {
41c9af18a5SGreg Clayton     {eCustomCompletion,          NULL},
42c9af18a5SGreg Clayton     {eSourceFileCompletion,      CommandCompletions::SourceFiles},
43558ce124SJim Ingham     {eDiskFileCompletion,        CommandCompletions::DiskFiles},
44558ce124SJim Ingham     {eDiskDirectoryCompletion,   CommandCompletions::DiskDirectories},
45c9af18a5SGreg Clayton     {eSymbolCompletion,          CommandCompletions::Symbols},
46c9af18a5SGreg Clayton     {eModuleCompletion,          CommandCompletions::Modules},
473df9a8dfSCaroline Tice     {eSettingsNameCompletion,    CommandCompletions::SettingsNames},
48ab65b34fSGreg Clayton     {ePlatformPluginCompletion,  CommandCompletions::PlatformPluginNames},
49ab65b34fSGreg Clayton     {eArchitectureCompletion,    CommandCompletions::ArchitectureNames},
50f21feadcSGreg Clayton     {eVariablePathCompletion,    CommandCompletions::VariablePath},
51c9af18a5SGreg Clayton     {eNoCompletion,              NULL}      // This one has to be last in the list.
52c9af18a5SGreg Clayton };
53c9af18a5SGreg Clayton 
54c9af18a5SGreg Clayton bool
556611103cSGreg Clayton CommandCompletions::InvokeCommonCompletionCallbacks
566611103cSGreg Clayton (
576611103cSGreg Clayton     CommandInterpreter &interpreter,
586611103cSGreg Clayton     uint32_t completion_mask,
59c9af18a5SGreg Clayton     const char *completion_str,
60c9af18a5SGreg Clayton     int match_start_point,
61c9af18a5SGreg Clayton     int max_return_elements,
62c9af18a5SGreg Clayton     SearchFilter *searcher,
63558ce124SJim Ingham     bool &word_complete,
646611103cSGreg Clayton     StringList &matches
656611103cSGreg Clayton )
66c9af18a5SGreg Clayton {
67c9af18a5SGreg Clayton     bool handled = false;
68c9af18a5SGreg Clayton 
69c9af18a5SGreg Clayton     if (completion_mask & eCustomCompletion)
70c9af18a5SGreg Clayton         return false;
71c9af18a5SGreg Clayton 
72c9af18a5SGreg Clayton     for (int i = 0; ; i++)
73c9af18a5SGreg Clayton     {
74c9af18a5SGreg Clayton         if (g_common_completions[i].type == eNoCompletion)
75c9af18a5SGreg Clayton             break;
76c9af18a5SGreg Clayton          else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
77c9af18a5SGreg Clayton                    && g_common_completions[i].callback != NULL)
78c9af18a5SGreg Clayton          {
79c9af18a5SGreg Clayton             handled = true;
806611103cSGreg Clayton             g_common_completions[i].callback (interpreter,
816611103cSGreg Clayton                                               completion_str,
82c9af18a5SGreg Clayton                                               match_start_point,
83c9af18a5SGreg Clayton                                               max_return_elements,
84c9af18a5SGreg Clayton                                               searcher,
85558ce124SJim Ingham                                               word_complete,
86c9af18a5SGreg Clayton                                               matches);
87c9af18a5SGreg Clayton         }
88c9af18a5SGreg Clayton     }
89c9af18a5SGreg Clayton     return handled;
90c9af18a5SGreg Clayton }
91c9af18a5SGreg Clayton 
92c9af18a5SGreg Clayton int
936611103cSGreg Clayton CommandCompletions::SourceFiles
946611103cSGreg Clayton (
956611103cSGreg Clayton     CommandInterpreter &interpreter,
966611103cSGreg Clayton     const char *partial_file_name,
97c9af18a5SGreg Clayton     int match_start_point,
98c9af18a5SGreg Clayton     int max_return_elements,
99c9af18a5SGreg Clayton     SearchFilter *searcher,
100558ce124SJim Ingham     bool &word_complete,
1016611103cSGreg Clayton     StringList &matches
1026611103cSGreg Clayton )
103c9af18a5SGreg Clayton {
104558ce124SJim Ingham     word_complete = true;
105c9af18a5SGreg Clayton     // Find some way to switch "include support files..."
1066611103cSGreg Clayton     SourceFileCompleter completer (interpreter,
1076611103cSGreg Clayton                                    false,
1086611103cSGreg Clayton                                    partial_file_name,
1096611103cSGreg Clayton                                    match_start_point,
1106611103cSGreg Clayton                                    max_return_elements,
111c9af18a5SGreg Clayton                                    matches);
112c9af18a5SGreg Clayton 
113c9af18a5SGreg Clayton     if (searcher == NULL)
114c9af18a5SGreg Clayton     {
1152976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
11633df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
117c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
118c9af18a5SGreg Clayton     }
119c9af18a5SGreg Clayton     else
120c9af18a5SGreg Clayton     {
121c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
122c9af18a5SGreg Clayton     }
123c9af18a5SGreg Clayton     return matches.GetSize();
124c9af18a5SGreg Clayton }
125c9af18a5SGreg Clayton 
126b2f1fb29SVirgile Bello typedef struct DiskFilesOrDirectoriesBaton
127b2f1fb29SVirgile Bello {
128b2f1fb29SVirgile Bello     const char *remainder;
129b2f1fb29SVirgile Bello     char *partial_name_copy;
130b2f1fb29SVirgile Bello     bool only_directories;
131b2f1fb29SVirgile Bello     bool *saw_directory;
132b2f1fb29SVirgile Bello     StringList *matches;
133b2f1fb29SVirgile Bello     char *end_ptr;
134b2f1fb29SVirgile Bello     size_t baselen;
1350b5e5f43SMichael Sartain } DiskFilesOrDirectoriesBaton;
136b2f1fb29SVirgile Bello 
137b2f1fb29SVirgile Bello FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
138b2f1fb29SVirgile Bello {
139b2f1fb29SVirgile Bello     const char *name = spec.GetFilename().AsCString();
140b2f1fb29SVirgile Bello 
141b2f1fb29SVirgile Bello     const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
142b2f1fb29SVirgile Bello     char *end_ptr = parameters->end_ptr;
143b2f1fb29SVirgile Bello     char *partial_name_copy = parameters->partial_name_copy;
144b2f1fb29SVirgile Bello     const char *remainder = parameters->remainder;
145b2f1fb29SVirgile Bello 
146b2f1fb29SVirgile Bello     // Omit ".", ".." and any . files if the match string doesn't start with .
147b2f1fb29SVirgile Bello     if (name[0] == '.')
148b2f1fb29SVirgile Bello     {
149b2f1fb29SVirgile Bello         if (name[1] == '\0')
150b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
151b2f1fb29SVirgile Bello         else if (name[1] == '.' && name[2] == '\0')
152b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
153b2f1fb29SVirgile Bello         else if (remainder[0] != '.')
154b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
155b2f1fb29SVirgile Bello     }
156b2f1fb29SVirgile Bello 
157b2f1fb29SVirgile Bello     // If we found a directory, we put a "/" at the end of the name.
158b2f1fb29SVirgile Bello 
159b2f1fb29SVirgile Bello     if (remainder[0] == '\0' || strstr(name, remainder) == name)
160b2f1fb29SVirgile Bello     {
161b2f1fb29SVirgile Bello         if (strlen(name) + parameters->baselen >= PATH_MAX)
162b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
163b2f1fb29SVirgile Bello 
164b2f1fb29SVirgile Bello         strcpy(end_ptr, name);
165b2f1fb29SVirgile Bello 
166b2f1fb29SVirgile Bello         bool isa_directory = false;
167b2f1fb29SVirgile Bello         if (file_type == FileSpec::eFileTypeDirectory)
168b2f1fb29SVirgile Bello             isa_directory = true;
169b2f1fb29SVirgile Bello         else if (file_type == FileSpec::eFileTypeSymbolicLink)
170b2f1fb29SVirgile Bello         {
171b2f1fb29SVirgile Bello             struct stat stat_buf;
172b2f1fb29SVirgile Bello             if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
173b2f1fb29SVirgile Bello                 isa_directory = true;
174b2f1fb29SVirgile Bello         }
175b2f1fb29SVirgile Bello 
176b2f1fb29SVirgile Bello         if (isa_directory)
177b2f1fb29SVirgile Bello         {
178b2f1fb29SVirgile Bello             *parameters->saw_directory = true;
179b2f1fb29SVirgile Bello             size_t len = strlen(parameters->partial_name_copy);
180b2f1fb29SVirgile Bello             partial_name_copy[len] = '/';
181b2f1fb29SVirgile Bello             partial_name_copy[len + 1] = '\0';
182b2f1fb29SVirgile Bello         }
183b2f1fb29SVirgile Bello         if (parameters->only_directories && !isa_directory)
184b2f1fb29SVirgile Bello             return FileSpec::eEnumerateDirectoryResultNext;
185b2f1fb29SVirgile Bello         parameters->matches->AppendString(partial_name_copy);
186b2f1fb29SVirgile Bello     }
187b2f1fb29SVirgile Bello 
188b2f1fb29SVirgile Bello     return FileSpec::eEnumerateDirectoryResultNext;
189b2f1fb29SVirgile Bello }
190b2f1fb29SVirgile Bello 
191558ce124SJim Ingham static int
192558ce124SJim Ingham DiskFilesOrDirectories
193558ce124SJim Ingham (
194558ce124SJim Ingham     const char *partial_file_name,
195558ce124SJim Ingham     bool only_directories,
196558ce124SJim Ingham     bool &saw_directory,
197558ce124SJim Ingham     StringList &matches
198558ce124SJim Ingham )
199558ce124SJim Ingham {
200558ce124SJim Ingham     // I'm going to  use the "glob" function with GLOB_TILDE for user directory expansion.
201558ce124SJim Ingham     // If it is not defined on your host system, you'll need to implement it yourself...
202558ce124SJim Ingham 
203c7bece56SGreg Clayton     size_t partial_name_len = strlen(partial_file_name);
204558ce124SJim Ingham 
205558ce124SJim Ingham     if (partial_name_len >= PATH_MAX)
206558ce124SJim Ingham         return matches.GetSize();
207558ce124SJim Ingham 
208558ce124SJim Ingham     // This copy of the string will be cut up into the directory part, and the remainder.  end_ptr
209558ce124SJim Ingham     // below will point to the place of the remainder in this string.  Then when we've resolved the
210558ce124SJim Ingham     // containing directory, and opened it, we'll read the directory contents and overwrite the
211558ce124SJim Ingham     // partial_name_copy starting from end_ptr with each of the matches.  Thus we will preserve
212558ce124SJim Ingham     // the form the user originally typed.
213558ce124SJim Ingham 
214558ce124SJim Ingham     char partial_name_copy[PATH_MAX];
215021b605dSBenjamin Kramer     memcpy(partial_name_copy, partial_file_name, partial_name_len);
216558ce124SJim Ingham     partial_name_copy[partial_name_len] = '\0';
217558ce124SJim Ingham 
218710dd5aeSGreg Clayton     // We'll need to save a copy of the remainder for comparison, which we do here.
219558ce124SJim Ingham     char remainder[PATH_MAX];
220558ce124SJim Ingham 
221558ce124SJim Ingham     // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
222558ce124SJim Ingham     char *end_ptr;
223558ce124SJim Ingham 
224558ce124SJim Ingham     end_ptr = strrchr(partial_name_copy, '/');
225558ce124SJim Ingham 
226558ce124SJim Ingham     // This will store the resolved form of the containing directory
2273f559740SZachary Turner     llvm::SmallString<64> containing_part;
228558ce124SJim Ingham 
229558ce124SJim Ingham     if (end_ptr == NULL)
230558ce124SJim Ingham     {
231558ce124SJim Ingham         // There's no directory.  If the thing begins with a "~" then this is a bare
232558ce124SJim Ingham         // user name.
233558ce124SJim Ingham         if (*partial_name_copy == '~')
234558ce124SJim Ingham         {
235558ce124SJim Ingham             // Nothing here but the user name.  We could just put a slash on the end,
2367cc478b9SJim Ingham             // but for completeness sake we'll resolve the user name and only put a slash
237558ce124SJim Ingham             // on the end if it exists.
2383f559740SZachary Turner             llvm::SmallString<64> resolved_username(partial_name_copy);
2393f559740SZachary Turner             FileSpec::ResolveUsername (resolved_username);
2407cc478b9SJim Ingham 
2417cc478b9SJim Ingham            // Not sure how this would happen, a username longer than PATH_MAX?  Still...
2423f559740SZachary Turner             if (resolved_username.size() == 0)
2437cc478b9SJim Ingham             {
2447cc478b9SJim Ingham                 // The user name didn't resolve, let's look in the password database for matches.
2457cc478b9SJim Ingham                 // The user name database contains duplicates, and is not in alphabetical order, so
2467cc478b9SJim Ingham                 // we'll use a set to manage that for us.
24784363078SJim Ingham                 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
24884363078SJim Ingham                 if (matches.GetSize() > 0)
2497cc478b9SJim Ingham                     saw_directory = true;
2507cc478b9SJim Ingham                 return matches.GetSize();
2517cc478b9SJim Ingham             }
25284363078SJim Ingham             else
25384363078SJim Ingham             {
254558ce124SJim Ingham                 //The thing exists, put a '/' on the end, and return it...
255558ce124SJim Ingham                 // FIXME: complete user names here:
256558ce124SJim Ingham                 partial_name_copy[partial_name_len] = '/';
257558ce124SJim Ingham                 partial_name_copy[partial_name_len+1] = '\0';
258558ce124SJim Ingham                 matches.AppendString(partial_name_copy);
259021b605dSBenjamin Kramer                 saw_directory = true;
260558ce124SJim Ingham                 return matches.GetSize();
261558ce124SJim Ingham             }
26284363078SJim Ingham         }
263558ce124SJim Ingham         else
264558ce124SJim Ingham         {
265558ce124SJim Ingham             // The containing part is the CWD, and the whole string is the remainder.
2663f559740SZachary Turner             containing_part = ".";
267558ce124SJim Ingham             strcpy(remainder, partial_name_copy);
268558ce124SJim Ingham             end_ptr = partial_name_copy;
269558ce124SJim Ingham         }
270558ce124SJim Ingham     }
271558ce124SJim Ingham     else
272558ce124SJim Ingham     {
273558ce124SJim Ingham         if (end_ptr == partial_name_copy)
274558ce124SJim Ingham         {
275558ce124SJim Ingham             // We're completing a file or directory in the root volume.
2763f559740SZachary Turner             containing_part = "/";
277558ce124SJim Ingham         }
278558ce124SJim Ingham         else
279558ce124SJim Ingham         {
2803f559740SZachary Turner             containing_part.append(partial_name_copy, end_ptr);
281558ce124SJim Ingham         }
282558ce124SJim Ingham         // Push end_ptr past the final "/" and set remainder.
283558ce124SJim Ingham         end_ptr++;
284558ce124SJim Ingham         strcpy(remainder, end_ptr);
285558ce124SJim Ingham     }
286558ce124SJim Ingham 
2877cc478b9SJim Ingham     // Look for a user name in the containing part, and if it's there, resolve it and stick the
288558ce124SJim Ingham     // result back into the containing_part:
289558ce124SJim Ingham 
290558ce124SJim Ingham     if (*partial_name_copy == '~')
291558ce124SJim Ingham     {
2923f559740SZachary Turner         FileSpec::ResolveUsername(containing_part);
293558ce124SJim Ingham         // User name doesn't exist, we're not getting any further...
2943f559740SZachary Turner         if (containing_part.empty())
295558ce124SJim Ingham             return matches.GetSize();
296558ce124SJim Ingham     }
297558ce124SJim Ingham 
298558ce124SJim Ingham     // Okay, containing_part is now the directory we want to open and look for files:
299558ce124SJim Ingham 
300558ce124SJim Ingham     size_t baselen = end_ptr - partial_name_copy;
301558ce124SJim Ingham 
302b2f1fb29SVirgile Bello     DiskFilesOrDirectoriesBaton parameters;
303b2f1fb29SVirgile Bello     parameters.remainder = remainder;
304b2f1fb29SVirgile Bello     parameters.partial_name_copy = partial_name_copy;
305b2f1fb29SVirgile Bello     parameters.only_directories = only_directories;
306b2f1fb29SVirgile Bello     parameters.saw_directory = &saw_directory;
307b2f1fb29SVirgile Bello     parameters.matches = &matches;
308b2f1fb29SVirgile Bello     parameters.end_ptr = end_ptr;
309b2f1fb29SVirgile Bello     parameters.baselen = baselen;
310558ce124SJim Ingham 
3113f559740SZachary Turner     FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
312558ce124SJim Ingham 
313558ce124SJim Ingham     return matches.GetSize();
314558ce124SJim Ingham }
315558ce124SJim Ingham 
316558ce124SJim Ingham int
317558ce124SJim Ingham CommandCompletions::DiskFiles
318558ce124SJim Ingham (
319558ce124SJim Ingham     CommandInterpreter &interpreter,
320558ce124SJim Ingham     const char *partial_file_name,
321558ce124SJim Ingham     int match_start_point,
322558ce124SJim Ingham     int max_return_elements,
323558ce124SJim Ingham     SearchFilter *searcher,
324558ce124SJim Ingham     bool &word_complete,
325558ce124SJim Ingham     StringList &matches
326558ce124SJim Ingham )
327558ce124SJim Ingham {
328558ce124SJim Ingham 
329558ce124SJim Ingham     int ret_val = DiskFilesOrDirectories (partial_file_name,
330558ce124SJim Ingham                                           false,
331558ce124SJim Ingham                                           word_complete,
332558ce124SJim Ingham                                           matches);
333558ce124SJim Ingham     word_complete = !word_complete;
334558ce124SJim Ingham     return ret_val;
335558ce124SJim Ingham }
336558ce124SJim Ingham 
337558ce124SJim Ingham int
338558ce124SJim Ingham CommandCompletions::DiskDirectories
339558ce124SJim Ingham (
340558ce124SJim Ingham     CommandInterpreter &interpreter,
341558ce124SJim Ingham     const char *partial_file_name,
342558ce124SJim Ingham     int match_start_point,
343558ce124SJim Ingham     int max_return_elements,
344558ce124SJim Ingham     SearchFilter *searcher,
345558ce124SJim Ingham     bool &word_complete,
346558ce124SJim Ingham     StringList &matches
347558ce124SJim Ingham )
348558ce124SJim Ingham {
349558ce124SJim Ingham     int ret_val =  DiskFilesOrDirectories (partial_file_name,
350558ce124SJim Ingham                                            true,
351558ce124SJim Ingham                                            word_complete,
352558ce124SJim Ingham                                            matches);
353558ce124SJim Ingham     word_complete = false;
354558ce124SJim Ingham     return ret_val;
355558ce124SJim Ingham }
356558ce124SJim Ingham 
357c9af18a5SGreg Clayton int
3586611103cSGreg Clayton CommandCompletions::Modules
3596611103cSGreg Clayton (
3606611103cSGreg Clayton     CommandInterpreter &interpreter,
3616611103cSGreg Clayton     const char *partial_file_name,
362c9af18a5SGreg Clayton     int match_start_point,
363c9af18a5SGreg Clayton     int max_return_elements,
364c9af18a5SGreg Clayton     SearchFilter *searcher,
365558ce124SJim Ingham     bool &word_complete,
3666611103cSGreg Clayton     StringList &matches
3676611103cSGreg Clayton )
368c9af18a5SGreg Clayton {
369558ce124SJim Ingham     word_complete = true;
3706611103cSGreg Clayton     ModuleCompleter completer (interpreter,
3716611103cSGreg Clayton                                partial_file_name,
3726611103cSGreg Clayton                                match_start_point,
3736611103cSGreg Clayton                                max_return_elements,
3746611103cSGreg Clayton                                matches);
375c9af18a5SGreg Clayton 
376c9af18a5SGreg Clayton     if (searcher == NULL)
377c9af18a5SGreg Clayton     {
3782976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
37933df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
380c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
381c9af18a5SGreg Clayton     }
382c9af18a5SGreg Clayton     else
383c9af18a5SGreg Clayton     {
384c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
385c9af18a5SGreg Clayton     }
386c9af18a5SGreg Clayton     return matches.GetSize();
387c9af18a5SGreg Clayton }
388c9af18a5SGreg Clayton 
389c9af18a5SGreg Clayton int
3906611103cSGreg Clayton CommandCompletions::Symbols
3916611103cSGreg Clayton (
3926611103cSGreg Clayton     CommandInterpreter &interpreter,
3936611103cSGreg Clayton     const char *partial_file_name,
394c9af18a5SGreg Clayton     int match_start_point,
395c9af18a5SGreg Clayton     int max_return_elements,
396c9af18a5SGreg Clayton     SearchFilter *searcher,
397558ce124SJim Ingham     bool &word_complete,
3986611103cSGreg Clayton     StringList &matches)
399c9af18a5SGreg Clayton {
400558ce124SJim Ingham     word_complete = true;
4016611103cSGreg Clayton     SymbolCompleter completer (interpreter,
4026611103cSGreg Clayton                                partial_file_name,
4036611103cSGreg Clayton                                match_start_point,
4046611103cSGreg Clayton                                max_return_elements,
4056611103cSGreg Clayton                                matches);
406c9af18a5SGreg Clayton 
407c9af18a5SGreg Clayton     if (searcher == NULL)
408c9af18a5SGreg Clayton     {
4092976d00aSJim Ingham         lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
41033df7cd3SJim Ingham         SearchFilterForUnconstrainedSearches null_searcher (target_sp);
411c9af18a5SGreg Clayton         completer.DoCompletion (&null_searcher);
412c9af18a5SGreg Clayton     }
413c9af18a5SGreg Clayton     else
414c9af18a5SGreg Clayton     {
415c9af18a5SGreg Clayton         completer.DoCompletion (searcher);
416c9af18a5SGreg Clayton     }
417c9af18a5SGreg Clayton     return matches.GetSize();
418c9af18a5SGreg Clayton }
419c9af18a5SGreg Clayton 
4203df9a8dfSCaroline Tice int
4213df9a8dfSCaroline Tice CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
4223df9a8dfSCaroline Tice                                    const char *partial_setting_name,
4233df9a8dfSCaroline Tice                                    int match_start_point,
4243df9a8dfSCaroline Tice                                    int max_return_elements,
4253df9a8dfSCaroline Tice                                    SearchFilter *searcher,
4263df9a8dfSCaroline Tice                                    bool &word_complete,
4273df9a8dfSCaroline Tice                                    StringList &matches)
4283df9a8dfSCaroline Tice {
42967cc0636SGreg Clayton     // Cache the full setting name list
43067cc0636SGreg Clayton     static StringList g_property_names;
43167cc0636SGreg Clayton     if (g_property_names.GetSize() == 0)
43267cc0636SGreg Clayton     {
43367cc0636SGreg Clayton         // Generate the full setting name list on demand
43467cc0636SGreg Clayton         lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
43567cc0636SGreg Clayton         if (properties_sp)
43667cc0636SGreg Clayton         {
43767cc0636SGreg Clayton             StreamString strm;
43867cc0636SGreg Clayton             properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
43967cc0636SGreg Clayton             const std::string &str = strm.GetString();
44067cc0636SGreg Clayton             g_property_names.SplitIntoLines(str.c_str(), str.size());
44167cc0636SGreg Clayton         }
44267cc0636SGreg Clayton     }
4433df9a8dfSCaroline Tice 
44467cc0636SGreg Clayton     size_t exact_matches_idx = SIZE_MAX;
44567cc0636SGreg Clayton     const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
44667cc0636SGreg Clayton     word_complete = exact_matches_idx != SIZE_MAX;
44767cc0636SGreg Clayton     return num_matches;
4483df9a8dfSCaroline Tice }
4493df9a8dfSCaroline Tice 
450ab65b34fSGreg Clayton 
451ab65b34fSGreg Clayton int
452ab65b34fSGreg Clayton CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
453ab65b34fSGreg Clayton                                          const char *partial_name,
454ab65b34fSGreg Clayton                                          int match_start_point,
455ab65b34fSGreg Clayton                                          int max_return_elements,
456ab65b34fSGreg Clayton                                          SearchFilter *searcher,
457ab65b34fSGreg Clayton                                          bool &word_complete,
458ab65b34fSGreg Clayton                                          lldb_private::StringList &matches)
459ab65b34fSGreg Clayton {
460ab65b34fSGreg Clayton     const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
461ab65b34fSGreg Clayton     word_complete = num_matches == 1;
462ab65b34fSGreg Clayton     return num_matches;
463ab65b34fSGreg Clayton }
464ab65b34fSGreg Clayton 
465ab65b34fSGreg Clayton int
466ab65b34fSGreg Clayton CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
467ab65b34fSGreg Clayton                                        const char *partial_name,
468ab65b34fSGreg Clayton                                        int match_start_point,
469ab65b34fSGreg Clayton                                        int max_return_elements,
470ab65b34fSGreg Clayton                                        SearchFilter *searcher,
471ab65b34fSGreg Clayton                                        bool &word_complete,
472ab65b34fSGreg Clayton                                        lldb_private::StringList &matches)
473ab65b34fSGreg Clayton {
474ab65b34fSGreg Clayton     const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
475ab65b34fSGreg Clayton     word_complete = num_matches == 1;
476ab65b34fSGreg Clayton     return num_matches;
477ab65b34fSGreg Clayton }
478ab65b34fSGreg Clayton 
479ab65b34fSGreg Clayton 
480f21feadcSGreg Clayton int
481f21feadcSGreg Clayton CommandCompletions::VariablePath (CommandInterpreter &interpreter,
482f21feadcSGreg Clayton                                   const char *partial_name,
483f21feadcSGreg Clayton                                   int match_start_point,
484f21feadcSGreg Clayton                                   int max_return_elements,
485f21feadcSGreg Clayton                                   SearchFilter *searcher,
486f21feadcSGreg Clayton                                   bool &word_complete,
487f21feadcSGreg Clayton                                   lldb_private::StringList &matches)
488f21feadcSGreg Clayton {
489f21feadcSGreg Clayton     return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
490f21feadcSGreg Clayton }
491f21feadcSGreg Clayton 
492f21feadcSGreg Clayton 
4936611103cSGreg Clayton CommandCompletions::Completer::Completer
4946611103cSGreg Clayton (
4956611103cSGreg Clayton     CommandInterpreter &interpreter,
496c9af18a5SGreg Clayton     const char *completion_str,
497c9af18a5SGreg Clayton     int match_start_point,
498c9af18a5SGreg Clayton     int max_return_elements,
499c9af18a5SGreg Clayton     StringList &matches
500c9af18a5SGreg Clayton ) :
5016611103cSGreg Clayton     m_interpreter (interpreter),
502c9af18a5SGreg Clayton     m_completion_str (completion_str),
503c9af18a5SGreg Clayton     m_match_start_point (match_start_point),
504c9af18a5SGreg Clayton     m_max_return_elements (max_return_elements),
505c9af18a5SGreg Clayton     m_matches (matches)
506c9af18a5SGreg Clayton {
507c9af18a5SGreg Clayton }
508c9af18a5SGreg Clayton 
509c9af18a5SGreg Clayton CommandCompletions::Completer::~Completer ()
510c9af18a5SGreg Clayton {
511c9af18a5SGreg Clayton 
512c9af18a5SGreg Clayton }
513c9af18a5SGreg Clayton 
514c9af18a5SGreg Clayton //----------------------------------------------------------------------
515c9af18a5SGreg Clayton // SourceFileCompleter
516c9af18a5SGreg Clayton //----------------------------------------------------------------------
517c9af18a5SGreg Clayton 
5186611103cSGreg Clayton CommandCompletions::SourceFileCompleter::SourceFileCompleter
5196611103cSGreg Clayton (
5206611103cSGreg Clayton     CommandInterpreter &interpreter,
521c9af18a5SGreg Clayton     bool include_support_files,
522c9af18a5SGreg Clayton     const char *completion_str,
523c9af18a5SGreg Clayton     int match_start_point,
524c9af18a5SGreg Clayton     int max_return_elements,
525c9af18a5SGreg Clayton     StringList &matches
526c9af18a5SGreg Clayton ) :
5276611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
528c9af18a5SGreg Clayton     m_include_support_files (include_support_files),
529c9af18a5SGreg Clayton     m_matching_files()
530c9af18a5SGreg Clayton {
531274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
532c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
533c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
534c9af18a5SGreg Clayton }
535c9af18a5SGreg Clayton 
536c9af18a5SGreg Clayton Searcher::Depth
537c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::GetDepth()
538c9af18a5SGreg Clayton {
539c9af18a5SGreg Clayton     return eDepthCompUnit;
540c9af18a5SGreg Clayton }
541c9af18a5SGreg Clayton 
542c9af18a5SGreg Clayton Searcher::CallbackReturn
543c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::SearchCallback (
544c9af18a5SGreg Clayton     SearchFilter &filter,
545c9af18a5SGreg Clayton     SymbolContext &context,
546c9af18a5SGreg Clayton     Address *addr,
547c9af18a5SGreg Clayton     bool complete
548c9af18a5SGreg Clayton )
549c9af18a5SGreg Clayton {
550c9af18a5SGreg Clayton     if (context.comp_unit != NULL)
551c9af18a5SGreg Clayton     {
552c9af18a5SGreg Clayton         if (m_include_support_files)
553c9af18a5SGreg Clayton         {
554c9af18a5SGreg Clayton             FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
555c9af18a5SGreg Clayton             for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
556c9af18a5SGreg Clayton             {
557c9af18a5SGreg Clayton                 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
558c9af18a5SGreg Clayton                 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
559c9af18a5SGreg Clayton                 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
560c9af18a5SGreg Clayton                 bool match = false;
561c9af18a5SGreg Clayton                 if (m_file_name && sfile_file_name
562c9af18a5SGreg Clayton                     && strstr (sfile_file_name, m_file_name) == sfile_file_name)
563c9af18a5SGreg Clayton                     match = true;
564c9af18a5SGreg Clayton                 if (match && m_dir_name && sfile_dir_name
565c9af18a5SGreg Clayton                     && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
566c9af18a5SGreg Clayton                     match = false;
567c9af18a5SGreg Clayton 
568c9af18a5SGreg Clayton                 if (match)
569c9af18a5SGreg Clayton                 {
570c9af18a5SGreg Clayton                     m_matching_files.AppendIfUnique(sfile_spec);
571c9af18a5SGreg Clayton                 }
572c9af18a5SGreg Clayton             }
573c9af18a5SGreg Clayton 
574c9af18a5SGreg Clayton         }
575c9af18a5SGreg Clayton         else
576c9af18a5SGreg Clayton         {
577c9af18a5SGreg Clayton             const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
578c9af18a5SGreg Clayton             const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
579c9af18a5SGreg Clayton 
580c9af18a5SGreg Clayton             bool match = false;
581c9af18a5SGreg Clayton             if (m_file_name && cur_file_name
582c9af18a5SGreg Clayton                 && strstr (cur_file_name, m_file_name) == cur_file_name)
583c9af18a5SGreg Clayton                 match = true;
584c9af18a5SGreg Clayton 
585c9af18a5SGreg Clayton             if (match && m_dir_name && cur_dir_name
586c9af18a5SGreg Clayton                 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
587c9af18a5SGreg Clayton                 match = false;
588c9af18a5SGreg Clayton 
589c9af18a5SGreg Clayton             if (match)
590c9af18a5SGreg Clayton             {
591c9af18a5SGreg Clayton                 m_matching_files.AppendIfUnique(context.comp_unit);
592c9af18a5SGreg Clayton             }
593c9af18a5SGreg Clayton         }
594c9af18a5SGreg Clayton     }
595c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
596c9af18a5SGreg Clayton }
597c9af18a5SGreg Clayton 
598c9af18a5SGreg Clayton size_t
599c9af18a5SGreg Clayton CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
600c9af18a5SGreg Clayton {
601c9af18a5SGreg Clayton     filter->Search (*this);
602c9af18a5SGreg Clayton     // Now convert the filelist to completions:
603c9af18a5SGreg Clayton     for (size_t i = 0; i < m_matching_files.GetSize(); i++)
604c9af18a5SGreg Clayton     {
605c9af18a5SGreg Clayton         m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
606c9af18a5SGreg Clayton     }
607c9af18a5SGreg Clayton     return m_matches.GetSize();
608c9af18a5SGreg Clayton 
609c9af18a5SGreg Clayton }
610c9af18a5SGreg Clayton 
611c9af18a5SGreg Clayton //----------------------------------------------------------------------
612c9af18a5SGreg Clayton // SymbolCompleter
613c9af18a5SGreg Clayton //----------------------------------------------------------------------
614c9af18a5SGreg Clayton 
615c9af18a5SGreg Clayton static bool
616c9af18a5SGreg Clayton regex_chars (const char comp)
617c9af18a5SGreg Clayton {
618649f8b9bSGreg Clayton     if (comp == '[' || comp == ']' ||
619649f8b9bSGreg Clayton         comp == '(' || comp == ')' ||
620649f8b9bSGreg Clayton         comp == '{' || comp == '}' ||
621649f8b9bSGreg Clayton         comp == '+' ||
622649f8b9bSGreg Clayton         comp == '.' ||
623649f8b9bSGreg Clayton         comp == '*' ||
624649f8b9bSGreg Clayton         comp == '|' ||
625649f8b9bSGreg Clayton         comp == '^' ||
626649f8b9bSGreg Clayton         comp == '$' ||
627649f8b9bSGreg Clayton         comp == '\\' ||
628649f8b9bSGreg Clayton         comp == '?')
629c9af18a5SGreg Clayton         return true;
630c9af18a5SGreg Clayton     else
631c9af18a5SGreg Clayton         return false;
632c9af18a5SGreg Clayton }
6336611103cSGreg Clayton CommandCompletions::SymbolCompleter::SymbolCompleter
6346611103cSGreg Clayton (
6356611103cSGreg Clayton     CommandInterpreter &interpreter,
636c9af18a5SGreg Clayton     const char *completion_str,
637c9af18a5SGreg Clayton     int match_start_point,
638c9af18a5SGreg Clayton     int max_return_elements,
639c9af18a5SGreg Clayton     StringList &matches
640c9af18a5SGreg Clayton ) :
6416611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
642c9af18a5SGreg Clayton {
643649f8b9bSGreg Clayton     std::string regex_str;
644649f8b9bSGreg Clayton     if (completion_str && completion_str[0])
645649f8b9bSGreg Clayton     {
646649f8b9bSGreg Clayton         regex_str.append("^");
647c9af18a5SGreg Clayton         regex_str.append(completion_str);
648649f8b9bSGreg Clayton     }
649649f8b9bSGreg Clayton     else
650649f8b9bSGreg Clayton     {
651649f8b9bSGreg Clayton         // Match anything since the completion string is empty
652649f8b9bSGreg Clayton         regex_str.append(".");
653649f8b9bSGreg Clayton     }
654649f8b9bSGreg Clayton     std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
655649f8b9bSGreg Clayton     while (pos < regex_str.end())
656649f8b9bSGreg Clayton     {
657c9af18a5SGreg Clayton         pos = regex_str.insert(pos, '\\');
658649f8b9bSGreg Clayton         pos = find_if(pos + 2, regex_str.end(), regex_chars);
659c9af18a5SGreg Clayton     }
660c9af18a5SGreg Clayton     m_regex.Compile(regex_str.c_str());
661c9af18a5SGreg Clayton }
662c9af18a5SGreg Clayton 
663c9af18a5SGreg Clayton Searcher::Depth
664c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::GetDepth()
665c9af18a5SGreg Clayton {
666c9af18a5SGreg Clayton     return eDepthModule;
667c9af18a5SGreg Clayton }
668c9af18a5SGreg Clayton 
669c9af18a5SGreg Clayton Searcher::CallbackReturn
670c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::SearchCallback (
671c9af18a5SGreg Clayton     SearchFilter &filter,
672c9af18a5SGreg Clayton     SymbolContext &context,
673c9af18a5SGreg Clayton     Address *addr,
674c9af18a5SGreg Clayton     bool complete
675c9af18a5SGreg Clayton )
676c9af18a5SGreg Clayton {
677c9af18a5SGreg Clayton     if (context.module_sp)
678c9af18a5SGreg Clayton     {
679931180e6SGreg Clayton         SymbolContextList sc_list;
680931180e6SGreg Clayton         const bool include_symbols = true;
6819df05fbbSSean Callanan         const bool include_inlines = true;
682931180e6SGreg Clayton         const bool append = true;
6839df05fbbSSean Callanan         context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
684c9af18a5SGreg Clayton 
685c9af18a5SGreg Clayton         SymbolContext sc;
686c9af18a5SGreg Clayton         // Now add the functions & symbols to the list - only add if unique:
687931180e6SGreg Clayton         for (uint32_t i = 0; i < sc_list.GetSize(); i++)
688c9af18a5SGreg Clayton         {
689931180e6SGreg Clayton             if (sc_list.GetContextAtIndex(i, sc))
690c9af18a5SGreg Clayton             {
691530a413cSJim Ingham                 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
692530a413cSJim Ingham                 if (!func_name.IsEmpty())
693530a413cSJim Ingham                     m_match_set.insert (func_name);
694c9af18a5SGreg Clayton             }
695c9af18a5SGreg Clayton         }
696c9af18a5SGreg Clayton     }
697c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
698c9af18a5SGreg Clayton }
699c9af18a5SGreg Clayton 
700c9af18a5SGreg Clayton size_t
701c9af18a5SGreg Clayton CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
702c9af18a5SGreg Clayton {
703c9af18a5SGreg Clayton     filter->Search (*this);
704c9af18a5SGreg Clayton     collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
705c9af18a5SGreg Clayton     for (pos = m_match_set.begin(); pos != end; pos++)
706c9af18a5SGreg Clayton         m_matches.AppendString((*pos).GetCString());
707c9af18a5SGreg Clayton 
708c9af18a5SGreg Clayton     return m_matches.GetSize();
709c9af18a5SGreg Clayton }
710c9af18a5SGreg Clayton 
711c9af18a5SGreg Clayton //----------------------------------------------------------------------
712c9af18a5SGreg Clayton // ModuleCompleter
713c9af18a5SGreg Clayton //----------------------------------------------------------------------
7146611103cSGreg Clayton CommandCompletions::ModuleCompleter::ModuleCompleter
7156611103cSGreg Clayton (
7166611103cSGreg Clayton     CommandInterpreter &interpreter,
717c9af18a5SGreg Clayton     const char *completion_str,
718c9af18a5SGreg Clayton     int match_start_point,
719c9af18a5SGreg Clayton     int max_return_elements,
720c9af18a5SGreg Clayton     StringList &matches
721c9af18a5SGreg Clayton ) :
7226611103cSGreg Clayton     CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
723c9af18a5SGreg Clayton {
724274060b6SGreg Clayton     FileSpec partial_spec (m_completion_str.c_str(), false);
725c9af18a5SGreg Clayton     m_file_name = partial_spec.GetFilename().GetCString();
726c9af18a5SGreg Clayton     m_dir_name = partial_spec.GetDirectory().GetCString();
727c9af18a5SGreg Clayton }
728c9af18a5SGreg Clayton 
729c9af18a5SGreg Clayton Searcher::Depth
730c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::GetDepth()
731c9af18a5SGreg Clayton {
732c9af18a5SGreg Clayton     return eDepthModule;
733c9af18a5SGreg Clayton }
734c9af18a5SGreg Clayton 
735c9af18a5SGreg Clayton Searcher::CallbackReturn
736c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::SearchCallback (
737c9af18a5SGreg Clayton     SearchFilter &filter,
738c9af18a5SGreg Clayton     SymbolContext &context,
739c9af18a5SGreg Clayton     Address *addr,
740c9af18a5SGreg Clayton     bool complete
741c9af18a5SGreg Clayton )
742c9af18a5SGreg Clayton {
743747bcb03SGreg Clayton     if (context.module_sp)
744c9af18a5SGreg Clayton     {
745c9af18a5SGreg Clayton         const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
746c9af18a5SGreg Clayton         const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
747c9af18a5SGreg Clayton 
748c9af18a5SGreg Clayton         bool match = false;
749c9af18a5SGreg Clayton         if (m_file_name && cur_file_name
750c9af18a5SGreg Clayton             && strstr (cur_file_name, m_file_name) == cur_file_name)
751c9af18a5SGreg Clayton             match = true;
752c9af18a5SGreg Clayton 
753c9af18a5SGreg Clayton         if (match && m_dir_name && cur_dir_name
754c9af18a5SGreg Clayton             && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
755c9af18a5SGreg Clayton             match = false;
756c9af18a5SGreg Clayton 
757c9af18a5SGreg Clayton         if (match)
758c9af18a5SGreg Clayton         {
759c9af18a5SGreg Clayton             m_matches.AppendString (cur_file_name);
760c9af18a5SGreg Clayton         }
761c9af18a5SGreg Clayton     }
762c9af18a5SGreg Clayton     return Searcher::eCallbackReturnContinue;
763c9af18a5SGreg Clayton }
764c9af18a5SGreg Clayton 
765c9af18a5SGreg Clayton size_t
766c9af18a5SGreg Clayton CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
767c9af18a5SGreg Clayton {
768c9af18a5SGreg Clayton     filter->Search (*this);
769c9af18a5SGreg Clayton     return m_matches.GetSize();
770c9af18a5SGreg Clayton }
771