blob: f0ad4a8967396db5e15509e495bb8cabd0985df3 [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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011
12// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000013#include <sys/stat.h>
Greg Claytonfd184262011-02-05 02:27:52 +000014#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000015#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000016#endif
Jim Ingham558ce122010-06-30 05:02:46 +000017
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// C++ Includes
19// Other libraries and framework includes
20// Project includes
Greg Clayton53239f02011-02-08 05:05:52 +000021#include "lldb/Host/FileSpec.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000022#include "lldb/Core/FileSpecList.h"
Greg Claytonab65b342011-04-13 22:47:15 +000023#include "lldb/Core/PluginManager.h"
Greg Clayton1f746072012-08-29 21:13:06 +000024#include "lldb/Core/Module.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000025#include "lldb/Interpreter/Args.h"
26#include "lldb/Interpreter/CommandCompletions.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
Greg Clayton1f746072012-08-29 21:13:06 +000028#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000029#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000030#include "lldb/Target/Target.h"
31#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032
Zachary Turner3f559742014-08-07 17:33:36 +000033#include "llvm/ADT/SmallString.h"
34
Chris Lattner30fdc8d2010-06-08 16:52:24 +000035using namespace lldb_private;
36
37CommandCompletions::CommonCompletionElement
38CommandCompletions::g_common_completions[] =
39{
Jim Ingham558ce122010-06-30 05:02:46 +000040 {eCustomCompletion, NULL},
41 {eSourceFileCompletion, CommandCompletions::SourceFiles},
42 {eDiskFileCompletion, CommandCompletions::DiskFiles},
43 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
44 {eSymbolCompletion, CommandCompletions::Symbols},
45 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice3df9a8d2010-09-04 00:03:46 +000046 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Greg Claytonab65b342011-04-13 22:47:15 +000047 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
48 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
Greg Claytonf21fead2013-05-14 23:43:18 +000049 {eVariablePathCompletion, CommandCompletions::VariablePath},
Jim Ingham558ce122010-06-30 05:02:46 +000050 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051};
52
53bool
Greg Clayton66111032010-06-23 01:19:29 +000054CommandCompletions::InvokeCommonCompletionCallbacks
55(
56 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,
Jim Ingham558ce122010-06-30 05:02:46 +000062 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +000063 StringList &matches
64)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065{
66 bool handled = false;
67
68 if (completion_mask & eCustomCompletion)
69 return false;
70
71 for (int i = 0; ; i++)
72 {
73 if (g_common_completions[i].type == eNoCompletion)
74 break;
75 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
76 && g_common_completions[i].callback != NULL)
77 {
78 handled = true;
Greg Clayton66111032010-06-23 01:19:29 +000079 g_common_completions[i].callback (interpreter,
80 completion_str,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081 match_start_point,
82 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083 searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000084 word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085 matches);
86 }
87 }
88 return handled;
89}
90
91int
Greg Clayton66111032010-06-23 01:19:29 +000092CommandCompletions::SourceFiles
93(
94 CommandInterpreter &interpreter,
95 const char *partial_file_name,
96 int match_start_point,
97 int max_return_elements,
98 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +000099 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000100 StringList &matches
101)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102{
Jim Ingham558ce122010-06-30 05:02:46 +0000103 word_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 // Find some way to switch "include support files..."
Greg Clayton66111032010-06-23 01:19:29 +0000105 SourceFileCompleter completer (interpreter,
106 false,
107 partial_file_name,
108 match_start_point,
109 max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110 matches);
111
112 if (searcher == NULL)
113 {
Jim Ingham2976d002010-08-26 21:32:51 +0000114 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 SearchFilter null_searcher (target_sp);
116 completer.DoCompletion (&null_searcher);
117 }
118 else
119 {
120 completer.DoCompletion (searcher);
121 }
122 return matches.GetSize();
123}
124
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000125typedef struct DiskFilesOrDirectoriesBaton
126{
127 const char *remainder;
128 char *partial_name_copy;
129 bool only_directories;
130 bool *saw_directory;
131 StringList *matches;
132 char *end_ptr;
133 size_t baselen;
Michael Sartain0b5e5f42013-08-26 17:07:34 +0000134} DiskFilesOrDirectoriesBaton;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000135
136FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec)
137{
138 const char *name = spec.GetFilename().AsCString();
139
140 const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton;
141 char *end_ptr = parameters->end_ptr;
142 char *partial_name_copy = parameters->partial_name_copy;
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000143 const char *remainder = parameters->remainder;
144
145 // Omit ".", ".." and any . files if the match string doesn't start with .
146 if (name[0] == '.')
147 {
148 if (name[1] == '\0')
149 return FileSpec::eEnumerateDirectoryResultNext;
150 else if (name[1] == '.' && name[2] == '\0')
151 return FileSpec::eEnumerateDirectoryResultNext;
152 else if (remainder[0] != '.')
153 return FileSpec::eEnumerateDirectoryResultNext;
154 }
155
156 // If we found a directory, we put a "/" at the end of the name.
157
158 if (remainder[0] == '\0' || strstr(name, remainder) == name)
159 {
160 if (strlen(name) + parameters->baselen >= PATH_MAX)
161 return FileSpec::eEnumerateDirectoryResultNext;
162
163 strcpy(end_ptr, name);
164
165 bool isa_directory = false;
166 if (file_type == FileSpec::eFileTypeDirectory)
167 isa_directory = true;
168 else if (file_type == FileSpec::eFileTypeSymbolicLink)
169 {
170 struct stat stat_buf;
171 if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
172 isa_directory = true;
173 }
174
175 if (isa_directory)
176 {
177 *parameters->saw_directory = true;
178 size_t len = strlen(parameters->partial_name_copy);
179 partial_name_copy[len] = '/';
180 partial_name_copy[len + 1] = '\0';
181 }
182 if (parameters->only_directories && !isa_directory)
183 return FileSpec::eEnumerateDirectoryResultNext;
184 parameters->matches->AppendString(partial_name_copy);
185 }
186
187 return FileSpec::eEnumerateDirectoryResultNext;
188}
189
Jim Ingham558ce122010-06-30 05:02:46 +0000190static int
191DiskFilesOrDirectories
192(
193 const char *partial_file_name,
194 bool only_directories,
195 bool &saw_directory,
196 StringList &matches
197)
198{
199 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
200 // If it is not defined on your host system, you'll need to implement it yourself...
201
Greg Claytonc7bece562013-01-25 18:06:21 +0000202 size_t partial_name_len = strlen(partial_file_name);
Jim Ingham558ce122010-06-30 05:02:46 +0000203
204 if (partial_name_len >= PATH_MAX)
205 return matches.GetSize();
206
207 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
208 // below will point to the place of the remainder in this string. Then when we've resolved the
209 // containing directory, and opened it, we'll read the directory contents and overwrite the
210 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
211 // the form the user originally typed.
212
213 char partial_name_copy[PATH_MAX];
Benjamin Kramer021b6052010-06-30 13:43:47 +0000214 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham558ce122010-06-30 05:02:46 +0000215 partial_name_copy[partial_name_len] = '\0';
216
Greg Clayton710dd5a2011-01-08 20:28:42 +0000217 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham558ce122010-06-30 05:02:46 +0000218 char remainder[PATH_MAX];
219
220 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
221 char *end_ptr;
222
223 end_ptr = strrchr(partial_name_copy, '/');
224
225 // This will store the resolved form of the containing directory
Zachary Turner3f559742014-08-07 17:33:36 +0000226 llvm::SmallString<64> containing_part;
Jim Ingham558ce122010-06-30 05:02:46 +0000227
228 if (end_ptr == NULL)
229 {
230 // There's no directory. If the thing begins with a "~" then this is a bare
231 // user name.
232 if (*partial_name_copy == '~')
233 {
234 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham7cc478b2010-07-02 00:45:55 +0000235 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham558ce122010-06-30 05:02:46 +0000236 // on the end if it exists.
Zachary Turner3f559742014-08-07 17:33:36 +0000237 llvm::SmallString<64> resolved_username(partial_name_copy);
238 FileSpec::ResolveUsername (resolved_username);
Jim Ingham7cc478b2010-07-02 00:45:55 +0000239
240 // Not sure how this would happen, a username longer than PATH_MAX? Still...
Zachary Turner3f559742014-08-07 17:33:36 +0000241 if (resolved_username.size() == 0)
Jim Ingham7cc478b2010-07-02 00:45:55 +0000242 {
243 // The user name didn't resolve, let's look in the password database for matches.
244 // The user name database contains duplicates, and is not in alphabetical order, so
245 // we'll use a set to manage that for us.
Jim Ingham84363072011-02-08 23:24:09 +0000246 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
247 if (matches.GetSize() > 0)
248 saw_directory = true;
Jim Ingham7cc478b2010-07-02 00:45:55 +0000249 return matches.GetSize();
Jim Ingham84363072011-02-08 23:24:09 +0000250 }
251 else
252 {
253 //The thing exists, put a '/' on the end, and return it...
254 // FIXME: complete user names here:
255 partial_name_copy[partial_name_len] = '/';
256 partial_name_copy[partial_name_len+1] = '\0';
257 matches.AppendString(partial_name_copy);
258 saw_directory = true;
259 return matches.GetSize();
260 }
Jim Ingham558ce122010-06-30 05:02:46 +0000261 }
262 else
263 {
264 // The containing part is the CWD, and the whole string is the remainder.
Zachary Turner3f559742014-08-07 17:33:36 +0000265 containing_part = ".";
Jim Ingham558ce122010-06-30 05:02:46 +0000266 strcpy(remainder, partial_name_copy);
267 end_ptr = partial_name_copy;
268 }
269 }
270 else
271 {
272 if (end_ptr == partial_name_copy)
273 {
274 // We're completing a file or directory in the root volume.
Zachary Turner3f559742014-08-07 17:33:36 +0000275 containing_part = "/";
Jim Ingham558ce122010-06-30 05:02:46 +0000276 }
277 else
278 {
Zachary Turner3f559742014-08-07 17:33:36 +0000279 containing_part.append(partial_name_copy, end_ptr);
Jim Ingham558ce122010-06-30 05:02:46 +0000280 }
281 // Push end_ptr past the final "/" and set remainder.
282 end_ptr++;
283 strcpy(remainder, end_ptr);
284 }
285
Jim Ingham7cc478b2010-07-02 00:45:55 +0000286 // 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 +0000287 // result back into the containing_part:
Greg Claytonfd184262011-02-05 02:27:52 +0000288
Jim Ingham558ce122010-06-30 05:02:46 +0000289 if (*partial_name_copy == '~')
290 {
Zachary Turner3f559742014-08-07 17:33:36 +0000291 FileSpec::ResolveUsername(containing_part);
Jim Ingham558ce122010-06-30 05:02:46 +0000292 // User name doesn't exist, we're not getting any further...
Zachary Turner3f559742014-08-07 17:33:36 +0000293 if (containing_part.empty())
Jim Ingham558ce122010-06-30 05:02:46 +0000294 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000295 }
Greg Claytonfd184262011-02-05 02:27:52 +0000296
Jim Ingham558ce122010-06-30 05:02:46 +0000297 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton9b62fd22011-02-01 05:15:22 +0000298
Jim Ingham558ce122010-06-30 05:02:46 +0000299 size_t baselen = end_ptr - partial_name_copy;
300
Virgile Bellob2f1fb22013-08-23 12:44:05 +0000301 DiskFilesOrDirectoriesBaton parameters;
302 parameters.remainder = remainder;
303 parameters.partial_name_copy = partial_name_copy;
304 parameters.only_directories = only_directories;
305 parameters.saw_directory = &saw_directory;
306 parameters.matches = &matches;
307 parameters.end_ptr = end_ptr;
308 parameters.baselen = baselen;
309
Zachary Turner3f559742014-08-07 17:33:36 +0000310 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true, DiskFilesOrDirectoriesCallback, &parameters);
Jim Ingham558ce122010-06-30 05:02:46 +0000311
312 return matches.GetSize();
313}
314
315int
316CommandCompletions::DiskFiles
317(
318 CommandInterpreter &interpreter,
319 const char *partial_file_name,
320 int match_start_point,
321 int max_return_elements,
322 SearchFilter *searcher,
323 bool &word_complete,
324 StringList &matches
325)
326{
327
328 int ret_val = DiskFilesOrDirectories (partial_file_name,
329 false,
330 word_complete,
331 matches);
332 word_complete = !word_complete;
333 return ret_val;
334}
335
336int
337CommandCompletions::DiskDirectories
338(
339 CommandInterpreter &interpreter,
340 const char *partial_file_name,
341 int match_start_point,
342 int max_return_elements,
343 SearchFilter *searcher,
344 bool &word_complete,
345 StringList &matches
346)
347{
348 int ret_val = DiskFilesOrDirectories (partial_file_name,
349 true,
350 word_complete,
351 matches);
352 word_complete = false;
353 return ret_val;
354}
355
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356int
Greg Clayton66111032010-06-23 01:19:29 +0000357CommandCompletions::Modules
358(
359 CommandInterpreter &interpreter,
360 const char *partial_file_name,
361 int match_start_point,
362 int max_return_elements,
363 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000364 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000365 StringList &matches
366)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367{
Jim Ingham558ce122010-06-30 05:02:46 +0000368 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000369 ModuleCompleter completer (interpreter,
370 partial_file_name,
371 match_start_point,
372 max_return_elements,
373 matches);
374
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 if (searcher == NULL)
376 {
Jim Ingham2976d002010-08-26 21:32:51 +0000377 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 SearchFilter null_searcher (target_sp);
379 completer.DoCompletion (&null_searcher);
380 }
381 else
382 {
383 completer.DoCompletion (searcher);
384 }
385 return matches.GetSize();
386}
387
388int
Greg Clayton66111032010-06-23 01:19:29 +0000389CommandCompletions::Symbols
390(
391 CommandInterpreter &interpreter,
392 const char *partial_file_name,
393 int match_start_point,
394 int max_return_elements,
395 SearchFilter *searcher,
Jim Ingham558ce122010-06-30 05:02:46 +0000396 bool &word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000397 StringList &matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398{
Jim Ingham558ce122010-06-30 05:02:46 +0000399 word_complete = true;
Greg Clayton66111032010-06-23 01:19:29 +0000400 SymbolCompleter completer (interpreter,
401 partial_file_name,
402 match_start_point,
403 max_return_elements,
404 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405
406 if (searcher == NULL)
407 {
Jim Ingham2976d002010-08-26 21:32:51 +0000408 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 SearchFilter null_searcher (target_sp);
410 completer.DoCompletion (&null_searcher);
411 }
412 else
413 {
414 completer.DoCompletion (searcher);
415 }
416 return matches.GetSize();
417}
418
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000419int
420CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
421 const char *partial_setting_name,
422 int match_start_point,
423 int max_return_elements,
424 SearchFilter *searcher,
425 bool &word_complete,
426 StringList &matches)
427{
Greg Clayton67cc0632012-08-22 17:17:09 +0000428 // Cache the full setting name list
429 static StringList g_property_names;
430 if (g_property_names.GetSize() == 0)
431 {
432 // Generate the full setting name list on demand
433 lldb::OptionValuePropertiesSP properties_sp (interpreter.GetDebugger().GetValueProperties());
434 if (properties_sp)
435 {
436 StreamString strm;
437 properties_sp->DumpValue(NULL, strm, OptionValue::eDumpOptionName);
438 const std::string &str = strm.GetString();
439 g_property_names.SplitIntoLines(str.c_str(), str.size());
440 }
441 }
442
443 size_t exact_matches_idx = SIZE_MAX;
444 const size_t num_matches = g_property_names.AutoComplete (partial_setting_name, matches, exact_matches_idx);
Greg Clayton67cc0632012-08-22 17:17:09 +0000445 word_complete = exact_matches_idx != SIZE_MAX;
446 return num_matches;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000447}
448
Greg Claytonab65b342011-04-13 22:47:15 +0000449
450int
451CommandCompletions::PlatformPluginNames (CommandInterpreter &interpreter,
452 const char *partial_name,
453 int match_start_point,
454 int max_return_elements,
455 SearchFilter *searcher,
456 bool &word_complete,
457 lldb_private::StringList &matches)
458{
459 const uint32_t num_matches = PluginManager::AutoCompletePlatformName(partial_name, matches);
460 word_complete = num_matches == 1;
461 return num_matches;
462}
463
464int
465CommandCompletions::ArchitectureNames (CommandInterpreter &interpreter,
466 const char *partial_name,
467 int match_start_point,
468 int max_return_elements,
469 SearchFilter *searcher,
470 bool &word_complete,
471 lldb_private::StringList &matches)
472{
473 const uint32_t num_matches = ArchSpec::AutoComplete (partial_name, matches);
474 word_complete = num_matches == 1;
475 return num_matches;
476}
477
478
Greg Claytonf21fead2013-05-14 23:43:18 +0000479int
480CommandCompletions::VariablePath (CommandInterpreter &interpreter,
481 const char *partial_name,
482 int match_start_point,
483 int max_return_elements,
484 SearchFilter *searcher,
485 bool &word_complete,
486 lldb_private::StringList &matches)
487{
488 return Variable::AutoComplete (interpreter.GetExecutionContext(), partial_name, matches, word_complete);
489}
490
491
Greg Clayton66111032010-06-23 01:19:29 +0000492CommandCompletions::Completer::Completer
493(
494 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000495 const char *completion_str,
496 int match_start_point,
497 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000498 StringList &matches
499) :
Greg Clayton66111032010-06-23 01:19:29 +0000500 m_interpreter (interpreter),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000501 m_completion_str (completion_str),
502 m_match_start_point (match_start_point),
503 m_max_return_elements (max_return_elements),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000504 m_matches (matches)
505{
506}
507
508CommandCompletions::Completer::~Completer ()
509{
510
511}
512
513//----------------------------------------------------------------------
514// SourceFileCompleter
515//----------------------------------------------------------------------
516
Greg Clayton66111032010-06-23 01:19:29 +0000517CommandCompletions::SourceFileCompleter::SourceFileCompleter
518(
519 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000520 bool include_support_files,
521 const char *completion_str,
522 int match_start_point,
523 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524 StringList &matches
525) :
Greg Clayton66111032010-06-23 01:19:29 +0000526 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000527 m_include_support_files (include_support_files),
528 m_matching_files()
529{
Greg Clayton274060b2010-10-20 20:54:39 +0000530 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000531 m_file_name = partial_spec.GetFilename().GetCString();
532 m_dir_name = partial_spec.GetDirectory().GetCString();
533}
534
535Searcher::Depth
536CommandCompletions::SourceFileCompleter::GetDepth()
537{
538 return eDepthCompUnit;
539}
540
541Searcher::CallbackReturn
542CommandCompletions::SourceFileCompleter::SearchCallback (
543 SearchFilter &filter,
544 SymbolContext &context,
545 Address *addr,
546 bool complete
547)
548{
549 if (context.comp_unit != NULL)
550 {
551 if (m_include_support_files)
552 {
553 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
554 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
555 {
556 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
557 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
558 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
559 bool match = false;
560 if (m_file_name && sfile_file_name
561 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
562 match = true;
563 if (match && m_dir_name && sfile_dir_name
564 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
565 match = false;
566
567 if (match)
568 {
569 m_matching_files.AppendIfUnique(sfile_spec);
570 }
571 }
572
573 }
574 else
575 {
576 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
577 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
578
579 bool match = false;
580 if (m_file_name && cur_file_name
581 && strstr (cur_file_name, m_file_name) == cur_file_name)
582 match = true;
583
584 if (match && m_dir_name && cur_dir_name
585 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
586 match = false;
587
588 if (match)
589 {
590 m_matching_files.AppendIfUnique(context.comp_unit);
591 }
592 }
593 }
594 return Searcher::eCallbackReturnContinue;
595}
596
597size_t
598CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
599{
600 filter->Search (*this);
601 // Now convert the filelist to completions:
602 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
603 {
604 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
605 }
606 return m_matches.GetSize();
607
608}
609
610//----------------------------------------------------------------------
611// SymbolCompleter
612//----------------------------------------------------------------------
613
614static bool
615regex_chars (const char comp)
616{
Greg Clayton649f8b92013-06-07 00:35:40 +0000617 if (comp == '[' || comp == ']' ||
618 comp == '(' || comp == ')' ||
619 comp == '{' || comp == '}' ||
620 comp == '+' ||
621 comp == '.' ||
622 comp == '*' ||
623 comp == '|' ||
624 comp == '^' ||
625 comp == '$' ||
626 comp == '\\' ||
627 comp == '?')
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628 return true;
629 else
630 return false;
631}
Greg Clayton66111032010-06-23 01:19:29 +0000632CommandCompletions::SymbolCompleter::SymbolCompleter
633(
634 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000635 const char *completion_str,
636 int match_start_point,
637 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000638 StringList &matches
639) :
Greg Clayton66111032010-06-23 01:19:29 +0000640 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641{
Greg Clayton649f8b92013-06-07 00:35:40 +0000642 std::string regex_str;
643 if (completion_str && completion_str[0])
644 {
645 regex_str.append("^");
646 regex_str.append(completion_str);
647 }
648 else
649 {
650 // Match anything since the completion string is empty
651 regex_str.append(".");
652 }
653 std::string::iterator pos = find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
654 while (pos < regex_str.end())
655 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000656 pos = regex_str.insert(pos, '\\');
Greg Clayton649f8b92013-06-07 00:35:40 +0000657 pos = find_if(pos + 2, regex_str.end(), regex_chars);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000658 }
659 m_regex.Compile(regex_str.c_str());
660}
661
662Searcher::Depth
663CommandCompletions::SymbolCompleter::GetDepth()
664{
665 return eDepthModule;
666}
667
668Searcher::CallbackReturn
669CommandCompletions::SymbolCompleter::SearchCallback (
670 SearchFilter &filter,
671 SymbolContext &context,
672 Address *addr,
673 bool complete
674)
675{
Greg Clayton931180e2011-01-27 06:44:37 +0000676 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000677 {
Greg Clayton931180e2011-01-27 06:44:37 +0000678 SymbolContextList sc_list;
679 const bool include_symbols = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000680 const bool include_inlines = true;
Greg Clayton931180e2011-01-27 06:44:37 +0000681 const bool append = true;
Sean Callanan9df05fb2012-02-10 22:52:19 +0000682 context.module_sp->FindFunctions (m_regex, include_symbols, include_inlines, append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000683
684 SymbolContext sc;
685 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton931180e2011-01-27 06:44:37 +0000686 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000687 {
Greg Clayton931180e2011-01-27 06:44:37 +0000688 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000689 {
Jim Ingham530a4132011-09-27 19:48:20 +0000690 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
691 if (!func_name.IsEmpty())
692 m_match_set.insert (func_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000693 }
694 }
695 }
696 return Searcher::eCallbackReturnContinue;
697}
698
699size_t
700CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
701{
702 filter->Search (*this);
703 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
704 for (pos = m_match_set.begin(); pos != end; pos++)
705 m_matches.AppendString((*pos).GetCString());
706
707 return m_matches.GetSize();
708}
709
710//----------------------------------------------------------------------
711// ModuleCompleter
712//----------------------------------------------------------------------
Greg Clayton66111032010-06-23 01:19:29 +0000713CommandCompletions::ModuleCompleter::ModuleCompleter
714(
715 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000716 const char *completion_str,
717 int match_start_point,
718 int max_return_elements,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000719 StringList &matches
720) :
Greg Clayton66111032010-06-23 01:19:29 +0000721 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000722{
Greg Clayton274060b2010-10-20 20:54:39 +0000723 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000724 m_file_name = partial_spec.GetFilename().GetCString();
725 m_dir_name = partial_spec.GetDirectory().GetCString();
726}
727
728Searcher::Depth
729CommandCompletions::ModuleCompleter::GetDepth()
730{
731 return eDepthModule;
732}
733
734Searcher::CallbackReturn
735CommandCompletions::ModuleCompleter::SearchCallback (
736 SearchFilter &filter,
737 SymbolContext &context,
738 Address *addr,
739 bool complete
740)
741{
Greg Clayton747bcb02011-09-17 06:21:20 +0000742 if (context.module_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000743 {
744 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
745 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
746
747 bool match = false;
748 if (m_file_name && cur_file_name
749 && strstr (cur_file_name, m_file_name) == cur_file_name)
750 match = true;
751
752 if (match && m_dir_name && cur_dir_name
753 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
754 match = false;
755
756 if (match)
757 {
758 m_matches.AppendString (cur_file_name);
759 }
760 }
761 return Searcher::eCallbackReturnContinue;
762}
763
764size_t
765CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
766{
767 filter->Search (*this);
768 return m_matches.GetSize();
769}