blob: 097bd45c3a880e0531e7d3e358bbd4a13ca51885 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- Options.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
Jim Ingham84cdc152010-06-15 19:49:27 +000010#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12// C Includes
13// C++ Includes
14#include <bitset>
15
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Interpreter/CommandObject.h"
19#include "lldb/Interpreter/CommandReturnObject.h"
20#include "lldb/Interpreter/CommandCompletions.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Target/Target.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//-------------------------------------------------------------------------
29// Options
30//-------------------------------------------------------------------------
31Options::Options () :
32 m_getopt_table ()
33{
Jim Ingham34e9a982010-06-15 18:47:14 +000034 BuildValidOptionSets();
Chris Lattner24943d22010-06-08 16:52:24 +000035}
36
37Options::~Options ()
38{
39}
40
41
42void
43Options::ResetOptionValues ()
44{
45 m_seen_options.clear();
46}
47
48void
49Options::OptionSeen (int option_idx)
50{
51 m_seen_options.insert ((char) option_idx);
52}
53
54// Returns true is set_a is a subset of set_b; Otherwise returns false.
55
56bool
57Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
58{
59 bool is_a_subset = true;
60 OptionSet::const_iterator pos_a;
61 OptionSet::const_iterator pos_b;
62
63 // set_a is a subset of set_b if every member of set_a is also a member of set_b
64
65 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
66 {
67 pos_b = set_b.find(*pos_a);
68 if (pos_b == set_b.end())
69 is_a_subset = false;
70 }
71
72 return is_a_subset;
73}
74
75// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
76
77size_t
78Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
79{
80 size_t num_diffs = 0;
81 OptionSet::const_iterator pos_a;
82 OptionSet::const_iterator pos_b;
83
84 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
85 {
86 pos_b = set_b.find(*pos_a);
87 if (pos_b == set_b.end())
88 {
89 ++num_diffs;
90 diffs.insert(*pos_a);
91 }
92 }
93
94 return num_diffs;
95}
96
97// Returns the union of set_a and set_b. Does not put duplicate members into the union.
98
99void
100Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
101{
102 OptionSet::const_iterator pos;
103 OptionSet::iterator pos_union;
104
105 // Put all the elements of set_a into the union.
106
107 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
108 union_set.insert(*pos);
109
110 // Put all the elements of set_b that are not already there into the union.
111 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
112 {
113 pos_union = union_set.find(*pos);
114 if (pos_union == union_set.end())
115 union_set.insert(*pos);
116 }
117}
118
119bool
120Options::VerifyOptions (CommandReturnObject &result)
121{
122 bool options_are_valid = false;
123
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000124 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000125 if (num_levels)
126 {
127 for (int i = 0; i < num_levels && !options_are_valid; ++i)
128 {
129 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
130 // (i.e. all the required options at this level are a subset of m_seen_options); AND
131 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
132 // m_seen_options are in the set of optional options at this level.
133
134 // Check to see if all of m_required_options[i] are a subset of m_seen_options
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000135 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner24943d22010-06-08 16:52:24 +0000136 {
137 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
138 OptionSet remaining_options;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000139 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000140 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000141 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner24943d22010-06-08 16:52:24 +0000142 options_are_valid = true;
143 }
144 }
145 }
146 else
147 {
148 options_are_valid = true;
149 }
150
151 if (options_are_valid)
152 {
153 result.SetStatus (eReturnStatusSuccessFinishNoResult);
154 }
155 else
156 {
157 result.AppendError ("invalid combination of options for the given command");
158 result.SetStatus (eReturnStatusFailed);
159 }
160
161 return options_are_valid;
162}
163
Jim Ingham34e9a982010-06-15 18:47:14 +0000164// This is called in the Options constructor, though we could call it lazily if that ends up being
165// a performance problem.
166
Chris Lattner24943d22010-06-08 16:52:24 +0000167void
168Options::BuildValidOptionSets ()
169{
170 // Check to see if we already did this.
171 if (m_required_options.size() != 0)
172 return;
173
174 // Check to see if there are any options.
175 int num_options = NumCommandOptions ();
176 if (num_options == 0)
177 return;
178
179 const lldb::OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000180 m_required_options.resize(1);
181 m_optional_options.resize(1);
Jim Ingham34e9a982010-06-15 18:47:14 +0000182
183 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
184
185 uint32_t num_option_sets = 0;
186
187 for (int i = 0; i < num_options; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000188 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000189 uint32_t this_usage_mask = full_options_table[i].usage_mask;
190 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000191 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000192 if (num_option_sets == 0)
193 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000194 }
195 else
196 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000197 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
198 {
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000199 if (this_usage_mask & (1 << j))
Jim Ingham34e9a982010-06-15 18:47:14 +0000200 {
201 if (num_option_sets <= j)
202 num_option_sets = j + 1;
203 }
204 }
Chris Lattner24943d22010-06-08 16:52:24 +0000205 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000206 }
Chris Lattner24943d22010-06-08 16:52:24 +0000207
Jim Ingham34e9a982010-06-15 18:47:14 +0000208 if (num_option_sets > 0)
209 {
210 m_required_options.resize(num_option_sets);
211 m_optional_options.resize(num_option_sets);
212
213 for (int i = 0; i < num_options; ++i)
214 {
215 for (int j = 0; j < num_option_sets; j++)
216 {
217 if (full_options_table[i].usage_mask & 1 << j)
218 {
219 if (full_options_table[i].required)
220 m_required_options[j].insert(full_options_table[i].short_option);
221 else
222 m_optional_options[j].insert(full_options_table[i].short_option);
223 }
224 }
225 }
Chris Lattner24943d22010-06-08 16:52:24 +0000226 }
227}
228
229uint32_t
230Options::NumCommandOptions ()
231{
232 const lldb::OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham34e9a982010-06-15 18:47:14 +0000233 if (full_options_table == NULL)
234 return 0;
235
Chris Lattner24943d22010-06-08 16:52:24 +0000236 int i = 0;
237
238 if (full_options_table != NULL)
239 {
240 while (full_options_table[i].long_option != NULL)
241 ++i;
242 }
243
244 return i;
245}
246
247struct option *
248Options::GetLongOptions ()
249{
250 // Check to see if this has already been done.
251 if (m_getopt_table.empty())
252 {
253 // Check to see if there are any options.
254 const uint32_t num_options = NumCommandOptions();
255 if (num_options == 0)
256 return NULL;
257
258 uint32_t i;
259 uint32_t j;
260 const lldb::OptionDefinition *full_options_table = GetDefinitions();
261
262 std::bitset<256> option_seen;
263
264 m_getopt_table.resize(num_options + 1);
265 for (i = 0, j = 0; i < num_options; ++i)
266 {
267 char short_opt = full_options_table[i].short_option;
268
269 if (option_seen.test(short_opt) == false)
270 {
271 m_getopt_table[j].name = full_options_table[i].long_option;
272 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
273 m_getopt_table[j].flag = NULL;
274 m_getopt_table[j].val = full_options_table[i].short_option;
275 option_seen.set(short_opt);
276 ++j;
277 }
278 }
279
280 //getopt_long requires a NULL final entry in the table:
281
282 m_getopt_table[j].name = NULL;
283 m_getopt_table[j].has_arg = 0;
284 m_getopt_table[j].flag = NULL;
285 m_getopt_table[j].val = 0;
286 }
287
Greg Clayton53d68e72010-07-20 22:52:08 +0000288 if (m_getopt_table.empty())
289 return NULL;
290
291 return &m_getopt_table.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000292}
293
294
295// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
296// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
297// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
298// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
299// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
300
301
302void
303Options::OutputFormattedUsageText
304(
305 Stream &strm,
306 const char *text,
307 uint32_t output_max_columns
308)
309{
310 int len = strlen (text);
311
312 // Will it all fit on one line?
313
314 if ((len + strm.GetIndentLevel()) < output_max_columns)
315 {
316 // Output it as a single line.
317 strm.Indent (text);
318 strm.EOL();
319 }
320 else
321 {
322 // We need to break it up into multiple lines.
323
324 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
325 int start = 0;
326 int end = start;
327 int final_end = strlen (text);
328 int sub_len;
329
330 while (end < final_end)
331 {
332 // Don't start the 'text' on a space, since we're already outputting the indentation.
333 while ((start < final_end) && (text[start] == ' '))
334 start++;
335
336 end = start + text_width;
337 if (end > final_end)
338 end = final_end;
339 else
340 {
341 // If we're not at the end of the text, make sure we break the line on white space.
342 while (end > start
343 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
344 end--;
345 }
346
347 sub_len = end - start;
348 if (start != 0)
349 strm.EOL();
350 strm.Indent();
351 assert (start < final_end);
352 assert (start + sub_len <= final_end);
353 strm.Write(text + start, sub_len);
354 start = end + 1;
355 }
356 strm.EOL();
357 }
358}
359
360void
361Options::GenerateOptionUsage
362(
363 Stream &strm,
364 CommandObject *cmd,
365 const char *program_name)
366{
367 uint32_t screen_width = 80;
368 const lldb::OptionDefinition *full_options_table = GetDefinitions();
369 const uint32_t save_indent_level = strm.GetIndentLevel();
370 const char *name;
371
372 if (cmd)
373 name = cmd->GetCommandName();
374 else
375 name = program_name;
376
377 strm.PutCString ("\nCommand Options Usage:\n");
378
379 strm.IndentMore(2);
380
381 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
382 // <cmd> [options-for-level-1]
383 // etc.
384
Chris Lattner24943d22010-06-08 16:52:24 +0000385 const uint32_t num_options = NumCommandOptions();
Jim Ingham34e9a982010-06-15 18:47:14 +0000386 if (num_options == 0)
387 return;
388
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000389 int num_option_sets = GetRequiredOptions().size();
Jim Ingham34e9a982010-06-15 18:47:14 +0000390
Chris Lattner24943d22010-06-08 16:52:24 +0000391 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000392
393 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner24943d22010-06-08 16:52:24 +0000394 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000395 uint32_t opt_set_mask;
396
397 opt_set_mask = 1 << opt_set;
398 if (opt_set > 0)
399 strm.Printf ("\n");
400 strm.Indent (name);
401
402 for (i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000403 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000404 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner24943d22010-06-08 16:52:24 +0000405 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000406 // Add current option to the end of out_stream.
Chris Lattner24943d22010-06-08 16:52:24 +0000407
Jim Ingham34e9a982010-06-15 18:47:14 +0000408 if (full_options_table[i].required)
409 {
410 if (full_options_table[i].option_has_arg == required_argument)
411 {
412 strm.Printf (" -%c %s",
413 full_options_table[i].short_option,
414 full_options_table[i].argument_name);
415 }
416 else if (full_options_table[i].option_has_arg == optional_argument)
417 {
418 strm.Printf (" -%c [%s]",
419 full_options_table[i].short_option,
420 full_options_table[i].argument_name);
421 }
422 else
423 strm.Printf (" -%c", full_options_table[i].short_option);
424 }
425 else
426 {
427 if (full_options_table[i].option_has_arg == required_argument)
428 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
429 full_options_table[i].argument_name);
430 else if (full_options_table[i].option_has_arg == optional_argument)
431 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
432 full_options_table[i].argument_name);
433 else
434 strm.Printf (" [-%c]", full_options_table[i].short_option);
435 }
Chris Lattner24943d22010-06-08 16:52:24 +0000436 }
Chris Lattner24943d22010-06-08 16:52:24 +0000437 }
438 }
Chris Lattner24943d22010-06-08 16:52:24 +0000439 strm.Printf ("\n\n");
440
441 // Now print out all the detailed information about the various options: long form, short form and help text:
442 // -- long_name <argument>
443 // - short <argument>
444 // help text
445
446 // This variable is used to keep track of which options' info we've printed out, because some options can be in
447 // more than one usage level, but we only want to print the long form of its information once.
448
449 OptionSet options_seen;
450 OptionSet::iterator pos;
451 strm.IndentMore (5);
452
453 int first_option_printed = 1;
454 for (i = 0; i < num_options; ++i)
455 {
456 // Only print out this option if we haven't already seen it.
457 pos = options_seen.find (full_options_table[i].short_option);
458 if (pos == options_seen.end())
459 {
460 // Put a newline separation between arguments
461 if (first_option_printed)
462 first_option_printed = 0;
463 else
464 strm.EOL();
465
466 options_seen.insert (full_options_table[i].short_option);
467 strm.Indent ();
468 strm.Printf ("-%c ", full_options_table[i].short_option);
469 if (full_options_table[i].argument_name != NULL)
470 strm.PutCString(full_options_table[i].argument_name);
471 strm.EOL();
472 strm.Indent ();
473 strm.Printf ("--%s ", full_options_table[i].long_option);
474 if (full_options_table[i].argument_name != NULL)
475 strm.PutCString(full_options_table[i].argument_name);
476 strm.EOL();
477
478 strm.IndentMore (5);
479
480 if (full_options_table[i].usage_text)
481 OutputFormattedUsageText (strm,
482 full_options_table[i].usage_text,
483 screen_width);
484 if (full_options_table[i].enum_values != NULL)
485 {
486 strm.Indent ();
487 strm.Printf("Values: ");
488 for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++)
489 {
490 if (j == 0)
491 strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
492 else
493 strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
494 }
495 strm.EOL();
496 }
497 strm.IndentLess (5);
498 }
499 }
500
501 // Restore the indent level
502 strm.SetIndentLevel (save_indent_level);
503}
504
505// This function is called when we have been given a potentially incomplete set of
506// options, such as when an alias has been defined (more options might be added at
507// at the time the alias is invoked). We need to verify that the options in the set
508// m_seen_options are all part of a set that may be used together, but m_seen_options
509// may be missing some of the "required" options.
510
511bool
512Options::VerifyPartialOptions (CommandReturnObject &result)
513{
514 bool options_are_valid = false;
515
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000516 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000517 if (num_levels)
518 {
519 for (int i = 0; i < num_levels && !options_are_valid; ++i)
520 {
521 // In this case we are treating all options as optional rather than required.
522 // Therefore a set of options is correct if m_seen_options is a subset of the
523 // union of m_required_options and m_optional_options.
524 OptionSet union_set;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000525 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner24943d22010-06-08 16:52:24 +0000526 if (IsASubset (m_seen_options, union_set))
527 options_are_valid = true;
528 }
529 }
530
531 return options_are_valid;
532}
533
534bool
535Options::HandleOptionCompletion
536(
Greg Clayton63094e02010-06-23 01:19:29 +0000537 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000538 Args &input,
539 OptionElementVector &opt_element_vector,
540 int cursor_index,
541 int char_pos,
542 int match_start_point,
543 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000544 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000545 lldb_private::StringList &matches
546)
547{
Jim Ingham802f8b02010-06-30 05:02:46 +0000548 word_complete = true;
549
Chris Lattner24943d22010-06-08 16:52:24 +0000550 // For now we just scan the completions to see if the cursor position is in
551 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
552 // In the future we can use completion to validate options as well if we want.
553
554 const OptionDefinition *opt_defs = GetDefinitions();
555
556 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
557 cur_opt_std_str.erase(char_pos);
558 const char *cur_opt_str = cur_opt_std_str.c_str();
559
560 for (int i = 0; i < opt_element_vector.size(); i++)
561 {
562 int opt_pos = opt_element_vector[i].opt_pos;
563 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
564 int opt_defs_index = opt_element_vector[i].opt_defs_index;
565 if (opt_pos == cursor_index)
566 {
567 // We're completing the option itself.
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000568
569 if (opt_defs_index == OptionArgElement::eBareDash)
570 {
571 // We're completing a bare dash. That means all options are open.
572 // FIXME: We should scan the other options provided and only complete options
573 // within the option group they belong to.
574 char opt_str[3] = {'-', 'a', '\0'};
575
Greg Claytonbef15832010-07-14 00:18:15 +0000576 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000577 {
Greg Claytonbef15832010-07-14 00:18:15 +0000578 opt_str[1] = opt_defs[j].short_option;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000579 matches.AppendString (opt_str);
580 }
581 return true;
582 }
583 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
584 {
585 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000586 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000587 {
588 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonbef15832010-07-14 00:18:15 +0000589 full_name.append (opt_defs[j].long_option);
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000590 matches.AppendString (full_name.c_str());
591 }
592 return true;
593 }
594 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner24943d22010-06-08 16:52:24 +0000595 {
596 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
597 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
598 // The string so the upper level code will know this is a full match and add the " ".
599 if (cur_opt_str && strlen (cur_opt_str) > 2
600 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
601 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
602 {
603 std::string full_name ("--");
604 full_name.append (opt_defs[opt_defs_index].long_option);
605 matches.AppendString(full_name.c_str());
606 return true;
607 }
608 else
609 {
610 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
611 return true;
612 }
613 }
614 else
615 {
616 // FIXME - not handling wrong options yet:
617 // Check to see if they are writing a long option & complete it.
618 // I think we will only get in here if the long option table has two elements
619 // that are not unique up to this point. getopt_long does shortest unique match
620 // for long options already.
621
622 if (cur_opt_str && strlen (cur_opt_str) > 2
623 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
624 {
Greg Claytonbef15832010-07-14 00:18:15 +0000625 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000626 {
Greg Claytonbef15832010-07-14 00:18:15 +0000627 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner24943d22010-06-08 16:52:24 +0000628 {
629 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000630 full_name.append (opt_defs[j].long_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000631 // The options definitions table has duplicates because of the
632 // way the grouping information is stored, so only add once.
633 bool duplicate = false;
Greg Claytonbef15832010-07-14 00:18:15 +0000634 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner24943d22010-06-08 16:52:24 +0000635 {
Greg Claytonbef15832010-07-14 00:18:15 +0000636 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner24943d22010-06-08 16:52:24 +0000637 {
638 duplicate = true;
639 break;
640 }
641 }
642 if (!duplicate)
643 matches.AppendString(full_name.c_str());
644 }
645 }
646 }
647 return true;
648 }
649
650
651 }
652 else if (opt_arg_pos == cursor_index)
653 {
654 // Okay the cursor is on the completion of an argument.
655 // See if it has a completion, otherwise return no matches.
656
657 if (opt_defs_index != -1)
658 {
Greg Clayton63094e02010-06-23 01:19:29 +0000659 HandleOptionArgumentCompletion (interpreter,
660 input,
661 cursor_index,
662 strlen (input.GetArgumentAtIndex(cursor_index)),
663 opt_element_vector,
664 i,
665 match_start_point,
666 max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000667 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000668 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000669 return true;
670 }
671 else
672 {
673 // No completion callback means no completions...
674 return true;
675 }
676
677 }
678 else
679 {
680 // Not the last element, keep going.
681 continue;
682 }
683 }
684 return false;
685}
686
687bool
688Options::HandleOptionArgumentCompletion
689(
Greg Clayton63094e02010-06-23 01:19:29 +0000690 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000691 Args &input,
692 int cursor_index,
693 int char_pos,
694 OptionElementVector &opt_element_vector,
695 int opt_element_index,
696 int match_start_point,
697 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000698 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000699 lldb_private::StringList &matches
700)
701{
702 const OptionDefinition *opt_defs = GetDefinitions();
703 std::auto_ptr<SearchFilter> filter_ap;
704
705 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
706 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
707
708 // See if this is an enumeration type option, and if so complete it here:
709
710 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
711 if (enum_values != NULL)
712 {
713 bool return_value = false;
714 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
715 for (int i = 0; enum_values[i].string_value != NULL; i++)
716 {
717 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
718 {
719 matches.AppendString (enum_values[i].string_value);
720 return_value = true;
721 }
722 }
723 return return_value;
724 }
725
726 // If this is a source file or symbol type completion, and there is a
727 // -shlib option somewhere in the supplied arguments, then make a search filter
728 // for that shared library.
729 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
730
731 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
732 if (completion_mask & CommandCompletions::eSourceFileCompletion
733 || completion_mask & CommandCompletions::eSymbolCompletion)
734 {
735 for (int i = 0; i < opt_element_vector.size(); i++)
736 {
737 int cur_defs_index = opt_element_vector[i].opt_defs_index;
738 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
739 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
740
741 // If this is the "shlib" option and there was an argument provided,
742 // restrict it to that shared library.
743 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
744 {
745 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
746 if (module_name)
747 {
748 FileSpec module_spec(module_name);
Jim Inghamc8332952010-08-26 21:32:51 +0000749 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000750 // Search filters require a target...
751 if (target_sp != NULL)
752 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
753 }
754 break;
755 }
756 }
757 }
758
Greg Clayton63094e02010-06-23 01:19:29 +0000759 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
760 completion_mask,
761 input.GetArgumentAtIndex (opt_arg_pos),
762 match_start_point,
763 max_return_elements,
764 filter_ap.get(),
Jim Ingham802f8b02010-06-30 05:02:46 +0000765 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000766 matches);
767
Chris Lattner24943d22010-06-08 16:52:24 +0000768}