blob: 3bc553d4bb38e29b793a5ad7d6cb3776180b1b29 [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
Chris Lattner24943d22010-06-08 16:52:24 +000042void
Greg Clayton24bc5d92011-03-30 18:16:51 +000043Options::Reset ()
Chris Lattner24943d22010-06-08 16:52:24 +000044{
45 m_seen_options.clear();
Greg Clayton24bc5d92011-03-30 18:16:51 +000046 // Let the subclass reset its option values
47 ResetOptionValues ();
Chris Lattner24943d22010-06-08 16:52:24 +000048}
49
50void
51Options::OptionSeen (int option_idx)
52{
53 m_seen_options.insert ((char) option_idx);
54}
55
56// Returns true is set_a is a subset of set_b; Otherwise returns false.
57
58bool
59Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
60{
61 bool is_a_subset = true;
62 OptionSet::const_iterator pos_a;
63 OptionSet::const_iterator pos_b;
64
65 // set_a is a subset of set_b if every member of set_a is also a member of set_b
66
67 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
68 {
69 pos_b = set_b.find(*pos_a);
70 if (pos_b == set_b.end())
71 is_a_subset = false;
72 }
73
74 return is_a_subset;
75}
76
77// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
78
79size_t
80Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
81{
82 size_t num_diffs = 0;
83 OptionSet::const_iterator pos_a;
84 OptionSet::const_iterator pos_b;
85
86 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
87 {
88 pos_b = set_b.find(*pos_a);
89 if (pos_b == set_b.end())
90 {
91 ++num_diffs;
92 diffs.insert(*pos_a);
93 }
94 }
95
96 return num_diffs;
97}
98
99// Returns the union of set_a and set_b. Does not put duplicate members into the union.
100
101void
102Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
103{
104 OptionSet::const_iterator pos;
105 OptionSet::iterator pos_union;
106
107 // Put all the elements of set_a into the union.
108
109 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
110 union_set.insert(*pos);
111
112 // Put all the elements of set_b that are not already there into the union.
113 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
114 {
115 pos_union = union_set.find(*pos);
116 if (pos_union == union_set.end())
117 union_set.insert(*pos);
118 }
119}
120
121bool
122Options::VerifyOptions (CommandReturnObject &result)
123{
124 bool options_are_valid = false;
125
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000126 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000127 if (num_levels)
128 {
129 for (int i = 0; i < num_levels && !options_are_valid; ++i)
130 {
131 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
132 // (i.e. all the required options at this level are a subset of m_seen_options); AND
133 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
134 // m_seen_options are in the set of optional options at this level.
135
136 // Check to see if all of m_required_options[i] are a subset of m_seen_options
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000137 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner24943d22010-06-08 16:52:24 +0000138 {
139 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
140 OptionSet remaining_options;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000141 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000142 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000143 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner24943d22010-06-08 16:52:24 +0000144 options_are_valid = true;
145 }
146 }
147 }
148 else
149 {
150 options_are_valid = true;
151 }
152
153 if (options_are_valid)
154 {
155 result.SetStatus (eReturnStatusSuccessFinishNoResult);
156 }
157 else
158 {
159 result.AppendError ("invalid combination of options for the given command");
160 result.SetStatus (eReturnStatusFailed);
161 }
162
163 return options_are_valid;
164}
165
Jim Ingham34e9a982010-06-15 18:47:14 +0000166// This is called in the Options constructor, though we could call it lazily if that ends up being
167// a performance problem.
168
Chris Lattner24943d22010-06-08 16:52:24 +0000169void
170Options::BuildValidOptionSets ()
171{
172 // Check to see if we already did this.
173 if (m_required_options.size() != 0)
174 return;
175
176 // Check to see if there are any options.
177 int num_options = NumCommandOptions ();
178 if (num_options == 0)
179 return;
180
Greg Claytonb3448432011-03-24 21:19:54 +0000181 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000182 m_required_options.resize(1);
183 m_optional_options.resize(1);
Jim Ingham34e9a982010-06-15 18:47:14 +0000184
185 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
186
187 uint32_t num_option_sets = 0;
188
189 for (int i = 0; i < num_options; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000190 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000191 uint32_t this_usage_mask = full_options_table[i].usage_mask;
192 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000193 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000194 if (num_option_sets == 0)
195 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000196 }
197 else
198 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000199 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
200 {
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000201 if (this_usage_mask & (1 << j))
Jim Ingham34e9a982010-06-15 18:47:14 +0000202 {
203 if (num_option_sets <= j)
204 num_option_sets = j + 1;
205 }
206 }
Chris Lattner24943d22010-06-08 16:52:24 +0000207 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000208 }
Chris Lattner24943d22010-06-08 16:52:24 +0000209
Jim Ingham34e9a982010-06-15 18:47:14 +0000210 if (num_option_sets > 0)
211 {
212 m_required_options.resize(num_option_sets);
213 m_optional_options.resize(num_option_sets);
214
215 for (int i = 0; i < num_options; ++i)
216 {
217 for (int j = 0; j < num_option_sets; j++)
218 {
219 if (full_options_table[i].usage_mask & 1 << j)
220 {
221 if (full_options_table[i].required)
222 m_required_options[j].insert(full_options_table[i].short_option);
223 else
224 m_optional_options[j].insert(full_options_table[i].short_option);
225 }
226 }
227 }
Chris Lattner24943d22010-06-08 16:52:24 +0000228 }
229}
230
231uint32_t
232Options::NumCommandOptions ()
233{
Greg Claytonb3448432011-03-24 21:19:54 +0000234 const OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham34e9a982010-06-15 18:47:14 +0000235 if (full_options_table == NULL)
236 return 0;
237
Chris Lattner24943d22010-06-08 16:52:24 +0000238 int i = 0;
239
240 if (full_options_table != NULL)
241 {
242 while (full_options_table[i].long_option != NULL)
243 ++i;
244 }
245
246 return i;
247}
248
249struct option *
250Options::GetLongOptions ()
251{
252 // Check to see if this has already been done.
253 if (m_getopt_table.empty())
254 {
255 // Check to see if there are any options.
256 const uint32_t num_options = NumCommandOptions();
257 if (num_options == 0)
258 return NULL;
259
260 uint32_t i;
261 uint32_t j;
Greg Claytonb3448432011-03-24 21:19:54 +0000262 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000263
264 std::bitset<256> option_seen;
265
266 m_getopt_table.resize(num_options + 1);
267 for (i = 0, j = 0; i < num_options; ++i)
268 {
269 char short_opt = full_options_table[i].short_option;
270
271 if (option_seen.test(short_opt) == false)
272 {
273 m_getopt_table[j].name = full_options_table[i].long_option;
274 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
275 m_getopt_table[j].flag = NULL;
276 m_getopt_table[j].val = full_options_table[i].short_option;
277 option_seen.set(short_opt);
278 ++j;
279 }
280 }
281
282 //getopt_long requires a NULL final entry in the table:
283
284 m_getopt_table[j].name = NULL;
285 m_getopt_table[j].has_arg = 0;
286 m_getopt_table[j].flag = NULL;
287 m_getopt_table[j].val = 0;
288 }
289
Greg Clayton53d68e72010-07-20 22:52:08 +0000290 if (m_getopt_table.empty())
291 return NULL;
292
293 return &m_getopt_table.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000294}
295
296
297// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
298// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
299// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
300// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
301// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
302
303
304void
305Options::OutputFormattedUsageText
306(
307 Stream &strm,
308 const char *text,
309 uint32_t output_max_columns
310)
311{
312 int len = strlen (text);
313
314 // Will it all fit on one line?
315
316 if ((len + strm.GetIndentLevel()) < output_max_columns)
317 {
318 // Output it as a single line.
319 strm.Indent (text);
320 strm.EOL();
321 }
322 else
323 {
324 // We need to break it up into multiple lines.
325
326 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
327 int start = 0;
328 int end = start;
329 int final_end = strlen (text);
330 int sub_len;
331
332 while (end < final_end)
333 {
334 // Don't start the 'text' on a space, since we're already outputting the indentation.
335 while ((start < final_end) && (text[start] == ' '))
336 start++;
337
338 end = start + text_width;
339 if (end > final_end)
340 end = final_end;
341 else
342 {
343 // If we're not at the end of the text, make sure we break the line on white space.
344 while (end > start
345 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
346 end--;
347 }
348
349 sub_len = end - start;
350 if (start != 0)
351 strm.EOL();
352 strm.Indent();
353 assert (start < final_end);
354 assert (start + sub_len <= final_end);
355 strm.Write(text + start, sub_len);
356 start = end + 1;
357 }
358 strm.EOL();
359 }
360}
361
362void
363Options::GenerateOptionUsage
364(
Greg Clayton238c0a12010-09-18 01:14:36 +0000365 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000366 Stream &strm,
Greg Clayton238c0a12010-09-18 01:14:36 +0000367 CommandObject *cmd
368)
Chris Lattner24943d22010-06-08 16:52:24 +0000369{
Greg Clayton238c0a12010-09-18 01:14:36 +0000370 const uint32_t screen_width = interpreter.GetDebugger().GetTerminalWidth();
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000371
Greg Claytonb3448432011-03-24 21:19:54 +0000372 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000373 const uint32_t save_indent_level = strm.GetIndentLevel();
374 const char *name;
375
Caroline Ticefb355112010-10-01 17:46:38 +0000376 StreamString arguments_str;
377
Chris Lattner24943d22010-06-08 16:52:24 +0000378 if (cmd)
Caroline Ticefb355112010-10-01 17:46:38 +0000379 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000380 name = cmd->GetCommandName();
Caroline Ticefb355112010-10-01 17:46:38 +0000381 cmd->GetFormattedCommandArguments (arguments_str);
382 }
Chris Lattner24943d22010-06-08 16:52:24 +0000383 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000384 name = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000385
386 strm.PutCString ("\nCommand Options Usage:\n");
387
388 strm.IndentMore(2);
389
390 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
391 // <cmd> [options-for-level-1]
392 // etc.
393
Chris Lattner24943d22010-06-08 16:52:24 +0000394 const uint32_t num_options = NumCommandOptions();
Jim Ingham34e9a982010-06-15 18:47:14 +0000395 if (num_options == 0)
396 return;
397
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000398 int num_option_sets = GetRequiredOptions().size();
Jim Ingham34e9a982010-06-15 18:47:14 +0000399
Chris Lattner24943d22010-06-08 16:52:24 +0000400 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000401
402 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner24943d22010-06-08 16:52:24 +0000403 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000404 uint32_t opt_set_mask;
405
406 opt_set_mask = 1 << opt_set;
407 if (opt_set > 0)
408 strm.Printf ("\n");
409 strm.Indent (name);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000410
Greg Claytonfe424a92010-09-18 03:37:20 +0000411 // First go through and print all options that take no arguments as
412 // a single string. If a command has "-a" "-b" and "-c", this will show
413 // up as [-abc]
414
415 std::set<char> options;
416 std::set<char>::const_iterator options_pos, options_end;
417 bool first;
418 for (i = 0, first = true; i < num_options; ++i)
419 {
420 if (full_options_table[i].usage_mask & opt_set_mask)
421 {
422 // Add current option to the end of out_stream.
423
424 if (full_options_table[i].required == true &&
425 full_options_table[i].option_has_arg == no_argument)
426 {
427 options.insert (full_options_table[i].short_option);
428 }
429 }
430 }
431
432 if (options.empty() == false)
433 {
434 // We have some required options with no arguments
435 strm.PutCString(" -");
436 for (i=0; i<2; ++i)
437 for (options_pos = options.begin(), options_end = options.end();
438 options_pos != options_end;
439 ++options_pos)
440 {
441 if (i==0 && ::isupper (*options_pos))
442 continue;
443 if (i==1 && ::islower (*options_pos))
444 continue;
445 strm << *options_pos;
446 }
447 }
448
449 for (i = 0, options.clear(); i < num_options; ++i)
450 {
451 if (full_options_table[i].usage_mask & opt_set_mask)
452 {
453 // Add current option to the end of out_stream.
454
455 if (full_options_table[i].required == false &&
456 full_options_table[i].option_has_arg == no_argument)
457 {
458 options.insert (full_options_table[i].short_option);
459 }
460 }
461 }
462
463 if (options.empty() == false)
464 {
465 // We have some required options with no arguments
466 strm.PutCString(" [-");
467 for (i=0; i<2; ++i)
468 for (options_pos = options.begin(), options_end = options.end();
469 options_pos != options_end;
470 ++options_pos)
471 {
472 if (i==0 && ::isupper (*options_pos))
473 continue;
474 if (i==1 && ::islower (*options_pos))
475 continue;
476 strm << *options_pos;
477 }
478 strm.PutChar(']');
479 }
480
Caroline Ticee5f18b02010-09-09 16:44:14 +0000481 // First go through and print the required options (list them up front).
Jim Ingham34e9a982010-06-15 18:47:14 +0000482
483 for (i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000484 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000485 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner24943d22010-06-08 16:52:24 +0000486 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000487 // Add current option to the end of out_stream.
Caroline Tice4d6675c2010-10-01 19:59:14 +0000488 CommandArgumentType arg_type = full_options_table[i].argument_type;
489
Jim Ingham34e9a982010-06-15 18:47:14 +0000490 if (full_options_table[i].required)
491 {
492 if (full_options_table[i].option_has_arg == required_argument)
493 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000494 strm.Printf (" -%c <%s>",
495 full_options_table[i].short_option,
496 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000497 }
498 else if (full_options_table[i].option_has_arg == optional_argument)
499 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000500 strm.Printf (" -%c [<%s>]",
Jim Ingham34e9a982010-06-15 18:47:14 +0000501 full_options_table[i].short_option,
Caroline Tice4d6675c2010-10-01 19:59:14 +0000502 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000503 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000504 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000505 }
506 }
507
508 // Now go through again, and this time only print the optional options.
509
510 for (i = 0; i < num_options; ++i)
511 {
512 if (full_options_table[i].usage_mask & opt_set_mask)
513 {
514 // Add current option to the end of out_stream.
515
Caroline Tice4d6675c2010-10-01 19:59:14 +0000516 CommandArgumentType arg_type = full_options_table[i].argument_type;
517
Caroline Ticee5f18b02010-09-09 16:44:14 +0000518 if (! full_options_table[i].required)
Jim Ingham34e9a982010-06-15 18:47:14 +0000519 {
520 if (full_options_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000521 strm.Printf (" [-%c <%s>]", full_options_table[i].short_option,
522 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000523 else if (full_options_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000524 strm.Printf (" [-%c [<%s>]]", full_options_table[i].short_option,
525 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000526 }
Chris Lattner24943d22010-06-08 16:52:24 +0000527 }
Chris Lattner24943d22010-06-08 16:52:24 +0000528 }
Caroline Ticefb355112010-10-01 17:46:38 +0000529 if (arguments_str.GetSize() > 0)
530 strm.Printf (" %s", arguments_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000531 }
Chris Lattner24943d22010-06-08 16:52:24 +0000532 strm.Printf ("\n\n");
533
534 // 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 +0000535 // --long_name <argument> ( -short <argument> )
Chris Lattner24943d22010-06-08 16:52:24 +0000536 // help text
537
538 // This variable is used to keep track of which options' info we've printed out, because some options can be in
539 // more than one usage level, but we only want to print the long form of its information once.
540
541 OptionSet options_seen;
542 OptionSet::iterator pos;
543 strm.IndentMore (5);
544
Caroline Ticee5f18b02010-09-09 16:44:14 +0000545 std::vector<char> sorted_options;
546
547
548 // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
549 // when writing out detailed help for each option.
550
Chris Lattner24943d22010-06-08 16:52:24 +0000551 for (i = 0; i < num_options; ++i)
552 {
Chris Lattner24943d22010-06-08 16:52:24 +0000553 pos = options_seen.find (full_options_table[i].short_option);
554 if (pos == options_seen.end())
555 {
Chris Lattner24943d22010-06-08 16:52:24 +0000556 options_seen.insert (full_options_table[i].short_option);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000557 sorted_options.push_back (full_options_table[i].short_option);
558 }
559 }
Chris Lattner24943d22010-06-08 16:52:24 +0000560
Caroline Ticee5f18b02010-09-09 16:44:14 +0000561 std::sort (sorted_options.begin(), sorted_options.end());
562
563 // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
564 // and write out the detailed help information for that option.
565
566 int first_option_printed = 1;
567 size_t end = sorted_options.size();
568 for (size_t j = 0; j < end; ++j)
569 {
570 char option = sorted_options[j];
571 bool found = false;
572 for (i = 0; i < num_options && !found; ++i)
573 {
574 if (full_options_table[i].short_option == option)
575 {
576 found = true;
577 //Print out the help information for this option.
578
579 // Put a newline separation between arguments
580 if (first_option_printed)
581 first_option_printed = 0;
582 else
583 strm.EOL();
584
Caroline Tice4d6675c2010-10-01 19:59:14 +0000585 CommandArgumentType arg_type = full_options_table[i].argument_type;
586
587 StreamString arg_name_str;
588 arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
589
Caroline Ticee5f18b02010-09-09 16:44:14 +0000590 strm.Indent ();
Caroline Tice9e8e6962010-09-20 21:52:58 +0000591 strm.Printf ("-%c", full_options_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000592 if (arg_type != eArgTypeNone)
593 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
Caroline Tice9e8e6962010-09-20 21:52:58 +0000594 strm.Printf (" ( --%s", full_options_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000595 if (arg_type != eArgTypeNone)
596 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
Greg Claytonfe424a92010-09-18 03:37:20 +0000597 strm.PutCString(" )\n");
Caroline Ticee5f18b02010-09-09 16:44:14 +0000598
599 strm.IndentMore (5);
600
601 if (full_options_table[i].usage_text)
Chris Lattner24943d22010-06-08 16:52:24 +0000602 OutputFormattedUsageText (strm,
603 full_options_table[i].usage_text,
604 screen_width);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000605 if (full_options_table[i].enum_values != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000606 {
Caroline Ticee5f18b02010-09-09 16:44:14 +0000607 strm.Indent ();
608 strm.Printf("Values: ");
609 for (int k = 0; full_options_table[i].enum_values[k].string_value != NULL; k++)
610 {
611 if (k == 0)
612 strm.Printf("%s", full_options_table[i].enum_values[k].string_value);
613 else
614 strm.Printf(" | %s", full_options_table[i].enum_values[k].string_value);
615 }
616 strm.EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000617 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000618 strm.IndentLess (5);
Chris Lattner24943d22010-06-08 16:52:24 +0000619 }
Chris Lattner24943d22010-06-08 16:52:24 +0000620 }
621 }
622
623 // Restore the indent level
624 strm.SetIndentLevel (save_indent_level);
625}
626
627// This function is called when we have been given a potentially incomplete set of
628// options, such as when an alias has been defined (more options might be added at
629// at the time the alias is invoked). We need to verify that the options in the set
630// m_seen_options are all part of a set that may be used together, but m_seen_options
631// may be missing some of the "required" options.
632
633bool
634Options::VerifyPartialOptions (CommandReturnObject &result)
635{
636 bool options_are_valid = false;
637
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000638 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000639 if (num_levels)
640 {
641 for (int i = 0; i < num_levels && !options_are_valid; ++i)
642 {
643 // In this case we are treating all options as optional rather than required.
644 // Therefore a set of options is correct if m_seen_options is a subset of the
645 // union of m_required_options and m_optional_options.
646 OptionSet union_set;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000647 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner24943d22010-06-08 16:52:24 +0000648 if (IsASubset (m_seen_options, union_set))
649 options_are_valid = true;
650 }
651 }
652
653 return options_are_valid;
654}
655
656bool
657Options::HandleOptionCompletion
658(
Greg Clayton63094e02010-06-23 01:19:29 +0000659 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000660 Args &input,
661 OptionElementVector &opt_element_vector,
662 int cursor_index,
663 int char_pos,
664 int match_start_point,
665 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000666 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000667 lldb_private::StringList &matches
668)
669{
Jim Ingham802f8b02010-06-30 05:02:46 +0000670 word_complete = true;
671
Chris Lattner24943d22010-06-08 16:52:24 +0000672 // For now we just scan the completions to see if the cursor position is in
673 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
674 // In the future we can use completion to validate options as well if we want.
675
676 const OptionDefinition *opt_defs = GetDefinitions();
677
678 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
679 cur_opt_std_str.erase(char_pos);
680 const char *cur_opt_str = cur_opt_std_str.c_str();
681
682 for (int i = 0; i < opt_element_vector.size(); i++)
683 {
684 int opt_pos = opt_element_vector[i].opt_pos;
685 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
686 int opt_defs_index = opt_element_vector[i].opt_defs_index;
687 if (opt_pos == cursor_index)
688 {
689 // We're completing the option itself.
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000690
691 if (opt_defs_index == OptionArgElement::eBareDash)
692 {
693 // We're completing a bare dash. That means all options are open.
694 // FIXME: We should scan the other options provided and only complete options
695 // within the option group they belong to.
696 char opt_str[3] = {'-', 'a', '\0'};
697
Greg Claytonbef15832010-07-14 00:18:15 +0000698 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000699 {
Greg Claytonbef15832010-07-14 00:18:15 +0000700 opt_str[1] = opt_defs[j].short_option;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000701 matches.AppendString (opt_str);
702 }
703 return true;
704 }
705 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
706 {
707 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000708 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000709 {
710 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonbef15832010-07-14 00:18:15 +0000711 full_name.append (opt_defs[j].long_option);
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000712 matches.AppendString (full_name.c_str());
713 }
714 return true;
715 }
716 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner24943d22010-06-08 16:52:24 +0000717 {
718 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
719 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
720 // The string so the upper level code will know this is a full match and add the " ".
721 if (cur_opt_str && strlen (cur_opt_str) > 2
722 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
723 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
724 {
725 std::string full_name ("--");
726 full_name.append (opt_defs[opt_defs_index].long_option);
727 matches.AppendString(full_name.c_str());
728 return true;
729 }
730 else
731 {
732 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
733 return true;
734 }
735 }
736 else
737 {
738 // FIXME - not handling wrong options yet:
739 // Check to see if they are writing a long option & complete it.
740 // I think we will only get in here if the long option table has two elements
741 // that are not unique up to this point. getopt_long does shortest unique match
742 // for long options already.
743
744 if (cur_opt_str && strlen (cur_opt_str) > 2
745 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
746 {
Greg Claytonbef15832010-07-14 00:18:15 +0000747 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000748 {
Greg Claytonbef15832010-07-14 00:18:15 +0000749 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner24943d22010-06-08 16:52:24 +0000750 {
751 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000752 full_name.append (opt_defs[j].long_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000753 // The options definitions table has duplicates because of the
754 // way the grouping information is stored, so only add once.
755 bool duplicate = false;
Greg Claytonbef15832010-07-14 00:18:15 +0000756 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner24943d22010-06-08 16:52:24 +0000757 {
Greg Claytonbef15832010-07-14 00:18:15 +0000758 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner24943d22010-06-08 16:52:24 +0000759 {
760 duplicate = true;
761 break;
762 }
763 }
764 if (!duplicate)
765 matches.AppendString(full_name.c_str());
766 }
767 }
768 }
769 return true;
770 }
771
772
773 }
774 else if (opt_arg_pos == cursor_index)
775 {
776 // Okay the cursor is on the completion of an argument.
777 // See if it has a completion, otherwise return no matches.
778
779 if (opt_defs_index != -1)
780 {
Greg Clayton63094e02010-06-23 01:19:29 +0000781 HandleOptionArgumentCompletion (interpreter,
782 input,
783 cursor_index,
784 strlen (input.GetArgumentAtIndex(cursor_index)),
785 opt_element_vector,
786 i,
787 match_start_point,
788 max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000789 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000790 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000791 return true;
792 }
793 else
794 {
795 // No completion callback means no completions...
796 return true;
797 }
798
799 }
800 else
801 {
802 // Not the last element, keep going.
803 continue;
804 }
805 }
806 return false;
807}
808
809bool
810Options::HandleOptionArgumentCompletion
811(
Greg Clayton63094e02010-06-23 01:19:29 +0000812 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000813 Args &input,
814 int cursor_index,
815 int char_pos,
816 OptionElementVector &opt_element_vector,
817 int opt_element_index,
818 int match_start_point,
819 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000820 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000821 lldb_private::StringList &matches
822)
823{
824 const OptionDefinition *opt_defs = GetDefinitions();
825 std::auto_ptr<SearchFilter> filter_ap;
826
827 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
828 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
829
830 // See if this is an enumeration type option, and if so complete it here:
831
832 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
833 if (enum_values != NULL)
834 {
835 bool return_value = false;
836 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
837 for (int i = 0; enum_values[i].string_value != NULL; i++)
838 {
839 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
840 {
841 matches.AppendString (enum_values[i].string_value);
842 return_value = true;
843 }
844 }
845 return return_value;
846 }
847
848 // If this is a source file or symbol type completion, and there is a
849 // -shlib option somewhere in the supplied arguments, then make a search filter
850 // for that shared library.
851 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
852
853 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
854 if (completion_mask & CommandCompletions::eSourceFileCompletion
855 || completion_mask & CommandCompletions::eSymbolCompletion)
856 {
857 for (int i = 0; i < opt_element_vector.size(); i++)
858 {
859 int cur_defs_index = opt_element_vector[i].opt_defs_index;
860 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
861 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
862
863 // If this is the "shlib" option and there was an argument provided,
864 // restrict it to that shared library.
865 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
866 {
867 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
868 if (module_name)
869 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000870 FileSpec module_spec(module_name, false);
Jim Inghamc8332952010-08-26 21:32:51 +0000871 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000872 // Search filters require a target...
873 if (target_sp != NULL)
874 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
875 }
876 break;
877 }
878 }
879 }
880
Greg Clayton63094e02010-06-23 01:19:29 +0000881 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
882 completion_mask,
883 input.GetArgumentAtIndex (opt_arg_pos),
884 match_start_point,
885 max_return_elements,
886 filter_ap.get(),
Jim Ingham802f8b02010-06-30 05:02:46 +0000887 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000888 matches);
889
Chris Lattner24943d22010-06-08 16:52:24 +0000890}