blob: 8f1e10abaeca0453092205bcfd4972f2b543d72c [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//-------------------------------------------------------------------------
Greg Claytonf15996e2011-04-07 22:46:35 +000032Options::Options (CommandInterpreter &interpreter) :
33 m_interpreter (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +000034 m_getopt_table ()
35{
Jim Ingham34e9a982010-06-15 18:47:14 +000036 BuildValidOptionSets();
Chris Lattner24943d22010-06-08 16:52:24 +000037}
38
39Options::~Options ()
40{
41}
42
Chris Lattner24943d22010-06-08 16:52:24 +000043void
Greg Clayton143fcc32011-04-13 00:18:08 +000044Options::NotifyOptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +000045{
46 m_seen_options.clear();
Greg Clayton24bc5d92011-03-30 18:16:51 +000047 // Let the subclass reset its option values
Greg Clayton143fcc32011-04-13 00:18:08 +000048 OptionParsingStarting ();
49}
50
51Error
52Options::NotifyOptionParsingFinished ()
53{
54 return OptionParsingFinished ();
Chris Lattner24943d22010-06-08 16:52:24 +000055}
56
57void
58Options::OptionSeen (int option_idx)
59{
60 m_seen_options.insert ((char) option_idx);
61}
62
63// Returns true is set_a is a subset of set_b; Otherwise returns false.
64
65bool
66Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b)
67{
68 bool is_a_subset = true;
69 OptionSet::const_iterator pos_a;
70 OptionSet::const_iterator pos_b;
71
72 // set_a is a subset of set_b if every member of set_a is also a member of set_b
73
74 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a)
75 {
76 pos_b = set_b.find(*pos_a);
77 if (pos_b == set_b.end())
78 is_a_subset = false;
79 }
80
81 return is_a_subset;
82}
83
84// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) }
85
86size_t
87Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs)
88{
89 size_t num_diffs = 0;
90 OptionSet::const_iterator pos_a;
91 OptionSet::const_iterator pos_b;
92
93 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a)
94 {
95 pos_b = set_b.find(*pos_a);
96 if (pos_b == set_b.end())
97 {
98 ++num_diffs;
99 diffs.insert(*pos_a);
100 }
101 }
102
103 return num_diffs;
104}
105
106// Returns the union of set_a and set_b. Does not put duplicate members into the union.
107
108void
109Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
110{
111 OptionSet::const_iterator pos;
112 OptionSet::iterator pos_union;
113
114 // Put all the elements of set_a into the union.
115
116 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
117 union_set.insert(*pos);
118
119 // Put all the elements of set_b that are not already there into the union.
120 for (pos = set_b.begin(); pos != set_b.end(); ++pos)
121 {
122 pos_union = union_set.find(*pos);
123 if (pos_union == union_set.end())
124 union_set.insert(*pos);
125 }
126}
127
128bool
129Options::VerifyOptions (CommandReturnObject &result)
130{
131 bool options_are_valid = false;
132
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000133 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000134 if (num_levels)
135 {
136 for (int i = 0; i < num_levels && !options_are_valid; ++i)
137 {
138 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i]
139 // (i.e. all the required options at this level are a subset of m_seen_options); AND
140 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of
141 // m_seen_options are in the set of optional options at this level.
142
143 // Check to see if all of m_required_options[i] are a subset of m_seen_options
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000144 if (IsASubset (GetRequiredOptions()[i], m_seen_options))
Chris Lattner24943d22010-06-08 16:52:24 +0000145 {
146 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]}
147 OptionSet remaining_options;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000148 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options);
Chris Lattner24943d22010-06-08 16:52:24 +0000149 // Check to see if remaining_options is a subset of m_optional_options[i]
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000150 if (IsASubset (remaining_options, GetOptionalOptions()[i]))
Chris Lattner24943d22010-06-08 16:52:24 +0000151 options_are_valid = true;
152 }
153 }
154 }
155 else
156 {
157 options_are_valid = true;
158 }
159
160 if (options_are_valid)
161 {
162 result.SetStatus (eReturnStatusSuccessFinishNoResult);
163 }
164 else
165 {
166 result.AppendError ("invalid combination of options for the given command");
167 result.SetStatus (eReturnStatusFailed);
168 }
169
170 return options_are_valid;
171}
172
Jim Ingham34e9a982010-06-15 18:47:14 +0000173// This is called in the Options constructor, though we could call it lazily if that ends up being
174// a performance problem.
175
Chris Lattner24943d22010-06-08 16:52:24 +0000176void
177Options::BuildValidOptionSets ()
178{
179 // Check to see if we already did this.
180 if (m_required_options.size() != 0)
181 return;
182
183 // Check to see if there are any options.
184 int num_options = NumCommandOptions ();
185 if (num_options == 0)
186 return;
187
Greg Claytonb3448432011-03-24 21:19:54 +0000188 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000189 m_required_options.resize(1);
190 m_optional_options.resize(1);
Jim Ingham34e9a982010-06-15 18:47:14 +0000191
192 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS...
193
194 uint32_t num_option_sets = 0;
195
196 for (int i = 0; i < num_options; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000197 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000198 uint32_t this_usage_mask = full_options_table[i].usage_mask;
199 if (this_usage_mask == LLDB_OPT_SET_ALL)
Chris Lattner24943d22010-06-08 16:52:24 +0000200 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000201 if (num_option_sets == 0)
202 num_option_sets = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000203 }
204 else
205 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000206 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++)
207 {
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000208 if (this_usage_mask & (1 << j))
Jim Ingham34e9a982010-06-15 18:47:14 +0000209 {
210 if (num_option_sets <= j)
211 num_option_sets = j + 1;
212 }
213 }
Chris Lattner24943d22010-06-08 16:52:24 +0000214 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000215 }
Chris Lattner24943d22010-06-08 16:52:24 +0000216
Jim Ingham34e9a982010-06-15 18:47:14 +0000217 if (num_option_sets > 0)
218 {
219 m_required_options.resize(num_option_sets);
220 m_optional_options.resize(num_option_sets);
221
222 for (int i = 0; i < num_options; ++i)
223 {
224 for (int j = 0; j < num_option_sets; j++)
225 {
226 if (full_options_table[i].usage_mask & 1 << j)
227 {
228 if (full_options_table[i].required)
229 m_required_options[j].insert(full_options_table[i].short_option);
230 else
231 m_optional_options[j].insert(full_options_table[i].short_option);
232 }
233 }
234 }
Chris Lattner24943d22010-06-08 16:52:24 +0000235 }
236}
237
238uint32_t
239Options::NumCommandOptions ()
240{
Greg Claytonb3448432011-03-24 21:19:54 +0000241 const OptionDefinition *full_options_table = GetDefinitions ();
Jim Ingham34e9a982010-06-15 18:47:14 +0000242 if (full_options_table == NULL)
243 return 0;
244
Chris Lattner24943d22010-06-08 16:52:24 +0000245 int i = 0;
246
247 if (full_options_table != NULL)
248 {
249 while (full_options_table[i].long_option != NULL)
250 ++i;
251 }
252
253 return i;
254}
255
256struct option *
257Options::GetLongOptions ()
258{
259 // Check to see if this has already been done.
260 if (m_getopt_table.empty())
261 {
262 // Check to see if there are any options.
263 const uint32_t num_options = NumCommandOptions();
264 if (num_options == 0)
265 return NULL;
266
267 uint32_t i;
268 uint32_t j;
Greg Claytonb3448432011-03-24 21:19:54 +0000269 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000270
271 std::bitset<256> option_seen;
272
273 m_getopt_table.resize(num_options + 1);
274 for (i = 0, j = 0; i < num_options; ++i)
275 {
276 char short_opt = full_options_table[i].short_option;
277
278 if (option_seen.test(short_opt) == false)
279 {
280 m_getopt_table[j].name = full_options_table[i].long_option;
281 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg;
282 m_getopt_table[j].flag = NULL;
283 m_getopt_table[j].val = full_options_table[i].short_option;
284 option_seen.set(short_opt);
285 ++j;
286 }
287 }
288
289 //getopt_long requires a NULL final entry in the table:
290
291 m_getopt_table[j].name = NULL;
292 m_getopt_table[j].has_arg = 0;
293 m_getopt_table[j].flag = NULL;
294 m_getopt_table[j].val = 0;
295 }
296
Greg Clayton53d68e72010-07-20 22:52:08 +0000297 if (m_getopt_table.empty())
298 return NULL;
299
300 return &m_getopt_table.front();
Chris Lattner24943d22010-06-08 16:52:24 +0000301}
302
303
304// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is
305// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on
306// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces,
307// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each
308// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
309
310
311void
312Options::OutputFormattedUsageText
313(
314 Stream &strm,
315 const char *text,
316 uint32_t output_max_columns
317)
318{
319 int len = strlen (text);
320
321 // Will it all fit on one line?
322
323 if ((len + strm.GetIndentLevel()) < output_max_columns)
324 {
325 // Output it as a single line.
326 strm.Indent (text);
327 strm.EOL();
328 }
329 else
330 {
331 // We need to break it up into multiple lines.
332
333 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
334 int start = 0;
335 int end = start;
336 int final_end = strlen (text);
337 int sub_len;
338
339 while (end < final_end)
340 {
341 // Don't start the 'text' on a space, since we're already outputting the indentation.
342 while ((start < final_end) && (text[start] == ' '))
343 start++;
344
345 end = start + text_width;
346 if (end > final_end)
347 end = final_end;
348 else
349 {
350 // If we're not at the end of the text, make sure we break the line on white space.
351 while (end > start
352 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
353 end--;
354 }
355
356 sub_len = end - start;
357 if (start != 0)
358 strm.EOL();
359 strm.Indent();
360 assert (start < final_end);
361 assert (start + sub_len <= final_end);
362 strm.Write(text + start, sub_len);
363 start = end + 1;
364 }
365 strm.EOL();
366 }
367}
368
369void
370Options::GenerateOptionUsage
371(
372 Stream &strm,
Greg Clayton238c0a12010-09-18 01:14:36 +0000373 CommandObject *cmd
374)
Chris Lattner24943d22010-06-08 16:52:24 +0000375{
Greg Claytonf15996e2011-04-07 22:46:35 +0000376 const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth();
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000377
Greg Claytonb3448432011-03-24 21:19:54 +0000378 const OptionDefinition *full_options_table = GetDefinitions();
Chris Lattner24943d22010-06-08 16:52:24 +0000379 const uint32_t save_indent_level = strm.GetIndentLevel();
380 const char *name;
381
Caroline Ticefb355112010-10-01 17:46:38 +0000382 StreamString arguments_str;
383
Chris Lattner24943d22010-06-08 16:52:24 +0000384 if (cmd)
Caroline Ticefb355112010-10-01 17:46:38 +0000385 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000386 name = cmd->GetCommandName();
Caroline Ticefb355112010-10-01 17:46:38 +0000387 cmd->GetFormattedCommandArguments (arguments_str);
388 }
Chris Lattner24943d22010-06-08 16:52:24 +0000389 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000390 name = "";
Chris Lattner24943d22010-06-08 16:52:24 +0000391
392 strm.PutCString ("\nCommand Options Usage:\n");
393
394 strm.IndentMore(2);
395
396 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0]
397 // <cmd> [options-for-level-1]
398 // etc.
399
Chris Lattner24943d22010-06-08 16:52:24 +0000400 const uint32_t num_options = NumCommandOptions();
Jim Ingham34e9a982010-06-15 18:47:14 +0000401 if (num_options == 0)
402 return;
403
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000404 int num_option_sets = GetRequiredOptions().size();
Jim Ingham34e9a982010-06-15 18:47:14 +0000405
Chris Lattner24943d22010-06-08 16:52:24 +0000406 uint32_t i;
Jim Ingham34e9a982010-06-15 18:47:14 +0000407
408 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set)
Chris Lattner24943d22010-06-08 16:52:24 +0000409 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000410 uint32_t opt_set_mask;
411
412 opt_set_mask = 1 << opt_set;
413 if (opt_set > 0)
414 strm.Printf ("\n");
415 strm.Indent (name);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000416
Greg Claytonfe424a92010-09-18 03:37:20 +0000417 // First go through and print all options that take no arguments as
418 // a single string. If a command has "-a" "-b" and "-c", this will show
419 // up as [-abc]
420
421 std::set<char> options;
422 std::set<char>::const_iterator options_pos, options_end;
423 bool first;
424 for (i = 0, first = true; i < num_options; ++i)
425 {
426 if (full_options_table[i].usage_mask & opt_set_mask)
427 {
428 // Add current option to the end of out_stream.
429
430 if (full_options_table[i].required == true &&
431 full_options_table[i].option_has_arg == no_argument)
432 {
433 options.insert (full_options_table[i].short_option);
434 }
435 }
436 }
437
438 if (options.empty() == false)
439 {
440 // We have some required options with no arguments
441 strm.PutCString(" -");
442 for (i=0; i<2; ++i)
443 for (options_pos = options.begin(), options_end = options.end();
444 options_pos != options_end;
445 ++options_pos)
446 {
447 if (i==0 && ::isupper (*options_pos))
448 continue;
449 if (i==1 && ::islower (*options_pos))
450 continue;
451 strm << *options_pos;
452 }
453 }
454
455 for (i = 0, options.clear(); i < num_options; ++i)
456 {
457 if (full_options_table[i].usage_mask & opt_set_mask)
458 {
459 // Add current option to the end of out_stream.
460
461 if (full_options_table[i].required == false &&
462 full_options_table[i].option_has_arg == no_argument)
463 {
464 options.insert (full_options_table[i].short_option);
465 }
466 }
467 }
468
469 if (options.empty() == false)
470 {
471 // We have some required options with no arguments
472 strm.PutCString(" [-");
473 for (i=0; i<2; ++i)
474 for (options_pos = options.begin(), options_end = options.end();
475 options_pos != options_end;
476 ++options_pos)
477 {
478 if (i==0 && ::isupper (*options_pos))
479 continue;
480 if (i==1 && ::islower (*options_pos))
481 continue;
482 strm << *options_pos;
483 }
484 strm.PutChar(']');
485 }
486
Caroline Ticee5f18b02010-09-09 16:44:14 +0000487 // First go through and print the required options (list them up front).
Jim Ingham34e9a982010-06-15 18:47:14 +0000488
489 for (i = 0; i < num_options; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000490 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000491 if (full_options_table[i].usage_mask & opt_set_mask)
Chris Lattner24943d22010-06-08 16:52:24 +0000492 {
Jim Ingham34e9a982010-06-15 18:47:14 +0000493 // Add current option to the end of out_stream.
Caroline Tice4d6675c2010-10-01 19:59:14 +0000494 CommandArgumentType arg_type = full_options_table[i].argument_type;
495
Jim Ingham34e9a982010-06-15 18:47:14 +0000496 if (full_options_table[i].required)
497 {
498 if (full_options_table[i].option_has_arg == required_argument)
499 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000500 strm.Printf (" -%c <%s>",
501 full_options_table[i].short_option,
502 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000503 }
504 else if (full_options_table[i].option_has_arg == optional_argument)
505 {
Caroline Tice4d6675c2010-10-01 19:59:14 +0000506 strm.Printf (" -%c [<%s>]",
Jim Ingham34e9a982010-06-15 18:47:14 +0000507 full_options_table[i].short_option,
Caroline Tice4d6675c2010-10-01 19:59:14 +0000508 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000509 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000510 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000511 }
512 }
513
514 // Now go through again, and this time only print the optional options.
515
516 for (i = 0; i < num_options; ++i)
517 {
518 if (full_options_table[i].usage_mask & opt_set_mask)
519 {
520 // Add current option to the end of out_stream.
521
Caroline Tice4d6675c2010-10-01 19:59:14 +0000522 CommandArgumentType arg_type = full_options_table[i].argument_type;
523
Caroline Ticee5f18b02010-09-09 16:44:14 +0000524 if (! full_options_table[i].required)
Jim Ingham34e9a982010-06-15 18:47:14 +0000525 {
526 if (full_options_table[i].option_has_arg == required_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000527 strm.Printf (" [-%c <%s>]", full_options_table[i].short_option,
528 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000529 else if (full_options_table[i].option_has_arg == optional_argument)
Caroline Tice4d6675c2010-10-01 19:59:14 +0000530 strm.Printf (" [-%c [<%s>]]", full_options_table[i].short_option,
531 CommandObject::GetArgumentName (arg_type));
Jim Ingham34e9a982010-06-15 18:47:14 +0000532 }
Chris Lattner24943d22010-06-08 16:52:24 +0000533 }
Chris Lattner24943d22010-06-08 16:52:24 +0000534 }
Caroline Ticefb355112010-10-01 17:46:38 +0000535 if (arguments_str.GetSize() > 0)
536 strm.Printf (" %s", arguments_str.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000537 }
Chris Lattner24943d22010-06-08 16:52:24 +0000538 strm.Printf ("\n\n");
539
540 // 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 +0000541 // --long_name <argument> ( -short <argument> )
Chris Lattner24943d22010-06-08 16:52:24 +0000542 // help text
543
544 // This variable is used to keep track of which options' info we've printed out, because some options can be in
545 // more than one usage level, but we only want to print the long form of its information once.
546
547 OptionSet options_seen;
548 OptionSet::iterator pos;
549 strm.IndentMore (5);
550
Caroline Ticee5f18b02010-09-09 16:44:14 +0000551 std::vector<char> sorted_options;
552
553
554 // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
555 // when writing out detailed help for each option.
556
Chris Lattner24943d22010-06-08 16:52:24 +0000557 for (i = 0; i < num_options; ++i)
558 {
Chris Lattner24943d22010-06-08 16:52:24 +0000559 pos = options_seen.find (full_options_table[i].short_option);
560 if (pos == options_seen.end())
561 {
Chris Lattner24943d22010-06-08 16:52:24 +0000562 options_seen.insert (full_options_table[i].short_option);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000563 sorted_options.push_back (full_options_table[i].short_option);
564 }
565 }
Chris Lattner24943d22010-06-08 16:52:24 +0000566
Caroline Ticee5f18b02010-09-09 16:44:14 +0000567 std::sort (sorted_options.begin(), sorted_options.end());
568
569 // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
570 // and write out the detailed help information for that option.
571
572 int first_option_printed = 1;
573 size_t end = sorted_options.size();
574 for (size_t j = 0; j < end; ++j)
575 {
576 char option = sorted_options[j];
577 bool found = false;
578 for (i = 0; i < num_options && !found; ++i)
579 {
580 if (full_options_table[i].short_option == option)
581 {
582 found = true;
583 //Print out the help information for this option.
584
585 // Put a newline separation between arguments
586 if (first_option_printed)
587 first_option_printed = 0;
588 else
589 strm.EOL();
590
Caroline Tice4d6675c2010-10-01 19:59:14 +0000591 CommandArgumentType arg_type = full_options_table[i].argument_type;
592
593 StreamString arg_name_str;
594 arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
595
Caroline Ticee5f18b02010-09-09 16:44:14 +0000596 strm.Indent ();
Caroline Tice9e8e6962010-09-20 21:52:58 +0000597 strm.Printf ("-%c", full_options_table[i].short_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000598 if (arg_type != eArgTypeNone)
599 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
Caroline Tice9e8e6962010-09-20 21:52:58 +0000600 strm.Printf (" ( --%s", full_options_table[i].long_option);
Caroline Tice4d6675c2010-10-01 19:59:14 +0000601 if (arg_type != eArgTypeNone)
602 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
Greg Claytonfe424a92010-09-18 03:37:20 +0000603 strm.PutCString(" )\n");
Caroline Ticee5f18b02010-09-09 16:44:14 +0000604
605 strm.IndentMore (5);
606
607 if (full_options_table[i].usage_text)
Chris Lattner24943d22010-06-08 16:52:24 +0000608 OutputFormattedUsageText (strm,
609 full_options_table[i].usage_text,
610 screen_width);
Caroline Ticee5f18b02010-09-09 16:44:14 +0000611 if (full_options_table[i].enum_values != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000612 {
Caroline Ticee5f18b02010-09-09 16:44:14 +0000613 strm.Indent ();
614 strm.Printf("Values: ");
615 for (int k = 0; full_options_table[i].enum_values[k].string_value != NULL; k++)
616 {
617 if (k == 0)
618 strm.Printf("%s", full_options_table[i].enum_values[k].string_value);
619 else
620 strm.Printf(" | %s", full_options_table[i].enum_values[k].string_value);
621 }
622 strm.EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000623 }
Caroline Ticee5f18b02010-09-09 16:44:14 +0000624 strm.IndentLess (5);
Chris Lattner24943d22010-06-08 16:52:24 +0000625 }
Chris Lattner24943d22010-06-08 16:52:24 +0000626 }
627 }
628
629 // Restore the indent level
630 strm.SetIndentLevel (save_indent_level);
631}
632
633// This function is called when we have been given a potentially incomplete set of
634// options, such as when an alias has been defined (more options might be added at
635// at the time the alias is invoked). We need to verify that the options in the set
636// m_seen_options are all part of a set that may be used together, but m_seen_options
637// may be missing some of the "required" options.
638
639bool
640Options::VerifyPartialOptions (CommandReturnObject &result)
641{
642 bool options_are_valid = false;
643
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000644 int num_levels = GetRequiredOptions().size();
Chris Lattner24943d22010-06-08 16:52:24 +0000645 if (num_levels)
646 {
647 for (int i = 0; i < num_levels && !options_are_valid; ++i)
648 {
649 // In this case we are treating all options as optional rather than required.
650 // Therefore a set of options is correct if m_seen_options is a subset of the
651 // union of m_required_options and m_optional_options.
652 OptionSet union_set;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000653 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set);
Chris Lattner24943d22010-06-08 16:52:24 +0000654 if (IsASubset (m_seen_options, union_set))
655 options_are_valid = true;
656 }
657 }
658
659 return options_are_valid;
660}
661
662bool
663Options::HandleOptionCompletion
664(
665 Args &input,
666 OptionElementVector &opt_element_vector,
667 int cursor_index,
668 int char_pos,
669 int match_start_point,
670 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000671 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000672 lldb_private::StringList &matches
673)
674{
Jim Ingham802f8b02010-06-30 05:02:46 +0000675 word_complete = true;
676
Chris Lattner24943d22010-06-08 16:52:24 +0000677 // For now we just scan the completions to see if the cursor position is in
678 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
679 // In the future we can use completion to validate options as well if we want.
680
681 const OptionDefinition *opt_defs = GetDefinitions();
682
683 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index));
684 cur_opt_std_str.erase(char_pos);
685 const char *cur_opt_str = cur_opt_std_str.c_str();
686
687 for (int i = 0; i < opt_element_vector.size(); i++)
688 {
689 int opt_pos = opt_element_vector[i].opt_pos;
690 int opt_arg_pos = opt_element_vector[i].opt_arg_pos;
691 int opt_defs_index = opt_element_vector[i].opt_defs_index;
692 if (opt_pos == cursor_index)
693 {
694 // We're completing the option itself.
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000695
696 if (opt_defs_index == OptionArgElement::eBareDash)
697 {
698 // We're completing a bare dash. That means all options are open.
699 // FIXME: We should scan the other options provided and only complete options
700 // within the option group they belong to.
701 char opt_str[3] = {'-', 'a', '\0'};
702
Greg Claytonbef15832010-07-14 00:18:15 +0000703 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000704 {
Greg Claytonbef15832010-07-14 00:18:15 +0000705 opt_str[1] = opt_defs[j].short_option;
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000706 matches.AppendString (opt_str);
707 }
708 return true;
709 }
710 else if (opt_defs_index == OptionArgElement::eBareDoubleDash)
711 {
712 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000713 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000714 {
715 full_name.erase(full_name.begin() + 2, full_name.end());
Greg Claytonbef15832010-07-14 00:18:15 +0000716 full_name.append (opt_defs[j].long_option);
Jim Ingham8b9af1c2010-06-24 20:30:15 +0000717 matches.AppendString (full_name.c_str());
718 }
719 return true;
720 }
721 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
Chris Lattner24943d22010-06-08 16:52:24 +0000722 {
723 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
724 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
725 // The string so the upper level code will know this is a full match and add the " ".
726 if (cur_opt_str && strlen (cur_opt_str) > 2
727 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-'
728 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0)
729 {
730 std::string full_name ("--");
731 full_name.append (opt_defs[opt_defs_index].long_option);
732 matches.AppendString(full_name.c_str());
733 return true;
734 }
735 else
736 {
737 matches.AppendString(input.GetArgumentAtIndex(cursor_index));
738 return true;
739 }
740 }
741 else
742 {
743 // FIXME - not handling wrong options yet:
744 // Check to see if they are writing a long option & complete it.
745 // I think we will only get in here if the long option table has two elements
746 // that are not unique up to this point. getopt_long does shortest unique match
747 // for long options already.
748
749 if (cur_opt_str && strlen (cur_opt_str) > 2
750 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-')
751 {
Greg Claytonbef15832010-07-14 00:18:15 +0000752 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000753 {
Greg Claytonbef15832010-07-14 00:18:15 +0000754 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option)
Chris Lattner24943d22010-06-08 16:52:24 +0000755 {
756 std::string full_name ("--");
Greg Claytonbef15832010-07-14 00:18:15 +0000757 full_name.append (opt_defs[j].long_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000758 // The options definitions table has duplicates because of the
759 // way the grouping information is stored, so only add once.
760 bool duplicate = false;
Greg Claytonbef15832010-07-14 00:18:15 +0000761 for (int k = 0; k < matches.GetSize(); k++)
Chris Lattner24943d22010-06-08 16:52:24 +0000762 {
Greg Claytonbef15832010-07-14 00:18:15 +0000763 if (matches.GetStringAtIndex(k) == full_name)
Chris Lattner24943d22010-06-08 16:52:24 +0000764 {
765 duplicate = true;
766 break;
767 }
768 }
769 if (!duplicate)
770 matches.AppendString(full_name.c_str());
771 }
772 }
773 }
774 return true;
775 }
776
777
778 }
779 else if (opt_arg_pos == cursor_index)
780 {
781 // Okay the cursor is on the completion of an argument.
782 // See if it has a completion, otherwise return no matches.
783
784 if (opt_defs_index != -1)
785 {
Greg Claytonf15996e2011-04-07 22:46:35 +0000786 HandleOptionArgumentCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000787 cursor_index,
788 strlen (input.GetArgumentAtIndex(cursor_index)),
789 opt_element_vector,
790 i,
791 match_start_point,
792 max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000793 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000794 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000795 return true;
796 }
797 else
798 {
799 // No completion callback means no completions...
800 return true;
801 }
802
803 }
804 else
805 {
806 // Not the last element, keep going.
807 continue;
808 }
809 }
810 return false;
811}
812
813bool
814Options::HandleOptionArgumentCompletion
815(
816 Args &input,
817 int cursor_index,
818 int char_pos,
819 OptionElementVector &opt_element_vector,
820 int opt_element_index,
821 int match_start_point,
822 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000823 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000824 lldb_private::StringList &matches
825)
826{
827 const OptionDefinition *opt_defs = GetDefinitions();
828 std::auto_ptr<SearchFilter> filter_ap;
829
830 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
831 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
832
833 // See if this is an enumeration type option, and if so complete it here:
834
835 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
836 if (enum_values != NULL)
837 {
838 bool return_value = false;
839 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos);
840 for (int i = 0; enum_values[i].string_value != NULL; i++)
841 {
842 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value)
843 {
844 matches.AppendString (enum_values[i].string_value);
845 return_value = true;
846 }
847 }
848 return return_value;
849 }
850
851 // If this is a source file or symbol type completion, and there is a
852 // -shlib option somewhere in the supplied arguments, then make a search filter
853 // for that shared library.
854 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names?
855
856 uint32_t completion_mask = opt_defs[opt_defs_index].completionType;
857 if (completion_mask & CommandCompletions::eSourceFileCompletion
858 || completion_mask & CommandCompletions::eSymbolCompletion)
859 {
860 for (int i = 0; i < opt_element_vector.size(); i++)
861 {
862 int cur_defs_index = opt_element_vector[i].opt_defs_index;
863 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
864 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
865
866 // If this is the "shlib" option and there was an argument provided,
867 // restrict it to that shared library.
868 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1)
869 {
870 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos);
871 if (module_name)
872 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000873 FileSpec module_spec(module_name, false);
Greg Claytonf15996e2011-04-07 22:46:35 +0000874 lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
Chris Lattner24943d22010-06-08 16:52:24 +0000875 // Search filters require a target...
876 if (target_sp != NULL)
877 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec));
878 }
879 break;
880 }
881 }
882 }
883
Greg Claytonf15996e2011-04-07 22:46:35 +0000884 return CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
Greg Clayton63094e02010-06-23 01:19:29 +0000885 completion_mask,
886 input.GetArgumentAtIndex (opt_arg_pos),
887 match_start_point,
888 max_return_elements,
889 filter_ap.get(),
Jim Ingham802f8b02010-06-30 05:02:46 +0000890 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000891 matches);
892
Chris Lattner24943d22010-06-08 16:52:24 +0000893}
Greg Clayton143fcc32011-04-13 00:18:08 +0000894
895
896
897
898void
899OptionGroupOptions::Append (OptionGroup* group)
900{
901 m_option_groups.push_back (group);
902 const OptionDefinition* group_option_defs = group->GetDefinitions ();
903 const uint32_t group_option_count = group->GetNumDefinitions();
904 for (uint32_t i=0; i<group_option_count; ++i)
905 m_option_defs.push_back (group_option_defs[i]);
906}
907
908void
909OptionGroupOptions::Append (OptionGroup* group, uint32_t usage_mask)
910{
911 m_option_groups.push_back (group);
912 const OptionDefinition* group_option_defs = group->GetDefinitions ();
913 const uint32_t group_option_count = group->GetNumDefinitions();
914 for (uint32_t i=0; i<group_option_count; ++i)
915 {
916 m_option_defs.push_back (group_option_defs[i]);
917 m_option_defs.back().usage_mask = usage_mask;
918 }
919}
920
921void
922OptionGroupOptions::Finalize ()
923{
924 m_did_finalize = true;
925 OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL };
926 m_option_defs.push_back (empty_option_def);
927}
928
929Error
930OptionGroupOptions::SetOptionValue (uint32_t option_idx,
931 const char *option_value)
932{
933 // After calling OptionGroupOptions::Append(...), you must finalize the groups
934 // by calling OptionGroupOptions::Finlize()
935 assert (m_did_finalize);
936
937 uint32_t curr_idx = 0;
938 OptionGroupsType::iterator pos, end = m_option_groups.end();
939 for (pos = m_option_groups.begin(); pos != end; ++pos)
940 {
941 const uint32_t num_group_definitions = (*pos)->GetNumDefinitions();
942 if (option_idx < curr_idx + num_group_definitions)
943 return (*pos)->SetOptionValue (m_interpreter, option_idx - curr_idx, option_value);
944 curr_idx += num_group_definitions;
945 }
946 Error error;
947 error.SetErrorString ("invalid option index"); // Shouldn't happen...
948 return error;
949}
950
951void
952OptionGroupOptions::OptionParsingStarting ()
953{
954 OptionGroupsType::iterator pos, end = m_option_groups.end();
955 for (pos = m_option_groups.begin(); pos != end; ++pos)
956 (*pos)->OptionParsingStarting (m_interpreter);
957}
958Error
959OptionGroupOptions::OptionParsingFinished ()
960{
961 Error error;
962 OptionGroupsType::iterator pos, end = m_option_groups.end();
963 for (pos = m_option_groups.begin(); pos != end; ++pos)
964 {
965 error = (*pos)->OptionParsingFinished (m_interpreter);
966 if (error.Fail())
967 return error;
968 }
969 return error;
970}