blob: 0ab6bdffda9e93ec3be1a150b99b24778b02f342 [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>
Caroline Ticee5f18b02010-09-09 16:44:14 +000015#include <algorithm>
Chris Lattner24943d22010-06-08 16:52:24 +000016
17// Other libraries and framework includes
18// Project includes
19#include "lldb/Interpreter/CommandObject.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
21#include "lldb/Interpreter/CommandCompletions.h"
22#include "lldb/Interpreter/CommandInterpreter.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Target/Target.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29//-------------------------------------------------------------------------
30// Options
31//-------------------------------------------------------------------------
32Options::Options () :
33 m_getopt_table ()
34{
Jim Ingham34e9a982010-06-15 18:47:14 +000035 BuildValidOptionSets();
Chris Lattner24943d22010-06-08 16:52:24 +000036}
37
38Options::~Options ()
39{
40}
41
42
43void
44Options::ResetOptionValues ()
45{
46 m_seen_options.clear();
47}
48
49void
50Options::OptionSeen (int option_idx)
51{
52 m_seen_options.insert ((char) option_idx);
53}
54
55// Returns true is set_a is a subset of set_b; Otherwise returns false.
56
57bool
58Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
59{
60 bool is_a_subset = true;
61 OptionSet::const_iterator pos_a;
62 OptionSet::const_iterator pos_b;
63
64 // set_a is a subset of set_b if every member of set_a is also a member of set_b
65
66 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
67 {
68 pos_b = set_b.find(*pos_a);
69 if (pos_b == set_b.end())
70 is_a_subset = false;
71 }
72
73 return is_a_subset;
74}
75
76// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
77
78size_t
79Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
80{
81 size_t num_diffs = 0;
82 OptionSet::const_iterator pos_a;
83 OptionSet::const_iterator pos_b;
84
85 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
86 {
87 pos_b = set_b.find(*pos_a);
88 if (pos_b == set_b.end())
89 {
90 ++num_diffs;
91 diffs.insert(*pos_a);
92 }
93 }
94
95 return num_diffs;
96}
97
98// Returns the union of set_a and set_b. Does not put duplicate members into the union.
99
100void
101Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
102{
103 OptionSet::const_iterator pos;
104 OptionSet::iterator pos_union;
105
106 // Put all the elements of set_a into the union.
107
108 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
109 union_set.insert(*pos);
110
111 // Put all the elements of set_b that are not already there into the union.
112 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
113 {
114 pos_union = union_set.find(*pos);
115 if (pos_union == union_set.end())
116 union_set.insert(*pos);
117 }
118}
119
120bool
121Options::VerifyOptions (CommandReturnObject &result)
122{
123 bool options_are_valid = false;
124
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000125 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000126 if (num_levels)
127 {
128 for (int i = 0; i < num_levels && !options_are_valid; ++i)
129 {
130 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
131 // (i.e. all the required options at this level are a subset of m_seen_options); AND
132 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
133 // m_seen_options are in the set of optional options at this level.
134
135 // Check to see if all of m_required_options[i] are a subset of m_seen_options
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000136 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner24943d22010-06-08 16:52:24 +0000137 {
138 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
139 OptionSet remaining_options;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000140 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000141 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000142 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner24943d22010-06-08 16:52:24 +0000143 options_are_valid = true;
144 }
145 }
146 }
147 else
148 {
149 options_are_valid = true;
150 }
151
152 if (options_are_valid)
153 {
154 result.SetStatus (eReturnStatusSuccessFinishNoResult);
155 }
156 else
157 {
158 result.AppendError ("invalid combination of options for the given command");
159 result.SetStatus (eReturnStatusFailed);
160 }
161
162 return options_are_valid;
163}
164
Jim Ingham34e9a982010-06-15 18:47:14 +0000165// This is called in the Options constructor, though we could call it lazily if that ends up being
166// a performance problem.
167
Chris Lattner24943d22010-06-08 16:52:24 +0000168void
169Options::BuildValidOptionSets ()
170{
171 // Check to see if we already did this.
172 if (m_required_options.size() != 0)
173 return;
174
175 // Check to see if there are any options.
176 int num_options = NumCommandOptions ();
177 if (num_options == 0)
178 return;
179
180 const lldb::OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000181 m_required_options.resize(1);
182 m_optional_options.resize(1);
Jim Ingham34e9a982010-06-15 18:47:14 +0000183
184 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
185
186 uint32_t num_option_sets = 0;
187
188 for (int i = 0; i < num_options; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000189 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000190 uint32_t this_usage_mask = full_options_table[i].usage_mask;
191 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000192 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000193 if (num_option_sets == 0)
194 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
196 else
197 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000198 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
199 {
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000200 if (this_usage_mask & (1 << j))
Jim Ingham34e9a982010-06-15 18:47:14 +0000201 {
202 if (num_option_sets <= j)
203 num_option_sets = j + 1;
204 }
205 }
Chris Lattner24943d22010-06-08 16:52:24 +0000206 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000207 }
Chris Lattner24943d22010-06-08 16:52:24 +0000208
Jim Ingham34e9a982010-06-15 18:47:14 +0000209 if (num_option_sets > 0)
210 {
211 m_required_options.resize(num_option_sets);
212 m_optional_options.resize(num_option_sets);
213
214 for (int i = 0; i < num_options; ++i)
215 {
216 for (int j = 0; j < num_option_sets; j++)
217 {
218 if (full_options_table[i].usage_mask & 1 << j)
219 {
220 if (full_options_table[i].required)
221 m_required_options[j].insert(full_options_table[i].short_option);
222 else
223 m_optional_options[j].insert(full_options_table[i].short_option);
224 }
225 }
226 }
Chris Lattner24943d22010-06-08 16:52:24 +0000227 }
228}
229
230uint32_t
231Options::NumCommandOptions ()
232{
233 const lldb::OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham34e9a982010-06-15 18:47:14 +0000234 if (full_options_table == NULL)
235 return 0;
236
Chris Lattner24943d22010-06-08 16:52:24 +0000237 int i = 0;
238
239 if (full_options_table != NULL)
240 {
241 while (full_options_table[i].long_option != NULL)
242 ++i;
243 }
244
245 return i;
246}
247
248struct option *
249Options::GetLongOptions ()
250{
251 // Check to see if this has already been done.
252 if (m_getopt_table.empty())
253 {
254 // Check to see if there are any options.
255 const uint32_t num_options = NumCommandOptions();
256 if (num_options == 0)
257 return NULL;
258
259 uint32_t i;
260 uint32_t j;
261 const lldb::OptionDefinition *full_options_table = GetDefinitions();
262
263 std::bitset<256> option_seen;
264
265 m_getopt_table.resize(num_options + 1);
266 for (i = 0, j = 0; i < num_options; ++i)
267 {
268 char short_opt = full_options_table[i].short_option;
269
270 if (option_seen.test(short_opt) == false)
271 {
272 m_getopt_table[j].name = full_options_table[i].long_option;
273 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
274 m_getopt_table[j].flag = NULL;
275 m_getopt_table[j].val = full_options_table[i].short_option;
276 option_seen.set(short_opt);
277 ++j;
278 }
279 }
280
281 //getopt_long requires a NULL final entry in the table:
282
283 m_getopt_table[j].name = NULL;
284 m_getopt_table[j].has_arg = 0;
285 m_getopt_table[j].flag = NULL;
286 m_getopt_table[j].val = 0;
287 }
288
Greg Clayton53d68e72010-07-20 22:52:08 +0000289 if (m_getopt_table.empty())
290 return NULL;
291
292 return &m_getopt_table.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000293}
294
295
296// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
297// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
298// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
299// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
300// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
301
302
303void
304Options::OutputFormattedUsageText
305(
306 Stream &strm,
307 const char *text,
308 uint32_t output_max_columns
309)
310{
311 int len = strlen (text);
312
313 // Will it all fit on one line?
314
315 if ((len + strm.GetIndentLevel()) < output_max_columns)
316 {
317 // Output it as a single line.
318 strm.Indent (text);
319 strm.EOL();
320 }
321 else
322 {
323 // We need to break it up into multiple lines.
324
325 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
326 int start = 0;
327 int end = start;
328 int final_end = strlen (text);
329 int sub_len;
330
331 while (end < final_end)
332 {
333 // Don't start the 'text' on a space, since we're already outputting the indentation.
334 while ((start < final_end) && (text[start] == ' '))
335 start++;
336
337 end = start + text_width;
338 if (end > final_end)
339 end = final_end;
340 else
341 {
342 // If we're not at the end of the text, make sure we break the line on white space.
343 while (end > start
344 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
345 end--;
346 }
347
348 sub_len = end - start;
349 if (start != 0)
350 strm.EOL();
351 strm.Indent();
352 assert (start < final_end);
353 assert (start + sub_len <= final_end);
354 strm.Write(text + start, sub_len);
355 start = end + 1;
356 }
357 strm.EOL();
358 }
359}
360
361void
362Options::GenerateOptionUsage
363(
Greg Clayton238c0a12010-09-18 01:14:36 +0000364 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000365 Stream &strm,
Greg Clayton238c0a12010-09-18 01:14:36 +0000366 CommandObject *cmd
367)
Chris Lattner24943d22010-06-08 16:52:24 +0000368{
Greg Clayton238c0a12010-09-18 01:14:36 +0000369 const uint32_t screen_width = interpreter.GetDebugger().GetTerminalWidth();
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000370
Chris Lattner24943d22010-06-08 16:52:24 +0000371 const lldb::OptionDefinition *full_options_table = GetDefinitions();
372 const uint32_t save_indent_level = strm.GetIndentLevel();
373 const char *name;
374
Caroline Ticefb355112010-10-01 17:46:38 +0000375 StreamString arguments_str;
376
Chris Lattner24943d22010-06-08 16:52:24 +0000377 if (cmd)
Caroline Ticefb355112010-10-01 17:46:38 +0000378 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000379 name = cmd->GetCommandName();
Caroline Ticefb355112010-10-01 17:46:38 +0000380 cmd->GetFormattedCommandArguments (arguments_str);
381 }
Chris Lattner24943d22010-06-08 16:52:24 +0000382 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000383 name = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000384
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 Lattner24943d22010-06-08 16:52:24 +0000393 const uint32_t num_options = NumCommandOptions();
Jim Ingham34e9a982010-06-15 18:47:14 +0000394 if (num_options == 0)
395 return;
396
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000397 int num_option_sets = GetRequiredOptions().size();
Jim Ingham34e9a982010-06-15 18:47:14 +0000398
Chris Lattner24943d22010-06-08 16:52:24 +0000399 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000400
401 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner24943d22010-06-08 16:52:24 +0000402 {
Jim Ingham34e9a982010-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);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000409
Greg Claytonfe424a92010-09-18 03:37:20 +0000410 // First go through and print all options that take no arguments as
411 // a single string. If a command has "-a" "-b" and "-c", this will show
412 // up as [-abc]
413
414 std::set<char> options;
415 std::set<char>::const_iterator options_pos, options_end;
416 bool first;
417 for (i = 0, first = true; i < num_options; ++i)
418 {
419 if (full_options_table[i].usage_mask & opt_set_mask)
420 {
421 // Add current option to the end of out_stream.
422
423 if (full_options_table[i].required == true &&
424 full_options_table[i].option_has_arg == no_argument)
425 {
426 options.insert (full_options_table[i].short_option);
427 }
428 }
429 }
430
431 if (options.empty() == false)
432 {
433 // We have some required options with no arguments
434 strm.PutCString(" -");
435 for (i=0; i<2; ++i)
436 for (options_pos = options.begin(), options_end = options.end();
437 options_pos != options_end;
438 ++options_pos)
439 {
440 if (i==0 && ::isupper (*options_pos))
441 continue;
442 if (i==1 && ::islower (*options_pos))
443 continue;
444 strm << *options_pos;
445 }
446 }
447
448 for (i = 0, options.clear(); i < num_options; ++i)
449 {
450 if (full_options_table[i].usage_mask & opt_set_mask)
451 {
452 // Add current option to the end of out_stream.
453
454 if (full_options_table[i].required == false &&
455 full_options_table[i].option_has_arg == no_argument)
456 {
457 options.insert (full_options_table[i].short_option);
458 }
459 }
460 }
461
462 if (options.empty() == false)
463 {
464 // We have some required options with no arguments
465 strm.PutCString(" [-");
466 for (i=0; i<2; ++i)
467 for (options_pos = options.begin(), options_end = options.end();
468 options_pos != options_end;
469 ++options_pos)
470 {
471 if (i==0 && ::isupper (*options_pos))
472 continue;
473 if (i==1 && ::islower (*options_pos))
474 continue;
475 strm << *options_pos;
476 }
477 strm.PutChar(']');
478 }
479
Caroline Ticee5f18b02010-09-09 16:44:14 +0000480 // First go through and print the required options (list them up front).
Jim Ingham34e9a982010-06-15 18:47:14 +0000481
482 for (i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000483 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000484 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner24943d22010-06-08 16:52:24 +0000485 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000486 // Add current option to the end of out_stream.
Chris Lattner24943d22010-06-08 16:52:24 +0000487
Jim Ingham34e9a982010-06-15 18:47:14 +0000488 if (full_options_table[i].required)
489 {
490 if (full_options_table[i].option_has_arg == required_argument)
491 {
492 strm.Printf (" -%c %s",
493 full_options_table[i].short_option,
494 full_options_table[i].argument_name);
495 }
496 else if (full_options_table[i].option_has_arg == optional_argument)
497 {
498 strm.Printf (" -%c [%s]",
499 full_options_table[i].short_option,
500 full_options_table[i].argument_name);
501 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000502 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000503 }
504 }
505
506 // Now go through again, and this time only print the optional options.
507
508 for (i = 0; i < num_options; ++i)
509 {
510 if (full_options_table[i].usage_mask & opt_set_mask)
511 {
512 // Add current option to the end of out_stream.
513
514 if (! full_options_table[i].required)
Jim Ingham34e9a982010-06-15 18:47:14 +0000515 {
516 if (full_options_table[i].option_has_arg == required_argument)
517 strm.Printf (" [-%c %s]", full_options_table[i].short_option,
518 full_options_table[i].argument_name);
519 else if (full_options_table[i].option_has_arg == optional_argument)
520 strm.Printf (" [-%c [%s]]", full_options_table[i].short_option,
521 full_options_table[i].argument_name);
Jim Ingham34e9a982010-06-15 18:47:14 +0000522 }
Chris Lattner24943d22010-06-08 16:52:24 +0000523 }
Chris Lattner24943d22010-06-08 16:52:24 +0000524 }
Caroline Ticefb355112010-10-01 17:46:38 +0000525 if (arguments_str.GetSize() > 0)
526 strm.Printf (" %s", arguments_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000527 }
Chris Lattner24943d22010-06-08 16:52:24 +0000528 strm.Printf ("\n\n");
529
530 // Now print out all the detailed information about the various options: long form, short form and help text:
Greg Claytonfe424a92010-09-18 03:37:20 +0000531 // --long_name <argument> ( -short <argument> )
Chris Lattner24943d22010-06-08 16:52:24 +0000532 // help text
533
534 // This variable is used to keep track of which options' info we've printed out, because some options can be in
535 // more than one usage level, but we only want to print the long form of its information once.
536
537 OptionSet options_seen;
538 OptionSet::iterator pos;
539 strm.IndentMore (5);
540
Caroline Ticee5f18b02010-09-09 16:44:14 +0000541 std::vector<char> sorted_options;
542
543
544 // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
545 // when writing out detailed help for each option.
546
Chris Lattner24943d22010-06-08 16:52:24 +0000547 for (i = 0; i < num_options; ++i)
548 {
Chris Lattner24943d22010-06-08 16:52:24 +0000549 pos = options_seen.find (full_options_table[i].short_option);
550 if (pos == options_seen.end())
551 {
Chris Lattner24943d22010-06-08 16:52:24 +0000552 options_seen.insert (full_options_table[i].short_option);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000553 sorted_options.push_back (full_options_table[i].short_option);
554 }
555 }
Chris Lattner24943d22010-06-08 16:52:24 +0000556
Caroline Ticee5f18b02010-09-09 16:44:14 +0000557 std::sort (sorted_options.begin(), sorted_options.end());
558
559 // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
560 // and write out the detailed help information for that option.
561
562 int first_option_printed = 1;
563 size_t end = sorted_options.size();
564 for (size_t j = 0; j < end; ++j)
565 {
566 char option = sorted_options[j];
567 bool found = false;
568 for (i = 0; i < num_options && !found; ++i)
569 {
570 if (full_options_table[i].short_option == option)
571 {
572 found = true;
573 //Print out the help information for this option.
574
575 // Put a newline separation between arguments
576 if (first_option_printed)
577 first_option_printed = 0;
578 else
579 strm.EOL();
580
581 strm.Indent ();
Caroline Tice9e8e6962010-09-20 21:52:58 +0000582 strm.Printf ("-%c", full_options_table[i].short_option);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000583 if (full_options_table[i].argument_name != NULL)
Greg Claytonfe424a92010-09-18 03:37:20 +0000584 strm.Printf (" %s", full_options_table[i].argument_name);
Caroline Tice9e8e6962010-09-20 21:52:58 +0000585 strm.Printf (" ( --%s", full_options_table[i].long_option);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000586 if (full_options_table[i].argument_name != NULL)
Greg Claytonfe424a92010-09-18 03:37:20 +0000587 strm.Printf (" %s", full_options_table[i].argument_name);
588 strm.PutCString(" )\n");
Caroline Ticee5f18b02010-09-09 16:44:14 +0000589
590 strm.IndentMore (5);
591
592 if (full_options_table[i].usage_text)
Chris Lattner24943d22010-06-08 16:52:24 +0000593 OutputFormattedUsageText (strm,
594 full_options_table[i].usage_text,
595 screen_width);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000596 if (full_options_table[i].enum_values != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000597 {
Caroline Ticee5f18b02010-09-09 16:44:14 +0000598 strm.Indent ();
599 strm.Printf("Values: ");
600 for (int k = 0; full_options_table[i].enum_values[k].string_value != NULL; k++)
601 {
602 if (k == 0)
603 strm.Printf("%s", full_options_table[i].enum_values[k].string_value);
604 else
605 strm.Printf(" | %s", full_options_table[i].enum_values[k].string_value);
606 }
607 strm.EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000608 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000609 strm.IndentLess (5);
Chris Lattner24943d22010-06-08 16:52:24 +0000610 }
Chris Lattner24943d22010-06-08 16:52:24 +0000611 }
612 }
613
614 // Restore the indent level
615 strm.SetIndentLevel (save_indent_level);
616}
617
618// This function is called when we have been given a potentially incomplete set of
619// options, such as when an alias has been defined (more options might be added at
620// at the time the alias is invoked). We need to verify that the options in the set
621// m_seen_options are all part of a set that may be used together, but m_seen_options
622// may be missing some of the "required" options.
623
624bool
625Options::VerifyPartialOptions (CommandReturnObject &result)
626{
627 bool options_are_valid = false;
628
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000629 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000630 if (num_levels)
631 {
632 for (int i = 0; i < num_levels && !options_are_valid; ++i)
633 {
634 // In this case we are treating all options as optional rather than required.
635 // Therefore a set of options is correct if m_seen_options is a subset of the
636 // union of m_required_options and m_optional_options.
637 OptionSet union_set;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000638 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner24943d22010-06-08 16:52:24 +0000639 if (IsASubset (m_seen_options, union_set))
640 options_are_valid = true;
641 }
642 }
643
644 return options_are_valid;
645}
646
647bool
648Options::HandleOptionCompletion
649(
Greg Clayton63094e02010-06-23 01:19:29 +0000650 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000651 Args &input,
652 OptionElementVector &opt_element_vector,
653 int cursor_index,
654 int char_pos,
655 int match_start_point,
656 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000657 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000658 lldb_private::StringList &matches
659)
660{
Jim Ingham802f8b02010-06-30 05:02:46 +0000661 word_complete = true;
662
Chris Lattner24943d22010-06-08 16:52:24 +0000663 // For now we just scan the completions to see if the cursor position is in
664 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
665 // In the future we can use completion to validate options as well if we want.
666
667 const OptionDefinition *opt_defs = GetDefinitions();
668
669 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
670 cur_opt_std_str.erase(char_pos);
671 const char *cur_opt_str = cur_opt_std_str.c_str();
672
673 for (int i = 0; i < opt_element_vector.size(); i++)
674 {
675 int opt_pos = opt_element_vector[i].opt_pos;
676 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
677 int opt_defs_index = opt_element_vector[i].opt_defs_index;
678 if (opt_pos == cursor_index)
679 {
680 // We're completing the option itself.
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000681
682 if (opt_defs_index == OptionArgElement::eBareDash)
683 {
684 // We're completing a bare dash. That means all options are open.
685 // FIXME: We should scan the other options provided and only complete options
686 // within the option group they belong to.
687 char opt_str[3] = {'-', 'a', '\0'};
688
Greg Claytonbef15832010-07-14 00:18:15 +0000689 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000690 {
Greg Claytonbef15832010-07-14 00:18:15 +0000691 opt_str[1] = opt_defs[j].short_option;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000692 matches.AppendString (opt_str);
693 }
694 return true;
695 }
696 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
697 {
698 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000699 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000700 {
701 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonbef15832010-07-14 00:18:15 +0000702 full_name.append (opt_defs[j].long_option);
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000703 matches.AppendString (full_name.c_str());
704 }
705 return true;
706 }
707 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner24943d22010-06-08 16:52:24 +0000708 {
709 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
710 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
711 // The string so the upper level code will know this is a full match and add the " ".
712 if (cur_opt_str && strlen (cur_opt_str) > 2
713 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
714 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
715 {
716 std::string full_name ("--");
717 full_name.append (opt_defs[opt_defs_index].long_option);
718 matches.AppendString(full_name.c_str());
719 return true;
720 }
721 else
722 {
723 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
724 return true;
725 }
726 }
727 else
728 {
729 // FIXME - not handling wrong options yet:
730 // Check to see if they are writing a long option & complete it.
731 // I think we will only get in here if the long option table has two elements
732 // that are not unique up to this point. getopt_long does shortest unique match
733 // for long options already.
734
735 if (cur_opt_str && strlen (cur_opt_str) > 2
736 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
737 {
Greg Claytonbef15832010-07-14 00:18:15 +0000738 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000739 {
Greg Claytonbef15832010-07-14 00:18:15 +0000740 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner24943d22010-06-08 16:52:24 +0000741 {
742 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000743 full_name.append (opt_defs[j].long_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000744 // The options definitions table has duplicates because of the
745 // way the grouping information is stored, so only add once.
746 bool duplicate = false;
Greg Claytonbef15832010-07-14 00:18:15 +0000747 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner24943d22010-06-08 16:52:24 +0000748 {
Greg Claytonbef15832010-07-14 00:18:15 +0000749 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner24943d22010-06-08 16:52:24 +0000750 {
751 duplicate = true;
752 break;
753 }
754 }
755 if (!duplicate)
756 matches.AppendString(full_name.c_str());
757 }
758 }
759 }
760 return true;
761 }
762
763
764 }
765 else if (opt_arg_pos == cursor_index)
766 {
767 // Okay the cursor is on the completion of an argument.
768 // See if it has a completion, otherwise return no matches.
769
770 if (opt_defs_index != -1)
771 {
Greg Clayton63094e02010-06-23 01:19:29 +0000772 HandleOptionArgumentCompletion (interpreter,
773 input,
774 cursor_index,
775 strlen (input.GetArgumentAtIndex(cursor_index)),
776 opt_element_vector,
777 i,
778 match_start_point,
779 max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000780 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000781 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000782 return true;
783 }
784 else
785 {
786 // No completion callback means no completions...
787 return true;
788 }
789
790 }
791 else
792 {
793 // Not the last element, keep going.
794 continue;
795 }
796 }
797 return false;
798}
799
800bool
801Options::HandleOptionArgumentCompletion
802(
Greg Clayton63094e02010-06-23 01:19:29 +0000803 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000804 Args &input,
805 int cursor_index,
806 int char_pos,
807 OptionElementVector &opt_element_vector,
808 int opt_element_index,
809 int match_start_point,
810 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000811 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000812 lldb_private::StringList &matches
813)
814{
815 const OptionDefinition *opt_defs = GetDefinitions();
816 std::auto_ptr<SearchFilter> filter_ap;
817
818 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
819 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
820
821 // See if this is an enumeration type option, and if so complete it here:
822
823 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
824 if (enum_values != NULL)
825 {
826 bool return_value = false;
827 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
828 for (int i = 0; enum_values[i].string_value != NULL; i++)
829 {
830 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
831 {
832 matches.AppendString (enum_values[i].string_value);
833 return_value = true;
834 }
835 }
836 return return_value;
837 }
838
839 // If this is a source file or symbol type completion, and there is a
840 // -shlib option somewhere in the supplied arguments, then make a search filter
841 // for that shared library.
842 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
843
844 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
845 if (completion_mask & CommandCompletions::eSourceFileCompletion
846 || completion_mask & CommandCompletions::eSymbolCompletion)
847 {
848 for (int i = 0; i < opt_element_vector.size(); i++)
849 {
850 int cur_defs_index = opt_element_vector[i].opt_defs_index;
851 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
852 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
853
854 // If this is the "shlib" option and there was an argument provided,
855 // restrict it to that shared library.
856 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
857 {
858 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
859 if (module_name)
860 {
861 FileSpec module_spec(module_name);
Jim Inghamc8332952010-08-26 21:32:51 +0000862 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000863 // Search filters require a target...
864 if (target_sp != NULL)
865 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
866 }
867 break;
868 }
869 }
870 }
871
Greg Clayton63094e02010-06-23 01:19:29 +0000872 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
873 completion_mask,
874 input.GetArgumentAtIndex (opt_arg_pos),
875 match_start_point,
876 max_return_elements,
877 filter_ap.get(),
Jim Ingham802f8b02010-06-30 05:02:46 +0000878 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000879 matches);
880
Chris Lattner24943d22010-06-08 16:52:24 +0000881}