blob: dd0ecb4b82e986143a42269b406fe8c92110f2a9 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000011#include <sys/stat.h>
Greg Claytonfd184262011-02-05 02:27:52 +000012#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000013#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000014#endif
Jim Ingham558ce122010-06-30 05:02:46 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000018#include "llvm/ADT/SmallString.h"
19
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020// Project includes
Greg Clayton9b62fd22011-02-01 05:15:22 +000021#include "lldb/Core/FileSpecList.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000023#include "lldb/Core/PluginManager.h"
24#include "lldb/Host/FileSpec.h"
25#include "lldb/Host/FileSystem.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/CommandCompletions.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000029#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000030#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000031#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000032#include "lldb/Target/Target.h"
33#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034
Zachary Turner190fadc2016-03-22 17:58:09 +000035#include "llvm/ADT/SmallString.h"
36
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037using namespace lldb_private;
38
39CommandCompletions::CommonCompletionElement
40CommandCompletions::g_common_completions[] =
41{
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000042 {eCustomCompletion, nullptr},
Jim Ingham558ce122010-06-30 05:02:46 +000043 {eSourceFileCompletion, CommandCompletions::SourceFiles},
44 {eDiskFileCompletion, CommandCompletions::DiskFiles},
45 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
46 {eSymbolCompletion, CommandCompletions::Symbols},
47 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice3df9a8d2010-09-04 00:03:46 +000048 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Claytonab65b342011-04-13 22:47:15 +000049 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
50 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Greg Claytonf21fead2013-05-14 23:43:18 +000051 {eVariablePathCompletion, CommandCompletions::VariablePath},
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000052 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053};
54
55bool
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000056CommandCompletions::InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter,
57 uint32_t completion_mask,
58 const char *completion_str,
59 int match_start_point,
60 int max_return_elements,
61 SearchFilter *searcher,
62 bool &word_complete,
63 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064{
65 bool handled = false;
66
67 if (completion_mask & eCustomCompletion)
68 return false;
69
70 for (int i = 0; ; i++)
71 {
72 if (g_common_completions[i].type == eNoCompletion)
73 break;
74 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000075 && g_common_completions[i].callback != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000076 {
77 handled = true;
Greg Clayton66111032010-06-23 01:19:29 +000078 g_common_completions[i].callback (interpreter,
79 completion_str,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080 match_start_point,
81 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082 searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000083 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084 matches);
85 }
86 }
87 return handled;
88}
89
90int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000091CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
92 const char *partial_file_name,
93 int match_start_point,
94 int max_return_elements,
95 SearchFilter *searcher,
96 bool &word_complete,
97 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098{
Jim Ingham558ce122010-06-30 05:02:46 +000099 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100 // Find some way to switch "include support files..."
Greg Clayton66111032010-06-23 01:19:29 +0000101 SourceFileCompleter completer (interpreter,
102 false,
103 partial_file_name,
104 match_start_point,
105 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 matches);
107
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000108 if (searcher == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 {
Jim Ingham2976d002010-08-26 21:32:51 +0000110 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000111 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000112 completer.DoCompletion (&null_searcher);
113 }
114 else
115 {
116 completer.DoCompletion (searcher);
117 }
118 return matches.GetSize();
119}
120
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000121typedef struct DiskFilesOrDirectoriesBaton
122{
123 const char *remainder;
124 char *partial_name_copy;
125 bool only_directories;
126 bool *saw_directory;
127 StringList *matches;
128 char *end_ptr;
129 size_t baselen;
Michael Sartain0b5e5f42013-08-26 17:07:34 +0000130} DiskFilesOrDirectoriesBaton;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000131
132FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
133{
134 const char *name = spec.GetFilename().AsCString();
135
136 const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
137 char *end_ptr = parameters->end_ptr;
138 char *partial_name_copy = parameters->partial_name_copy;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000139 const char *remainder = parameters->remainder;
140
141 // Omit ".", ".." and any . files if the match string doesn't start with .
142 if (name[0] == '.')
143 {
144 if (name[1] == '\0')
145 return FileSpec::eEnumerateDirectoryResultNext;
146 else if (name[1] == '.' && name[2] == '\0')
147 return FileSpec::eEnumerateDirectoryResultNext;
148 else if (remainder[0] != '.')
149 return FileSpec::eEnumerateDirectoryResultNext;
150 }
151
152 // If we found a directory, we put a "/" at the end of the name.
153
154 if (remainder[0] == '\0' || strstr(name, remainder) == name)
155 {
156 if (strlen(name) + parameters->baselen >= PATH_MAX)
157 return FileSpec::eEnumerateDirectoryResultNext;
158
159 strcpy(end_ptr, name);
160
161 bool isa_directory = false;
162 if (file_type == FileSpec::eFileTypeDirectory)
163 isa_directory = true;
164 else if (file_type == FileSpec::eFileTypeSymbolicLink)
165 {
Zachary Turner190fadc2016-03-22 17:58:09 +0000166 if (FileSpec(partial_name_copy, false).IsDirectory())
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000167 isa_directory = true;
168 }
169
170 if (isa_directory)
171 {
172 *parameters->saw_directory = true;
173 size_t len = strlen(parameters->partial_name_copy);
174 partial_name_copy[len] = '/';
175 partial_name_copy[len + 1] = '\0';
176 }
177 if (parameters->only_directories && !isa_directory)
178 return FileSpec::eEnumerateDirectoryResultNext;
179 parameters->matches->AppendString(partial_name_copy);
180 }
181
182 return FileSpec::eEnumerateDirectoryResultNext;
183}
184
Jim Ingham558ce122010-06-30 05:02:46 +0000185static int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000186DiskFilesOrDirectories(const char *partial_file_name,
187 bool only_directories,
188 bool &saw_directory,
189 StringList &matches)
Jim Ingham558ce122010-06-30 05:02:46 +0000190{
191 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
192 // If it is not defined on your host system, you'll need to implement it yourself...
193
Greg Claytonc7bece562013-01-25 18:06:21 +0000194 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000195
196 if (partial_name_len >= PATH_MAX)
197 return matches.GetSize();
198
199 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
200 // below will point to the place of the remainder in this string. Then when we've resolved the
201 // containing directory, and opened it, we'll read the directory contents and overwrite the
202 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
203 // the form the user originally typed.
204
205 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000206 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000207 partial_name_copy[partial_name_len] = '\0';
208
Greg Clayton710dd5a2011-01-08 20:28:42 +0000209 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000210 char remainder[PATH_MAX];
211
212 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
213 char *end_ptr;
214
215 end_ptr = strrchr(partial_name_copy, '/');
216
217 // This will store the resolved form of the containing directory
Zachary Turner3f559742014-08-07 17:33:36 +0000218 llvm::SmallString<64> containing_part;
Jim Ingham558ce122010-06-30 05:02:46 +0000219
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000220 if (end_ptr == nullptr)
Jim Ingham558ce122010-06-30 05:02:46 +0000221 {
222 // There's no directory. If the thing begins with a "~" then this is a bare
223 // user name.
224 if (*partial_name_copy == '~')
225 {
226 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000227 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000228 // on the end if it exists.
Zachary Turner3f559742014-08-07 17:33:36 +0000229 llvm::SmallString<64> resolved_username(partial_name_copy);
230 FileSpec::ResolveUsername (resolved_username);
Jim Ingham7cc478b2010-07-02 00:45:55 +0000231
232 // Not sure how this would happen, a username longer than PATH_MAX? Still...
Zachary Turner3f559742014-08-07 17:33:36 +0000233 if (resolved_username.size() == 0)
Jim Ingham7cc478b2010-07-02 00:45:55 +0000234 {
235 // The user name didn't resolve, let's look in the password database for matches.
236 // The user name database contains duplicates, and is not in alphabetical order, so
237 // we'll use a set to manage that for us.
Jim Ingham84363072011-02-08 23:24:09 +0000238 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
239 if (matches.GetSize() > 0)
240 saw_directory = true;
Jim Ingham7cc478b2010-07-02 00:45:55 +0000241 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000242 }
243 else
244 {
245 //The thing exists, put a '/' on the end, and return it...
246 // FIXME: complete user names here:
247 partial_name_copy[partial_name_len] = '/';
248 partial_name_copy[partial_name_len+1] = '\0';
249 matches.AppendString(partial_name_copy);
250 saw_directory = true;
251 return matches.GetSize();
252 }
Jim Ingham558ce122010-06-30 05:02:46 +0000253 }
254 else
255 {
256 // The containing part is the CWD, and the whole string is the remainder.
Zachary Turner3f559742014-08-07 17:33:36 +0000257 containing_part = ".";
Jim Ingham558ce122010-06-30 05:02:46 +0000258 strcpy(remainder, partial_name_copy);
259 end_ptr = partial_name_copy;
260 }
261 }
262 else
263 {
264 if (end_ptr == partial_name_copy)
265 {
266 // We're completing a file or directory in the root volume.
Zachary Turner3f559742014-08-07 17:33:36 +0000267 containing_part = "/";
Jim Ingham558ce122010-06-30 05:02:46 +0000268 }
269 else
270 {
Zachary Turner3f559742014-08-07 17:33:36 +0000271 containing_part.append(partial_name_copy, end_ptr);
Jim Ingham558ce122010-06-30 05:02:46 +0000272 }
273 // Push end_ptr past the final "/" and set remainder.
274 end_ptr++;
275 strcpy(remainder, end_ptr);
276 }
277
Jim Ingham7cc478b2010-07-02 00:45:55 +0000278 // Look for a user name in the containing part, and if it's there, resolve it and stick the
Jim Ingham558ce122010-06-30 05:02:46 +0000279 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000280
Jim Ingham558ce122010-06-30 05:02:46 +0000281 if (*partial_name_copy == '~')
282 {
Zachary Turner3f559742014-08-07 17:33:36 +0000283 FileSpec::ResolveUsername(containing_part);
Jim Ingham558ce122010-06-30 05:02:46 +0000284 // User name doesn't exist, we're not getting any further...
Zachary Turner3f559742014-08-07 17:33:36 +0000285 if (containing_part.empty())
Jim Ingham558ce122010-06-30 05:02:46 +0000286 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000287 }
Greg Claytonfd184262011-02-05 02:27:52 +0000288
Jim Ingham558ce122010-06-30 05:02:46 +0000289 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000290
Jim Ingham558ce122010-06-30 05:02:46 +0000291 size_t baselen = end_ptr - partial_name_copy;
292
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000293 DiskFilesOrDirectoriesBaton parameters;
294 parameters.remainder = remainder;
295 parameters.partial_name_copy = partial_name_copy;
296 parameters.only_directories = only_directories;
297 parameters.saw_directory = &saw_directory;
298 parameters.matches = &matches;
299 parameters.end_ptr = end_ptr;
300 parameters.baselen = baselen;
301
Zachary Turner3f559742014-08-07 17:33:36 +0000302 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
Jim Ingham558ce122010-06-30 05:02:46 +0000303
304 return matches.GetSize();
305}
306
307int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000308CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
309 const char *partial_file_name,
310 int match_start_point,
311 int max_return_elements,
312 SearchFilter *searcher,
313 bool &word_complete,
314 StringList &matches)
Jim Ingham558ce122010-06-30 05:02:46 +0000315{
Jim Ingham558ce122010-06-30 05:02:46 +0000316 int ret_val = DiskFilesOrDirectories (partial_file_name,
317 false,
318 word_complete,
319 matches);
320 word_complete = !word_complete;
321 return ret_val;
322}
323
324int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000325CommandCompletions::DiskDirectories(CommandInterpreter &interpreter,
326 const char *partial_file_name,
327 int match_start_point,
328 int max_return_elements,
329 SearchFilter *searcher,
330 bool &word_complete,
331 StringList &matches)
Jim Ingham558ce122010-06-30 05:02:46 +0000332{
333 int ret_val = DiskFilesOrDirectories (partial_file_name,
334 true,
335 word_complete,
336 matches);
337 word_complete = false;
338 return ret_val;
339}
340
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000341int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000342CommandCompletions::Modules(CommandInterpreter &interpreter,
343 const char *partial_file_name,
344 int match_start_point,
345 int max_return_elements,
346 SearchFilter *searcher,
347 bool &word_complete,
348 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000349{
Jim Ingham558ce122010-06-30 05:02:46 +0000350 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000351 ModuleCompleter completer (interpreter,
352 partial_file_name,
353 match_start_point,
354 max_return_elements,
355 matches);
356
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000357 if (searcher == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000358 {
Jim Ingham2976d002010-08-26 21:32:51 +0000359 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000360 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 completer.DoCompletion (&null_searcher);
362 }
363 else
364 {
365 completer.DoCompletion (searcher);
366 }
367 return matches.GetSize();
368}
369
370int
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000371CommandCompletions::Symbols(CommandInterpreter &interpreter,
372 const char *partial_file_name,
373 int match_start_point,
374 int max_return_elements,
375 SearchFilter *searcher,
376 bool &word_complete,
377 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378{
Jim Ingham558ce122010-06-30 05:02:46 +0000379 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000380 SymbolCompleter completer (interpreter,
381 partial_file_name,
382 match_start_point,
383 max_return_elements,
384 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000386 if (searcher == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387 {
Jim Ingham2976d002010-08-26 21:32:51 +0000388 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Jim Ingham33df7cd2014-12-06 01:28:03 +0000389 SearchFilterForUnconstrainedSearches null_searcher (target_sp);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 completer.DoCompletion (&null_searcher);
391 }
392 else
393 {
394 completer.DoCompletion (searcher);
395 }
396 return matches.GetSize();
397}
398
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000399int
400CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
401 const char *partial_setting_name,
402 int match_start_point,
403 int max_return_elements,
404 SearchFilter *searcher,
405 bool &word_complete,
406 StringList &matches)
407{
Greg Clayton67cc0632012-08-22 17:17:09 +0000408 // Cache the full setting name list
409 static StringList g_property_names;
410 if (g_property_names.GetSize() == 0)
411 {
412 // Generate the full setting name list on demand
413 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
414 if (properties_sp)
415 {
416 StreamString strm;
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000417 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
Greg Clayton67cc0632012-08-22 17:17:09 +0000418 const std::string &str = strm.GetString();
419 g_property_names.SplitIntoLines(str.c_str(), str.size());
420 }
421 }
422
423 size_t exact_matches_idx = SIZE_MAX;
424 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000425 word_complete = exact_matches_idx != SIZE_MAX;
426 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000427}
428
Greg Claytonab65b342011-04-13 22:47:15 +0000429int
430CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
431 const char *partial_name,
432 int match_start_point,
433 int max_return_elements,
434 SearchFilter *searcher,
435 bool &word_complete,
436 lldb_private::StringList &matches)
437{
438 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
439 word_complete = num_matches == 1;
440 return num_matches;
441}
442
443int
444CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
445 const char *partial_name,
446 int match_start_point,
447 int max_return_elements,
448 SearchFilter *searcher,
449 bool &word_complete,
450 lldb_private::StringList &matches)
451{
452 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
453 word_complete = num_matches == 1;
454 return num_matches;
455}
456
Greg Claytonf21fead2013-05-14 23:43:18 +0000457int
458CommandCompletions::VariablePath (CommandInterpreter &interpreter,
459 const char *partial_name,
460 int match_start_point,
461 int max_return_elements,
462 SearchFilter *searcher,
463 bool &word_complete,
464 lldb_private::StringList &matches)
465{
466 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
467}
468
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000469CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
470 const char *completion_str,
471 int match_start_point,
472 int max_return_elements,
473 StringList &matches) :
Greg Clayton66111032010-06-23 01:19:29 +0000474 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000475 m_completion_str (completion_str),
476 m_match_start_point (match_start_point),
477 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000478 m_matches (matches)
479{
480}
481
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000482CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483
484//----------------------------------------------------------------------
485// SourceFileCompleter
486//----------------------------------------------------------------------
487
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000488CommandCompletions::SourceFileCompleter::SourceFileCompleter(CommandInterpreter &interpreter,
489 bool include_support_files,
490 const char *completion_str,
491 int match_start_point,
492 int max_return_elements,
493 StringList &matches) :
Greg Clayton66111032010-06-23 01:19:29 +0000494 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000495 m_include_support_files (include_support_files),
496 m_matching_files()
497{
Greg Clayton274060b2010-10-20 20:54:39 +0000498 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000499 m_file_name = partial_spec.GetFilename().GetCString();
500 m_dir_name = partial_spec.GetDirectory().GetCString();
501}
502
503Searcher::Depth
504CommandCompletions::SourceFileCompleter::GetDepth()
505{
506 return eDepthCompUnit;
507}
508
509Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000510CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
511 SymbolContext &context,
512 Address *addr,
513 bool complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000514{
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000515 if (context.comp_unit != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000516 {
517 if (m_include_support_files)
518 {
519 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
520 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
521 {
522 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
523 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
524 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
525 bool match = false;
526 if (m_file_name && sfile_file_name
527 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
528 match = true;
529 if (match && m_dir_name && sfile_dir_name
530 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
531 match = false;
532
533 if (match)
534 {
535 m_matching_files.AppendIfUnique(sfile_spec);
536 }
537 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538 }
539 else
540 {
541 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
542 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
543
544 bool match = false;
545 if (m_file_name && cur_file_name
546 && strstr (cur_file_name, m_file_name) == cur_file_name)
547 match = true;
548
549 if (match && m_dir_name && cur_dir_name
550 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
551 match = false;
552
553 if (match)
554 {
555 m_matching_files.AppendIfUnique(context.comp_unit);
556 }
557 }
558 }
559 return Searcher::eCallbackReturnContinue;
560}
561
562size_t
563CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
564{
565 filter->Search (*this);
566 // Now convert the filelist to completions:
567 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
568 {
569 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
570 }
571 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000572}
573
574//----------------------------------------------------------------------
575// SymbolCompleter
576//----------------------------------------------------------------------
577
578static bool
579regex_chars (const char comp)
580{
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000581 return (comp == '[' || comp == ']' ||
582 comp == '(' || comp == ')' ||
583 comp == '{' || comp == '}' ||
584 comp == '+' ||
585 comp == '.' ||
586 comp == '*' ||
587 comp == '|' ||
588 comp == '^' ||
589 comp == '$' ||
590 comp == '\\' ||
591 comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000592}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000593
594CommandCompletions::SymbolCompleter::SymbolCompleter(CommandInterpreter &interpreter,
595 const char *completion_str,
596 int match_start_point,
597 int max_return_elements,
598 StringList &matches) :
Greg Clayton66111032010-06-23 01:19:29 +0000599 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000600{
Greg Clayton649f8b92013-06-07 00:35:40 +0000601 std::string regex_str;
602 if (completion_str && completion_str[0])
603 {
604 regex_str.append("^");
605 regex_str.append(completion_str);
606 }
607 else
608 {
609 // Match anything since the completion string is empty
610 regex_str.append(".");
611 }
612 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
613 while (pos < regex_str.end())
614 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000615 pos = regex_str.insert(pos, '\\');
Greg Clayton649f8b92013-06-07 00:35:40 +0000616 pos = find_if(pos + 2, regex_str.end(), regex_chars);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000617 }
618 m_regex.Compile(regex_str.c_str());
619}
620
621Searcher::Depth
622CommandCompletions::SymbolCompleter::GetDepth()
623{
624 return eDepthModule;
625}
626
627Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000628CommandCompletions::SymbolCompleter::SearchCallback(SearchFilter &filter,
629 SymbolContext &context,
630 Address *addr,
631 bool complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632{
Greg Clayton931180e2011-01-27 06:44:37 +0000633 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 {
Greg Clayton931180e2011-01-27 06:44:37 +0000635 SymbolContextList sc_list;
636 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000637 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000638 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000639 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640
641 SymbolContext sc;
642 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000643 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000644 {
Greg Clayton931180e2011-01-27 06:44:37 +0000645 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 {
Jim Ingham530a4132011-09-27 19:48:20 +0000647 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
648 if (!func_name.IsEmpty())
649 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000650 }
651 }
652 }
653 return Searcher::eCallbackReturnContinue;
654}
655
656size_t
657CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
658{
659 filter->Search (*this);
660 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
661 for (pos = m_match_set.begin(); pos != end; pos++)
662 m_matches.AppendString((*pos).GetCString());
663
664 return m_matches.GetSize();
665}
666
667//----------------------------------------------------------------------
668// ModuleCompleter
669//----------------------------------------------------------------------
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000670CommandCompletions::ModuleCompleter::ModuleCompleter(CommandInterpreter &interpreter,
671 const char *completion_str,
672 int match_start_point,
673 int max_return_elements,
674 StringList &matches) :
Greg Clayton66111032010-06-23 01:19:29 +0000675 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000676{
Greg Clayton274060b2010-10-20 20:54:39 +0000677 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000678 m_file_name = partial_spec.GetFilename().GetCString();
679 m_dir_name = partial_spec.GetDirectory().GetCString();
680}
681
682Searcher::Depth
683CommandCompletions::ModuleCompleter::GetDepth()
684{
685 return eDepthModule;
686}
687
688Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000689CommandCompletions::ModuleCompleter::SearchCallback(SearchFilter &filter,
690 SymbolContext &context,
691 Address *addr,
692 bool complete)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693{
Greg Clayton747bcb02011-09-17 06:21:20 +0000694 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000695 {
696 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
697 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
698
699 bool match = false;
700 if (m_file_name && cur_file_name
701 && strstr (cur_file_name, m_file_name) == cur_file_name)
702 match = true;
703
704 if (match && m_dir_name && cur_dir_name
705 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
706 match = false;
707
708 if (match)
709 {
710 m_matches.AppendString (cur_file_name);
711 }
712 }
713 return Searcher::eCallbackReturnContinue;
714}
715
716size_t
717CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
718{
719 filter->Search (*this);
720 return m_matches.GetSize();
721}