blob: 60ab1202853c63f1f083f8fea5d68bde2f7ebd83 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Ingham40af72e2010-06-15 19:49:27 +000010#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-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 Ingham86511212010-06-15 18:47:14 +000034 BuildValidOptionSets();
Chris Lattner30fdc8d2010-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 Inghamd6ccc602010-06-24 20:30:15 +0000124 int num_levels = GetRequiredOptions().size();
Chris Lattner30fdc8d2010-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 Inghamd6ccc602010-06-24 20:30:15 +0000135 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner30fdc8d2010-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 Inghamd6ccc602010-06-24 20:30:15 +0000139 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000140 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Inghamd6ccc602010-06-24 20:30:15 +0000141 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner30fdc8d2010-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 Ingham86511212010-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 Lattner30fdc8d2010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000180 m_required_options.resize(1);
181 m_optional_options.resize(1);
Jim Ingham86511212010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000188 {
Jim Ingham86511212010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000191 {
Jim Ingham86511212010-06-15 18:47:14 +0000192 if (num_option_sets == 0)
193 num_option_sets = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194 }
195 else
196 {
Jim Ingham86511212010-06-15 18:47:14 +0000197 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
198 {
Jim Inghamd6ccc602010-06-24 20:30:15 +0000199 if (this_usage_mask & (1 << j))
Jim Ingham86511212010-06-15 18:47:14 +0000200 {
201 if (num_option_sets <= j)
202 num_option_sets = j + 1;
203 }
204 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205 }
Jim Ingham86511212010-06-15 18:47:14 +0000206 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207
Jim Ingham86511212010-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 Lattner30fdc8d2010-06-08 16:52:24 +0000226 }
227}
228
229uint32_t
230Options::NumCommandOptions ()
231{
232 const lldb::OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham86511212010-06-15 18:47:14 +0000233 if (full_options_table == NULL)
234 return 0;
235
Chris Lattner30fdc8d2010-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 Clayton471b31c2010-07-20 22:52:08 +0000288 if (m_getopt_table.empty())
289 return NULL;
290
291 return &m_getopt_table.front();
Chris Lattner30fdc8d2010-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{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000367 lldb::SettableVariableType var_type;
368 const char *screen_width_str =
369 Debugger::GetSettingsController()->GetVariable ("term-width", var_type).GetStringAtIndex(0);
370 uint32_t screen_width = atoi (screen_width_str);
371 if (screen_width == 0)
372 screen_width = 80;
373
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 const lldb::OptionDefinition *full_options_table = GetDefinitions();
375 const uint32_t save_indent_level = strm.GetIndentLevel();
376 const char *name;
377
378 if (cmd)
379 name = cmd->GetCommandName();
380 else
381 name = program_name;
382
383 strm.PutCString ("\nCommand Options Usage:\n");
384
385 strm.IndentMore(2);
386
387 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
388 // <cmd> [options-for-level-1]
389 // etc.
390
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000391 const uint32_t num_options = NumCommandOptions();
Jim Ingham86511212010-06-15 18:47:14 +0000392 if (num_options == 0)
393 return;
394
Jim Inghamd6ccc602010-06-24 20:30:15 +0000395 int num_option_sets = GetRequiredOptions().size();
Jim Ingham86511212010-06-15 18:47:14 +0000396
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 uint32_t i;
Jim Ingham86511212010-06-15 18:47:14 +0000398
399 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400 {
Jim Ingham86511212010-06-15 18:47:14 +0000401 uint32_t opt_set_mask;
402
403 opt_set_mask = 1 << opt_set;
404 if (opt_set > 0)
405 strm.Printf ("\n");
406 strm.Indent (name);
407
408 for (i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 {
Jim Ingham86511212010-06-15 18:47:14 +0000410 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411 {
Jim Ingham86511212010-06-15 18:47:14 +0000412 // Add current option to the end of out_stream.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413
Jim Ingham86511212010-06-15 18:47:14 +0000414 if (full_options_table[i].required)
415 {
416 if (full_options_table[i].option_has_arg == required_argument)
417 {
418 strm.Printf (" -%c %s",
419 full_options_table[i].short_option,
420 full_options_table[i].argument_name);
421 }
422 else if (full_options_table[i].option_has_arg == optional_argument)
423 {
424 strm.Printf (" -%c [%s]",
425 full_options_table[i].short_option,
426 full_options_table[i].argument_name);
427 }
428 else
429 strm.Printf (" -%c", full_options_table[i].short_option);
430 }
431 else
432 {
433 if (full_options_table[i].option_has_arg == required_argument)
434 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
435 full_options_table[i].argument_name);
436 else if (full_options_table[i].option_has_arg == optional_argument)
437 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
438 full_options_table[i].argument_name);
439 else
440 strm.Printf (" [-%c]", full_options_table[i].short_option);
441 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000442 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000443 }
444 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445 strm.Printf ("\n\n");
446
447 // Now print out all the detailed information about the various options: long form, short form and help text:
448 // -- long_name <argument>
449 // - short <argument>
450 // help text
451
452 // This variable is used to keep track of which options' info we've printed out, because some options can be in
453 // more than one usage level, but we only want to print the long form of its information once.
454
455 OptionSet options_seen;
456 OptionSet::iterator pos;
457 strm.IndentMore (5);
458
459 int first_option_printed = 1;
460 for (i = 0; i < num_options; ++i)
461 {
462 // Only print out this option if we haven't already seen it.
463 pos = options_seen.find (full_options_table[i].short_option);
464 if (pos == options_seen.end())
465 {
466 // Put a newline separation between arguments
467 if (first_option_printed)
468 first_option_printed = 0;
469 else
470 strm.EOL();
471
472 options_seen.insert (full_options_table[i].short_option);
473 strm.Indent ();
474 strm.Printf ("-%c ", full_options_table[i].short_option);
475 if (full_options_table[i].argument_name != NULL)
476 strm.PutCString(full_options_table[i].argument_name);
477 strm.EOL();
478 strm.Indent ();
479 strm.Printf ("--%s ", full_options_table[i].long_option);
480 if (full_options_table[i].argument_name != NULL)
481 strm.PutCString(full_options_table[i].argument_name);
482 strm.EOL();
483
484 strm.IndentMore (5);
485
486 if (full_options_table[i].usage_text)
487 OutputFormattedUsageText (strm,
488 full_options_table[i].usage_text,
489 screen_width);
490 if (full_options_table[i].enum_values != NULL)
491 {
492 strm.Indent ();
493 strm.Printf("Values: ");
494 for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++)
495 {
496 if (j == 0)
497 strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
498 else
499 strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
500 }
501 strm.EOL();
502 }
503 strm.IndentLess (5);
504 }
505 }
506
507 // Restore the indent level
508 strm.SetIndentLevel (save_indent_level);
509}
510
511// This function is called when we have been given a potentially incomplete set of
512// options, such as when an alias has been defined (more options might be added at
513// at the time the alias is invoked). We need to verify that the options in the set
514// m_seen_options are all part of a set that may be used together, but m_seen_options
515// may be missing some of the "required" options.
516
517bool
518Options::VerifyPartialOptions (CommandReturnObject &result)
519{
520 bool options_are_valid = false;
521
Jim Inghamd6ccc602010-06-24 20:30:15 +0000522 int num_levels = GetRequiredOptions().size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000523 if (num_levels)
524 {
525 for (int i = 0; i < num_levels && !options_are_valid; ++i)
526 {
527 // In this case we are treating all options as optional rather than required.
528 // Therefore a set of options is correct if m_seen_options is a subset of the
529 // union of m_required_options and m_optional_options.
530 OptionSet union_set;
Jim Inghamd6ccc602010-06-24 20:30:15 +0000531 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000532 if (IsASubset (m_seen_options, union_set))
533 options_are_valid = true;
534 }
535 }
536
537 return options_are_valid;
538}
539
540bool
541Options::HandleOptionCompletion
542(
Greg Clayton66111032010-06-23 01:19:29 +0000543 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544 Args &input,
545 OptionElementVector &opt_element_vector,
546 int cursor_index,
547 int char_pos,
548 int match_start_point,
549 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000550 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551 lldb_private::StringList &matches
552)
553{
Jim Ingham558ce122010-06-30 05:02:46 +0000554 word_complete = true;
555
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556 // For now we just scan the completions to see if the cursor position is in
557 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
558 // In the future we can use completion to validate options as well if we want.
559
560 const OptionDefinition *opt_defs = GetDefinitions();
561
562 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
563 cur_opt_std_str.erase(char_pos);
564 const char *cur_opt_str = cur_opt_std_str.c_str();
565
566 for (int i = 0; i < opt_element_vector.size(); i++)
567 {
568 int opt_pos = opt_element_vector[i].opt_pos;
569 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
570 int opt_defs_index = opt_element_vector[i].opt_defs_index;
571 if (opt_pos == cursor_index)
572 {
573 // We're completing the option itself.
Jim Inghamd6ccc602010-06-24 20:30:15 +0000574
575 if (opt_defs_index == OptionArgElement::eBareDash)
576 {
577 // We're completing a bare dash. That means all options are open.
578 // FIXME: We should scan the other options provided and only complete options
579 // within the option group they belong to.
580 char opt_str[3] = {'-', 'a', '\0'};
581
Greg Claytonb1320972010-07-14 00:18:15 +0000582 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Inghamd6ccc602010-06-24 20:30:15 +0000583 {
Greg Claytonb1320972010-07-14 00:18:15 +0000584 opt_str[1] = opt_defs[j].short_option;
Jim Inghamd6ccc602010-06-24 20:30:15 +0000585 matches.AppendString (opt_str);
586 }
587 return true;
588 }
589 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
590 {
591 std::string full_name ("--");
Greg Claytonb1320972010-07-14 00:18:15 +0000592 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Inghamd6ccc602010-06-24 20:30:15 +0000593 {
594 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonb1320972010-07-14 00:18:15 +0000595 full_name.append (opt_defs[j].long_option);
Jim Inghamd6ccc602010-06-24 20:30:15 +0000596 matches.AppendString (full_name.c_str());
597 }
598 return true;
599 }
600 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000601 {
602 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
603 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
604 // The string so the upper level code will know this is a full match and add the " ".
605 if (cur_opt_str && strlen (cur_opt_str) > 2
606 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
607 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
608 {
609 std::string full_name ("--");
610 full_name.append (opt_defs[opt_defs_index].long_option);
611 matches.AppendString(full_name.c_str());
612 return true;
613 }
614 else
615 {
616 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
617 return true;
618 }
619 }
620 else
621 {
622 // FIXME - not handling wrong options yet:
623 // Check to see if they are writing a long option & complete it.
624 // I think we will only get in here if the long option table has two elements
625 // that are not unique up to this point. getopt_long does shortest unique match
626 // for long options already.
627
628 if (cur_opt_str && strlen (cur_opt_str) > 2
629 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
630 {
Greg Claytonb1320972010-07-14 00:18:15 +0000631 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632 {
Greg Claytonb1320972010-07-14 00:18:15 +0000633 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 {
635 std::string full_name ("--");
Greg Claytonb1320972010-07-14 00:18:15 +0000636 full_name.append (opt_defs[j].long_option);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000637 // The options definitions table has duplicates because of the
638 // way the grouping information is stored, so only add once.
639 bool duplicate = false;
Greg Claytonb1320972010-07-14 00:18:15 +0000640 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641 {
Greg Claytonb1320972010-07-14 00:18:15 +0000642 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643 {
644 duplicate = true;
645 break;
646 }
647 }
648 if (!duplicate)
649 matches.AppendString(full_name.c_str());
650 }
651 }
652 }
653 return true;
654 }
655
656
657 }
658 else if (opt_arg_pos == cursor_index)
659 {
660 // Okay the cursor is on the completion of an argument.
661 // See if it has a completion, otherwise return no matches.
662
663 if (opt_defs_index != -1)
664 {
Greg Clayton66111032010-06-23 01:19:29 +0000665 HandleOptionArgumentCompletion (interpreter,
666 input,
667 cursor_index,
668 strlen (input.GetArgumentAtIndex(cursor_index)),
669 opt_element_vector,
670 i,
671 match_start_point,
672 max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000673 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000674 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000675 return true;
676 }
677 else
678 {
679 // No completion callback means no completions...
680 return true;
681 }
682
683 }
684 else
685 {
686 // Not the last element, keep going.
687 continue;
688 }
689 }
690 return false;
691}
692
693bool
694Options::HandleOptionArgumentCompletion
695(
Greg Clayton66111032010-06-23 01:19:29 +0000696 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000697 Args &input,
698 int cursor_index,
699 int char_pos,
700 OptionElementVector &opt_element_vector,
701 int opt_element_index,
702 int match_start_point,
703 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000704 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000705 lldb_private::StringList &matches
706)
707{
708 const OptionDefinition *opt_defs = GetDefinitions();
709 std::auto_ptr<SearchFilter> filter_ap;
710
711 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
712 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
713
714 // See if this is an enumeration type option, and if so complete it here:
715
716 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
717 if (enum_values != NULL)
718 {
719 bool return_value = false;
720 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
721 for (int i = 0; enum_values[i].string_value != NULL; i++)
722 {
723 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
724 {
725 matches.AppendString (enum_values[i].string_value);
726 return_value = true;
727 }
728 }
729 return return_value;
730 }
731
732 // If this is a source file or symbol type completion, and there is a
733 // -shlib option somewhere in the supplied arguments, then make a search filter
734 // for that shared library.
735 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
736
737 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
738 if (completion_mask & CommandCompletions::eSourceFileCompletion
739 || completion_mask & CommandCompletions::eSymbolCompletion)
740 {
741 for (int i = 0; i < opt_element_vector.size(); i++)
742 {
743 int cur_defs_index = opt_element_vector[i].opt_defs_index;
744 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
745 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
746
747 // If this is the "shlib" option and there was an argument provided,
748 // restrict it to that shared library.
749 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
750 {
751 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
752 if (module_name)
753 {
754 FileSpec module_spec(module_name);
Jim Ingham2976d002010-08-26 21:32:51 +0000755 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000756 // Search filters require a target...
757 if (target_sp != NULL)
758 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
759 }
760 break;
761 }
762 }
763 }
764
Greg Clayton66111032010-06-23 01:19:29 +0000765 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
766 completion_mask,
767 input.GetArgumentAtIndex (opt_arg_pos),
768 match_start_point,
769 max_return_elements,
770 filter_ap.get(),
Jim Ingham558ce122010-06-30 05:02:46 +0000771 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000772 matches);
773
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000774}