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
21#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 const char *condition = option_def.validator->ShortConditionString();
270 if (condition) {
271 actual_text = "[";
272 actual_text.append(condition);
273 actual_text.append("] ");
274 }
275 }
276 actual_text.append(
277 ansi::FormatAnsiTerminalCodes(option_def.usage_text, use_color));
278 const size_t visible_length = ansi::ColumnWidth(actual_text);
279
280 // Will it all fit on one line?
281
282 if (static_cast<uint32_t>(visible_length + strm.GetIndentLevel()) <
283 output_max_columns) {
284 // Output it as a single line.
285 strm.Indent(ansi::FormatAnsiTerminalCodes(actual_text, use_color));
286 strm.EOL();
287 } else {
288 // We need to break it up into multiple lines.
289
290 int text_width = output_max_columns - strm.GetIndentLevel() - 1;
291 int start = 0;
292 int end = start;
293 int final_end = visible_length;
294 int sub_len;
295
296 while (end < final_end) {
297 // Don't start the 'text' on a space, since we're already outputting the
298 // indentation.
299 while ((start < final_end) && (actual_text[start] == ' '))
300 start++;
301
302 end = start + text_width;
303 if (end > final_end)
304 end = final_end;
305 else {
306 // If we're not at the end of the text, make sure we break the line on
307 // white space.
308 while (end > start && actual_text[end] != ' ' &&
309 actual_text[end] != '\t' && actual_text[end] != '\n')
310 end--;
311 }
312
313 sub_len = end - start;
314 if (start != 0)
315 strm.EOL();
316 strm.Indent();
317 assert(start < final_end);
318 assert(start + sub_len <= final_end);
320 llvm::StringRef(actual_text.c_str() + start, sub_len), use_color));
321 start = end + 1;
322 }
323 strm.EOL();
324 }
325}
326
327bool Options::SupportsLongOption(const char *long_option) {
328 if (!long_option || !long_option[0])
329 return false;
330
331 auto opt_defs = GetDefinitions();
332 if (opt_defs.empty())
333 return false;
334
335 const char *long_option_name = long_option;
336 if (long_option[0] == '-' && long_option[1] == '-')
337 long_option_name += 2;
338
339 for (auto &def : opt_defs) {
340 if (!def.long_option)
341 continue;
342
343 if (strcmp(def.long_option, long_option_name) == 0)
344 return true;
345 }
346
347 return false;
348}
349
355
356static bool PrintOption(const OptionDefinition &opt_def,
357 OptionDisplayType display_type, const char *header,
358 const char *footer, bool show_optional, Stream &strm) {
359 if (display_type == eDisplayShortOption && !opt_def.HasShortOption())
360 return false;
361
362 if (header && header[0])
363 strm.PutCString(header);
364
365 if (show_optional && !opt_def.required)
366 strm.PutChar('[');
367 const bool show_short_option =
368 opt_def.HasShortOption() && display_type != eDisplayLongOption;
369 if (show_short_option)
370 strm.Printf("-%c", opt_def.short_option);
371 else
372 strm.Printf("--%s", opt_def.long_option);
373 switch (opt_def.option_has_arg) {
375 break;
378 break;
379
381 strm.Printf("%s[<%s>]", show_short_option ? "" : "=",
383 break;
384 }
385 if (show_optional && !opt_def.required)
386 strm.PutChar(']');
387 if (footer && footer[0])
388 strm.PutCString(footer);
389 return true;
390}
391
393 uint32_t screen_width, bool use_color) {
394 auto opt_defs = GetDefinitions();
395 const uint32_t save_indent_level = strm.GetIndentLevel();
396 llvm::StringRef name = cmd.GetCommandName();
397 StreamString arguments_str;
398 cmd.GetFormattedCommandArguments(arguments_str);
399
400 const uint32_t num_options = NumCommandOptions();
401 if (num_options == 0)
402 return;
403
404 const bool only_print_args = cmd.IsDashDashCommand();
405 if (!only_print_args)
406 strm.PutCString("\nCommand Options Usage:\n");
407
408 strm.IndentMore(2);
409
410 // First, show each usage level set of options, e.g. <cmd> [options-for-
411 // level-0]
412 // <cmd>
413 // [options-for-level-1]
414 // etc.
415
416 if (!only_print_args) {
417 uint32_t num_option_sets = GetRequiredOptions().size();
418 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) {
419 if (opt_set > 0)
420 strm.Printf("\n");
421 strm.Indent(name);
422
423 // Different option sets may require different args.
424 StreamString args_str;
425 uint32_t opt_set_mask = 1 << opt_set;
426 cmd.GetFormattedCommandArguments(args_str, opt_set_mask);
427
428 // First go through and print all options that take no arguments as a
429 // single string. If a command has "-a" "-b" and "-c", this will show up
430 // as [-abc]
431
432 // We use a set here so that they will be sorted.
433 std::set<int> required_options;
434 std::set<int> optional_options;
435
436 for (auto &def : opt_defs) {
437 if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
438 def.option_has_arg == OptionParser::eNoArgument) {
439 if (def.required) {
440 required_options.insert(def.short_option);
441 } else {
442 optional_options.insert(def.short_option);
443 }
444 }
445 }
446
447 if (!required_options.empty()) {
448 strm.PutCString(" -");
449 for (int short_option : required_options)
450 strm.PutChar(short_option);
451 }
452
453 if (!optional_options.empty()) {
454 strm.PutCString(" [-");
455 for (int short_option : optional_options)
456 strm.PutChar(short_option);
457 strm.PutChar(']');
458 }
459
460 // First go through and print the required options (list them up front).
461 for (auto &def : opt_defs) {
462 if (def.usage_mask & opt_set_mask && def.HasShortOption() &&
463 def.required && def.option_has_arg != OptionParser::eNoArgument)
464 PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
465 }
466
467 // Now go through again, and this time only print the optional options.
468 for (auto &def : opt_defs) {
469 if (def.usage_mask & opt_set_mask && !def.required &&
470 def.option_has_arg != OptionParser::eNoArgument)
471 PrintOption(def, eDisplayBestOption, " ", nullptr, true, strm);
472 }
473
474 if (args_str.GetSize() > 0) {
475 if (cmd.WantsRawCommandString())
476 strm.Printf(" --");
477 strm << " " << args_str.GetString();
478 }
479 }
480 }
481
482 if ((only_print_args || cmd.WantsRawCommandString()) &&
483 arguments_str.GetSize() > 0) {
484 if (!only_print_args)
485 strm.PutChar('\n');
486 strm.Indent(name);
487 strm << " " << arguments_str.GetString();
488 }
489
490 if (!only_print_args) {
491 strm.Printf("\n\n");
492
493 // Now print out all the detailed information about the various options:
494 // long form, short form and help text:
495 // -short <argument> ( --long_name <argument> )
496 // help text
497
498 strm.IndentMore(5);
499
500 // Put the command options in a sorted container, so we can output
501 // them alphabetically by short_option.
502 std::multimap<int, uint32_t> options_ordered;
503 for (auto def : llvm::enumerate(opt_defs))
504 options_ordered.insert(
505 std::make_pair(def.value().short_option, def.index()));
506
507 // Go through each option, find the table entry and write out the detailed
508 // help information for that option.
509
510 bool first_option_printed = false;
511
512 for (auto pos : options_ordered) {
513 // Put a newline separation between arguments
514 if (first_option_printed)
515 strm.EOL();
516 else
517 first_option_printed = true;
518
519 OptionDefinition opt_def = opt_defs[pos.second];
520
521 strm.Indent();
522 if (opt_def.short_option && opt_def.HasShortOption()) {
523 PrintOption(opt_def, eDisplayShortOption, nullptr, nullptr, false,
524 strm);
525 PrintOption(opt_def, eDisplayLongOption, " ( ", " )", false, strm);
526 } else {
527 // Short option is not printable, just print long option
528 PrintOption(opt_def, eDisplayLongOption, nullptr, nullptr, false, strm);
529 }
530 strm.EOL();
531
532 strm.IndentMore(5);
533
534 if (opt_def.usage_text)
535 OutputFormattedUsageText(strm, opt_def, screen_width, use_color);
536 if (!opt_def.enum_values.empty()) {
537 strm.Indent();
538 strm.Printf("Values: ");
539 bool is_first = true;
540 for (const auto &enum_value : opt_def.enum_values) {
541 if (is_first) {
542 strm.Printf("%s", enum_value.string_value);
543 is_first = false;
544 }
545 else
546 strm.Printf(" | %s", enum_value.string_value);
547 }
548 strm.EOL();
549 }
550 strm.IndentLess(5);
551 }
552 }
553
554 // Restore the indent level
555 strm.SetIndentLevel(save_indent_level);
556}
557
559 bool options_are_valid = false;
560
561 int num_levels = GetRequiredOptions().size();
562 if (num_levels) {
563 for (int i = 0; i < num_levels && !options_are_valid; ++i) {
564 // This is the correct set of options if: 1). m_seen_options contains
565 // all of m_required_options[i] (i.e. all the required options at this
566 // level are a subset of m_seen_options); AND 2). { m_seen_options -
567 // m_required_options[i] is a subset of m_options_options[i] (i.e. all
568 // the rest of m_seen_options are in the set of optional options at this
569 // level.
570
571 // Check to see if all of m_required_options[i] are a subset of
572 // m_seen_options
574 // Construct the set difference: remaining_options = {m_seen_options} -
575 // {m_required_options[i]}
576 OptionSet remaining_options;
578 remaining_options);
579 // Check to see if remaining_options is a subset of
580 // m_optional_options[i]
581 if (IsASubset(remaining_options, GetOptionalOptions()[i]))
582 options_are_valid = true;
583 }
584 }
585 } else {
586 options_are_valid = true;
587 }
588
589 if (!options_are_valid)
590 return llvm::createStringError(
591 "invalid combination of options for the given command");
592
593 return llvm::Error::success();
594}
595
596// This function is called when we have been given a potentially incomplete set
597// of options, such as when an alias has been defined (more options might be
598// added at at the time the alias is invoked). We need to verify that the
599// options in the set m_seen_options are all part of a set that may be used
600// together, but m_seen_options may be missing some of the "required" options.
602 bool options_are_valid = false;
603
604 int num_levels = GetRequiredOptions().size();
605 if (num_levels) {
606 for (int i = 0; i < num_levels && !options_are_valid; ++i) {
607 // In this case we are treating all options as optional rather than
608 // required. Therefore a set of options is correct if m_seen_options is a
609 // subset of the union of m_required_options and m_optional_options.
610 OptionSet union_set;
612 union_set);
613 if (IsASubset(m_seen_options, union_set))
614 options_are_valid = true;
615 }
616 }
617
618 if (!options_are_valid)
619 return llvm::createStringError(
620 "invalid combination of options for the given command");
621
622 return llvm::Error::success();
623}
624
626 OptionElementVector &opt_element_vector,
627 CommandInterpreter &interpreter) {
628 // For now we just scan the completions to see if the cursor position is in
629 // an option or its argument. Otherwise we'll call HandleArgumentCompletion.
630 // In the future we can use completion to validate options as well if we
631 // want.
632
633 auto opt_defs = GetDefinitions();
634
635 llvm::StringRef cur_opt_str = request.GetCursorArgumentPrefix();
636 const bool use_color = interpreter.GetDebugger().GetUseColor();
637
638 for (size_t i = 0; i < opt_element_vector.size(); i++) {
639 size_t opt_pos = static_cast<size_t>(opt_element_vector[i].opt_pos);
640 size_t opt_arg_pos = static_cast<size_t>(opt_element_vector[i].opt_arg_pos);
641 int opt_defs_index = opt_element_vector[i].opt_defs_index;
642 if (opt_pos == request.GetCursorIndex()) {
643 // We're completing the option itself.
644
645 if (opt_defs_index == OptionArgElement::eBareDash) {
646 // We're completing a bare dash. That means all options are open.
647 // FIXME: We should scan the other options provided and only complete
648 // options
649 // within the option group they belong to.
650 std::string opt_str = "-a";
651
652 for (auto &def : opt_defs) {
653 if (!def.short_option)
654 continue;
655 opt_str[1] = def.short_option;
657 def.usage_text, use_color));
658 }
659
660 return true;
661 } else if (opt_defs_index == OptionArgElement::eBareDoubleDash) {
662 std::string full_name("--");
663 for (auto &def : opt_defs) {
664 if (!def.short_option)
665 continue;
666
667 full_name.erase(full_name.begin() + 2, full_name.end());
668 full_name.append(def.long_option);
670 def.usage_text, use_color));
671 }
672 return true;
673 } else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) {
674 // We recognized it, if it an incomplete long option, complete it
675 // anyway (getopt_long_only is happy with shortest unique string, but
676 // it's still a nice thing to do.) Otherwise return The string so the
677 // upper level code will know this is a full match and add the " ".
678 const OptionDefinition &opt = opt_defs[opt_defs_index];
679 llvm::StringRef long_option = opt.long_option;
680 if (cur_opt_str.starts_with("--") && cur_opt_str != long_option) {
681 request.AddCompletion(
682 "--" + long_option.str(),
684 return true;
685 } else
686 request.AddCompletion(request.GetCursorArgumentPrefix());
687 return true;
688 } else {
689 // FIXME - not handling wrong options yet:
690 // Check to see if they are writing a long option & complete it.
691 // I think we will only get in here if the long option table has two
692 // elements
693 // that are not unique up to this point. getopt_long_only does
694 // shortest unique match for long options already.
695 if (cur_opt_str.consume_front("--")) {
696 for (auto &def : opt_defs) {
697 llvm::StringRef long_option(def.long_option);
698 if (long_option.starts_with(cur_opt_str))
699 request.AddCompletion(
700 "--" + long_option.str(),
701 ansi::FormatAnsiTerminalCodes(def.usage_text, use_color));
702 }
703 }
704 return true;
705 }
706
707 } else if (opt_arg_pos == request.GetCursorIndex()) {
708 // Okay the cursor is on the completion of an argument. See if it has a
709 // completion, otherwise return no matches. Note, opt_defs_index == -1
710 // means we're after an option, but that option doesn't exist. We'll
711 // end up treating that as an argument. Not sure we can do much better.
712 if (opt_defs_index != -1) {
713 HandleOptionArgumentCompletion(request, opt_element_vector, i,
714 interpreter);
715 return true;
716 } else {
717 // No completion callback means no completions...
718 return true;
719 }
720
721 } else {
722 // Not the last element, keep going.
723 continue;
724 }
725 }
726 return false;
727}
728
730 CompletionRequest &request, OptionElementVector &opt_element_vector,
731 int opt_element_index, CommandInterpreter &interpreter) {
732 auto opt_defs = GetDefinitions();
733 std::unique_ptr<SearchFilter> filter_up;
734
735 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
736
737 // See if this is an enumeration type option, and if so complete it here:
738 const auto &enum_values = opt_defs[opt_defs_index].enum_values;
739 if (!enum_values.empty())
740 for (const auto &enum_value : enum_values)
741 request.TryCompleteCurrentArg(enum_value.string_value);
742
743 // If this is a source file or symbol type completion, and there is a -shlib
744 // option somewhere in the supplied arguments, then make a search filter for
745 // that shared library.
746 // FIXME: Do we want to also have an "OptionType" so we don't have to match
747 // string names?
748
749 uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
750
751 if (completion_mask == 0) {
752 lldb::CommandArgumentType option_arg_type =
753 opt_defs[opt_defs_index].argument_type;
754 if (option_arg_type != eArgTypeNone) {
755 const CommandObject::ArgumentTableEntry *arg_entry =
757 opt_defs[opt_defs_index].argument_type);
758 if (arg_entry)
759 completion_mask = arg_entry->completion_type;
760 }
761 }
762
763 if (completion_mask & lldb::eSourceFileCompletion ||
764 completion_mask & lldb::eSymbolCompletion) {
765 for (size_t i = 0; i < opt_element_vector.size(); i++) {
766 int cur_defs_index = opt_element_vector[i].opt_defs_index;
767
768 // trying to use <0 indices will definitely cause problems
769 if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
770 cur_defs_index == OptionArgElement::eBareDash ||
771 cur_defs_index == OptionArgElement::eBareDoubleDash)
772 continue;
773
774 int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
775 const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
776
777 // If this is the "shlib" option and there was an argument provided,
778 // restrict it to that shared library.
779 if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 &&
780 cur_arg_pos != -1) {
781 const char *module_name =
782 request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
783 if (module_name) {
784 FileSpec module_spec(module_name);
785 lldb::TargetSP target_sp =
786 interpreter.GetDebugger().GetSelectedTarget();
787 // Search filters require a target...
788 if (target_sp)
789 filter_up =
790 std::make_unique<SearchFilterByModule>(target_sp, module_spec);
791 }
792 break;
793 }
794 }
795 }
796
798 interpreter, completion_mask, request, filter_up.get());
799}
800
802 auto group_option_defs = group->GetDefinitions();
803 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
804 m_option_infos.push_back(OptionInfo(group, i));
805 m_option_defs.push_back(group_option_defs[i]);
806 }
807}
808
810 for (uint32_t i = 0; i < m_option_defs.size(); i++) {
811 OptionDefinition opt_def = m_option_defs[i];
812 if (opt_def.short_option == short_opt)
813 return m_option_infos[i].option_group;
814 }
815 return nullptr;
816}
817
818void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask,
819 uint32_t dst_mask) {
820 auto group_option_defs = group->GetDefinitions();
821 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
822 if (group_option_defs[i].usage_mask & src_mask) {
823 m_option_infos.push_back(OptionInfo(group, i));
824 m_option_defs.push_back(group_option_defs[i]);
825 m_option_defs.back().usage_mask = dst_mask;
826 }
827 }
828}
829
831 OptionGroup *group, llvm::ArrayRef<llvm::StringRef> exclude_long_options) {
832 auto group_option_defs = group->GetDefinitions();
833 for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
834 const auto &definition = group_option_defs[i];
835 if (llvm::is_contained(exclude_long_options, definition.long_option))
836 continue;
837
838 m_option_infos.push_back(OptionInfo(group, i));
839 m_option_defs.push_back(definition);
840 }
841}
842
846
848 llvm::StringRef option_value,
849 ExecutionContext *execution_context) {
850 // After calling OptionGroupOptions::Append(...), you must finalize the
851 // groups by calling OptionGroupOptions::Finlize()
852 assert(m_did_finalize);
854 if (option_idx < m_option_infos.size()) {
855 error = m_option_infos[option_idx].option_group->SetOptionValue(
856 m_option_infos[option_idx].option_index, option_value,
857 execution_context);
858
859 } else {
860 error =
861 Status::FromErrorString("invalid option index"); // Shouldn't happen...
862 }
863 return error;
864}
865
867 ExecutionContext *execution_context) {
868 std::set<OptionGroup *> group_set;
869 OptionInfos::iterator pos, end = m_option_infos.end();
870 for (pos = m_option_infos.begin(); pos != end; ++pos) {
871 OptionGroup *group = pos->option_group;
872 if (group_set.find(group) == group_set.end()) {
873 group->OptionParsingStarting(execution_context);
874 group_set.insert(group);
875 }
876 }
877}
878Status
880 std::set<OptionGroup *> group_set;
882 OptionInfos::iterator pos, end = m_option_infos.end();
883 for (pos = m_option_infos.begin(); pos != end; ++pos) {
884 OptionGroup *group = pos->option_group;
885 if (group_set.find(group) == group_set.end()) {
886 error = group->OptionParsingFinished(execution_context);
887 group_set.insert(group);
888 if (error.Fail())
889 return error;
890 }
891 }
892 return error;
893}
894
895// OptionParser permutes the arguments while processing them, so we create a
896// temporary array holding to avoid modification of the input arguments. The
897// options themselves are never modified, but the API expects a char * anyway,
898// hence the const_cast.
899static std::vector<char *> GetArgvForParsing(const Args &args) {
900 std::vector<char *> result;
901 // OptionParser always skips the first argument as it is based on getopt().
902 result.push_back(const_cast<char *>("<FAKE-ARG0>"));
903 for (const Args::ArgEntry &entry : args)
904 result.push_back(const_cast<char *>(entry.c_str()));
905 result.push_back(nullptr);
906 return result;
907}
908
909// Given a permuted argument, find it's position in the original Args vector.
911 const Args &original) {
912 return llvm::find_if(
913 original, [arg](const Args::ArgEntry &D) { return D.c_str() == arg; });
914}
915
916// Given a permuted argument, find it's index in the original Args vector.
917static size_t FindOriginalIndex(const char *arg, const Args &original) {
918 return std::distance(original.begin(), FindOriginalIter(arg, original));
919}
920
921// Construct a new Args object, consisting of the entries from the original
922// arguments, but in the permuted order.
923static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
924 const Args &original) {
925 Args result;
926 for (const char *arg : parsed) {
927 auto pos = FindOriginalIter(arg, original);
928 assert(pos != original.end());
929 result.AppendArgument(pos->ref(), pos->GetQuoteChar());
930 }
931 return result;
932}
933
934static size_t FindArgumentIndexForOption(const Args &args,
935 const Option &long_option) {
936 std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
937 std::string long_opt =
938 std::string(llvm::formatv("--{0}", long_option.definition->long_option));
939 for (const auto &entry : llvm::enumerate(args)) {
940 if (entry.value().ref().starts_with(short_opt) ||
941 entry.value().ref().starts_with(long_opt))
942 return entry.index();
943 }
944
945 return size_t(-1);
946}
947
948static std::string BuildShortOptions(const Option *long_options) {
949 std::string storage;
950 llvm::raw_string_ostream sstr(storage);
951
952 // Leading : tells getopt to return a : for a missing option argument AND to
953 // suppress error messages.
954 sstr << ":";
955
956 for (size_t i = 0; long_options[i].definition != nullptr; ++i) {
957 if (long_options[i].flag == nullptr) {
958 sstr << (char)long_options[i].val;
959 switch (long_options[i].definition->option_has_arg) {
960 default:
962 break;
964 sstr << ":";
965 break;
967 sstr << "::";
968 break;
969 }
970 }
971 }
972 return storage;
973}
974
975llvm::Expected<Args> Options::ParseAlias(const Args &args,
976 OptionArgVector *option_arg_vector,
977 std::string &input_line) {
978 Option *long_options = GetLongOptions();
979
980 if (long_options == nullptr) {
981 return llvm::createStringError("Invalid long options");
982 }
983
984 std::string short_options = BuildShortOptions(long_options);
985
986 Args args_copy = args;
987 std::vector<char *> argv = GetArgvForParsing(args);
988
989 std::unique_lock<std::mutex> lock;
991 int val;
992 while (true) {
993 int long_options_index = -1;
994 val = OptionParser::Parse(argv, short_options, long_options,
995 &long_options_index);
996
997 if (val == ':') {
998 return llvm::createStringError(llvm::inconvertibleErrorCode(),
999 "last option requires an argument");
1000 }
1001
1002 if (val == -1)
1003 break;
1004
1005 if (val == '?') {
1006 return llvm::createStringError("Unknown or ambiguous option");
1007 }
1008
1009 if (val == 0)
1010 continue;
1011
1012 OptionSeen(val);
1013
1014 // Look up the long option index
1015 if (long_options_index == -1) {
1016 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1017 long_options[j].val;
1018 ++j) {
1019 if (long_options[j].val == val) {
1020 long_options_index = j;
1021 break;
1022 }
1023 }
1024 }
1025
1026 // See if the option takes an argument, and see if one was supplied.
1027 if (long_options_index == -1) {
1028 return llvm::createStringError(
1029 llvm::formatv("Invalid option with value '{0}'.", char(val)).str());
1030 }
1031
1032 StreamString option_str;
1033 option_str.Printf("-%c", val);
1034 const OptionDefinition *def = long_options[long_options_index].definition;
1035 int has_arg =
1036 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1037
1038 const char *option_arg = nullptr;
1039 switch (has_arg) {
1041 if (OptionParser::GetOptionArgument() == nullptr) {
1042 return llvm::createStringError(
1043 llvm::formatv("Option '{0}' is missing argument specifier.",
1044 option_str.GetString())
1045 .str());
1046 }
1047 [[fallthrough]];
1049 option_arg = OptionParser::GetOptionArgument();
1050 [[fallthrough]];
1052 break;
1053 default:
1054 return llvm::createStringError(
1055 llvm::formatv("error with options table; invalid value in has_arg "
1056 "field for option '{0}'.",
1057 char(val))
1058 .str());
1059 }
1060 // Find option in the argument list; also see if it was supposed to take an
1061 // argument and if one was supplied. Remove option (and argument, if
1062 // given) from the argument list. Also remove them from the
1063 // raw_input_string, if one was passed in.
1064 // Note: We also need to preserve any option argument values that were
1065 // surrounded by backticks, as we lose track of them in the
1066 // option_args_vector.
1067 size_t idx =
1068 FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
1069 std::string option_to_insert;
1070 if (option_arg) {
1071 if (idx != size_t(-1) && has_arg) {
1072 bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
1073 if (arg_has_backtick)
1074 option_to_insert = "`";
1075 option_to_insert += option_arg;
1076 if (arg_has_backtick)
1077 option_to_insert += "`";
1078 } else
1079 option_to_insert = option_arg;
1080 } else
1081 option_to_insert = CommandInterpreter::g_no_argument;
1082
1083 option_arg_vector->emplace_back(std::string(option_str.GetString()),
1084 has_arg, option_to_insert);
1085
1086 if (idx == size_t(-1))
1087 continue;
1088
1089 if (!input_line.empty()) {
1090 llvm::StringRef tmp_arg = args_copy[idx].ref();
1091 size_t pos = input_line.find(tmp_arg);
1092 if (pos != std::string::npos)
1093 input_line.erase(pos, tmp_arg.size());
1094 }
1095 args_copy.DeleteArgumentAtIndex(idx);
1096 if ((option_to_insert != CommandInterpreter::g_no_argument) &&
1097 (OptionParser::GetOptionArgument() != nullptr) &&
1098 (idx < args_copy.GetArgumentCount()) &&
1099 (args_copy[idx].ref() == OptionParser::GetOptionArgument())) {
1100 if (input_line.size() > 0) {
1101 size_t pos = input_line.find(option_to_insert);
1102 if (pos != std::string::npos)
1103 input_line.erase(pos, option_to_insert.size());
1104 }
1105 args_copy.DeleteArgumentAtIndex(idx);
1106 }
1107 }
1108
1109 return std::move(args_copy);
1110}
1111
1113 uint32_t cursor_index) {
1114 OptionElementVector option_element_vector;
1115 Option *long_options = GetLongOptions();
1116 option_element_vector.clear();
1117
1118 if (long_options == nullptr)
1119 return option_element_vector;
1120
1121 std::string short_options = BuildShortOptions(long_options);
1122
1123 std::unique_lock<std::mutex> lock;
1126
1127 int val;
1128 auto opt_defs = GetDefinitions();
1129
1130 std::vector<char *> dummy_vec = GetArgvForParsing(args);
1131
1132 bool failed_once = false;
1133 uint32_t dash_dash_pos = -1;
1134
1135 while (true) {
1136 bool missing_argument = false;
1137 int long_options_index = -1;
1138
1139 val = OptionParser::Parse(dummy_vec, short_options, long_options,
1140 &long_options_index);
1141
1142 if (val == -1) {
1143 // When we're completing a "--" which is the last option on line,
1144 if (failed_once)
1145 break;
1146
1147 failed_once = true;
1148
1149 // If this is a bare "--" we mark it as such so we can complete it
1150 // successfully later. Handling the "--" is a little tricky, since that
1151 // may mean end of options or arguments, or the user might want to
1152 // complete options by long name. I make this work by checking whether
1153 // the cursor is in the "--" argument, and if so I assume we're
1154 // completing the long option, otherwise I let it pass to
1155 // OptionParser::Parse which will terminate the option parsing. Note, in
1156 // either case we continue parsing the line so we can figure out what
1157 // other options were passed. This will be useful when we come to
1158 // restricting completions based on what other options we've seen on the
1159 // line.
1160
1161 if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1162 dummy_vec.size() &&
1163 (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1164 dash_dash_pos = FindOriginalIndex(
1165 dummy_vec[OptionParser::GetOptionIndex() - 1], args);
1166 if (dash_dash_pos == cursor_index) {
1167 option_element_vector.push_back(
1170 continue;
1171 } else
1172 break;
1173 } else
1174 break;
1175 } else if (val == '?') {
1176 option_element_vector.push_back(OptionArgElement(
1179 args),
1181 continue;
1182 } else if (val == 0) {
1183 continue;
1184 } else if (val == ':') {
1185 // This is a missing argument.
1187 missing_argument = true;
1188 }
1189
1190 OptionSeen(val);
1191
1192 // Look up the long option index
1193 if (long_options_index == -1) {
1194 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1195 long_options[j].val;
1196 ++j) {
1197 if (long_options[j].val == val) {
1198 long_options_index = j;
1199 break;
1200 }
1201 }
1202 }
1203
1204 // See if the option takes an argument, and see if one was supplied.
1205 if (long_options_index >= 0) {
1206 int opt_defs_index = -1;
1207 for (size_t i = 0; i < opt_defs.size(); i++) {
1208 if (opt_defs[i].short_option != val)
1209 continue;
1210 opt_defs_index = i;
1211 break;
1212 }
1213
1214 const OptionDefinition *def = long_options[long_options_index].definition;
1215 int has_arg =
1216 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1217 switch (has_arg) {
1219 option_element_vector.push_back(OptionArgElement(
1220 opt_defs_index,
1222 args),
1223 0));
1224 break;
1226 if (OptionParser::GetOptionArgument() != nullptr) {
1227 int arg_index;
1228 if (missing_argument)
1229 arg_index = -1;
1230 else
1231 arg_index = OptionParser::GetOptionIndex() - 2;
1232
1233 option_element_vector.push_back(OptionArgElement(
1234 opt_defs_index,
1236 args),
1237 arg_index));
1238 } else {
1239 option_element_vector.push_back(OptionArgElement(
1240 opt_defs_index,
1242 args),
1243 -1));
1244 }
1245 break;
1247 option_element_vector.push_back(OptionArgElement(
1248 opt_defs_index,
1250 args),
1252 args)));
1253 break;
1254 default:
1255 // The options table is messed up. Here we'll just continue
1256 option_element_vector.push_back(OptionArgElement(
1259 args),
1261 break;
1262 }
1263 } else {
1264 option_element_vector.push_back(OptionArgElement(
1267 args),
1269 }
1270 }
1271
1272 // Finally we have to handle the case where the cursor index points at a
1273 // single "-". We want to mark that in the option_element_vector, but only
1274 // if it is not after the "--". But it turns out that OptionParser::Parse
1275 // just ignores an isolated "-". So we have to look it up by hand here. We
1276 // only care if it is AT the cursor position. Note, a single quoted dash is
1277 // not the same as a single dash...
1278
1279 const Args::ArgEntry &cursor = args[cursor_index];
1280 if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1281 cursor_index < dash_dash_pos) &&
1282 !cursor.IsQuoted() && cursor.ref() == "-") {
1283 option_element_vector.push_back(
1286 }
1287 return option_element_vector;
1288}
1289
1290llvm::Expected<Args> Options::Parse(const Args &args,
1291 ExecutionContext *execution_context,
1292 lldb::PlatformSP platform_sp,
1293 bool require_validation) {
1294 Status error;
1295 Option *long_options = GetLongOptions();
1296 if (long_options == nullptr) {
1297 return llvm::createStringError("invalid long options");
1298 }
1299
1300 std::string short_options = BuildShortOptions(long_options);
1301 std::vector<char *> argv = GetArgvForParsing(args);
1302
1303 std::unique_lock<std::mutex> lock;
1305 while (true) {
1306 int long_options_index = -1;
1307 int val = OptionParser::Parse(argv, short_options, long_options,
1308 &long_options_index);
1309
1310 if (val == ':') {
1311 error = Status::FromErrorString("last option requires an argument");
1312 break;
1313 }
1314
1315 if (val == -1)
1316 break;
1317
1318 // Did we get an error?
1319 if (val == '?') {
1320 // Account for "argv[0]" and that it points to the next option.
1321 int idx = OptionParser::GetOptionIndex() - 2;
1322 if (idx >= 0 && (size_t)idx < args.GetArgumentCount())
1323 error = Status::FromError(llvm::make_error<OptionParseError>(
1324 args[idx], "unknown or ambiguous option"));
1325 else
1326 error = Status("unknown or ambiguous option");
1327
1328 break;
1329 }
1330 // The option auto-set itself
1331 if (val == 0)
1332 continue;
1333
1334 OptionSeen(val);
1335
1336 // Lookup the long option index
1337 if (long_options_index == -1) {
1338 for (int i = 0; long_options[i].definition || long_options[i].flag ||
1339 long_options[i].val;
1340 ++i) {
1341 if (long_options[i].val == val) {
1342 long_options_index = i;
1343 break;
1344 }
1345 }
1346 }
1347 // Call the callback with the option
1348 if (long_options_index >= 0 &&
1349 long_options[long_options_index].definition) {
1350 const OptionDefinition *def = long_options[long_options_index].definition;
1351
1352 if (!platform_sp) {
1353 // User did not pass in an explicit platform. Try to grab from the
1354 // execution context.
1355 TargetSP target_sp =
1356 execution_context ? execution_context->GetTargetSP() : TargetSP();
1357 platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
1358 }
1360
1361 if (!platform_sp && require_validation) {
1362 // Caller requires validation but we cannot validate as we don't have
1363 // the mandatory platform against which to validate.
1364 return llvm::createStringError(
1365 "cannot validate options: no platform available");
1366 }
1367
1368 bool validation_failed = false;
1369 if (platform_sp) {
1370 // Ensure we have an execution context, empty or not.
1371 ExecutionContext dummy_context;
1372 ExecutionContext *exe_ctx_p =
1373 execution_context ? execution_context : &dummy_context;
1374 if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
1375 validation_failed = true;
1377 "Option \"%s\" invalid. %s", def->long_option,
1379 }
1380 }
1381
1382 // As long as validation didn't fail, we set the option value.
1383 if (!validation_failed)
1384 error =
1385 SetOptionValue(long_options_index,
1387 ? nullptr
1389 execution_context);
1390 // If the Option setting returned an error, we should stop parsing
1391 // and return the error.
1392 if (error.Fail())
1393 break;
1394 } else {
1396 "invalid option with value '%i'", val);
1397 }
1398 }
1399
1400 if (error.Fail())
1401 return error.ToError();
1402
1403 argv.pop_back();
1404 argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
1405 return ReconstituteArgsAfterParsing(argv, args);
1406}
1407
1409 llvm::StringRef option_arg, const char short_option,
1410 llvm::StringRef long_option, llvm::StringRef additional_context) {
1411 std::string buffer;
1412 llvm::raw_string_ostream stream(buffer);
1413 stream << "Invalid value ('" << option_arg << "') for -" << short_option;
1414 if (!long_option.empty())
1415 stream << " (" << long_option << ")";
1416 if (!additional_context.empty())
1417 stream << ": " << additional_context;
1418 return llvm::createStringError(llvm::inconvertibleErrorCode(), buffer);
1419}
static llvm::raw_ostream & error(Stream &strm)
static Args ReconstituteArgsAfterParsing(llvm::ArrayRef< char * > parsed, const Args &original)
Definition Options.cpp:923
static std::string BuildShortOptions(const Option *long_options)
Definition Options.cpp:948
static std::vector< char * > GetArgvForParsing(const Args &args)
Definition Options.cpp:899
static bool PrintOption(const OptionDefinition &opt_def, OptionDisplayType display_type, const char *header, const char *footer, bool show_optional, Stream &strm)
Definition Options.cpp:356
static Args::const_iterator FindOriginalIter(const char *arg, const Args &original)
Definition Options.cpp:910
static size_t FindArgumentIndexForOption(const Args &args, const Option &long_option)
Definition Options.cpp:934
OptionDisplayType
Definition Options.cpp:350
@ eDisplayShortOption
Definition Options.cpp:352
@ eDisplayBestOption
Definition Options.cpp:351
@ eDisplayLongOption
Definition Options.cpp:353
static size_t FindOriginalIndex(const char *arg, const Args &original)
Definition Options.cpp:917
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:180
bool GetUseColor() const
Definition Debugger.cpp:452
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:866
std::vector< OptionDefinition > m_option_defs
Definition Options.h:334
const OptionGroup * GetGroupWithOption(char short_opt)
Definition Options.cpp:809
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
Definition Options.cpp:847
Status OptionParsingFinished(ExecutionContext *execution_context) override
Definition Options.cpp:879
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition Options.cpp:801
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:392
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:729
llvm::Error VerifyOptions()
Definition Options.cpp:558
virtual Status OptionParsingFinished(ExecutionContext *execution_context)
Definition Options.h:226
llvm::Error VerifyPartialOptions()
Definition Options.cpp:601
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:975
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:625
bool IsASubset(const OptionSet &set_a, const OptionSet &set_b)
Definition Options.cpp:84
bool SupportsLongOption(const char *long_option)
Definition Options.cpp:327
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:1290
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:1112
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:1408
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