LLDB mainline
Options.cpp
Go to the documentation of this file.
1//===-- Options.cpp -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include <algorithm>
12#include <bitset>
13#include <map>
14#include <set>
15
22#include "lldb/Target/Target.h"
25#include "llvm/ADT/STLExtras.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30namespace lldb_private {
31
32/// An llvm::Error that represents an option parsing diagnostic.
34 : public llvm::ErrorInfo<OptionParseError, DiagnosticError> {
35 std::vector<DiagnosticDetail> m_details;
36
37public:
38 using llvm::ErrorInfo<OptionParseError, DiagnosticError>::ErrorInfo;
40 : ErrorInfo(std::error_code(EINVAL, std::generic_category())),
41 m_details({detail}) {}
42 OptionParseError(const Args::ArgEntry &arg, std::string msg)
43 : ErrorInfo(std::error_code(EINVAL, std::generic_category())) {
45 if (auto pos = arg.GetPos()) {
46 uint16_t len = arg.GetLength();
47 sloc = {FileSpec{}, 1, *pos, len, false, true};
48 }
49 m_details.push_back(DiagnosticDetail{sloc, lldb::eSeverityError, msg, msg});
50 }
51 std::unique_ptr<CloneableError> Clone() const override {
52 return std::make_unique<OptionParseError>(m_details[0]);
53 }
54 llvm::ArrayRef<DiagnosticDetail> GetDetails() const override {
55 return m_details;
56 }
57 static char ID;
58};
59
61
62} // namespace lldb_private
63
64// Options
66
67Options::~Options() = default;
68
70 m_seen_options.clear();
71 // Let the subclass reset its option values
72 OptionParsingStarting(execution_context);
73}
74
77 return OptionParsingFinished(execution_context);
78}
79
80void Options::OptionSeen(int option_idx) { m_seen_options.insert(option_idx); }
81
82// Returns true is set_a is a subset of set_b; Otherwise returns false.
83
84bool Options::IsASubset(const OptionSet &set_a, const OptionSet &set_b) {
85 bool is_a_subset = true;
86 OptionSet::const_iterator pos_a;
87 OptionSet::const_iterator pos_b;
88
89 // set_a is a subset of set_b if every member of set_a is also a member of
90 // set_b
91
92 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) {
93 pos_b = set_b.find(*pos_a);
94 if (pos_b == set_b.end())
95 is_a_subset = false;
96 }
97
98 return is_a_subset;
99}
100
101// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) &&
102// !ElementOf (x, set_b) }
103
104size_t Options::OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b,
105 OptionSet &diffs) {
106 size_t num_diffs = 0;
107 OptionSet::const_iterator pos_a;
108 OptionSet::const_iterator pos_b;
109
110 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) {
111 pos_b = set_b.find(*pos_a);
112 if (pos_b == set_b.end()) {
113 ++num_diffs;
114 diffs.insert(*pos_a);
115 }
116 }
117
118 return num_diffs;
119}
120
121// Returns the union of set_a and set_b. Does not put duplicate members into
122// the union.
123
124void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
125 OptionSet &union_set) {
126 OptionSet::const_iterator pos;
127 OptionSet::iterator pos_union;
128
129 // Put all the elements of set_a into the union.
130
131 for (pos = set_a.begin(); pos != set_a.end(); ++pos)
132 union_set.insert(*pos);
133
134 // Put all the elements of set_b that are not already there into the union.
135 for (pos = set_b.begin(); pos != set_b.end(); ++pos) {
136 pos_union = union_set.find(*pos);
137 if (pos_union == union_set.end())
138 union_set.insert(*pos);
139 }
140}
141
142// This is called in the Options constructor, though we could call it lazily if
143// that ends up being a performance problem.
144
146 // Check to see if we already did this.
147 if (m_required_options.size() != 0)
148 return;
149
150 // Check to see if there are any options.
151 int num_options = NumCommandOptions();
152 if (num_options == 0)
153 return;
154
155 auto opt_defs = GetDefinitions();
156 m_required_options.resize(1);
157 m_optional_options.resize(1);
158
159 // First count the number of option sets we've got. Ignore
160 // LLDB_ALL_OPTION_SETS...
161
162 uint32_t num_option_sets = 0;
163
164 for (const auto &def : opt_defs) {
165 uint32_t this_usage_mask = def.usage_mask;
166 if (this_usage_mask == LLDB_OPT_SET_ALL) {
167 if (num_option_sets == 0)
168 num_option_sets = 1;
169 } else {
170 for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) {
171 if (this_usage_mask & (1 << j)) {
172 if (num_option_sets <= j)
173 num_option_sets = j + 1;
174 }
175 }
176 }
177 }
178
179 if (num_option_sets > 0) {
180 m_required_options.resize(num_option_sets);
181 m_optional_options.resize(num_option_sets);
182
183 for (const auto &def : opt_defs) {
184 for (uint32_t j = 0; j < num_option_sets; j++) {
185 if (def.usage_mask & 1 << j) {
186 if (def.required)
187 m_required_options[j].insert(def.short_option);
188 else
189 m_optional_options[j].insert(def.short_option);
190 }
191 }
192 }
193 }
194}
195
196uint32_t Options::NumCommandOptions() { return GetDefinitions().size(); }
197
199 // Check to see if this has already been done.
200 if (m_getopt_table.empty()) {
201 auto defs = GetDefinitions();
202 if (defs.empty())
203 return nullptr;
204
205 std::map<int, uint32_t> option_seen;
206
207 m_getopt_table.resize(defs.size() + 1);
208 for (size_t i = 0; i < defs.size(); ++i) {
209 const int short_opt = defs[i].short_option;
210
211 m_getopt_table[i].definition = &defs[i];
212 m_getopt_table[i].flag = nullptr;
213 m_getopt_table[i].val = short_opt;
214
215 auto [pos, inserted] = option_seen.try_emplace(short_opt, i);
216 if (!inserted && short_opt) {
217 m_getopt_table[i].val = 0;
218 StreamString strm;
219 if (defs[i].HasShortOption())
221 llvm::formatv(
222 "option[{0}] --{1} has a short option -{2} that "
223 "conflicts with option[{3}] --{4}, short option won't "
224 "be used for --{5}",
225 i, defs[i].long_option, short_opt, pos->second,
226 m_getopt_table[pos->second].definition->long_option,
227 defs[i].long_option)
228 .str());
229 else
231 llvm::formatv(
232 "option[{0}] --{1} has a short option {2:x} that "
233 "conflicts with option[{3}] --{4}, short option won't "
234 "be used for --{5}",
235 (int)i, defs[i].long_option, short_opt, pos->second,
236 m_getopt_table[pos->second].definition->long_option,
237 defs[i].long_option)
238 .str());
239 }
240 }
241
242 // getopt_long_only requires a NULL final entry in the table:
243
244 m_getopt_table.back().definition = nullptr;
245 m_getopt_table.back().flag = nullptr;
246 m_getopt_table.back().val = 0;
247 }
248
249 if (m_getopt_table.empty())
250 return nullptr;
251
252 return &m_getopt_table.front();
253}
254
255// This function takes INDENT, which tells how many spaces to output at the
256// front of each line; SPACES, which is a string containing 80 spaces; and
257// TEXT, which is the text that is to be output. It outputs the text, on
258// multiple lines if necessary, to RESULT, with INDENT spaces at the front of
259// each line. It breaks lines on spaces, tabs or newlines, shortening the line
260// if necessary to not break in the middle of a word. It assumes that each
261// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
262
264 const OptionDefinition &option_def,
265 uint32_t output_max_columns,
266 bool use_color) {
267 std::string actual_text;
268 if (option_def.validator) {
269 if (const char *condition = option_def.validator->ShortConditionString()) {
270 actual_text = "[";
271 actual_text.append(condition);
272 actual_text.append("] ");
273 }
274 }
275 actual_text.append(
276 ansi::FormatAnsiTerminalCodes(option_def.usage_text, use_color));
277 const size_t visible_length = ansi::ColumnWidth(actual_text);
278
279 // Will it all fit on one line?
280 if (static_cast<uint32_t>(visible_length + strm.GetIndentLevel()) <
281 output_max_columns) {
282 // Output it as a single line.
283 strm.Indent(actual_text);
284 strm.EOL();
285 return;
286 }
287
288 // We need to break it up into multiple lines. We can do this based on the
289 // formatted text because we know that:
290 // * We only break lines on whitespace, therefore we will not break in the
291 // middle of a Unicode character or escape code.
292 // * Escape codes are so far not applied to multiple words, so there is no
293 // risk of breaking up a phrase and the escape code being incorrectly
294 // applied to the indent too.
295
296 const int max_text_width = output_max_columns - strm.GetIndentLevel() - 1;
297 int start = 0;
298 int end = start;
299 const int final_end = visible_length;
300
301 while (end < final_end) {
302 // Don't start the 'text' on a space, since we're already outputting the
303 // indentation.
304 while ((start < final_end) && (actual_text[start] == ' '))
305 start++;
306
307 end = start + max_text_width;
308 if (end > final_end) {
309 end = final_end;
310 } else {
311 // If we're not at the end of the text, make sure we break the line on
312 // white space.
313 while (end > start && actual_text[end] != ' ' &&
314 actual_text[end] != '\t' && actual_text[end] != '\n')
315 end--;
316 }
317
318 const int sub_len = end - start;
319 if (start != 0)
320 strm.EOL();
321 strm.Indent();
322 assert(start < final_end);
323 assert(start + sub_len <= final_end);
324 strm.PutCString(llvm::StringRef(actual_text.c_str() + start, sub_len));
325 start = end + 1;
326 }
327 strm.EOL();
328}
329
330bool Options::SupportsLongOption(const char *long_option) {
331 if (!long_option || !long_option[0])
332 return false;
333
334 auto opt_defs = GetDefinitions();
335 if (opt_defs.empty())
336 return false;
337
338 const char *long_option_name = long_option;
339 if (long_option[0] == '-' && long_option[1] == '-')
340 long_option_name += 2;
341
342 for (auto &def : opt_defs) {
343 if (!def.long_option)
344 continue;
345
346 if (strcmp(def.long_option, long_option_name) == 0)
347 return true;
348 }
349
350 return false;
351}
352
358
359static bool PrintOption(const OptionDefinition &opt_def,
360 OptionDisplayType display_type, const char *header,
361 const char *footer, bool show_optional, Stream &strm) {
362 if (display_type == eDisplayShortOption && !opt_def.HasShortOption())
363 return false;
364
365 if (header && header[0])
366 strm.PutCString(header);
367
368 if (show_optional && !opt_def.required)
369 strm.PutChar('[');
370 const bool show_short_option =
371 opt_def.HasShortOption() && display_type != eDisplayLongOption;
372 if (show_short_option)
373 strm.Printf("-%c", opt_def.short_option);
374 else
375 strm.Printf("--%s", opt_def.long_option);
376 switch (opt_def.option_has_arg) {
378 break;
381 break;
382
384 strm.Printf("%s[<%s>]", show_short_option ? "" : "=",
386 break;
387 }
388 if (show_optional && !opt_def.required)
389 strm.PutChar(']');
390 if (footer && footer[0])
391 strm.PutCString(footer);
392 return true;
393}
394
396 uint32_t screen_width, bool use_color) {
397 auto opt_defs = GetDefinitions();
398 const uint32_t save_indent_level = strm.GetIndentLevel();
399 llvm::StringRef name = cmd.GetCommandName();
400 StreamString arguments_str;
401 cmd.GetFormattedCommandArguments(arguments_str);
402
403 const uint32_t num_options = NumCommandOptions();
404 if (num_options == 0)
405 return;
406
407 const bool only_print_args = cmd.IsDashDashCommand();
408 if (!only_print_args)
409 strm.PutCString("\nCommand Options Usage:\n");
410
411 strm.IndentMore(2);
412
413 // First, show each usage level set of options, e.g. <cmd> [options-for-
414 // level-0]
415 // <cmd>
416 // [options-for-level-1]
417 // etc.
418
419 if (!only_print_args) {
420 uint32_t num_option_sets = GetRequiredOptions().size();
421 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) {
422 if (opt_set > 0)
423 strm.Printf("\n");
424 strm.Indent(name);
425
426 // Different option sets may require different args.
427 StreamString args_str;
428 uint32_t opt_set_mask = 1 << opt_set;
429 cmd.GetFormattedCommandArguments(args_str, opt_set_mask);
430
431 // First go through and print all options that take no arguments as a
432 // single string. If a command has "-a" "-b" and "-c", this will show up
433 // as [-abc]
434
435 // We use a set here so that they will be sorted.
436 std::set<int> required_options;
437 std::set<int> optional_options;
438
439 for (auto &def : opt_defs) {
440 if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
441 def.option_has_arg == OptionParser::eNoArgument) {
442 if (def.required) {
443 required_options.insert(def.short_option);
444 } else {
445 optional_options.insert(def.short_option);
446 }
447 }
448 }
449
450 if (!required_options.empty()) {
451 strm.PutCString(" -");
452 for (int short_option : required_options)
453 strm.PutChar(short_option);
454 }
455
456 if (!optional_options.empty()) {
457 strm.PutCString(" [-");
458 for (int short_option : optional_options)
459 strm.PutChar(short_option);
460 strm.PutChar(']');
461 }
462
463 // First go through and print the required options (list them up front).
464 for (auto &def : opt_defs) {
465 if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
466 def.required && def.option_has_arg != OptionParser::eNoArgument)
467 PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
468 }
469
470 // Now go through again, and this time only print the optional options.
471 for (auto &def : opt_defs) {
472 if (def.usage_mask & opt_set_mask && !def.required &&
473 def.option_has_arg != OptionParser::eNoArgument)
474 PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
475 }
476
477 if (args_str.GetSize() > 0) {
478 if (cmd.WantsRawCommandString())
479 strm.Printf(" --");
480 strm << " " << args_str.GetString();
481 }
482 }
483 }
484
485 if ((only_print_args || cmd.WantsRawCommandString()) &&
486 arguments_str.GetSize() > 0) {
487 if (!only_print_args)
488 strm.PutChar('\n');
489 strm.Indent(name);
490 strm << " " << arguments_str.GetString();
491 }
492
493 if (!only_print_args) {
494 strm.Printf("\n\n");
495
496 // Now print out all the detailed information about the various options:
497 // long form, short form and help text:
498 // -short <argument> ( --long_name <argument> )
499 // help text
500
501 strm.IndentMore(5);
502
503 // Put the command options in a sorted container, so we can output
504 // them alphabetically by short_option.
505 std::multimap<int, uint32_t> options_ordered;
506 for (auto def : llvm::enumerate(opt_defs))
507 options_ordered.insert(
508 std::make_pair(def.value().short_option, def.index()));
509
510 // Go through each option, find the table entry and write out the detailed
511 // help information for that option.
512
513 bool first_option_printed = false;
514
515 for (auto pos : options_ordered) {
516 // Put a newline separation between arguments
517 if (first_option_printed)
518 strm.EOL();
519 else
520 first_option_printed = true;
521
522 OptionDefinition opt_def = opt_defs[pos.second];
523
524 strm.Indent();
525 if (opt_def.short_option && opt_def.HasShortOption()) {
526 PrintOption(opt_def, eDisplayShortOption, nullptr, nullptr, false,
527 strm);
528 PrintOption(opt_def, eDisplayLongOption, " ( ", " )", false, strm);
529 } else {
530 // Short option is not printable, just print long option
531 PrintOption(opt_def, eDisplayLongOption, nullptr, nullptr, false, strm);
532 }
533 strm.EOL();
534
535 strm.IndentMore(5);
536
537 if (opt_def.usage_text)
538 OutputFormattedUsageText(strm, opt_def, screen_width, use_color);
539 if (!opt_def.enum_values.empty()) {
540 strm.Indent();
541 strm.Printf("Values: ");
542 bool is_first = true;
543 for (const auto &enum_value : opt_def.enum_values) {
544 if (is_first) {
545 strm.Printf("%s", enum_value.string_value);
546 is_first = false;
547 }
548 else
549 strm.Printf(" | %s", enum_value.string_value);
550 }
551 strm.EOL();
552 }
553 strm.IndentLess(5);
554 }
555 }
556
557 // Restore the indent level
558 strm.SetIndentLevel(save_indent_level);
559}
560
562 bool options_are_valid = false;
563
564 int num_levels = GetRequiredOptions().size();
565 if (num_levels) {
566 for (int i = 0; i < num_levels && !options_are_valid; ++i) {
567 // This is the correct set of options if: 1). m_seen_options contains
568 // all of m_required_options[i] (i.e. all the required options at this
569 // level are a subset of m_seen_options); AND 2). { m_seen_options -
570 // m_required_options[i] is a subset of m_options_options[i] (i.e. all
571 // the rest of m_seen_options are in the set of optional options at this
572 // level.
573
574 // Check to see if all of m_required_options[i] are a subset of
575 // m_seen_options
577 // Construct the set difference: remaining_options = {m_seen_options} -
578 // {m_required_options[i]}
579 OptionSet remaining_options;
581 remaining_options);
582 // Check to see if remaining_options is a subset of
583 // m_optional_options[i]
584 if (IsASubset(remaining_options, GetOptionalOptions()[i]))
585 options_are_valid = true;
586 }
587 }
588 } else {
589 options_are_valid = true;
590 }
591
592 if (!options_are_valid)
593 return llvm::createStringError(
594 "invalid combination of options for the given command");
595
596 return llvm::Error::success();
597}
598
599// This function is called when we have been given a potentially incomplete set
600// of options, such as when an alias has been defined (more options might be
601// added at at the time the alias is invoked). We need to verify that the
602// options in the set m_seen_options are all part of a set that may be used
603// together, but m_seen_options may be missing some of the "required" options.
605 bool options_are_valid = false;
606
607 int num_levels = GetRequiredOptions().size();
608 if (num_levels) {
609 for (int i = 0; i < num_levels && !options_are_valid; ++i) {
610 // In this case we are treating all options as optional rather than
611 // required. Therefore a set of options is correct if m_seen_options is a
612 // subset of the union of m_required_options and m_optional_options.
613 OptionSet union_set;
615 union_set);
616 if (IsASubset(m_seen_options, union_set))
617 options_are_valid = true;
618 }
619 }
620
621 if (!options_are_valid)
622 return llvm::createStringError(
623 "invalid combination of options for the given command");
624
625 return llvm::Error::success();
626}
627
629 OptionElementVector &opt_element_vector,
630 CommandInterpreter &interpreter) {
631 // For now we just scan the completions to see if the cursor position is in
632 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
633 // In the future we can use completion to validate options as well if we
634 // want.
635
636 auto opt_defs = GetDefinitions();
637
638 llvm::StringRef cur_opt_str = request.GetCursorArgumentPrefix();
639 const bool use_color = interpreter.GetDebugger().GetUseColor();
640
641 for (size_t i = 0; i < opt_element_vector.size(); i++) {
642 size_t opt_pos = static_cast<size_t>(opt_element_vector[i].opt_pos);
643 size_t opt_arg_pos = static_cast<size_t>(opt_element_vector[i].opt_arg_pos);
644 int opt_defs_index = opt_element_vector[i].opt_defs_index;
645 if (opt_pos == request.GetCursorIndex()) {
646 // We're completing the option itself.
647
648 if (opt_defs_index == OptionArgElement::eBareDash) {
649 // We're completing a bare dash. That means all options are open.
650 // FIXME: We should scan the other options provided and only complete
651 // options
652 // within the option group they belong to.
653 std::string opt_str = "-a";
654
655 for (auto &def : opt_defs) {
656 if (!def.short_option)
657 continue;
658 opt_str[1] = def.short_option;
660 def.usage_text, use_color));
661 }
662
663 return true;
664 } else if (opt_defs_index == OptionArgElement::eBareDoubleDash) {
665 std::string full_name("--");
666 for (auto &def : opt_defs) {
667 if (!def.short_option)
668 continue;
669
670 full_name.erase(full_name.begin() + 2, full_name.end());
671 full_name.append(def.long_option);
673 def.usage_text, use_color));
674 }
675 return true;
676 } else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) {
677 // We recognized it, if it an incomplete long option, complete it
678 // anyway (getopt_long_only is happy with shortest unique string, but
679 // it's still a nice thing to do.) Otherwise return The string so the
680 // upper level code will know this is a full match and add the " ".
681 const OptionDefinition &opt = opt_defs[opt_defs_index];
682 llvm::StringRef long_option = opt.long_option;
683 if (cur_opt_str.starts_with("--") && cur_opt_str != long_option) {
684 request.AddCompletion(
685 "--" + long_option.str(),
687 return true;
688 } else
689 request.AddCompletion(request.GetCursorArgumentPrefix());
690 return true;
691 } else {
692 // FIXME - not handling wrong options yet:
693 // Check to see if they are writing a long option & complete it.
694 // I think we will only get in here if the long option table has two
695 // elements
696 // that are not unique up to this point. getopt_long_only does
697 // shortest unique match for long options already.
698 if (cur_opt_str.consume_front("--")) {
699 for (auto &def : opt_defs) {
700 llvm::StringRef long_option(def.long_option);
701 if (long_option.starts_with(cur_opt_str))
702 request.AddCompletion(
703 "--" + long_option.str(),
704 ansi::FormatAnsiTerminalCodes(def.usage_text, use_color));
705 }
706 }
707 return true;
708 }
709
710 } else if (opt_arg_pos == request.GetCursorIndex()) {
711 // Okay the cursor is on the completion of an argument. See if it has a
712 // completion, otherwise return no matches. Note, opt_defs_index == -1
713 // means we're after an option, but that option doesn't exist. We'll
714 // end up treating that as an argument. Not sure we can do much better.
715 if (opt_defs_index != -1) {
716 HandleOptionArgumentCompletion(request, opt_element_vector, i,
717 interpreter);
718 return true;
719 } else {
720 // No completion callback means no completions...
721 return true;
722 }
723
724 } else {
725 // Not the last element, keep going.
726 continue;
727 }
728 }
729 return false;
730}
731
733 CompletionRequest &request, OptionElementVector &opt_element_vector,
734 int opt_element_index, CommandInterpreter &interpreter) {
735 auto opt_defs = GetDefinitions();
736 std::unique_ptr<SearchFilter> filter_up;
737
738 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
739
740 // See if this is an enumeration type option, and if so complete it here:
741 const auto &enum_values = opt_defs[opt_defs_index].enum_values;
742 if (!enum_values.empty())
743 for (const auto &enum_value : enum_values)
744 request.TryCompleteCurrentArg(enum_value.string_value);
745
746 // If this is a source file or symbol type completion, and there is a -shlib
747 // option somewhere in the supplied arguments, then make a search filter for
748 // that shared library.
749 // FIXME: Do we want to also have an "OptionType" so we don't have to match
750 // string names?
751
752 uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
753
754 if (completion_mask == 0) {
755 lldb::CommandArgumentType option_arg_type =
756 opt_defs[opt_defs_index].argument_type;
757 if (option_arg_type != eArgTypeNone) {
758 const CommandObject::ArgumentTableEntry *arg_entry =
760 opt_defs[opt_defs_index].argument_type);
761 if (arg_entry)
762 completion_mask = arg_entry->completion_type;
763 }
764 }
765
766 if (completion_mask & lldb::eSourceFileCompletion ||
767 completion_mask & lldb::eSymbolCompletion) {
768 for (size_t i = 0; i < opt_element_vector.size(); i++) {
769 int cur_defs_index = opt_element_vector[i].opt_defs_index;
770
771 // trying to use <0 indices will definitely cause problems
772 if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
773 cur_defs_index == OptionArgElement::eBareDash ||
774 cur_defs_index == OptionArgElement::eBareDoubleDash)
775 continue;
776
777 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
778 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
779
780 // If this is the "shlib" option and there was an argument provided,
781 // restrict it to that shared library.
782 if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 &&
783 cur_arg_pos != -1) {
784 const char *module_name =
785 request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
786 if (module_name) {
787 FileSpec module_spec(module_name);
788 lldb::TargetSP target_sp =
789 interpreter.GetDebugger().GetSelectedTarget();
790 // Search filters require a target...
791 if (target_sp)
792 filter_up =
793 std::make_unique<SearchFilterByModule>(target_sp, module_spec);
794 }
795 break;
796 }
797 }
798 }
799
801 interpreter, completion_mask, request, filter_up.get());
802}
803
805 auto group_option_defs = group->GetDefinitions();
806 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
807 m_option_infos.push_back(OptionInfo(group, i));
808 m_option_defs.push_back(group_option_defs[i]);
809 }
810}
811
813 for (uint32_t i = 0; i < m_option_defs.size(); i++) {
814 OptionDefinition opt_def = m_option_defs[i];
815 if (opt_def.short_option == short_opt)
816 return m_option_infos[i].option_group;
817 }
818 return nullptr;
819}
820
821void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask,
822 uint32_t dst_mask) {
823 auto group_option_defs = group->GetDefinitions();
824 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
825 if (group_option_defs[i].usage_mask & src_mask) {
826 m_option_infos.push_back(OptionInfo(group, i));
827 m_option_defs.push_back(group_option_defs[i]);
828 m_option_defs.back().usage_mask = dst_mask;
829 }
830 }
831}
832
834 OptionGroup *group, llvm::ArrayRef<llvm::StringRef> exclude_long_options) {
835 auto group_option_defs = group->GetDefinitions();
836 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
837 const auto &definition = group_option_defs[i];
838 if (llvm::is_contained(exclude_long_options, definition.long_option))
839 continue;
840
841 m_option_infos.push_back(OptionInfo(group, i));
842 m_option_defs.push_back(definition);
843 }
844}
845
849
851 llvm::StringRef option_value,
852 ExecutionContext *execution_context) {
853 // After calling OptionGroupOptions::Append(...), you must finalize the
854 // groups by calling OptionGroupOptions::Finlize()
855 assert(m_did_finalize);
857 if (option_idx < m_option_infos.size()) {
858 error = m_option_infos[option_idx].option_group->SetOptionValue(
859 m_option_infos[option_idx].option_index, option_value,
860 execution_context);
861
862 } else {
863 error =
864 Status::FromErrorString("invalid option index"); // Shouldn't happen...
865 }
866 return error;
867}
868
870 ExecutionContext *execution_context) {
871 std::set<OptionGroup *> group_set;
872 OptionInfos::iterator pos, end = m_option_infos.end();
873 for (pos = m_option_infos.begin(); pos != end; ++pos) {
874 OptionGroup *group = pos->option_group;
875 if (group_set.find(group) == group_set.end()) {
876 group->OptionParsingStarting(execution_context);
877 group_set.insert(group);
878 }
879 }
880}
881Status
883 std::set<OptionGroup *> group_set;
885 OptionInfos::iterator pos, end = m_option_infos.end();
886 for (pos = m_option_infos.begin(); pos != end; ++pos) {
887 OptionGroup *group = pos->option_group;
888 if (group_set.find(group) == group_set.end()) {
889 error = group->OptionParsingFinished(execution_context);
890 group_set.insert(group);
891 if (error.Fail())
892 return error;
893 }
894 }
895 return error;
896}
897
898// OptionParser permutes the arguments while processing them, so we create a
899// temporary array holding to avoid modification of the input arguments. The
900// options themselves are never modified, but the API expects a char * anyway,
901// hence the const_cast.
902static std::vector<char *> GetArgvForParsing(const Args &args) {
903 std::vector<char *> result;
904 // OptionParser always skips the first argument as it is based on getopt().
905 result.push_back(const_cast<char *>("<FAKE-ARG0>"));
906 for (const Args::ArgEntry &entry : args)
907 result.push_back(const_cast<char *>(entry.c_str()));
908 result.push_back(nullptr);
909 return result;
910}
911
912// Given a permuted argument, find it's position in the original Args vector.
914 const Args &original) {
915 return llvm::find_if(
916 original, [arg](const Args::ArgEntry &D) { return D.c_str() == arg; });
917}
918
919// Given a permuted argument, find it's index in the original Args vector.
920static size_t FindOriginalIndex(const char *arg, const Args &original) {
921 return std::distance(original.begin(), FindOriginalIter(arg, original));
922}
923
924// Construct a new Args object, consisting of the entries from the original
925// arguments, but in the permuted order.
926static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
927 const Args &original) {
928 Args result;
929 for (const char *arg : parsed) {
930 auto pos = FindOriginalIter(arg, original);
931 assert(pos != original.end());
932 result.AppendArgument(pos->ref(), pos->GetQuoteChar());
933 }
934 return result;
935}
936
937static size_t FindArgumentIndexForOption(const Args &args,
938 const Option &long_option) {
939 std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
940 std::string long_opt =
941 std::string(llvm::formatv("--{0}", long_option.definition->long_option));
942 for (const auto &entry : llvm::enumerate(args)) {
943 if (entry.value().ref().starts_with(short_opt) ||
944 entry.value().ref().starts_with(long_opt))
945 return entry.index();
946 }
947
948 return size_t(-1);
949}
950
951static std::string BuildShortOptions(const Option *long_options) {
952 std::string storage;
953 llvm::raw_string_ostream sstr(storage);
954
955 // Leading : tells getopt to return a : for a missing option argument AND to
956 // suppress error messages.
957 sstr << ":";
958
959 for (size_t i = 0; long_options[i].definition != nullptr; ++i) {
960 if (long_options[i].flag == nullptr) {
961 sstr << (char)long_options[i].val;
962 switch (long_options[i].definition->option_has_arg) {
963 default:
965 break;
967 sstr << ":";
968 break;
970 sstr << "::";
971 break;
972 }
973 }
974 }
975 return storage;
976}
977
978llvm::Expected<Args> Options::ParseAlias(const Args &args,
979 OptionArgVector *option_arg_vector,
980 std::string &input_line) {
981 Option *long_options = GetLongOptions();
982
983 if (long_options == nullptr) {
984 return llvm::createStringError("Invalid long options");
985 }
986
987 std::string short_options = BuildShortOptions(long_options);
988
989 Args args_copy = args;
990 std::vector<char *> argv = GetArgvForParsing(args);
991
992 std::unique_lock<std::mutex> lock;
994 int val;
995 while (true) {
996 int long_options_index = -1;
997 val = OptionParser::Parse(argv, short_options, long_options,
998 &long_options_index);
999
1000 if (val == ':') {
1001 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1002 "last option requires an argument");
1003 }
1004
1005 if (val == -1)
1006 break;
1007
1008 if (val == '?') {
1009 return llvm::createStringError("Unknown or ambiguous option");
1010 }
1011
1012 if (val == 0)
1013 continue;
1014
1015 OptionSeen(val);
1016
1017 // Look up the long option index
1018 if (long_options_index == -1) {
1019 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1020 long_options[j].val;
1021 ++j) {
1022 if (long_options[j].val == val) {
1023 long_options_index = j;
1024 break;
1025 }
1026 }
1027 }
1028
1029 // See if the option takes an argument, and see if one was supplied.
1030 if (long_options_index == -1) {
1031 return llvm::createStringError(
1032 llvm::formatv("Invalid option with value '{0}'.", char(val)).str());
1033 }
1034
1035 StreamString option_str;
1036 option_str.Printf("-%c", val);
1037 const OptionDefinition *def = long_options[long_options_index].definition;
1038 int has_arg =
1039 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1040
1041 const char *option_arg = nullptr;
1042 switch (has_arg) {
1044 if (OptionParser::GetOptionArgument() == nullptr) {
1045 return llvm::createStringError(
1046 llvm::formatv("Option '{0}' is missing argument specifier.",
1047 option_str.GetString())
1048 .str());
1049 }
1050 [[fallthrough]];
1052 option_arg = OptionParser::GetOptionArgument();
1053 [[fallthrough]];
1055 break;
1056 default:
1057 return llvm::createStringError(
1058 llvm::formatv("error with options table; invalid value in has_arg "
1059 "field for option '{0}'.",
1060 char(val))
1061 .str());
1062 }
1063 // Find option in the argument list; also see if it was supposed to take an
1064 // argument and if one was supplied. Remove option (and argument, if
1065 // given) from the argument list. Also remove them from the
1066 // raw_input_string, if one was passed in.
1067 // Note: We also need to preserve any option argument values that were
1068 // surrounded by backticks, as we lose track of them in the
1069 // option_args_vector.
1070 size_t idx =
1071 FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
1072 std::string option_to_insert;
1073 if (option_arg) {
1074 if (idx != size_t(-1) && has_arg) {
1075 bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
1076 if (arg_has_backtick)
1077 option_to_insert = "`";
1078 option_to_insert += option_arg;
1079 if (arg_has_backtick)
1080 option_to_insert += "`";
1081 } else
1082 option_to_insert = option_arg;
1083 } else
1084 option_to_insert = CommandInterpreter::g_no_argument;
1085
1086 option_arg_vector->emplace_back(std::string(option_str.GetString()),
1087 has_arg, option_to_insert);
1088
1089 if (idx == size_t(-1))
1090 continue;
1091
1092 if (!input_line.empty()) {
1093 llvm::StringRef tmp_arg = args_copy[idx].ref();
1094 size_t pos = input_line.find(tmp_arg);
1095 if (pos != std::string::npos)
1096 input_line.erase(pos, tmp_arg.size());
1097 }
1098 args_copy.DeleteArgumentAtIndex(idx);
1099 if ((option_to_insert != CommandInterpreter::g_no_argument) &&
1100 (OptionParser::GetOptionArgument() != nullptr) &&
1101 (idx < args_copy.GetArgumentCount()) &&
1102 (args_copy[idx].ref() == OptionParser::GetOptionArgument())) {
1103 if (input_line.size() > 0) {
1104 size_t pos = input_line.find(option_to_insert);
1105 if (pos != std::string::npos)
1106 input_line.erase(pos, option_to_insert.size());
1107 }
1108 args_copy.DeleteArgumentAtIndex(idx);
1109 }
1110 }
1111
1112 return std::move(args_copy);
1113}
1114
1116 uint32_t cursor_index) {
1117 OptionElementVector option_element_vector;
1118 Option *long_options = GetLongOptions();
1119 option_element_vector.clear();
1120
1121 if (long_options == nullptr)
1122 return option_element_vector;
1123
1124 std::string short_options = BuildShortOptions(long_options);
1125
1126 std::unique_lock<std::mutex> lock;
1129
1130 int val;
1131 auto opt_defs = GetDefinitions();
1132
1133 std::vector<char *> dummy_vec = GetArgvForParsing(args);
1134
1135 bool failed_once = false;
1136 uint32_t dash_dash_pos = -1;
1137
1138 while (true) {
1139 bool missing_argument = false;
1140 int long_options_index = -1;
1141
1142 val = OptionParser::Parse(dummy_vec, short_options, long_options,
1143 &long_options_index);
1144
1145 if (val == -1) {
1146 // When we're completing a "--" which is the last option on line,
1147 if (failed_once)
1148 break;
1149
1150 failed_once = true;
1151
1152 // If this is a bare "--" we mark it as such so we can complete it
1153 // successfully later. Handling the "--" is a little tricky, since that
1154 // may mean end of options or arguments, or the user might want to
1155 // complete options by long name. I make this work by checking whether
1156 // the cursor is in the "--" argument, and if so I assume we're
1157 // completing the long option, otherwise I let it pass to
1158 // OptionParser::Parse which will terminate the option parsing. Note, in
1159 // either case we continue parsing the line so we can figure out what
1160 // other options were passed. This will be useful when we come to
1161 // restricting completions based on what other options we've seen on the
1162 // line.
1163
1164 if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1165 dummy_vec.size() &&
1166 (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1167 dash_dash_pos = FindOriginalIndex(
1168 dummy_vec[OptionParser::GetOptionIndex() - 1], args);
1169 if (dash_dash_pos == cursor_index) {
1170 option_element_vector.push_back(
1173 continue;
1174 } else
1175 break;
1176 } else
1177 break;
1178 } else if (val == '?') {
1179 option_element_vector.push_back(OptionArgElement(
1182 args),
1184 continue;
1185 } else if (val == 0) {
1186 continue;
1187 } else if (val == ':') {
1188 // This is a missing argument.
1190 missing_argument = true;
1191 }
1192
1193 OptionSeen(val);
1194
1195 // Look up the long option index
1196 if (long_options_index == -1) {
1197 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1198 long_options[j].val;
1199 ++j) {
1200 if (long_options[j].val == val) {
1201 long_options_index = j;
1202 break;
1203 }
1204 }
1205 }
1206
1207 // See if the option takes an argument, and see if one was supplied.
1208 if (long_options_index >= 0) {
1209 int opt_defs_index = -1;
1210 for (size_t i = 0; i < opt_defs.size(); i++) {
1211 if (opt_defs[i].short_option != val)
1212 continue;
1213 opt_defs_index = i;
1214 break;
1215 }
1216
1217 const OptionDefinition *def = long_options[long_options_index].definition;
1218 int has_arg =
1219 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1220 switch (has_arg) {
1222 option_element_vector.push_back(OptionArgElement(
1223 opt_defs_index,
1225 args),
1226 0));
1227 break;
1229 if (OptionParser::GetOptionArgument() != nullptr) {
1230 int arg_index;
1231 if (missing_argument)
1232 arg_index = -1;
1233 else
1234 arg_index = OptionParser::GetOptionIndex() - 2;
1235
1236 option_element_vector.push_back(OptionArgElement(
1237 opt_defs_index,
1239 args),
1240 arg_index));
1241 } else {
1242 option_element_vector.push_back(OptionArgElement(
1243 opt_defs_index,
1245 args),
1246 -1));
1247 }
1248 break;
1250 option_element_vector.push_back(OptionArgElement(
1251 opt_defs_index,
1253 args),
1255 args)));
1256 break;
1257 default:
1258 // The options table is messed up. Here we'll just continue
1259 option_element_vector.push_back(OptionArgElement(
1262 args),
1264 break;
1265 }
1266 } else {
1267 option_element_vector.push_back(OptionArgElement(
1270 args),
1272 }
1273 }
1274
1275 // Finally we have to handle the case where the cursor index points at a
1276 // single "-". We want to mark that in the option_element_vector, but only
1277 // if it is not after the "--". But it turns out that OptionParser::Parse
1278 // just ignores an isolated "-". So we have to look it up by hand here. We
1279 // only care if it is AT the cursor position. Note, a single quoted dash is
1280 // not the same as a single dash...
1281
1282 const Args::ArgEntry &cursor = args[cursor_index];
1283 if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1284 cursor_index < dash_dash_pos) &&
1285 !cursor.IsQuoted() && cursor.ref() == "-") {
1286 option_element_vector.push_back(
1289 }
1290 return option_element_vector;
1291}
1292
1293llvm::Expected<Args> Options::Parse(const Args &args,
1294 ExecutionContext *execution_context,
1295 lldb::PlatformSP platform_sp,
1296 bool require_validation) {
1297 Status error;
1298 Option *long_options = GetLongOptions();
1299 if (long_options == nullptr) {
1300 return llvm::createStringError("invalid long options");
1301 }
1302
1303 std::string short_options = BuildShortOptions(long_options);
1304 std::vector<char *> argv = GetArgvForParsing(args);
1305
1306 std::unique_lock<std::mutex> lock;
1308 while (true) {
1309 int long_options_index = -1;
1310 int val = OptionParser::Parse(argv, short_options, long_options,
1311 &long_options_index);
1312
1313 if (val == ':') {
1314 error = Status::FromErrorString("last option requires an argument");
1315 break;
1316 }
1317
1318 if (val == -1)
1319 break;
1320
1321 // Did we get an error?
1322 if (val == '?') {
1323 // Account for "argv[0]" and that it points to the next option.
1324 int idx = OptionParser::GetOptionIndex() - 2;
1325 if (idx >= 0 && (size_t)idx < args.GetArgumentCount())
1326 error = Status::FromError(llvm::make_error<OptionParseError>(
1327 args[idx], "unknown or ambiguous option"));
1328 else
1329 error = Status("unknown or ambiguous option");
1330
1331 break;
1332 }
1333 // The option auto-set itself
1334 if (val == 0)
1335 continue;
1336
1337 OptionSeen(val);
1338
1339 // Lookup the long option index
1340 if (long_options_index == -1) {
1341 for (int i = 0; long_options[i].definition || long_options[i].flag ||
1342 long_options[i].val;
1343 ++i) {
1344 if (long_options[i].val == val) {
1345 long_options_index = i;
1346 break;
1347 }
1348 }
1349 }
1350 // Call the callback with the option
1351 if (long_options_index >= 0 &&
1352 long_options[long_options_index].definition) {
1353 const OptionDefinition *def = long_options[long_options_index].definition;
1354
1355 if (!platform_sp) {
1356 // User did not pass in an explicit platform. Try to grab from the
1357 // execution context.
1358 TargetSP target_sp =
1359 execution_context ? execution_context->GetTargetSP() : TargetSP();
1360 platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
1361 }
1363
1364 if (!platform_sp && require_validation) {
1365 // Caller requires validation but we cannot validate as we don't have
1366 // the mandatory platform against which to validate.
1367 return llvm::createStringError(
1368 "cannot validate options: no platform available");
1369 }
1370
1371 bool validation_failed = false;
1372 if (platform_sp) {
1373 // Ensure we have an execution context, empty or not.
1374 ExecutionContext dummy_context;
1375 ExecutionContext *exe_ctx_p =
1376 execution_context ? execution_context : &dummy_context;
1377 if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
1378 validation_failed = true;
1380 "Option \"%s\" invalid. %s", def->long_option,
1382 }
1383 }
1384
1385 // As long as validation didn't fail, we set the option value.
1386 if (!validation_failed)
1387 error =
1388 SetOptionValue(long_options_index,
1390 ? nullptr
1392 execution_context);
1393 // If the Option setting returned an error, we should stop parsing
1394 // and return the error.
1395 if (error.Fail())
1396 break;
1397 } else {
1399 "invalid option with value '%i'", val);
1400 }
1401 }
1402
1403 if (error.Fail())
1404 return error.ToError();
1405
1406 argv.pop_back();
1407 argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
1408 return ReconstituteArgsAfterParsing(argv, args);
1409}
1410
1412 llvm::StringRef option_arg, const char short_option,
1413 llvm::StringRef long_option, llvm::StringRef additional_context) {
1414 std::string buffer;
1415 llvm::raw_string_ostream stream(buffer);
1416 stream << "invalid value ('" << option_arg << "')";
1417 if (short_option)
1418 stream << " for -" << short_option;
1419 if (!long_option.empty())
1420 stream << " (" << long_option << ")";
1421 if (!additional_context.empty())
1422 stream << ": " << additional_context;
1423 return llvm::createStringError(llvm::inconvertibleErrorCode(), buffer);
1424}
static llvm::raw_ostream & error(Stream &strm)
static Args ReconstituteArgsAfterParsing(llvm::ArrayRef< char * > parsed, const Args &original)
Definition Options.cpp:926
static std::string BuildShortOptions(const Option *long_options)
Definition Options.cpp:951
static std::vector< char * > GetArgvForParsing(const Args &args)
Definition Options.cpp:902
static bool PrintOption(const OptionDefinition &opt_def, OptionDisplayType display_type, const char *header, const char *footer, bool show_optional, Stream &strm)
Definition Options.cpp:359
static Args::const_iterator FindOriginalIter(const char *arg, const Args &original)
Definition Options.cpp:913
static size_t FindArgumentIndexForOption(const Args &args, const Option &long_option)
Definition Options.cpp:937
OptionDisplayType
Definition Options.cpp:353
@ eDisplayShortOption
Definition Options.cpp:355
@ eDisplayBestOption
Definition Options.cpp:354
@ eDisplayLongOption
Definition Options.cpp:356
static size_t FindOriginalIndex(const char *arg, const Args &original)
Definition Options.cpp:920
A command line argument class.
Definition Args.h:33
std::vector< ArgEntry >::const_iterator const_iterator
Definition Args.h:134
void DeleteArgumentAtIndex(size_t idx)
Deletes the argument value at index if idx is a valid argument index.
Definition Args.cpp:359
const_iterator begin() const
Definition Args.h:136
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition Args.h:120
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition Args.cpp:332
const_iterator end() const
Definition Args.h:137
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition Args.cpp:273
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
virtual bool WantsRawCommandString()=0
static const ArgumentTableEntry * FindArgumentDataByType(lldb::CommandArgumentType arg_type)
llvm::StringRef GetCommandName() const
void GetFormattedCommandArguments(Stream &str, uint32_t opt_set_mask=LLDB_OPT_SET_ALL)
static const char * GetArgumentName(lldb::CommandArgumentType arg_type)
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
llvm::StringRef GetCursorArgumentPrefix() const
void TryCompleteCurrentArg(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string if the completion would complete the current argument.
lldb::TargetSP GetSelectedTarget()
Definition Debugger.h:190
bool GetUseColor() const
Definition Debugger.cpp:484
static void ReportError(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report error events.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
A file utility class.
Definition FileSpec.h:57
void OptionParsingStarting(ExecutionContext *execution_context) override
Definition Options.cpp:869
std::vector< OptionDefinition > m_option_defs
Definition Options.h:334
const OptionGroup * GetGroupWithOption(char short_opt)
Definition Options.cpp:812
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
Definition Options.cpp:850
Status OptionParsingFinished(ExecutionContext *execution_context) override
Definition Options.cpp:882
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition Options.cpp:804
virtual Status OptionParsingFinished(ExecutionContext *execution_context)
Definition Options.h:248
virtual llvm::ArrayRef< OptionDefinition > GetDefinitions()=0
virtual void OptionParsingStarting(ExecutionContext *execution_context)=0
OptionParseError(DiagnosticDetail detail)
Definition Options.cpp:39
std::vector< DiagnosticDetail > m_details
Definition Options.cpp:35
llvm::ArrayRef< DiagnosticDetail > GetDetails() const override
Definition Options.cpp:54
OptionParseError(const Args::ArgEntry &arg, std::string msg)
Definition Options.cpp:42
std::unique_ptr< CloneableError > Clone() const override
Definition Options.cpp:51
static void Prepare(std::unique_lock< std::mutex > &lock)
static int Parse(llvm::MutableArrayRef< char * > argv, llvm::StringRef optstring, const Option *longopts, int *longindex)
Argv must be an argument vector "as passed to main", i.e.
static char * GetOptionArgument()
static void EnableError(bool error)
void OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set)
Definition Options.cpp:124
void GenerateOptionUsage(Stream &strm, CommandObject &cmd, uint32_t screen_width, bool use_color)
Definition Options.cpp:395
virtual void HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter)
Handles the generic bits of figuring out whether we are in an option, and if so completing it.
Definition Options.cpp:732
llvm::Error VerifyOptions()
Definition Options.cpp:561
virtual Status OptionParsingFinished(ExecutionContext *execution_context)
Definition Options.h:226
llvm::Error VerifyPartialOptions()
Definition Options.cpp:604
virtual Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context)=0
Set the value of an option.
uint32_t NumCommandOptions()
Definition Options.cpp:196
virtual void OptionParsingStarting(ExecutionContext *execution_context)=0
void OptionSeen(int short_option)
Definition Options.cpp:80
virtual llvm::ArrayRef< OptionDefinition > GetDefinitions()
Definition Options.h:98
Status NotifyOptionParsingFinished(ExecutionContext *execution_context)
Definition Options.cpp:76
Option * GetLongOptions()
Get the option definitions to use when parsing Args options.
Definition Options.cpp:198
OptionSetVector m_optional_options
Definition Options.h:201
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition Options.cpp:69
llvm::Expected< Args > ParseAlias(const Args &args, OptionArgVector *option_arg_vector, std::string &input_line)
Definition Options.cpp:978
std::set< int > OptionSet
Definition Options.h:195
void OutputFormattedUsageText(Stream &strm, const OptionDefinition &option_def, uint32_t output_max_columns, bool use_color)
Definition Options.cpp:263
OptionSetVector m_required_options
Definition Options.h:200
OptionSetVector & GetOptionalOptions()
Definition Options.h:208
size_t OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b, OptionSet &diffs)
Definition Options.cpp:104
bool HandleOptionCompletion(lldb_private::CompletionRequest &request, OptionElementVector &option_map, CommandInterpreter &interpreter)
Handles the generic bits of figuring out whether we are in an option, and if so completing it.
Definition Options.cpp:628
bool IsASubset(const OptionSet &set_a, const OptionSet &set_b)
Definition Options.cpp:84
bool SupportsLongOption(const char *long_option)
Definition Options.cpp:330
std::vector< Option > m_getopt_table
Definition Options.h:198
llvm::Expected< Args > Parse(const Args &args, ExecutionContext *execution_context, lldb::PlatformSP platform_sp, bool require_validation)
Parse the provided arguments.
Definition Options.cpp:1293
OptionSetVector & GetRequiredOptions()
Definition Options.h:203
OptionSet m_seen_options
Definition Options.h:199
OptionElementVector ParseForCompletion(const Args &args, uint32_t cursor_index)
Definition Options.cpp:1115
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:137
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
size_t PutChar(char ch)
Definition Stream.cpp:131
void SetIndentLevel(unsigned level)
Set the current indentation level.
Definition Stream.cpp:190
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition Stream.cpp:198
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition Stream.cpp:195
unsigned GetIndentLevel() const
Get the current indentation level.
Definition Stream.cpp:187
#define LLDB_MAX_NUM_OPTION_SETS
Option Set definitions.
#define LLDB_OPT_SET_ALL
std::string FormatAnsiTerminalCodes(llvm::StringRef format, bool do_color=true)
size_t ColumnWidth(llvm::StringRef str)
A class that represents a running process on the host machine.
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
TableValidator< 0 > validator
llvm::Error CreateOptionParsingError(llvm::StringRef option_arg, const char short_option, llvm::StringRef long_option={}, llvm::StringRef additional_context={})
Creates an error that represents the failure to parse an command line option argument.
Definition Options.cpp:1411
std::vector< std::tuple< std::string, int, std::string > > OptionArgVector
Definition Options.h:29
@ eSourceFileCompletion
std::shared_ptr< lldb_private::Platform > PlatformSP
std::shared_ptr< lldb_private::Target > TargetSP
const char * c_str() const
Definition Args.h:51
llvm::StringRef ref() const
Definition Args.h:50
bool IsQuoted() const
Returns true if this argument was quoted in any way.
Definition Args.h:54
std::optional< uint16_t > GetPos() const
Definition Args.h:56
Entries in the main argument information table.
A source location consisting of a file name and position.
A compiler-independent representation of an lldb_private::Diagnostic.
bool HasShortOption() const
Whether this has a short option character.
OptionValidator * validator
If non-NULL, option is valid iff |validator->IsValid()|, otherwise always valid.
const char * long_option
Full name for this option.
const char * usage_text
Full text explaining what this options does and what (if any) argument to pass it.
bool required
This option is required (in the current usage level).
int option_has_arg
no_argument, required_argument or optional_argument
lldb::CommandArgumentType argument_type
Type of argument this option takes.
OptionEnumValues enum_values
If not empty, an array of enum values.
int short_option
Single character for this option.
virtual const char * LongConditionString() const =0
virtual const char * ShortConditionString() const =0
const OptionDefinition * definition