blob: 35a9fa40e1b6589755185e1352990f67e84a89b2 [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
10#include "lldb/Core/Options.h"
11
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{
34}
35
36Options::~Options ()
37{
38}
39
40
41void
42Options::ResetOptionValues ()
43{
44 m_seen_options.clear();
45}
46
47void
48Options::OptionSeen (int option_idx)
49{
50 m_seen_options.insert ((char) option_idx);
51}
52
53// Returns true is set_a is a subset of set_b; Otherwise returns false.
54
55bool
56Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
57{
58 bool is_a_subset = true;
59 OptionSet::const_iterator pos_a;
60 OptionSet::const_iterator pos_b;
61
62 // set_a is a subset of set_b if every member of set_a is also a member of set_b
63
64 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
65 {
66 pos_b = set_b.find(*pos_a);
67 if (pos_b == set_b.end())
68 is_a_subset = false;
69 }
70
71 return is_a_subset;
72}
73
74// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
75
76size_t
77Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
78{
79 size_t num_diffs = 0;
80 OptionSet::const_iterator pos_a;
81 OptionSet::const_iterator pos_b;
82
83 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
84 {
85 pos_b = set_b.find(*pos_a);
86 if (pos_b == set_b.end())
87 {
88 ++num_diffs;
89 diffs.insert(*pos_a);
90 }
91 }
92
93 return num_diffs;
94}
95
96// Returns the union of set_a and set_b. Does not put duplicate members into the union.
97
98void
99Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
100{
101 OptionSet::const_iterator pos;
102 OptionSet::iterator pos_union;
103
104 // Put all the elements of set_a into the union.
105
106 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
107 union_set.insert(*pos);
108
109 // Put all the elements of set_b that are not already there into the union.
110 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
111 {
112 pos_union = union_set.find(*pos);
113 if (pos_union == union_set.end())
114 union_set.insert(*pos);
115 }
116}
117
118bool
119Options::VerifyOptions (CommandReturnObject &result)
120{
121 bool options_are_valid = false;
122
123 int num_levels = m_required_options.size();
124 if (num_levels)
125 {
126 for (int i = 0; i < num_levels && !options_are_valid; ++i)
127 {
128 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
129 // (i.e. all the required options at this level are a subset of m_seen_options); AND
130 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
131 // m_seen_options are in the set of optional options at this level.
132
133 // Check to see if all of m_required_options[i] are a subset of m_seen_options
134 if (IsASubset (m_required_options[i], m_seen_options))
135 {
136 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
137 OptionSet remaining_options;
138 OptionsSetDiff (m_seen_options, m_required_options[i], remaining_options);
139 // Check to see if remaining_options is a subset of m_optional_options[i]
140 if (IsASubset (remaining_options, m_optional_options[i]))
141 options_are_valid = true;
142 }
143 }
144 }
145 else
146 {
147 options_are_valid = true;
148 }
149
150 if (options_are_valid)
151 {
152 result.SetStatus (eReturnStatusSuccessFinishNoResult);
153 }
154 else
155 {
156 result.AppendError ("invalid combination of options for the given command");
157 result.SetStatus (eReturnStatusFailed);
158 }
159
160 return options_are_valid;
161}
162
163void
164Options::BuildValidOptionSets ()
165{
166 // Check to see if we already did this.
167 if (m_required_options.size() != 0)
168 return;
169
170 // Check to see if there are any options.
171 int num_options = NumCommandOptions ();
172 if (num_options == 0)
173 return;
174
175 const lldb::OptionDefinition *full_options_table = GetDefinitions();
176 uint32_t usage_level = 0;
177 m_required_options.resize(1);
178 m_optional_options.resize(1);
179
180 for (int i = 0; i < num_options; ++i)
181 {
182 // NOTE: Assumption: The full options table is ordered with usage level growing monotonically.
183 assert (full_options_table[i].usage_level >= usage_level);
184
185 if (full_options_table[i].usage_level > usage_level)
186 {
187 // start a new level
188 usage_level = full_options_table[i].usage_level;
189 m_required_options.resize(m_required_options.size()+1);
190 m_optional_options.resize(m_optional_options.size()+1);
191 }
192 else
193 {
194 assert (m_required_options.empty() == false);
195 assert (m_optional_options.empty() == false);
196 }
197
198 if (full_options_table[i].required)
199 m_required_options.back().insert(full_options_table[i].short_option);
200 else
201 m_optional_options.back().insert(full_options_table[i].short_option);
202 }
203}
204
205uint32_t
206Options::NumCommandOptions ()
207{
208 const lldb::OptionDefinition *full_options_table = GetDefinitions ();
209 int i = 0;
210
211 if (full_options_table != NULL)
212 {
213 while (full_options_table[i].long_option != NULL)
214 ++i;
215 }
216
217 return i;
218}
219
220struct option *
221Options::GetLongOptions ()
222{
223 // Check to see if this has already been done.
224 if (m_getopt_table.empty())
225 {
226 // Check to see if there are any options.
227 const uint32_t num_options = NumCommandOptions();
228 if (num_options == 0)
229 return NULL;
230
231 uint32_t i;
232 uint32_t j;
233 const lldb::OptionDefinition *full_options_table = GetDefinitions();
234
235 std::bitset<256> option_seen;
236
237 m_getopt_table.resize(num_options + 1);
238 for (i = 0, j = 0; i < num_options; ++i)
239 {
240 char short_opt = full_options_table[i].short_option;
241
242 if (option_seen.test(short_opt) == false)
243 {
244 m_getopt_table[j].name = full_options_table[i].long_option;
245 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
246 m_getopt_table[j].flag = NULL;
247 m_getopt_table[j].val = full_options_table[i].short_option;
248 option_seen.set(short_opt);
249 ++j;
250 }
251 }
252
253 //getopt_long requires a NULL final entry in the table:
254
255 m_getopt_table[j].name = NULL;
256 m_getopt_table[j].has_arg = 0;
257 m_getopt_table[j].flag = NULL;
258 m_getopt_table[j].val = 0;
259 }
260
261 return m_getopt_table.data();
262}
263
264
265// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
266// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
267// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
268// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
269// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
270
271
272void
273Options::OutputFormattedUsageText
274(
275 Stream &strm,
276 const char *text,
277 uint32_t output_max_columns
278)
279{
280 int len = strlen (text);
281
282 // Will it all fit on one line?
283
284 if ((len + strm.GetIndentLevel()) < output_max_columns)
285 {
286 // Output it as a single line.
287 strm.Indent (text);
288 strm.EOL();
289 }
290 else
291 {
292 // We need to break it up into multiple lines.
293
294 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
295 int start = 0;
296 int end = start;
297 int final_end = strlen (text);
298 int sub_len;
299
300 while (end < final_end)
301 {
302 // Don't start the 'text' on a space, since we're already outputting the indentation.
303 while ((start < final_end) && (text[start] == ' '))
304 start++;
305
306 end = start + text_width;
307 if (end > final_end)
308 end = final_end;
309 else
310 {
311 // If we're not at the end of the text, make sure we break the line on white space.
312 while (end > start
313 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
314 end--;
315 }
316
317 sub_len = end - start;
318 if (start != 0)
319 strm.EOL();
320 strm.Indent();
321 assert (start < final_end);
322 assert (start + sub_len <= final_end);
323 strm.Write(text + start, sub_len);
324 start = end + 1;
325 }
326 strm.EOL();
327 }
328}
329
330void
331Options::GenerateOptionUsage
332(
333 Stream &strm,
334 CommandObject *cmd,
335 const char *program_name)
336{
337 uint32_t screen_width = 80;
338 const lldb::OptionDefinition *full_options_table = GetDefinitions();
339 const uint32_t save_indent_level = strm.GetIndentLevel();
340 const char *name;
341
342 if (cmd)
343 name = cmd->GetCommandName();
344 else
345 name = program_name;
346
347 strm.PutCString ("\nCommand Options Usage:\n");
348
349 strm.IndentMore(2);
350
351 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
352 // <cmd> [options-for-level-1]
353 // etc.
354
355 uint32_t usage_level = 0;
356 const uint32_t num_options = NumCommandOptions();
357 uint32_t i;
358 for (i = 0; i < num_options; ++i)
359 {
360 if (i==0 || full_options_table[i].usage_level > usage_level)
361 {
362 // start a new level
363 usage_level = full_options_table[i].usage_level;
364 if (usage_level > 0)
365 {
366 strm.Printf ("\n");
367 }
368 strm.Indent (name);
369 }
370
371 // Add current option to the end of out_stream.
372
373 if (full_options_table[i].required)
374 {
375 if (full_options_table[i].option_has_arg == required_argument)
376 {
377 strm.Printf (" -%c %s",
378 full_options_table[i].short_option,
379 full_options_table[i].argument_name);
380 }
381 else if (full_options_table[i].option_has_arg == optional_argument)
382 {
383 strm.Printf (" -%c [%s]",
384 full_options_table[i].short_option,
385 full_options_table[i].argument_name);
386 }
387 else
388 strm.Printf (" -%c", full_options_table[i].short_option);
389 }
390 else
391 {
392 if (full_options_table[i].option_has_arg == required_argument)
393 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
394 full_options_table[i].argument_name);
395 else if (full_options_table[i].option_has_arg == optional_argument)
396 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
397 full_options_table[i].argument_name);
398 else
399 strm.Printf (" [-%c]", full_options_table[i].short_option);
400 }
401 }
402
403 strm.Printf ("\n\n");
404
405 // Now print out all the detailed information about the various options: long form, short form and help text:
406 // -- long_name <argument>
407 // - short <argument>
408 // help text
409
410 // This variable is used to keep track of which options' info we've printed out, because some options can be in
411 // more than one usage level, but we only want to print the long form of its information once.
412
413 OptionSet options_seen;
414 OptionSet::iterator pos;
415 strm.IndentMore (5);
416
417 int first_option_printed = 1;
418 for (i = 0; i < num_options; ++i)
419 {
420 // Only print out this option if we haven't already seen it.
421 pos = options_seen.find (full_options_table[i].short_option);
422 if (pos == options_seen.end())
423 {
424 // Put a newline separation between arguments
425 if (first_option_printed)
426 first_option_printed = 0;
427 else
428 strm.EOL();
429
430 options_seen.insert (full_options_table[i].short_option);
431 strm.Indent ();
432 strm.Printf ("-%c ", full_options_table[i].short_option);
433 if (full_options_table[i].argument_name != NULL)
434 strm.PutCString(full_options_table[i].argument_name);
435 strm.EOL();
436 strm.Indent ();
437 strm.Printf ("--%s ", full_options_table[i].long_option);
438 if (full_options_table[i].argument_name != NULL)
439 strm.PutCString(full_options_table[i].argument_name);
440 strm.EOL();
441
442 strm.IndentMore (5);
443
444 if (full_options_table[i].usage_text)
445 OutputFormattedUsageText (strm,
446 full_options_table[i].usage_text,
447 screen_width);
448 if (full_options_table[i].enum_values != NULL)
449 {
450 strm.Indent ();
451 strm.Printf("Values: ");
452 for (int j = 0; full_options_table[i].enum_values[j].string_value != NULL; j++)
453 {
454 if (j == 0)
455 strm.Printf("%s", full_options_table[i].enum_values[j].string_value);
456 else
457 strm.Printf(" | %s", full_options_table[i].enum_values[j].string_value);
458 }
459 strm.EOL();
460 }
461 strm.IndentLess (5);
462 }
463 }
464
465 // Restore the indent level
466 strm.SetIndentLevel (save_indent_level);
467}
468
469// This function is called when we have been given a potentially incomplete set of
470// options, such as when an alias has been defined (more options might be added at
471// at the time the alias is invoked). We need to verify that the options in the set
472// m_seen_options are all part of a set that may be used together, but m_seen_options
473// may be missing some of the "required" options.
474
475bool
476Options::VerifyPartialOptions (CommandReturnObject &result)
477{
478 bool options_are_valid = false;
479
480 int num_levels = m_required_options.size();
481 if (num_levels)
482 {
483 for (int i = 0; i < num_levels && !options_are_valid; ++i)
484 {
485 // In this case we are treating all options as optional rather than required.
486 // Therefore a set of options is correct if m_seen_options is a subset of the
487 // union of m_required_options and m_optional_options.
488 OptionSet union_set;
489 OptionsSetUnion (m_required_options[i], m_optional_options[i], union_set);
490 if (IsASubset (m_seen_options, union_set))
491 options_are_valid = true;
492 }
493 }
494
495 return options_are_valid;
496}
497
498bool
499Options::HandleOptionCompletion
500(
501 Args &input,
502 OptionElementVector &opt_element_vector,
503 int cursor_index,
504 int char_pos,
505 int match_start_point,
506 int max_return_elements,
507 lldb_private::CommandInterpreter *interpreter,
508 lldb_private::StringList &matches
509)
510{
511 // For now we just scan the completions to see if the cursor position is in
512 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
513 // In the future we can use completion to validate options as well if we want.
514
515 const OptionDefinition *opt_defs = GetDefinitions();
516
517 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
518 cur_opt_std_str.erase(char_pos);
519 const char *cur_opt_str = cur_opt_std_str.c_str();
520
521 for (int i = 0; i < opt_element_vector.size(); i++)
522 {
523 int opt_pos = opt_element_vector[i].opt_pos;
524 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
525 int opt_defs_index = opt_element_vector[i].opt_defs_index;
526 if (opt_pos == cursor_index)
527 {
528 // We're completing the option itself.
529 if (opt_defs_index != -1)
530 {
531 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
532 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
533 // The string so the upper level code will know this is a full match and add the " ".
534 if (cur_opt_str && strlen (cur_opt_str) > 2
535 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
536 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
537 {
538 std::string full_name ("--");
539 full_name.append (opt_defs[opt_defs_index].long_option);
540 matches.AppendString(full_name.c_str());
541 return true;
542 }
543 else
544 {
545 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
546 return true;
547 }
548 }
549 else
550 {
551 // FIXME - not handling wrong options yet:
552 // Check to see if they are writing a long option & complete it.
553 // I think we will only get in here if the long option table has two elements
554 // that are not unique up to this point. getopt_long does shortest unique match
555 // for long options already.
556
557 if (cur_opt_str && strlen (cur_opt_str) > 2
558 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
559 {
560 for (int i = 0 ; opt_defs[i].short_option != 0 ; i++)
561 {
562 if (strstr(opt_defs[i].long_option, cur_opt_str + 2) == opt_defs[i].long_option)
563 {
564 std::string full_name ("--");
565 full_name.append (opt_defs[i].long_option);
566 // The options definitions table has duplicates because of the
567 // way the grouping information is stored, so only add once.
568 bool duplicate = false;
569 for (int j = 0; j < matches.GetSize(); j++)
570 {
571 if (matches.GetStringAtIndex(j) == full_name)
572 {
573 duplicate = true;
574 break;
575 }
576 }
577 if (!duplicate)
578 matches.AppendString(full_name.c_str());
579 }
580 }
581 }
582 return true;
583 }
584
585
586 }
587 else if (opt_arg_pos == cursor_index)
588 {
589 // Okay the cursor is on the completion of an argument.
590 // See if it has a completion, otherwise return no matches.
591
592 if (opt_defs_index != -1)
593 {
594 HandleOptionArgumentCompletion (input,
595 cursor_index,
596 strlen (input.GetArgumentAtIndex(cursor_index)),
597 opt_element_vector,
598 i,
599 match_start_point,
600 max_return_elements,
601 interpreter,
602 matches);
603 return true;
604 }
605 else
606 {
607 // No completion callback means no completions...
608 return true;
609 }
610
611 }
612 else
613 {
614 // Not the last element, keep going.
615 continue;
616 }
617 }
618 return false;
619}
620
621bool
622Options::HandleOptionArgumentCompletion
623(
624 Args &input,
625 int cursor_index,
626 int char_pos,
627 OptionElementVector &opt_element_vector,
628 int opt_element_index,
629 int match_start_point,
630 int max_return_elements,
631 lldb_private::CommandInterpreter *interpreter,
632 lldb_private::StringList &matches
633)
634{
635 const OptionDefinition *opt_defs = GetDefinitions();
636 std::auto_ptr<SearchFilter> filter_ap;
637
638 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
639 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
640
641 // See if this is an enumeration type option, and if so complete it here:
642
643 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
644 if (enum_values != NULL)
645 {
646 bool return_value = false;
647 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
648 for (int i = 0; enum_values[i].string_value != NULL; i++)
649 {
650 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
651 {
652 matches.AppendString (enum_values[i].string_value);
653 return_value = true;
654 }
655 }
656 return return_value;
657 }
658
659 // If this is a source file or symbol type completion, and there is a
660 // -shlib option somewhere in the supplied arguments, then make a search filter
661 // for that shared library.
662 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
663
664 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
665 if (completion_mask & CommandCompletions::eSourceFileCompletion
666 || completion_mask & CommandCompletions::eSymbolCompletion)
667 {
668 for (int i = 0; i < opt_element_vector.size(); i++)
669 {
670 int cur_defs_index = opt_element_vector[i].opt_defs_index;
671 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
672 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
673
674 // If this is the "shlib" option and there was an argument provided,
675 // restrict it to that shared library.
676 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
677 {
678 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
679 if (module_name)
680 {
681 FileSpec module_spec(module_name);
682 lldb::TargetSP target_sp = interpreter->Context()->GetTarget()->GetSP();
683 // Search filters require a target...
684 if (target_sp != NULL)
685 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
686 }
687 break;
688 }
689 }
690 }
691
692 return CommandCompletions::InvokeCommonCompletionCallbacks (completion_mask,
693 input.GetArgumentAtIndex (opt_arg_pos),
694 match_start_point,
695 max_return_elements,
696 interpreter,
697 filter_ap.get(),
698 matches);
699
700}