blob: fcfc29b4e88fa3b0bd167cb220aa3a64b35c4f7f [file] [log] [blame]
Chris Lattner24943d22010-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
10
11// C Includes
Jim Ingham802f8b02010-06-30 05:02:46 +000012#include <sys/stat.h>
13#include <dirent.h>
Greg Clayton8da92a72011-02-05 02:27:52 +000014#if defined(__APPLE__) || defined(__linux__)
Jim Ingham84a0d332010-07-02 00:45:55 +000015#include <pwd.h>
Greg Clayton8da92a72011-02-05 02:27:52 +000016#endif
Jim Ingham802f8b02010-06-30 05:02:46 +000017
Chris Lattner24943d22010-06-08 16:52:24 +000018// C++ Includes
19// Other libraries and framework includes
20// Project includes
Greg Clayton5f54ac32011-02-08 05:05:52 +000021#include "lldb/Host/FileSpec.h"
Greg Clayton74800612011-02-01 05:15:22 +000022#include "lldb/Core/FileSpecList.h"
23#include "lldb/Interpreter/Args.h"
24#include "lldb/Interpreter/CommandCompletions.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
26#include "lldb/Target/Target.h"
27#include "lldb/Utility/CleanUp.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028
29using namespace lldb_private;
30
31CommandCompletions::CommonCompletionElement
32CommandCompletions::g_common_completions[] =
33{
Jim Ingham802f8b02010-06-30 05:02:46 +000034 {eCustomCompletion, NULL},
35 {eSourceFileCompletion, CommandCompletions::SourceFiles},
36 {eDiskFileCompletion, CommandCompletions::DiskFiles},
37 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
38 {eSymbolCompletion, CommandCompletions::Symbols},
39 {eModuleCompletion, CommandCompletions::Modules},
Caroline Tice6e4c5ce2010-09-04 00:03:46 +000040 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
Jim Ingham802f8b02010-06-30 05:02:46 +000041 {eNoCompletion, NULL} // This one has to be last in the list.
Chris Lattner24943d22010-06-08 16:52:24 +000042};
43
44bool
Greg Clayton63094e02010-06-23 01:19:29 +000045CommandCompletions::InvokeCommonCompletionCallbacks
46(
47 CommandInterpreter &interpreter,
48 uint32_t completion_mask,
49 const char *completion_str,
50 int match_start_point,
51 int max_return_elements,
52 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000053 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000054 StringList &matches
55)
Chris Lattner24943d22010-06-08 16:52:24 +000056{
57 bool handled = false;
58
59 if (completion_mask & eCustomCompletion)
60 return false;
61
62 for (int i = 0; ; i++)
63 {
64 if (g_common_completions[i].type == eNoCompletion)
65 break;
66 else if ((g_common_completions[i].type & completion_mask) == g_common_completions[i].type
67 && g_common_completions[i].callback != NULL)
68 {
69 handled = true;
Greg Clayton63094e02010-06-23 01:19:29 +000070 g_common_completions[i].callback (interpreter,
71 completion_str,
Chris Lattner24943d22010-06-08 16:52:24 +000072 match_start_point,
73 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +000074 searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000075 word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +000076 matches);
77 }
78 }
79 return handled;
80}
81
82int
Greg Clayton63094e02010-06-23 01:19:29 +000083CommandCompletions::SourceFiles
84(
85 CommandInterpreter &interpreter,
86 const char *partial_file_name,
87 int match_start_point,
88 int max_return_elements,
89 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +000090 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +000091 StringList &matches
92)
Chris Lattner24943d22010-06-08 16:52:24 +000093{
Jim Ingham802f8b02010-06-30 05:02:46 +000094 word_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +000095 // Find some way to switch "include support files..."
Greg Clayton63094e02010-06-23 01:19:29 +000096 SourceFileCompleter completer (interpreter,
97 false,
98 partial_file_name,
99 match_start_point,
100 max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000101 matches);
102
103 if (searcher == NULL)
104 {
Jim Inghamc8332952010-08-26 21:32:51 +0000105 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000106 SearchFilter null_searcher (target_sp);
107 completer.DoCompletion (&null_searcher);
108 }
109 else
110 {
111 completer.DoCompletion (searcher);
112 }
113 return matches.GetSize();
114}
115
Jim Ingham802f8b02010-06-30 05:02:46 +0000116static int
117DiskFilesOrDirectories
118(
119 const char *partial_file_name,
120 bool only_directories,
121 bool &saw_directory,
122 StringList &matches
123)
124{
125 // I'm going to use the "glob" function with GLOB_TILDE for user directory expansion.
126 // If it is not defined on your host system, you'll need to implement it yourself...
127
128 int partial_name_len = strlen(partial_file_name);
129
130 if (partial_name_len >= PATH_MAX)
131 return matches.GetSize();
132
133 // This copy of the string will be cut up into the directory part, and the remainder. end_ptr
134 // below will point to the place of the remainder in this string. Then when we've resolved the
135 // containing directory, and opened it, we'll read the directory contents and overwrite the
136 // partial_name_copy starting from end_ptr with each of the matches. Thus we will preserve
137 // the form the user originally typed.
138
139 char partial_name_copy[PATH_MAX];
Benjamin Kramerbdbb9af2010-06-30 13:43:47 +0000140 memcpy(partial_name_copy, partial_file_name, partial_name_len);
Jim Ingham802f8b02010-06-30 05:02:46 +0000141 partial_name_copy[partial_name_len] = '\0';
142
Greg Clayton5d187e52011-01-08 20:28:42 +0000143 // We'll need to save a copy of the remainder for comparison, which we do here.
Jim Ingham802f8b02010-06-30 05:02:46 +0000144 char remainder[PATH_MAX];
145
146 // end_ptr will point past the last / in partial_name_copy, or if there is no slash to the beginning of the string.
147 char *end_ptr;
148
149 end_ptr = strrchr(partial_name_copy, '/');
150
151 // This will store the resolved form of the containing directory
152 char containing_part[PATH_MAX];
153
154 if (end_ptr == NULL)
155 {
156 // There's no directory. If the thing begins with a "~" then this is a bare
157 // user name.
158 if (*partial_name_copy == '~')
159 {
160 // Nothing here but the user name. We could just put a slash on the end,
Jim Ingham84a0d332010-07-02 00:45:55 +0000161 // but for completeness sake we'll resolve the user name and only put a slash
Jim Ingham802f8b02010-06-30 05:02:46 +0000162 // on the end if it exists.
Jim Ingham84a0d332010-07-02 00:45:55 +0000163 char resolved_username[PATH_MAX];
Greg Clayton54e7afa2010-07-09 20:39:50 +0000164 size_t resolved_username_len = FileSpec::ResolveUsername (partial_name_copy, resolved_username,
Jim Ingham84a0d332010-07-02 00:45:55 +0000165 sizeof (resolved_username));
166
167 // Not sure how this would happen, a username longer than PATH_MAX? Still...
168 if (resolved_username_len >= sizeof (resolved_username))
169 return matches.GetSize();
Jim Ingham158842c2011-02-08 23:24:09 +0000170 else if (resolved_username_len == 0)
Jim Ingham84a0d332010-07-02 00:45:55 +0000171 {
172 // The user name didn't resolve, let's look in the password database for matches.
173 // The user name database contains duplicates, and is not in alphabetical order, so
174 // we'll use a set to manage that for us.
Jim Ingham158842c2011-02-08 23:24:09 +0000175 FileSpec::ResolvePartialUsername (partial_name_copy, matches);
176 if (matches.GetSize() > 0)
177 saw_directory = true;
Jim Ingham84a0d332010-07-02 00:45:55 +0000178 return matches.GetSize();
Jim Ingham158842c2011-02-08 23:24:09 +0000179 }
180 else
181 {
182 //The thing exists, put a '/' on the end, and return it...
183 // FIXME: complete user names here:
184 partial_name_copy[partial_name_len] = '/';
185 partial_name_copy[partial_name_len+1] = '\0';
186 matches.AppendString(partial_name_copy);
187 saw_directory = true;
188 return matches.GetSize();
189 }
Jim Ingham802f8b02010-06-30 05:02:46 +0000190 }
191 else
192 {
193 // The containing part is the CWD, and the whole string is the remainder.
194 containing_part[0] = '.';
195 containing_part[1] = '\0';
196 strcpy(remainder, partial_name_copy);
197 end_ptr = partial_name_copy;
198 }
199 }
200 else
201 {
202 if (end_ptr == partial_name_copy)
203 {
204 // We're completing a file or directory in the root volume.
205 containing_part[0] = '/';
206 containing_part[1] = '\0';
207 }
208 else
209 {
210 size_t len = end_ptr - partial_name_copy;
211 memcpy(containing_part, partial_name_copy, len);
212 containing_part[len] = '\0';
213 }
214 // Push end_ptr past the final "/" and set remainder.
215 end_ptr++;
216 strcpy(remainder, end_ptr);
217 }
218
Jim Ingham84a0d332010-07-02 00:45:55 +0000219 // Look for a user name in the containing part, and if it's there, resolve it and stick the
Jim Ingham802f8b02010-06-30 05:02:46 +0000220 // result back into the containing_part:
Greg Clayton8da92a72011-02-05 02:27:52 +0000221
Jim Ingham802f8b02010-06-30 05:02:46 +0000222 if (*partial_name_copy == '~')
223 {
Jim Ingham158842c2011-02-08 23:24:09 +0000224 size_t resolved_username_len = FileSpec::ResolveUsername(containing_part,
225 containing_part,
226 sizeof (containing_part));
Jim Ingham802f8b02010-06-30 05:02:46 +0000227 // User name doesn't exist, we're not getting any further...
Greg Clayton099c7972010-07-06 16:11:44 +0000228 if (resolved_username_len == 0 || resolved_username_len >= sizeof (containing_part))
Jim Ingham802f8b02010-06-30 05:02:46 +0000229 return matches.GetSize();
Jim Ingham802f8b02010-06-30 05:02:46 +0000230 }
Greg Clayton8da92a72011-02-05 02:27:52 +0000231
Jim Ingham802f8b02010-06-30 05:02:46 +0000232 // Okay, containing_part is now the directory we want to open and look for files:
Greg Clayton74800612011-02-01 05:15:22 +0000233
234 lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir);
235 if (!dir_stream.is_valid())
Jim Ingham802f8b02010-06-30 05:02:46 +0000236 return matches.GetSize();
Greg Clayton74800612011-02-01 05:15:22 +0000237
Jim Ingham802f8b02010-06-30 05:02:46 +0000238 struct dirent *dirent_buf;
239
240 size_t baselen = end_ptr - partial_name_copy;
241
Greg Clayton74800612011-02-01 05:15:22 +0000242 while ((dirent_buf = readdir(dir_stream.get())) != NULL)
Jim Ingham802f8b02010-06-30 05:02:46 +0000243 {
244 char *name = dirent_buf->d_name;
245
246 // Omit ".", ".." and any . files if the match string doesn't start with .
247 if (name[0] == '.')
248 {
249 if (name[1] == '\0')
250 continue;
251 else if (name[1] == '.' && name[2] == '\0')
252 continue;
253 else if (remainder[0] != '.')
254 continue;
255 }
256
Jim Ingham84a0d332010-07-02 00:45:55 +0000257 // If we found a directory, we put a "/" at the end of the name.
258
Jim Ingham802f8b02010-06-30 05:02:46 +0000259 if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name)
260 {
261 if (strlen(name) + baselen >= PATH_MAX)
262 continue;
263
264 strcpy(end_ptr, name);
265
266 bool isa_directory = false;
267 if (dirent_buf->d_type & DT_DIR)
268 isa_directory = true;
269 else if (dirent_buf->d_type & DT_LNK)
270 {
271 struct stat stat_buf;
272 if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR))
273 isa_directory = true;
274 }
275
276 if (isa_directory)
277 {
278 saw_directory = true;
279 size_t len = strlen(partial_name_copy);
280 partial_name_copy[len] = '/';
281 partial_name_copy[len + 1] = '\0';
282 }
283 if (only_directories && !isa_directory)
284 continue;
285 matches.AppendString(partial_name_copy);
286 }
287 }
288
289 return matches.GetSize();
290}
291
292int
293CommandCompletions::DiskFiles
294(
295 CommandInterpreter &interpreter,
296 const char *partial_file_name,
297 int match_start_point,
298 int max_return_elements,
299 SearchFilter *searcher,
300 bool &word_complete,
301 StringList &matches
302)
303{
304
305 int ret_val = DiskFilesOrDirectories (partial_file_name,
306 false,
307 word_complete,
308 matches);
309 word_complete = !word_complete;
310 return ret_val;
311}
312
313int
314CommandCompletions::DiskDirectories
315(
316 CommandInterpreter &interpreter,
317 const char *partial_file_name,
318 int match_start_point,
319 int max_return_elements,
320 SearchFilter *searcher,
321 bool &word_complete,
322 StringList &matches
323)
324{
325 int ret_val = DiskFilesOrDirectories (partial_file_name,
326 true,
327 word_complete,
328 matches);
329 word_complete = false;
330 return ret_val;
331}
332
Chris Lattner24943d22010-06-08 16:52:24 +0000333int
Greg Clayton63094e02010-06-23 01:19:29 +0000334CommandCompletions::Modules
335(
336 CommandInterpreter &interpreter,
337 const char *partial_file_name,
338 int match_start_point,
339 int max_return_elements,
340 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000341 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000342 StringList &matches
343)
Chris Lattner24943d22010-06-08 16:52:24 +0000344{
Jim Ingham802f8b02010-06-30 05:02:46 +0000345 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000346 ModuleCompleter completer (interpreter,
347 partial_file_name,
348 match_start_point,
349 max_return_elements,
350 matches);
351
Chris Lattner24943d22010-06-08 16:52:24 +0000352 if (searcher == NULL)
353 {
Jim Inghamc8332952010-08-26 21:32:51 +0000354 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000355 SearchFilter null_searcher (target_sp);
356 completer.DoCompletion (&null_searcher);
357 }
358 else
359 {
360 completer.DoCompletion (searcher);
361 }
362 return matches.GetSize();
363}
364
365int
Greg Clayton63094e02010-06-23 01:19:29 +0000366CommandCompletions::Symbols
367(
368 CommandInterpreter &interpreter,
369 const char *partial_file_name,
370 int match_start_point,
371 int max_return_elements,
372 SearchFilter *searcher,
Jim Ingham802f8b02010-06-30 05:02:46 +0000373 bool &word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000374 StringList &matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000375{
Jim Ingham802f8b02010-06-30 05:02:46 +0000376 word_complete = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000377 SymbolCompleter completer (interpreter,
378 partial_file_name,
379 match_start_point,
380 max_return_elements,
381 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000382
383 if (searcher == NULL)
384 {
Jim Inghamc8332952010-08-26 21:32:51 +0000385 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000386 SearchFilter null_searcher (target_sp);
387 completer.DoCompletion (&null_searcher);
388 }
389 else
390 {
391 completer.DoCompletion (searcher);
392 }
393 return matches.GetSize();
394}
395
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000396int
397CommandCompletions::SettingsNames (CommandInterpreter &interpreter,
398 const char *partial_setting_name,
399 int match_start_point,
400 int max_return_elements,
401 SearchFilter *searcher,
402 bool &word_complete,
403 StringList &matches)
404{
405 lldb::UserSettingsControllerSP root_settings = Debugger::GetSettingsController();
406 Args partial_setting_name_pieces = UserSettingsController::BreakNameIntoPieces (partial_setting_name);
407
408 return UserSettingsController::CompleteSettingsNames (root_settings,
409 partial_setting_name_pieces,
410 word_complete,
411 matches);
412
413 //return matches.GetSize();
414}
415
Greg Clayton63094e02010-06-23 01:19:29 +0000416CommandCompletions::Completer::Completer
417(
418 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000419 const char *completion_str,
420 int match_start_point,
421 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000422 StringList &matches
423) :
Greg Clayton63094e02010-06-23 01:19:29 +0000424 m_interpreter (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +0000425 m_completion_str (completion_str),
426 m_match_start_point (match_start_point),
427 m_max_return_elements (max_return_elements),
Chris Lattner24943d22010-06-08 16:52:24 +0000428 m_matches (matches)
429{
430}
431
432CommandCompletions::Completer::~Completer ()
433{
434
435}
436
437//----------------------------------------------------------------------
438// SourceFileCompleter
439//----------------------------------------------------------------------
440
Greg Clayton63094e02010-06-23 01:19:29 +0000441CommandCompletions::SourceFileCompleter::SourceFileCompleter
442(
443 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000444 bool include_support_files,
445 const char *completion_str,
446 int match_start_point,
447 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000448 StringList &matches
449) :
Greg Clayton63094e02010-06-23 01:19:29 +0000450 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches),
Chris Lattner24943d22010-06-08 16:52:24 +0000451 m_include_support_files (include_support_files),
452 m_matching_files()
453{
Greg Clayton537a7a82010-10-20 20:54:39 +0000454 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000455 m_file_name = partial_spec.GetFilename().GetCString();
456 m_dir_name = partial_spec.GetDirectory().GetCString();
457}
458
459Searcher::Depth
460CommandCompletions::SourceFileCompleter::GetDepth()
461{
462 return eDepthCompUnit;
463}
464
465Searcher::CallbackReturn
466CommandCompletions::SourceFileCompleter::SearchCallback (
467 SearchFilter &filter,
468 SymbolContext &context,
469 Address *addr,
470 bool complete
471)
472{
473 if (context.comp_unit != NULL)
474 {
475 if (m_include_support_files)
476 {
477 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
478 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++)
479 {
480 const FileSpec &sfile_spec = supporting_files.GetFileSpecAtIndex(sfiles);
481 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
482 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
483 bool match = false;
484 if (m_file_name && sfile_file_name
485 && strstr (sfile_file_name, m_file_name) == sfile_file_name)
486 match = true;
487 if (match && m_dir_name && sfile_dir_name
488 && strstr (sfile_dir_name, m_dir_name) != sfile_dir_name)
489 match = false;
490
491 if (match)
492 {
493 m_matching_files.AppendIfUnique(sfile_spec);
494 }
495 }
496
497 }
498 else
499 {
500 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
501 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
502
503 bool match = false;
504 if (m_file_name && cur_file_name
505 && strstr (cur_file_name, m_file_name) == cur_file_name)
506 match = true;
507
508 if (match && m_dir_name && cur_dir_name
509 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
510 match = false;
511
512 if (match)
513 {
514 m_matching_files.AppendIfUnique(context.comp_unit);
515 }
516 }
517 }
518 return Searcher::eCallbackReturnContinue;
519}
520
521size_t
522CommandCompletions::SourceFileCompleter::DoCompletion (SearchFilter *filter)
523{
524 filter->Search (*this);
525 // Now convert the filelist to completions:
526 for (size_t i = 0; i < m_matching_files.GetSize(); i++)
527 {
528 m_matches.AppendString (m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
529 }
530 return m_matches.GetSize();
531
532}
533
534//----------------------------------------------------------------------
535// SymbolCompleter
536//----------------------------------------------------------------------
537
538static bool
539regex_chars (const char comp)
540{
541 if (comp == '[' || comp == ']' || comp == '(' || comp == ')')
542 return true;
543 else
544 return false;
545}
Greg Clayton63094e02010-06-23 01:19:29 +0000546CommandCompletions::SymbolCompleter::SymbolCompleter
547(
548 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000549 const char *completion_str,
550 int match_start_point,
551 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000552 StringList &matches
553) :
Greg Clayton63094e02010-06-23 01:19:29 +0000554 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000555{
556 std::string regex_str ("^");
557 regex_str.append(completion_str);
558 regex_str.append(".*");
559 std::string::iterator pos;
560
561 pos = find_if(regex_str.begin(), regex_str.end(), regex_chars);
562 while (pos < regex_str.end()) {
563 pos = regex_str.insert(pos, '\\');
564 pos += 2;
565 pos = find_if(pos, regex_str.end(), regex_chars);
566 }
567 m_regex.Compile(regex_str.c_str());
568}
569
570Searcher::Depth
571CommandCompletions::SymbolCompleter::GetDepth()
572{
573 return eDepthModule;
574}
575
576Searcher::CallbackReturn
577CommandCompletions::SymbolCompleter::SearchCallback (
578 SearchFilter &filter,
579 SymbolContext &context,
580 Address *addr,
581 bool complete
582)
583{
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000584 if (context.module_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000585 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000586 SymbolContextList sc_list;
587 const bool include_symbols = true;
588 const bool append = true;
589 context.module_sp->FindFunctions (m_regex, include_symbols, append, sc_list);
Chris Lattner24943d22010-06-08 16:52:24 +0000590
591 SymbolContext sc;
592 // Now add the functions & symbols to the list - only add if unique:
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000593 for (uint32_t i = 0; i < sc_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000594 {
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000595 if (sc_list.GetContextAtIndex(i, sc))
Chris Lattner24943d22010-06-08 16:52:24 +0000596 {
597 if (sc.function)
598 {
599 m_match_set.insert (sc.function->GetMangled().GetDemangledName());
600 }
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000601 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
Chris Lattner24943d22010-06-08 16:52:24 +0000602 {
603 m_match_set.insert (sc.symbol->GetMangled().GetDemangledName());
604 }
605 }
606 }
607 }
608 return Searcher::eCallbackReturnContinue;
609}
610
611size_t
612CommandCompletions::SymbolCompleter::DoCompletion (SearchFilter *filter)
613{
614 filter->Search (*this);
615 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
616 for (pos = m_match_set.begin(); pos != end; pos++)
617 m_matches.AppendString((*pos).GetCString());
618
619 return m_matches.GetSize();
620}
621
622//----------------------------------------------------------------------
623// ModuleCompleter
624//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000625CommandCompletions::ModuleCompleter::ModuleCompleter
626(
627 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000628 const char *completion_str,
629 int match_start_point,
630 int max_return_elements,
Chris Lattner24943d22010-06-08 16:52:24 +0000631 StringList &matches
632) :
Greg Clayton63094e02010-06-23 01:19:29 +0000633 CommandCompletions::Completer (interpreter, completion_str, match_start_point, max_return_elements, matches)
Chris Lattner24943d22010-06-08 16:52:24 +0000634{
Greg Clayton537a7a82010-10-20 20:54:39 +0000635 FileSpec partial_spec (m_completion_str.c_str(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000636 m_file_name = partial_spec.GetFilename().GetCString();
637 m_dir_name = partial_spec.GetDirectory().GetCString();
638}
639
640Searcher::Depth
641CommandCompletions::ModuleCompleter::GetDepth()
642{
643 return eDepthModule;
644}
645
646Searcher::CallbackReturn
647CommandCompletions::ModuleCompleter::SearchCallback (
648 SearchFilter &filter,
649 SymbolContext &context,
650 Address *addr,
651 bool complete
652)
653{
654 if (context.module_sp != NULL)
655 {
656 const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString();
657 const char *cur_dir_name = context.module_sp->GetFileSpec().GetDirectory().GetCString();
658
659 bool match = false;
660 if (m_file_name && cur_file_name
661 && strstr (cur_file_name, m_file_name) == cur_file_name)
662 match = true;
663
664 if (match && m_dir_name && cur_dir_name
665 && strstr (cur_dir_name, m_dir_name) != cur_dir_name)
666 match = false;
667
668 if (match)
669 {
670 m_matches.AppendString (cur_file_name);
671 }
672 }
673 return Searcher::eCallbackReturnContinue;
674}
675
676size_t
677CommandCompletions::ModuleCompleter::DoCompletion (SearchFilter *filter)
678{
679 filter->Search (*this);
680 return m_matches.GetSize();
681}