blob: a5896646ed0f600c4f5eb52bb263c3714950ed14 [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,
Caroline Tice101c7c22010-09-09 06:25:08 +0000365 const char *debugger_instance_name,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366 const char *program_name)
367{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000368 lldb::SettableVariableType var_type;
369 const char *screen_width_str =
Caroline Tice101c7c22010-09-09 06:25:08 +0000370 Debugger::GetSettingsController()->GetVariable ("term-width", var_type,
371 debugger_instance_name).GetStringAtIndex(0);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000372 uint32_t screen_width = atoi (screen_width_str);
373 if (screen_width == 0)
374 screen_width = 80;
375
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 const lldb::OptionDefinition *full_options_table = GetDefinitions();
377 const uint32_t save_indent_level = strm.GetIndentLevel();
378 const char *name;
379
380 if (cmd)
381 name = cmd->GetCommandName();
382 else
383 name = program_name;
384
385 strm.PutCString ("\nCommand Options Usage:\n");
386
387 strm.IndentMore(2);
388
389 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
390 // <cmd> [options-for-level-1]
391 // etc.
392
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393 const uint32_t num_options = NumCommandOptions();
Jim Ingham86511212010-06-15 18:47:14 +0000394 if (num_options == 0)
395 return;
396
Jim Inghamd6ccc602010-06-24 20:30:15 +0000397 int num_option_sets = GetRequiredOptions().size();
Jim Ingham86511212010-06-15 18:47:14 +0000398
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 uint32_t i;
Jim Ingham86511212010-06-15 18:47:14 +0000400
401 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402 {
Jim Ingham86511212010-06-15 18:47:14 +0000403 uint32_t opt_set_mask;
404
405 opt_set_mask = 1 << opt_set;
406 if (opt_set > 0)
407 strm.Printf ("\n");
408 strm.Indent (name);
409
410 for (i = 0; i < num_options; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000411 {
Jim Ingham86511212010-06-15 18:47:14 +0000412 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413 {
Jim Ingham86511212010-06-15 18:47:14 +0000414 // Add current option to the end of out_stream.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415
Jim Ingham86511212010-06-15 18:47:14 +0000416 if (full_options_table[i].required)
417 {
418 if (full_options_table[i].option_has_arg == required_argument)
419 {
420 strm.Printf (" -%c %s",
421 full_options_table[i].short_option,
422 full_options_table[i].argument_name);
423 }
424 else if (full_options_table[i].option_has_arg == optional_argument)
425 {
426 strm.Printf (" -%c [%s]",
427 full_options_table[i].short_option,
428 full_options_table[i].argument_name);
429 }
430 else
431 strm.Printf (" -%c", full_options_table[i].short_option);
432 }
433 else
434 {
435 if (full_options_table[i].option_has_arg == required_argument)
436 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
437 full_options_table[i].argument_name);
438 else if (full_options_table[i].option_has_arg == optional_argument)
439 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
440 full_options_table[i].argument_name);
441 else
442 strm.Printf (" [-%c]", full_options_table[i].short_option);
443 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000444 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445 }
446 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000447 strm.Printf ("\n\n");
448
449 // Now print out all the detailed information about the various options: long form, short form and help text:
450 // -- long_name <argument>
451 // - short <argument>
452 // help text
453
454 // This variable is used to keep track of which options' info we've printed out, because some options can be in
455 // more than one usage level, but we only want to print the long form of its information once.
456
457 OptionSet options_seen;
458 OptionSet::iterator pos;
459 strm.IndentMore (5);
460
461 int first_option_printed = 1;
462 for (i = 0; i < num_options; ++i)
463 {
464 // Only print out this option if we haven't already seen it.
465 pos = options_seen.find (full_options_table[i].short_option);
466 if (pos == options_seen.end())
467 {
468 // Put a newline separation between arguments
469 if (first_option_printed)
470 first_option_printed = 0;
471 else
472 strm.EOL();
473
474 options_seen.insert (full_options_table[i].short_option);
475 strm.Indent ();
476 strm.Printf ("-%c ", full_options_table[i].short_option);
477 if (full_options_table[i].argument_name != NULL)
478 strm.PutCString(full_options_table[i].argument_name);
479 strm.EOL();
480 strm.Indent ();
481 strm.Printf ("--%s ", full_options_table[i].long_option);
482 if (full_options_table[i].argument_name != NULL)
483 strm.PutCString(full_options_table[i].argument_name);
484 strm.EOL();
485
486 strm.IndentMore (5);
487
488 if (full_options_table[i].usage_text)
489 OutputFormattedUsageText (strm,
490 full_options_table[i].usage_text,
491 screen_width);
492 if (full_options_table[i].enum_values != NULL)
493 {
494 strm.Indent ();
495 strm.Printf("Values: ");
496 for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++)
497 {
498 if (j == 0)
499 strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
500 else
501 strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
502 }
503 strm.EOL();
504 }
505 strm.IndentLess (5);
506 }
507 }
508
509 // Restore the indent level
510 strm.SetIndentLevel (save_indent_level);
511}
512
513// This function is called when we have been given a potentially incomplete set of
514// options, such as when an alias has been defined (more options might be added at
515// at the time the alias is invoked). We need to verify that the options in the set
516// m_seen_options are all part of a set that may be used together, but m_seen_options
517// may be missing some of the "required" options.
518
519bool
520Options::VerifyPartialOptions (CommandReturnObject &result)
521{
522 bool options_are_valid = false;
523
Jim Inghamd6ccc602010-06-24 20:30:15 +0000524 int num_levels = GetRequiredOptions().size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000525 if (num_levels)
526 {
527 for (int i = 0; i < num_levels && !options_are_valid; ++i)
528 {
529 // In this case we are treating all options as optional rather than required.
530 // Therefore a set of options is correct if m_seen_options is a subset of the
531 // union of m_required_options and m_optional_options.
532 OptionSet union_set;
Jim Inghamd6ccc602010-06-24 20:30:15 +0000533 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534 if (IsASubset (m_seen_options, union_set))
535 options_are_valid = true;
536 }
537 }
538
539 return options_are_valid;
540}
541
542bool
543Options::HandleOptionCompletion
544(
Greg Clayton66111032010-06-23 01:19:29 +0000545 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000546 Args &input,
547 OptionElementVector &opt_element_vector,
548 int cursor_index,
549 int char_pos,
550 int match_start_point,
551 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000552 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553 lldb_private::StringList &matches
554)
555{
Jim Ingham558ce122010-06-30 05:02:46 +0000556 word_complete = true;
557
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000558 // For now we just scan the completions to see if the cursor position is in
559 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
560 // In the future we can use completion to validate options as well if we want.
561
562 const OptionDefinition *opt_defs = GetDefinitions();
563
564 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
565 cur_opt_std_str.erase(char_pos);
566 const char *cur_opt_str = cur_opt_std_str.c_str();
567
568 for (int i = 0; i < opt_element_vector.size(); i++)
569 {
570 int opt_pos = opt_element_vector[i].opt_pos;
571 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
572 int opt_defs_index = opt_element_vector[i].opt_defs_index;
573 if (opt_pos == cursor_index)
574 {
575 // We're completing the option itself.
Jim Inghamd6ccc602010-06-24 20:30:15 +0000576
577 if (opt_defs_index == OptionArgElement::eBareDash)
578 {
579 // We're completing a bare dash. That means all options are open.
580 // FIXME: We should scan the other options provided and only complete options
581 // within the option group they belong to.
582 char opt_str[3] = {'-', 'a', '\0'};
583
Greg Claytonb1320972010-07-14 00:18:15 +0000584 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Inghamd6ccc602010-06-24 20:30:15 +0000585 {
Greg Claytonb1320972010-07-14 00:18:15 +0000586 opt_str[1] = opt_defs[j].short_option;
Jim Inghamd6ccc602010-06-24 20:30:15 +0000587 matches.AppendString (opt_str);
588 }
589 return true;
590 }
591 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
592 {
593 std::string full_name ("--");
Greg Claytonb1320972010-07-14 00:18:15 +0000594 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Inghamd6ccc602010-06-24 20:30:15 +0000595 {
596 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonb1320972010-07-14 00:18:15 +0000597 full_name.append (opt_defs[j].long_option);
Jim Inghamd6ccc602010-06-24 20:30:15 +0000598 matches.AppendString (full_name.c_str());
599 }
600 return true;
601 }
602 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000603 {
604 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
605 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
606 // The string so the upper level code will know this is a full match and add the " ".
607 if (cur_opt_str && strlen (cur_opt_str) > 2
608 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
609 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
610 {
611 std::string full_name ("--");
612 full_name.append (opt_defs[opt_defs_index].long_option);
613 matches.AppendString(full_name.c_str());
614 return true;
615 }
616 else
617 {
618 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
619 return true;
620 }
621 }
622 else
623 {
624 // FIXME - not handling wrong options yet:
625 // Check to see if they are writing a long option & complete it.
626 // I think we will only get in here if the long option table has two elements
627 // that are not unique up to this point. getopt_long does shortest unique match
628 // for long options already.
629
630 if (cur_opt_str && strlen (cur_opt_str) > 2
631 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
632 {
Greg Claytonb1320972010-07-14 00:18:15 +0000633 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 {
Greg Claytonb1320972010-07-14 00:18:15 +0000635 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 {
637 std::string full_name ("--");
Greg Claytonb1320972010-07-14 00:18:15 +0000638 full_name.append (opt_defs[j].long_option);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 // The options definitions table has duplicates because of the
640 // way the grouping information is stored, so only add once.
641 bool duplicate = false;
Greg Claytonb1320972010-07-14 00:18:15 +0000642 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643 {
Greg Claytonb1320972010-07-14 00:18:15 +0000644 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645 {
646 duplicate = true;
647 break;
648 }
649 }
650 if (!duplicate)
651 matches.AppendString(full_name.c_str());
652 }
653 }
654 }
655 return true;
656 }
657
658
659 }
660 else if (opt_arg_pos == cursor_index)
661 {
662 // Okay the cursor is on the completion of an argument.
663 // See if it has a completion, otherwise return no matches.
664
665 if (opt_defs_index != -1)
666 {
Greg Clayton66111032010-06-23 01:19:29 +0000667 HandleOptionArgumentCompletion (interpreter,
668 input,
669 cursor_index,
670 strlen (input.GetArgumentAtIndex(cursor_index)),
671 opt_element_vector,
672 i,
673 match_start_point,
674 max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000675 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000676 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000677 return true;
678 }
679 else
680 {
681 // No completion callback means no completions...
682 return true;
683 }
684
685 }
686 else
687 {
688 // Not the last element, keep going.
689 continue;
690 }
691 }
692 return false;
693}
694
695bool
696Options::HandleOptionArgumentCompletion
697(
Greg Clayton66111032010-06-23 01:19:29 +0000698 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000699 Args &input,
700 int cursor_index,
701 int char_pos,
702 OptionElementVector &opt_element_vector,
703 int opt_element_index,
704 int match_start_point,
705 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000706 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000707 lldb_private::StringList &matches
708)
709{
710 const OptionDefinition *opt_defs = GetDefinitions();
711 std::auto_ptr<SearchFilter> filter_ap;
712
713 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
714 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
715
716 // See if this is an enumeration type option, and if so complete it here:
717
718 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
719 if (enum_values != NULL)
720 {
721 bool return_value = false;
722 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
723 for (int i = 0; enum_values[i].string_value != NULL; i++)
724 {
725 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
726 {
727 matches.AppendString (enum_values[i].string_value);
728 return_value = true;
729 }
730 }
731 return return_value;
732 }
733
734 // If this is a source file or symbol type completion, and there is a
735 // -shlib option somewhere in the supplied arguments, then make a search filter
736 // for that shared library.
737 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
738
739 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
740 if (completion_mask & CommandCompletions::eSourceFileCompletion
741 || completion_mask & CommandCompletions::eSymbolCompletion)
742 {
743 for (int i = 0; i < opt_element_vector.size(); i++)
744 {
745 int cur_defs_index = opt_element_vector[i].opt_defs_index;
746 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
747 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
748
749 // If this is the "shlib" option and there was an argument provided,
750 // restrict it to that shared library.
751 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
752 {
753 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
754 if (module_name)
755 {
756 FileSpec module_spec(module_name);
Jim Ingham2976d002010-08-26 21:32:51 +0000757 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000758 // Search filters require a target...
759 if (target_sp != NULL)
760 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
761 }
762 break;
763 }
764 }
765 }
766
Greg Clayton66111032010-06-23 01:19:29 +0000767 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
768 completion_mask,
769 input.GetArgumentAtIndex (opt_arg_pos),
770 match_start_point,
771 max_return_elements,
772 filter_ap.get(),
Jim Ingham558ce122010-06-30 05:02:46 +0000773 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000774 matches);
775
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000776}