Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Interpreter/Options.cpp
39587 views
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
9
#include "lldb/Interpreter/Options.h"
10
11
#include <algorithm>
12
#include <bitset>
13
#include <map>
14
#include <set>
15
16
#include "lldb/Host/OptionParser.h"
17
#include "lldb/Interpreter/CommandCompletions.h"
18
#include "lldb/Interpreter/CommandInterpreter.h"
19
#include "lldb/Interpreter/CommandObject.h"
20
#include "lldb/Interpreter/CommandReturnObject.h"
21
#include "lldb/Target/Target.h"
22
#include "lldb/Utility/StreamString.h"
23
#include "llvm/ADT/STLExtras.h"
24
25
using namespace lldb;
26
using namespace lldb_private;
27
28
// Options
29
Options::Options() { BuildValidOptionSets(); }
30
31
Options::~Options() = default;
32
33
void Options::NotifyOptionParsingStarting(ExecutionContext *execution_context) {
34
m_seen_options.clear();
35
// Let the subclass reset its option values
36
OptionParsingStarting(execution_context);
37
}
38
39
Status
40
Options::NotifyOptionParsingFinished(ExecutionContext *execution_context) {
41
return OptionParsingFinished(execution_context);
42
}
43
44
void Options::OptionSeen(int option_idx) { m_seen_options.insert(option_idx); }
45
46
// Returns true is set_a is a subset of set_b; Otherwise returns false.
47
48
bool Options::IsASubset(const OptionSet &set_a, const OptionSet &set_b) {
49
bool is_a_subset = true;
50
OptionSet::const_iterator pos_a;
51
OptionSet::const_iterator pos_b;
52
53
// set_a is a subset of set_b if every member of set_a is also a member of
54
// set_b
55
56
for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) {
57
pos_b = set_b.find(*pos_a);
58
if (pos_b == set_b.end())
59
is_a_subset = false;
60
}
61
62
return is_a_subset;
63
}
64
65
// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) &&
66
// !ElementOf (x, set_b) }
67
68
size_t Options::OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b,
69
OptionSet &diffs) {
70
size_t num_diffs = 0;
71
OptionSet::const_iterator pos_a;
72
OptionSet::const_iterator pos_b;
73
74
for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) {
75
pos_b = set_b.find(*pos_a);
76
if (pos_b == set_b.end()) {
77
++num_diffs;
78
diffs.insert(*pos_a);
79
}
80
}
81
82
return num_diffs;
83
}
84
85
// Returns the union of set_a and set_b. Does not put duplicate members into
86
// the union.
87
88
void Options::OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b,
89
OptionSet &union_set) {
90
OptionSet::const_iterator pos;
91
OptionSet::iterator pos_union;
92
93
// Put all the elements of set_a into the union.
94
95
for (pos = set_a.begin(); pos != set_a.end(); ++pos)
96
union_set.insert(*pos);
97
98
// Put all the elements of set_b that are not already there into the union.
99
for (pos = set_b.begin(); pos != set_b.end(); ++pos) {
100
pos_union = union_set.find(*pos);
101
if (pos_union == union_set.end())
102
union_set.insert(*pos);
103
}
104
}
105
106
bool Options::VerifyOptions(CommandReturnObject &result) {
107
bool options_are_valid = false;
108
109
int num_levels = GetRequiredOptions().size();
110
if (num_levels) {
111
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
112
// This is the correct set of options if: 1). m_seen_options contains
113
// all of m_required_options[i] (i.e. all the required options at this
114
// level are a subset of m_seen_options); AND 2). { m_seen_options -
115
// m_required_options[i] is a subset of m_options_options[i] (i.e. all
116
// the rest of m_seen_options are in the set of optional options at this
117
// level.
118
119
// Check to see if all of m_required_options[i] are a subset of
120
// m_seen_options
121
if (IsASubset(GetRequiredOptions()[i], m_seen_options)) {
122
// Construct the set difference: remaining_options = {m_seen_options} -
123
// {m_required_options[i]}
124
OptionSet remaining_options;
125
OptionsSetDiff(m_seen_options, GetRequiredOptions()[i],
126
remaining_options);
127
// Check to see if remaining_options is a subset of
128
// m_optional_options[i]
129
if (IsASubset(remaining_options, GetOptionalOptions()[i]))
130
options_are_valid = true;
131
}
132
}
133
} else {
134
options_are_valid = true;
135
}
136
137
if (options_are_valid) {
138
result.SetStatus(eReturnStatusSuccessFinishNoResult);
139
} else {
140
result.AppendError("invalid combination of options for the given command");
141
}
142
143
return options_are_valid;
144
}
145
146
// This is called in the Options constructor, though we could call it lazily if
147
// that ends up being a performance problem.
148
149
void Options::BuildValidOptionSets() {
150
// Check to see if we already did this.
151
if (m_required_options.size() != 0)
152
return;
153
154
// Check to see if there are any options.
155
int num_options = NumCommandOptions();
156
if (num_options == 0)
157
return;
158
159
auto opt_defs = GetDefinitions();
160
m_required_options.resize(1);
161
m_optional_options.resize(1);
162
163
// First count the number of option sets we've got. Ignore
164
// LLDB_ALL_OPTION_SETS...
165
166
uint32_t num_option_sets = 0;
167
168
for (const auto &def : opt_defs) {
169
uint32_t this_usage_mask = def.usage_mask;
170
if (this_usage_mask == LLDB_OPT_SET_ALL) {
171
if (num_option_sets == 0)
172
num_option_sets = 1;
173
} else {
174
for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) {
175
if (this_usage_mask & (1 << j)) {
176
if (num_option_sets <= j)
177
num_option_sets = j + 1;
178
}
179
}
180
}
181
}
182
183
if (num_option_sets > 0) {
184
m_required_options.resize(num_option_sets);
185
m_optional_options.resize(num_option_sets);
186
187
for (const auto &def : opt_defs) {
188
for (uint32_t j = 0; j < num_option_sets; j++) {
189
if (def.usage_mask & 1 << j) {
190
if (def.required)
191
m_required_options[j].insert(def.short_option);
192
else
193
m_optional_options[j].insert(def.short_option);
194
}
195
}
196
}
197
}
198
}
199
200
uint32_t Options::NumCommandOptions() { return GetDefinitions().size(); }
201
202
Option *Options::GetLongOptions() {
203
// Check to see if this has already been done.
204
if (m_getopt_table.empty()) {
205
auto defs = GetDefinitions();
206
if (defs.empty())
207
return nullptr;
208
209
std::map<int, uint32_t> option_seen;
210
211
m_getopt_table.resize(defs.size() + 1);
212
for (size_t i = 0; i < defs.size(); ++i) {
213
const int short_opt = defs[i].short_option;
214
215
m_getopt_table[i].definition = &defs[i];
216
m_getopt_table[i].flag = nullptr;
217
m_getopt_table[i].val = short_opt;
218
219
if (option_seen.find(short_opt) == option_seen.end()) {
220
option_seen[short_opt] = i;
221
} else if (short_opt) {
222
m_getopt_table[i].val = 0;
223
std::map<int, uint32_t>::const_iterator pos =
224
option_seen.find(short_opt);
225
StreamString strm;
226
if (defs[i].HasShortOption())
227
Debugger::ReportError(
228
llvm::formatv(
229
"option[{0}] --{1} has a short option -{2} that "
230
"conflicts with option[{3}] --{4}, short option won't "
231
"be used for --{5}",
232
i, defs[i].long_option, short_opt, pos->second,
233
m_getopt_table[pos->second].definition->long_option,
234
defs[i].long_option)
235
.str());
236
else
237
Debugger::ReportError(
238
llvm::formatv(
239
"option[{0}] --{1} has a short option {2:x} that "
240
"conflicts with option[{3}] --{4}, short option won't "
241
"be used for --{5}",
242
(int)i, defs[i].long_option, short_opt, pos->second,
243
m_getopt_table[pos->second].definition->long_option,
244
defs[i].long_option)
245
.str());
246
}
247
}
248
249
// getopt_long_only requires a NULL final entry in the table:
250
251
m_getopt_table.back().definition = nullptr;
252
m_getopt_table.back().flag = nullptr;
253
m_getopt_table.back().val = 0;
254
}
255
256
if (m_getopt_table.empty())
257
return nullptr;
258
259
return &m_getopt_table.front();
260
}
261
262
// This function takes INDENT, which tells how many spaces to output at the
263
// front of each line; SPACES, which is a string containing 80 spaces; and
264
// TEXT, which is the text that is to be output. It outputs the text, on
265
// multiple lines if necessary, to RESULT, with INDENT spaces at the front of
266
// each line. It breaks lines on spaces, tabs or newlines, shortening the line
267
// if necessary to not break in the middle of a word. It assumes that each
268
// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
269
270
void Options::OutputFormattedUsageText(Stream &strm,
271
const OptionDefinition &option_def,
272
uint32_t output_max_columns) {
273
std::string actual_text;
274
if (option_def.validator) {
275
const char *condition = option_def.validator->ShortConditionString();
276
if (condition) {
277
actual_text = "[";
278
actual_text.append(condition);
279
actual_text.append("] ");
280
}
281
}
282
actual_text.append(option_def.usage_text);
283
284
// Will it all fit on one line?
285
286
if (static_cast<uint32_t>(actual_text.length() + strm.GetIndentLevel()) <
287
output_max_columns) {
288
// Output it as a single line.
289
strm.Indent(actual_text);
290
strm.EOL();
291
} else {
292
// We need to break it up into multiple lines.
293
294
int text_width = output_max_columns - strm.GetIndentLevel() - 1;
295
int start = 0;
296
int end = start;
297
int final_end = actual_text.length();
298
int sub_len;
299
300
while (end < final_end) {
301
// Don't start the 'text' on a space, since we're already outputting the
302
// indentation.
303
while ((start < final_end) && (actual_text[start] == ' '))
304
start++;
305
306
end = start + text_width;
307
if (end > final_end)
308
end = final_end;
309
else {
310
// If we're not at the end of the text, make sure we break the line on
311
// white space.
312
while (end > start && actual_text[end] != ' ' &&
313
actual_text[end] != '\t' && actual_text[end] != '\n')
314
end--;
315
}
316
317
sub_len = end - start;
318
if (start != 0)
319
strm.EOL();
320
strm.Indent();
321
assert(start < final_end);
322
assert(start + sub_len <= final_end);
323
strm.Write(actual_text.c_str() + start, sub_len);
324
start = end + 1;
325
}
326
strm.EOL();
327
}
328
}
329
330
bool 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
353
enum OptionDisplayType {
354
eDisplayBestOption,
355
eDisplayShortOption,
356
eDisplayLongOption
357
};
358
359
static 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) {
377
case OptionParser::eNoArgument:
378
break;
379
case OptionParser::eRequiredArgument:
380
strm.Printf(" <%s>", CommandObject::GetArgumentName(opt_def.argument_type));
381
break;
382
383
case OptionParser::eOptionalArgument:
384
strm.Printf("%s[<%s>]", show_short_option ? "" : "=",
385
CommandObject::GetArgumentName(opt_def.argument_type));
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
395
void Options::GenerateOptionUsage(Stream &strm, CommandObject &cmd,
396
uint32_t screen_width) {
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);
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
561
// This function is called when we have been given a potentially incomplete set
562
// of options, such as when an alias has been defined (more options might be
563
// added at at the time the alias is invoked). We need to verify that the
564
// options in the set m_seen_options are all part of a set that may be used
565
// together, but m_seen_options may be missing some of the "required" options.
566
567
bool Options::VerifyPartialOptions(CommandReturnObject &result) {
568
bool options_are_valid = false;
569
570
int num_levels = GetRequiredOptions().size();
571
if (num_levels) {
572
for (int i = 0; i < num_levels && !options_are_valid; ++i) {
573
// In this case we are treating all options as optional rather than
574
// required. Therefore a set of options is correct if m_seen_options is a
575
// subset of the union of m_required_options and m_optional_options.
576
OptionSet union_set;
577
OptionsSetUnion(GetRequiredOptions()[i], GetOptionalOptions()[i],
578
union_set);
579
if (IsASubset(m_seen_options, union_set))
580
options_are_valid = true;
581
}
582
}
583
584
return options_are_valid;
585
}
586
587
bool Options::HandleOptionCompletion(CompletionRequest &request,
588
OptionElementVector &opt_element_vector,
589
CommandInterpreter &interpreter) {
590
// For now we just scan the completions to see if the cursor position is in
591
// an option or its argument. Otherwise we'll call HandleArgumentCompletion.
592
// In the future we can use completion to validate options as well if we
593
// want.
594
595
auto opt_defs = GetDefinitions();
596
597
llvm::StringRef cur_opt_str = request.GetCursorArgumentPrefix();
598
599
for (size_t i = 0; i < opt_element_vector.size(); i++) {
600
size_t opt_pos = static_cast<size_t>(opt_element_vector[i].opt_pos);
601
size_t opt_arg_pos = static_cast<size_t>(opt_element_vector[i].opt_arg_pos);
602
int opt_defs_index = opt_element_vector[i].opt_defs_index;
603
if (opt_pos == request.GetCursorIndex()) {
604
// We're completing the option itself.
605
606
if (opt_defs_index == OptionArgElement::eBareDash) {
607
// We're completing a bare dash. That means all options are open.
608
// FIXME: We should scan the other options provided and only complete
609
// options
610
// within the option group they belong to.
611
std::string opt_str = "-a";
612
613
for (auto &def : opt_defs) {
614
if (!def.short_option)
615
continue;
616
opt_str[1] = def.short_option;
617
request.AddCompletion(opt_str, def.usage_text);
618
}
619
620
return true;
621
} else if (opt_defs_index == OptionArgElement::eBareDoubleDash) {
622
std::string full_name("--");
623
for (auto &def : opt_defs) {
624
if (!def.short_option)
625
continue;
626
627
full_name.erase(full_name.begin() + 2, full_name.end());
628
full_name.append(def.long_option);
629
request.AddCompletion(full_name, def.usage_text);
630
}
631
return true;
632
} else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) {
633
// We recognized it, if it an incomplete long option, complete it
634
// anyway (getopt_long_only is happy with shortest unique string, but
635
// it's still a nice thing to do.) Otherwise return The string so the
636
// upper level code will know this is a full match and add the " ".
637
const OptionDefinition &opt = opt_defs[opt_defs_index];
638
llvm::StringRef long_option = opt.long_option;
639
if (cur_opt_str.starts_with("--") && cur_opt_str != long_option) {
640
request.AddCompletion("--" + long_option.str(), opt.usage_text);
641
return true;
642
} else
643
request.AddCompletion(request.GetCursorArgumentPrefix());
644
return true;
645
} else {
646
// FIXME - not handling wrong options yet:
647
// Check to see if they are writing a long option & complete it.
648
// I think we will only get in here if the long option table has two
649
// elements
650
// that are not unique up to this point. getopt_long_only does
651
// shortest unique match for long options already.
652
if (cur_opt_str.consume_front("--")) {
653
for (auto &def : opt_defs) {
654
llvm::StringRef long_option(def.long_option);
655
if (long_option.starts_with(cur_opt_str))
656
request.AddCompletion("--" + long_option.str(), def.usage_text);
657
}
658
}
659
return true;
660
}
661
662
} else if (opt_arg_pos == request.GetCursorIndex()) {
663
// Okay the cursor is on the completion of an argument. See if it has a
664
// completion, otherwise return no matches.
665
if (opt_defs_index != -1) {
666
HandleOptionArgumentCompletion(request, opt_element_vector, i,
667
interpreter);
668
return true;
669
} else {
670
// No completion callback means no completions...
671
return true;
672
}
673
674
} else {
675
// Not the last element, keep going.
676
continue;
677
}
678
}
679
return false;
680
}
681
682
void Options::HandleOptionArgumentCompletion(
683
CompletionRequest &request, OptionElementVector &opt_element_vector,
684
int opt_element_index, CommandInterpreter &interpreter) {
685
auto opt_defs = GetDefinitions();
686
std::unique_ptr<SearchFilter> filter_up;
687
688
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
689
690
// See if this is an enumeration type option, and if so complete it here:
691
692
const auto &enum_values = opt_defs[opt_defs_index].enum_values;
693
if (!enum_values.empty())
694
for (const auto &enum_value : enum_values)
695
request.TryCompleteCurrentArg(enum_value.string_value);
696
697
// If this is a source file or symbol type completion, and there is a -shlib
698
// option somewhere in the supplied arguments, then make a search filter for
699
// that shared library.
700
// FIXME: Do we want to also have an "OptionType" so we don't have to match
701
// string names?
702
703
uint32_t completion_mask = opt_defs[opt_defs_index].completion_type;
704
705
if (completion_mask == 0) {
706
lldb::CommandArgumentType option_arg_type =
707
opt_defs[opt_defs_index].argument_type;
708
if (option_arg_type != eArgTypeNone) {
709
const CommandObject::ArgumentTableEntry *arg_entry =
710
CommandObject::FindArgumentDataByType(
711
opt_defs[opt_defs_index].argument_type);
712
if (arg_entry)
713
completion_mask = arg_entry->completion_type;
714
}
715
}
716
717
if (completion_mask & lldb::eSourceFileCompletion ||
718
completion_mask & lldb::eSymbolCompletion) {
719
for (size_t i = 0; i < opt_element_vector.size(); i++) {
720
int cur_defs_index = opt_element_vector[i].opt_defs_index;
721
722
// trying to use <0 indices will definitely cause problems
723
if (cur_defs_index == OptionArgElement::eUnrecognizedArg ||
724
cur_defs_index == OptionArgElement::eBareDash ||
725
cur_defs_index == OptionArgElement::eBareDoubleDash)
726
continue;
727
728
int cur_arg_pos = opt_element_vector[i].opt_arg_pos;
729
const char *cur_opt_name = opt_defs[cur_defs_index].long_option;
730
731
// If this is the "shlib" option and there was an argument provided,
732
// restrict it to that shared library.
733
if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 &&
734
cur_arg_pos != -1) {
735
const char *module_name =
736
request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
737
if (module_name) {
738
FileSpec module_spec(module_name);
739
lldb::TargetSP target_sp =
740
interpreter.GetDebugger().GetSelectedTarget();
741
// Search filters require a target...
742
if (target_sp)
743
filter_up =
744
std::make_unique<SearchFilterByModule>(target_sp, module_spec);
745
}
746
break;
747
}
748
}
749
}
750
751
lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
752
interpreter, completion_mask, request, filter_up.get());
753
}
754
755
void OptionGroupOptions::Append(OptionGroup *group) {
756
auto group_option_defs = group->GetDefinitions();
757
for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
758
m_option_infos.push_back(OptionInfo(group, i));
759
m_option_defs.push_back(group_option_defs[i]);
760
}
761
}
762
763
const OptionGroup *OptionGroupOptions::GetGroupWithOption(char short_opt) {
764
for (uint32_t i = 0; i < m_option_defs.size(); i++) {
765
OptionDefinition opt_def = m_option_defs[i];
766
if (opt_def.short_option == short_opt)
767
return m_option_infos[i].option_group;
768
}
769
return nullptr;
770
}
771
772
void OptionGroupOptions::Append(OptionGroup *group, uint32_t src_mask,
773
uint32_t dst_mask) {
774
auto group_option_defs = group->GetDefinitions();
775
for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
776
if (group_option_defs[i].usage_mask & src_mask) {
777
m_option_infos.push_back(OptionInfo(group, i));
778
m_option_defs.push_back(group_option_defs[i]);
779
m_option_defs.back().usage_mask = dst_mask;
780
}
781
}
782
}
783
784
void OptionGroupOptions::Append(
785
OptionGroup *group, llvm::ArrayRef<llvm::StringRef> exclude_long_options) {
786
auto group_option_defs = group->GetDefinitions();
787
for (uint32_t i = 0; i < group_option_defs.size(); ++i) {
788
const auto &definition = group_option_defs[i];
789
if (llvm::is_contained(exclude_long_options, definition.long_option))
790
continue;
791
792
m_option_infos.push_back(OptionInfo(group, i));
793
m_option_defs.push_back(definition);
794
}
795
}
796
797
void OptionGroupOptions::Finalize() {
798
m_did_finalize = true;
799
}
800
801
Status OptionGroupOptions::SetOptionValue(uint32_t option_idx,
802
llvm::StringRef option_value,
803
ExecutionContext *execution_context) {
804
// After calling OptionGroupOptions::Append(...), you must finalize the
805
// groups by calling OptionGroupOptions::Finlize()
806
assert(m_did_finalize);
807
Status error;
808
if (option_idx < m_option_infos.size()) {
809
error = m_option_infos[option_idx].option_group->SetOptionValue(
810
m_option_infos[option_idx].option_index, option_value,
811
execution_context);
812
813
} else {
814
error.SetErrorString("invalid option index"); // Shouldn't happen...
815
}
816
return error;
817
}
818
819
void OptionGroupOptions::OptionParsingStarting(
820
ExecutionContext *execution_context) {
821
std::set<OptionGroup *> group_set;
822
OptionInfos::iterator pos, end = m_option_infos.end();
823
for (pos = m_option_infos.begin(); pos != end; ++pos) {
824
OptionGroup *group = pos->option_group;
825
if (group_set.find(group) == group_set.end()) {
826
group->OptionParsingStarting(execution_context);
827
group_set.insert(group);
828
}
829
}
830
}
831
Status
832
OptionGroupOptions::OptionParsingFinished(ExecutionContext *execution_context) {
833
std::set<OptionGroup *> group_set;
834
Status error;
835
OptionInfos::iterator pos, end = m_option_infos.end();
836
for (pos = m_option_infos.begin(); pos != end; ++pos) {
837
OptionGroup *group = pos->option_group;
838
if (group_set.find(group) == group_set.end()) {
839
error = group->OptionParsingFinished(execution_context);
840
group_set.insert(group);
841
if (error.Fail())
842
return error;
843
}
844
}
845
return error;
846
}
847
848
// OptionParser permutes the arguments while processing them, so we create a
849
// temporary array holding to avoid modification of the input arguments. The
850
// options themselves are never modified, but the API expects a char * anyway,
851
// hence the const_cast.
852
static std::vector<char *> GetArgvForParsing(const Args &args) {
853
std::vector<char *> result;
854
// OptionParser always skips the first argument as it is based on getopt().
855
result.push_back(const_cast<char *>("<FAKE-ARG0>"));
856
for (const Args::ArgEntry &entry : args)
857
result.push_back(const_cast<char *>(entry.c_str()));
858
result.push_back(nullptr);
859
return result;
860
}
861
862
// Given a permuted argument, find it's position in the original Args vector.
863
static Args::const_iterator FindOriginalIter(const char *arg,
864
const Args &original) {
865
return llvm::find_if(
866
original, [arg](const Args::ArgEntry &D) { return D.c_str() == arg; });
867
}
868
869
// Given a permuted argument, find it's index in the original Args vector.
870
static size_t FindOriginalIndex(const char *arg, const Args &original) {
871
return std::distance(original.begin(), FindOriginalIter(arg, original));
872
}
873
874
// Construct a new Args object, consisting of the entries from the original
875
// arguments, but in the permuted order.
876
static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
877
const Args &original) {
878
Args result;
879
for (const char *arg : parsed) {
880
auto pos = FindOriginalIter(arg, original);
881
assert(pos != original.end());
882
result.AppendArgument(pos->ref(), pos->GetQuoteChar());
883
}
884
return result;
885
}
886
887
static size_t FindArgumentIndexForOption(const Args &args,
888
const Option &long_option) {
889
std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
890
std::string long_opt =
891
std::string(llvm::formatv("--{0}", long_option.definition->long_option));
892
for (const auto &entry : llvm::enumerate(args)) {
893
if (entry.value().ref().starts_with(short_opt) ||
894
entry.value().ref().starts_with(long_opt))
895
return entry.index();
896
}
897
898
return size_t(-1);
899
}
900
901
static std::string BuildShortOptions(const Option *long_options) {
902
std::string storage;
903
llvm::raw_string_ostream sstr(storage);
904
905
// Leading : tells getopt to return a : for a missing option argument AND to
906
// suppress error messages.
907
sstr << ":";
908
909
for (size_t i = 0; long_options[i].definition != nullptr; ++i) {
910
if (long_options[i].flag == nullptr) {
911
sstr << (char)long_options[i].val;
912
switch (long_options[i].definition->option_has_arg) {
913
default:
914
case OptionParser::eNoArgument:
915
break;
916
case OptionParser::eRequiredArgument:
917
sstr << ":";
918
break;
919
case OptionParser::eOptionalArgument:
920
sstr << "::";
921
break;
922
}
923
}
924
}
925
return std::move(sstr.str());
926
}
927
928
llvm::Expected<Args> Options::ParseAlias(const Args &args,
929
OptionArgVector *option_arg_vector,
930
std::string &input_line) {
931
Option *long_options = GetLongOptions();
932
933
if (long_options == nullptr) {
934
return llvm::createStringError("Invalid long options");
935
}
936
937
std::string short_options = BuildShortOptions(long_options);
938
939
Args args_copy = args;
940
std::vector<char *> argv = GetArgvForParsing(args);
941
942
std::unique_lock<std::mutex> lock;
943
OptionParser::Prepare(lock);
944
int val;
945
while (true) {
946
int long_options_index = -1;
947
val = OptionParser::Parse(argv, short_options, long_options,
948
&long_options_index);
949
950
if (val == ':') {
951
return llvm::createStringError(llvm::inconvertibleErrorCode(),
952
"last option requires an argument");
953
}
954
955
if (val == -1)
956
break;
957
958
if (val == '?') {
959
return llvm::createStringError("Unknown or ambiguous option");
960
}
961
962
if (val == 0)
963
continue;
964
965
OptionSeen(val);
966
967
// Look up the long option index
968
if (long_options_index == -1) {
969
for (int j = 0; long_options[j].definition || long_options[j].flag ||
970
long_options[j].val;
971
++j) {
972
if (long_options[j].val == val) {
973
long_options_index = j;
974
break;
975
}
976
}
977
}
978
979
// See if the option takes an argument, and see if one was supplied.
980
if (long_options_index == -1) {
981
return llvm::createStringError(
982
llvm::formatv("Invalid option with value '{0}'.", char(val)).str());
983
}
984
985
StreamString option_str;
986
option_str.Printf("-%c", val);
987
const OptionDefinition *def = long_options[long_options_index].definition;
988
int has_arg =
989
(def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
990
991
const char *option_arg = nullptr;
992
switch (has_arg) {
993
case OptionParser::eRequiredArgument:
994
if (OptionParser::GetOptionArgument() == nullptr) {
995
return llvm::createStringError(
996
llvm::formatv("Option '{0}' is missing argument specifier.",
997
option_str.GetString())
998
.str());
999
}
1000
[[fallthrough]];
1001
case OptionParser::eOptionalArgument:
1002
option_arg = OptionParser::GetOptionArgument();
1003
[[fallthrough]];
1004
case OptionParser::eNoArgument:
1005
break;
1006
default:
1007
return llvm::createStringError(
1008
llvm::formatv("error with options table; invalid value in has_arg "
1009
"field for option '{0}'.",
1010
char(val))
1011
.str());
1012
}
1013
// Find option in the argument list; also see if it was supposed to take an
1014
// argument and if one was supplied. Remove option (and argument, if
1015
// given) from the argument list. Also remove them from the
1016
// raw_input_string, if one was passed in.
1017
// Note: We also need to preserve any option argument values that were
1018
// surrounded by backticks, as we lose track of them in the
1019
// option_args_vector.
1020
size_t idx =
1021
FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
1022
std::string option_to_insert;
1023
if (option_arg) {
1024
if (idx != size_t(-1) && has_arg) {
1025
bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
1026
if (arg_has_backtick)
1027
option_to_insert = "`";
1028
option_to_insert += option_arg;
1029
if (arg_has_backtick)
1030
option_to_insert += "`";
1031
} else
1032
option_to_insert = option_arg;
1033
} else
1034
option_to_insert = CommandInterpreter::g_no_argument;
1035
1036
option_arg_vector->emplace_back(std::string(option_str.GetString()),
1037
has_arg, option_to_insert);
1038
1039
if (idx == size_t(-1))
1040
continue;
1041
1042
if (!input_line.empty()) {
1043
llvm::StringRef tmp_arg = args_copy[idx].ref();
1044
size_t pos = input_line.find(std::string(tmp_arg));
1045
if (pos != std::string::npos)
1046
input_line.erase(pos, tmp_arg.size());
1047
}
1048
args_copy.DeleteArgumentAtIndex(idx);
1049
if ((option_to_insert != CommandInterpreter::g_no_argument) &&
1050
(OptionParser::GetOptionArgument() != nullptr) &&
1051
(idx < args_copy.GetArgumentCount()) &&
1052
(args_copy[idx].ref() == OptionParser::GetOptionArgument())) {
1053
if (input_line.size() > 0) {
1054
size_t pos = input_line.find(option_to_insert);
1055
if (pos != std::string::npos)
1056
input_line.erase(pos, option_to_insert.size());
1057
}
1058
args_copy.DeleteArgumentAtIndex(idx);
1059
}
1060
}
1061
1062
return std::move(args_copy);
1063
}
1064
1065
OptionElementVector Options::ParseForCompletion(const Args &args,
1066
uint32_t cursor_index) {
1067
OptionElementVector option_element_vector;
1068
Option *long_options = GetLongOptions();
1069
option_element_vector.clear();
1070
1071
if (long_options == nullptr)
1072
return option_element_vector;
1073
1074
std::string short_options = BuildShortOptions(long_options);
1075
1076
std::unique_lock<std::mutex> lock;
1077
OptionParser::Prepare(lock);
1078
OptionParser::EnableError(false);
1079
1080
int val;
1081
auto opt_defs = GetDefinitions();
1082
1083
std::vector<char *> dummy_vec = GetArgvForParsing(args);
1084
1085
bool failed_once = false;
1086
uint32_t dash_dash_pos = -1;
1087
1088
while (true) {
1089
bool missing_argument = false;
1090
int long_options_index = -1;
1091
1092
val = OptionParser::Parse(dummy_vec, short_options, long_options,
1093
&long_options_index);
1094
1095
if (val == -1) {
1096
// When we're completing a "--" which is the last option on line,
1097
if (failed_once)
1098
break;
1099
1100
failed_once = true;
1101
1102
// If this is a bare "--" we mark it as such so we can complete it
1103
// successfully later. Handling the "--" is a little tricky, since that
1104
// may mean end of options or arguments, or the user might want to
1105
// complete options by long name. I make this work by checking whether
1106
// the cursor is in the "--" argument, and if so I assume we're
1107
// completing the long option, otherwise I let it pass to
1108
// OptionParser::Parse which will terminate the option parsing. Note, in
1109
// either case we continue parsing the line so we can figure out what
1110
// other options were passed. This will be useful when we come to
1111
// restricting completions based on what other options we've seen on the
1112
// line.
1113
1114
if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1115
dummy_vec.size() &&
1116
(strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1117
dash_dash_pos = FindOriginalIndex(
1118
dummy_vec[OptionParser::GetOptionIndex() - 1], args);
1119
if (dash_dash_pos == cursor_index) {
1120
option_element_vector.push_back(
1121
OptionArgElement(OptionArgElement::eBareDoubleDash, dash_dash_pos,
1122
OptionArgElement::eBareDoubleDash));
1123
continue;
1124
} else
1125
break;
1126
} else
1127
break;
1128
} else if (val == '?') {
1129
option_element_vector.push_back(OptionArgElement(
1130
OptionArgElement::eUnrecognizedArg,
1131
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1132
args),
1133
OptionArgElement::eUnrecognizedArg));
1134
continue;
1135
} else if (val == 0) {
1136
continue;
1137
} else if (val == ':') {
1138
// This is a missing argument.
1139
val = OptionParser::GetOptionErrorCause();
1140
missing_argument = true;
1141
}
1142
1143
OptionSeen(val);
1144
1145
// Look up the long option index
1146
if (long_options_index == -1) {
1147
for (int j = 0; long_options[j].definition || long_options[j].flag ||
1148
long_options[j].val;
1149
++j) {
1150
if (long_options[j].val == val) {
1151
long_options_index = j;
1152
break;
1153
}
1154
}
1155
}
1156
1157
// See if the option takes an argument, and see if one was supplied.
1158
if (long_options_index >= 0) {
1159
int opt_defs_index = -1;
1160
for (size_t i = 0; i < opt_defs.size(); i++) {
1161
if (opt_defs[i].short_option != val)
1162
continue;
1163
opt_defs_index = i;
1164
break;
1165
}
1166
1167
const OptionDefinition *def = long_options[long_options_index].definition;
1168
int has_arg =
1169
(def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1170
switch (has_arg) {
1171
case OptionParser::eNoArgument:
1172
option_element_vector.push_back(OptionArgElement(
1173
opt_defs_index,
1174
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1175
args),
1176
0));
1177
break;
1178
case OptionParser::eRequiredArgument:
1179
if (OptionParser::GetOptionArgument() != nullptr) {
1180
int arg_index;
1181
if (missing_argument)
1182
arg_index = -1;
1183
else
1184
arg_index = OptionParser::GetOptionIndex() - 2;
1185
1186
option_element_vector.push_back(OptionArgElement(
1187
opt_defs_index,
1188
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
1189
args),
1190
arg_index));
1191
} else {
1192
option_element_vector.push_back(OptionArgElement(
1193
opt_defs_index,
1194
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1195
args),
1196
-1));
1197
}
1198
break;
1199
case OptionParser::eOptionalArgument:
1200
option_element_vector.push_back(OptionArgElement(
1201
opt_defs_index,
1202
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 2],
1203
args),
1204
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1205
args)));
1206
break;
1207
default:
1208
// The options table is messed up. Here we'll just continue
1209
option_element_vector.push_back(OptionArgElement(
1210
OptionArgElement::eUnrecognizedArg,
1211
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1212
args),
1213
OptionArgElement::eUnrecognizedArg));
1214
break;
1215
}
1216
} else {
1217
option_element_vector.push_back(OptionArgElement(
1218
OptionArgElement::eUnrecognizedArg,
1219
FindOriginalIndex(dummy_vec[OptionParser::GetOptionIndex() - 1],
1220
args),
1221
OptionArgElement::eUnrecognizedArg));
1222
}
1223
}
1224
1225
// Finally we have to handle the case where the cursor index points at a
1226
// single "-". We want to mark that in the option_element_vector, but only
1227
// if it is not after the "--". But it turns out that OptionParser::Parse
1228
// just ignores an isolated "-". So we have to look it up by hand here. We
1229
// only care if it is AT the cursor position. Note, a single quoted dash is
1230
// not the same as a single dash...
1231
1232
const Args::ArgEntry &cursor = args[cursor_index];
1233
if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1234
cursor_index < dash_dash_pos) &&
1235
!cursor.IsQuoted() && cursor.ref() == "-") {
1236
option_element_vector.push_back(
1237
OptionArgElement(OptionArgElement::eBareDash, cursor_index,
1238
OptionArgElement::eBareDash));
1239
}
1240
return option_element_vector;
1241
}
1242
1243
llvm::Expected<Args> Options::Parse(const Args &args,
1244
ExecutionContext *execution_context,
1245
lldb::PlatformSP platform_sp,
1246
bool require_validation) {
1247
Status error;
1248
Option *long_options = GetLongOptions();
1249
if (long_options == nullptr) {
1250
return llvm::createStringError("Invalid long options.");
1251
}
1252
1253
std::string short_options = BuildShortOptions(long_options);
1254
std::vector<char *> argv = GetArgvForParsing(args);
1255
std::unique_lock<std::mutex> lock;
1256
OptionParser::Prepare(lock);
1257
int val;
1258
while (true) {
1259
int long_options_index = -1;
1260
val = OptionParser::Parse(argv, short_options, long_options,
1261
&long_options_index);
1262
1263
if (val == ':') {
1264
error.SetErrorString("last option requires an argument");
1265
break;
1266
}
1267
1268
if (val == -1)
1269
break;
1270
1271
// Did we get an error?
1272
if (val == '?') {
1273
error.SetErrorString("unknown or ambiguous option");
1274
break;
1275
}
1276
// The option auto-set itself
1277
if (val == 0)
1278
continue;
1279
1280
OptionSeen(val);
1281
1282
// Lookup the long option index
1283
if (long_options_index == -1) {
1284
for (int i = 0; long_options[i].definition || long_options[i].flag ||
1285
long_options[i].val;
1286
++i) {
1287
if (long_options[i].val == val) {
1288
long_options_index = i;
1289
break;
1290
}
1291
}
1292
}
1293
// Call the callback with the option
1294
if (long_options_index >= 0 &&
1295
long_options[long_options_index].definition) {
1296
const OptionDefinition *def = long_options[long_options_index].definition;
1297
1298
if (!platform_sp) {
1299
// User did not pass in an explicit platform. Try to grab from the
1300
// execution context.
1301
TargetSP target_sp =
1302
execution_context ? execution_context->GetTargetSP() : TargetSP();
1303
platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
1304
}
1305
OptionValidator *validator = def->validator;
1306
1307
if (!platform_sp && require_validation) {
1308
// Caller requires validation but we cannot validate as we don't have
1309
// the mandatory platform against which to validate.
1310
return llvm::createStringError(
1311
"cannot validate options: no platform available");
1312
}
1313
1314
bool validation_failed = false;
1315
if (platform_sp) {
1316
// Ensure we have an execution context, empty or not.
1317
ExecutionContext dummy_context;
1318
ExecutionContext *exe_ctx_p =
1319
execution_context ? execution_context : &dummy_context;
1320
if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
1321
validation_failed = true;
1322
error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
1323
def->long_option,
1324
def->validator->LongConditionString());
1325
}
1326
}
1327
1328
// As long as validation didn't fail, we set the option value.
1329
if (!validation_failed)
1330
error =
1331
SetOptionValue(long_options_index,
1332
(def->option_has_arg == OptionParser::eNoArgument)
1333
? nullptr
1334
: OptionParser::GetOptionArgument(),
1335
execution_context);
1336
// If the Option setting returned an error, we should stop parsing
1337
// and return the error.
1338
if (error.Fail())
1339
break;
1340
} else {
1341
error.SetErrorStringWithFormat("invalid option with value '%i'", val);
1342
}
1343
}
1344
1345
if (error.Fail())
1346
return error.ToError();
1347
1348
argv.pop_back();
1349
argv.erase(argv.begin(), argv.begin() + OptionParser::GetOptionIndex());
1350
return ReconstituteArgsAfterParsing(argv, args);
1351
}
1352
1353
llvm::Error lldb_private::CreateOptionParsingError(
1354
llvm::StringRef option_arg, const char short_option,
1355
llvm::StringRef long_option, llvm::StringRef additional_context) {
1356
std::string buffer;
1357
llvm::raw_string_ostream stream(buffer);
1358
stream << "Invalid value ('" << option_arg << "') for -" << short_option;
1359
if (!long_option.empty())
1360
stream << " (" << long_option << ")";
1361
if (!additional_context.empty())
1362
stream << ": " << additional_context;
1363
return llvm::createStringError(llvm::inconvertibleErrorCode(), buffer);
1364
}
1365
1366