1254721Semaste//===-- Options.cpp ---------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "lldb/Interpreter/Options.h" 13254721Semaste 14254721Semaste// C Includes 15254721Semaste// C++ Includes 16254721Semaste#include <algorithm> 17254721Semaste#include <bitset> 18254721Semaste#include <map> 19254721Semaste 20254721Semaste// Other libraries and framework includes 21254721Semaste// Project includes 22254721Semaste#include "lldb/Interpreter/CommandObject.h" 23254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 24254721Semaste#include "lldb/Interpreter/CommandCompletions.h" 25254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 26254721Semaste#include "lldb/Core/StreamString.h" 27254721Semaste#include "lldb/Target/Target.h" 28254721Semaste 29254721Semasteusing namespace lldb; 30254721Semasteusing namespace lldb_private; 31254721Semaste 32254721Semaste//------------------------------------------------------------------------- 33254721Semaste// Options 34254721Semaste//------------------------------------------------------------------------- 35254721SemasteOptions::Options (CommandInterpreter &interpreter) : 36254721Semaste m_interpreter (interpreter), 37254721Semaste m_getopt_table () 38254721Semaste{ 39254721Semaste BuildValidOptionSets(); 40254721Semaste} 41254721Semaste 42254721SemasteOptions::~Options () 43254721Semaste{ 44254721Semaste} 45254721Semaste 46254721Semastevoid 47254721SemasteOptions::NotifyOptionParsingStarting () 48254721Semaste{ 49254721Semaste m_seen_options.clear(); 50254721Semaste // Let the subclass reset its option values 51254721Semaste OptionParsingStarting (); 52254721Semaste} 53254721Semaste 54254721SemasteError 55254721SemasteOptions::NotifyOptionParsingFinished () 56254721Semaste{ 57254721Semaste return OptionParsingFinished (); 58254721Semaste} 59254721Semaste 60254721Semastevoid 61254721SemasteOptions::OptionSeen (int option_idx) 62254721Semaste{ 63254721Semaste m_seen_options.insert (option_idx); 64254721Semaste} 65254721Semaste 66254721Semaste// Returns true is set_a is a subset of set_b; Otherwise returns false. 67254721Semaste 68254721Semastebool 69254721SemasteOptions::IsASubset (const OptionSet& set_a, const OptionSet& set_b) 70254721Semaste{ 71254721Semaste bool is_a_subset = true; 72254721Semaste OptionSet::const_iterator pos_a; 73254721Semaste OptionSet::const_iterator pos_b; 74254721Semaste 75254721Semaste // set_a is a subset of set_b if every member of set_a is also a member of set_b 76254721Semaste 77254721Semaste for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) 78254721Semaste { 79254721Semaste pos_b = set_b.find(*pos_a); 80254721Semaste if (pos_b == set_b.end()) 81254721Semaste is_a_subset = false; 82254721Semaste } 83254721Semaste 84254721Semaste return is_a_subset; 85254721Semaste} 86254721Semaste 87254721Semaste// Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) } 88254721Semaste 89254721Semastesize_t 90254721SemasteOptions::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs) 91254721Semaste{ 92254721Semaste size_t num_diffs = 0; 93254721Semaste OptionSet::const_iterator pos_a; 94254721Semaste OptionSet::const_iterator pos_b; 95254721Semaste 96254721Semaste for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) 97254721Semaste { 98254721Semaste pos_b = set_b.find(*pos_a); 99254721Semaste if (pos_b == set_b.end()) 100254721Semaste { 101254721Semaste ++num_diffs; 102254721Semaste diffs.insert(*pos_a); 103254721Semaste } 104254721Semaste } 105254721Semaste 106254721Semaste return num_diffs; 107254721Semaste} 108254721Semaste 109254721Semaste// Returns the union of set_a and set_b. Does not put duplicate members into the union. 110254721Semaste 111254721Semastevoid 112254721SemasteOptions::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set) 113254721Semaste{ 114254721Semaste OptionSet::const_iterator pos; 115254721Semaste OptionSet::iterator pos_union; 116254721Semaste 117254721Semaste // Put all the elements of set_a into the union. 118254721Semaste 119254721Semaste for (pos = set_a.begin(); pos != set_a.end(); ++pos) 120254721Semaste union_set.insert(*pos); 121254721Semaste 122254721Semaste // Put all the elements of set_b that are not already there into the union. 123254721Semaste for (pos = set_b.begin(); pos != set_b.end(); ++pos) 124254721Semaste { 125254721Semaste pos_union = union_set.find(*pos); 126254721Semaste if (pos_union == union_set.end()) 127254721Semaste union_set.insert(*pos); 128254721Semaste } 129254721Semaste} 130254721Semaste 131254721Semastebool 132254721SemasteOptions::VerifyOptions (CommandReturnObject &result) 133254721Semaste{ 134254721Semaste bool options_are_valid = false; 135254721Semaste 136254721Semaste int num_levels = GetRequiredOptions().size(); 137254721Semaste if (num_levels) 138254721Semaste { 139254721Semaste for (int i = 0; i < num_levels && !options_are_valid; ++i) 140254721Semaste { 141254721Semaste // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i] 142254721Semaste // (i.e. all the required options at this level are a subset of m_seen_options); AND 143254721Semaste // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of 144254721Semaste // m_seen_options are in the set of optional options at this level. 145254721Semaste 146254721Semaste // Check to see if all of m_required_options[i] are a subset of m_seen_options 147254721Semaste if (IsASubset (GetRequiredOptions()[i], m_seen_options)) 148254721Semaste { 149254721Semaste // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]} 150254721Semaste OptionSet remaining_options; 151254721Semaste OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options); 152254721Semaste // Check to see if remaining_options is a subset of m_optional_options[i] 153254721Semaste if (IsASubset (remaining_options, GetOptionalOptions()[i])) 154254721Semaste options_are_valid = true; 155254721Semaste } 156254721Semaste } 157254721Semaste } 158254721Semaste else 159254721Semaste { 160254721Semaste options_are_valid = true; 161254721Semaste } 162254721Semaste 163254721Semaste if (options_are_valid) 164254721Semaste { 165254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 166254721Semaste } 167254721Semaste else 168254721Semaste { 169254721Semaste result.AppendError ("invalid combination of options for the given command"); 170254721Semaste result.SetStatus (eReturnStatusFailed); 171254721Semaste } 172254721Semaste 173254721Semaste return options_are_valid; 174254721Semaste} 175254721Semaste 176254721Semaste// This is called in the Options constructor, though we could call it lazily if that ends up being 177254721Semaste// a performance problem. 178254721Semaste 179254721Semastevoid 180254721SemasteOptions::BuildValidOptionSets () 181254721Semaste{ 182254721Semaste // Check to see if we already did this. 183254721Semaste if (m_required_options.size() != 0) 184254721Semaste return; 185254721Semaste 186254721Semaste // Check to see if there are any options. 187254721Semaste int num_options = NumCommandOptions (); 188254721Semaste if (num_options == 0) 189254721Semaste return; 190254721Semaste 191254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 192254721Semaste m_required_options.resize(1); 193254721Semaste m_optional_options.resize(1); 194254721Semaste 195254721Semaste // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS... 196254721Semaste 197254721Semaste uint32_t num_option_sets = 0; 198254721Semaste 199254721Semaste for (int i = 0; i < num_options; i++) 200254721Semaste { 201254721Semaste uint32_t this_usage_mask = opt_defs[i].usage_mask; 202254721Semaste if (this_usage_mask == LLDB_OPT_SET_ALL) 203254721Semaste { 204254721Semaste if (num_option_sets == 0) 205254721Semaste num_option_sets = 1; 206254721Semaste } 207254721Semaste else 208254721Semaste { 209254721Semaste for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) 210254721Semaste { 211254721Semaste if (this_usage_mask & (1 << j)) 212254721Semaste { 213254721Semaste if (num_option_sets <= j) 214254721Semaste num_option_sets = j + 1; 215254721Semaste } 216254721Semaste } 217254721Semaste } 218254721Semaste } 219254721Semaste 220254721Semaste if (num_option_sets > 0) 221254721Semaste { 222254721Semaste m_required_options.resize(num_option_sets); 223254721Semaste m_optional_options.resize(num_option_sets); 224254721Semaste 225254721Semaste for (int i = 0; i < num_options; ++i) 226254721Semaste { 227254721Semaste for (uint32_t j = 0; j < num_option_sets; j++) 228254721Semaste { 229254721Semaste if (opt_defs[i].usage_mask & 1 << j) 230254721Semaste { 231254721Semaste if (opt_defs[i].required) 232254721Semaste m_required_options[j].insert(opt_defs[i].short_option); 233254721Semaste else 234254721Semaste m_optional_options[j].insert(opt_defs[i].short_option); 235254721Semaste } 236254721Semaste } 237254721Semaste } 238254721Semaste } 239254721Semaste} 240254721Semaste 241254721Semasteuint32_t 242254721SemasteOptions::NumCommandOptions () 243254721Semaste{ 244254721Semaste const OptionDefinition *opt_defs = GetDefinitions (); 245254721Semaste if (opt_defs == NULL) 246254721Semaste return 0; 247254721Semaste 248254721Semaste int i = 0; 249254721Semaste 250254721Semaste if (opt_defs != NULL) 251254721Semaste { 252254721Semaste while (opt_defs[i].long_option != NULL) 253254721Semaste ++i; 254254721Semaste } 255254721Semaste 256254721Semaste return i; 257254721Semaste} 258254721Semaste 259263363SemasteOption * 260254721SemasteOptions::GetLongOptions () 261254721Semaste{ 262254721Semaste // Check to see if this has already been done. 263254721Semaste if (m_getopt_table.empty()) 264254721Semaste { 265254721Semaste // Check to see if there are any options. 266254721Semaste const uint32_t num_options = NumCommandOptions(); 267254721Semaste if (num_options == 0) 268254721Semaste return NULL; 269254721Semaste 270254721Semaste uint32_t i; 271254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 272254721Semaste 273254721Semaste std::map<int, uint32_t> option_seen; 274254721Semaste 275254721Semaste m_getopt_table.resize(num_options + 1); 276254721Semaste for (i = 0; i < num_options; ++i) 277254721Semaste { 278254721Semaste const int short_opt = opt_defs[i].short_option; 279254721Semaste 280254721Semaste m_getopt_table[i].name = opt_defs[i].long_option; 281254721Semaste m_getopt_table[i].has_arg = opt_defs[i].option_has_arg; 282254721Semaste m_getopt_table[i].flag = NULL; 283254721Semaste m_getopt_table[i].val = short_opt; 284254721Semaste 285254721Semaste if (option_seen.find(short_opt) == option_seen.end()) 286254721Semaste { 287254721Semaste option_seen[short_opt] = i; 288254721Semaste } 289254721Semaste else if (short_opt) 290254721Semaste { 291254721Semaste m_getopt_table[i].val = 0; 292254721Semaste std::map<int, uint32_t>::const_iterator pos = option_seen.find(short_opt); 293254721Semaste StreamString strm; 294254721Semaste if (isprint8(short_opt)) 295254721Semaste Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option -%c that conflicts with option[%u] --%s, short option won't be used for --%s\n", 296254721Semaste i, 297254721Semaste opt_defs[i].long_option, 298254721Semaste short_opt, 299254721Semaste pos->second, 300254721Semaste m_getopt_table[pos->second].name, 301254721Semaste opt_defs[i].long_option); 302254721Semaste else 303254721Semaste Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n", 304254721Semaste i, 305254721Semaste opt_defs[i].long_option, 306254721Semaste short_opt, 307254721Semaste pos->second, 308254721Semaste m_getopt_table[pos->second].name, 309254721Semaste opt_defs[i].long_option); 310254721Semaste } 311254721Semaste } 312254721Semaste 313254721Semaste //getopt_long_only requires a NULL final entry in the table: 314254721Semaste 315254721Semaste m_getopt_table[i].name = NULL; 316254721Semaste m_getopt_table[i].has_arg = 0; 317254721Semaste m_getopt_table[i].flag = NULL; 318254721Semaste m_getopt_table[i].val = 0; 319254721Semaste } 320254721Semaste 321254721Semaste if (m_getopt_table.empty()) 322254721Semaste return NULL; 323254721Semaste 324254721Semaste return &m_getopt_table.front(); 325254721Semaste} 326254721Semaste 327254721Semaste 328254721Semaste// This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is 329254721Semaste// a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on 330254721Semaste// multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces, 331254721Semaste// tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each 332254721Semaste// output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. 333254721Semaste 334254721Semaste 335254721Semastevoid 336254721SemasteOptions::OutputFormattedUsageText 337254721Semaste( 338254721Semaste Stream &strm, 339254721Semaste const char *text, 340254721Semaste uint32_t output_max_columns 341254721Semaste) 342254721Semaste{ 343254721Semaste int len = strlen (text); 344254721Semaste 345254721Semaste // Will it all fit on one line? 346254721Semaste 347254721Semaste if ((len + strm.GetIndentLevel()) < output_max_columns) 348254721Semaste { 349254721Semaste // Output it as a single line. 350254721Semaste strm.Indent (text); 351254721Semaste strm.EOL(); 352254721Semaste } 353254721Semaste else 354254721Semaste { 355254721Semaste // We need to break it up into multiple lines. 356254721Semaste 357254721Semaste int text_width = output_max_columns - strm.GetIndentLevel() - 1; 358254721Semaste int start = 0; 359254721Semaste int end = start; 360254721Semaste int final_end = strlen (text); 361254721Semaste int sub_len; 362254721Semaste 363254721Semaste while (end < final_end) 364254721Semaste { 365254721Semaste // Don't start the 'text' on a space, since we're already outputting the indentation. 366254721Semaste while ((start < final_end) && (text[start] == ' ')) 367254721Semaste start++; 368254721Semaste 369254721Semaste end = start + text_width; 370254721Semaste if (end > final_end) 371254721Semaste end = final_end; 372254721Semaste else 373254721Semaste { 374254721Semaste // If we're not at the end of the text, make sure we break the line on white space. 375254721Semaste while (end > start 376254721Semaste && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 377254721Semaste end--; 378254721Semaste } 379254721Semaste 380254721Semaste sub_len = end - start; 381254721Semaste if (start != 0) 382254721Semaste strm.EOL(); 383254721Semaste strm.Indent(); 384254721Semaste assert (start < final_end); 385254721Semaste assert (start + sub_len <= final_end); 386254721Semaste strm.Write(text + start, sub_len); 387254721Semaste start = end + 1; 388254721Semaste } 389254721Semaste strm.EOL(); 390254721Semaste } 391254721Semaste} 392254721Semaste 393254721Semastebool 394254721SemasteOptions::SupportsLongOption (const char *long_option) 395254721Semaste{ 396254721Semaste if (long_option && long_option[0]) 397254721Semaste { 398254721Semaste const OptionDefinition *opt_defs = GetDefinitions (); 399254721Semaste if (opt_defs) 400254721Semaste { 401254721Semaste const char *long_option_name = long_option; 402254721Semaste if (long_option[0] == '-' && long_option[1] == '-') 403254721Semaste long_option_name += 2; 404254721Semaste 405254721Semaste for (uint32_t i = 0; opt_defs[i].long_option; ++i) 406254721Semaste { 407254721Semaste if (strcmp(opt_defs[i].long_option, long_option_name) == 0) 408254721Semaste return true; 409254721Semaste } 410254721Semaste } 411254721Semaste } 412254721Semaste return false; 413254721Semaste} 414254721Semaste 415254721Semasteenum OptionDisplayType 416254721Semaste{ 417254721Semaste eDisplayBestOption, 418254721Semaste eDisplayShortOption, 419254721Semaste eDisplayLongOption 420254721Semaste}; 421254721Semaste 422254721Semastestatic bool 423254721SemastePrintOption (const OptionDefinition &opt_def, 424254721Semaste OptionDisplayType display_type, 425254721Semaste const char *header, 426254721Semaste const char *footer, 427254721Semaste bool show_optional, 428254721Semaste Stream &strm) 429254721Semaste{ 430254721Semaste const bool has_short_option = isprint8(opt_def.short_option) != 0; 431254721Semaste 432254721Semaste if (display_type == eDisplayShortOption && !has_short_option) 433254721Semaste return false; 434254721Semaste 435254721Semaste if (header && header[0]) 436254721Semaste strm.PutCString(header); 437254721Semaste 438254721Semaste if (show_optional && !opt_def.required) 439254721Semaste strm.PutChar('['); 440254721Semaste const bool show_short_option = has_short_option && display_type != eDisplayLongOption; 441254721Semaste if (show_short_option) 442254721Semaste strm.Printf ("-%c", opt_def.short_option); 443254721Semaste else 444254721Semaste strm.Printf ("--%s", opt_def.long_option); 445254721Semaste switch (opt_def.option_has_arg) 446254721Semaste { 447263363Semaste case OptionParser::eNoArgument: 448254721Semaste break; 449263363Semaste case OptionParser::eRequiredArgument: 450254721Semaste strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type)); 451254721Semaste break; 452254721Semaste 453263363Semaste case OptionParser::eOptionalArgument: 454254721Semaste strm.Printf ("%s[<%s>]", 455254721Semaste show_short_option ? "" : "=", 456254721Semaste CommandObject::GetArgumentName (opt_def.argument_type)); 457254721Semaste break; 458254721Semaste } 459254721Semaste if (show_optional && !opt_def.required) 460254721Semaste strm.PutChar(']'); 461254721Semaste if (footer && footer[0]) 462254721Semaste strm.PutCString(footer); 463254721Semaste return true; 464254721Semaste} 465254721Semaste 466254721Semastevoid 467254721SemasteOptions::GenerateOptionUsage 468254721Semaste( 469254721Semaste Stream &strm, 470254721Semaste CommandObject *cmd 471254721Semaste) 472254721Semaste{ 473254721Semaste const uint32_t screen_width = m_interpreter.GetDebugger().GetTerminalWidth(); 474254721Semaste 475254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 476254721Semaste const uint32_t save_indent_level = strm.GetIndentLevel(); 477254721Semaste const char *name; 478254721Semaste 479254721Semaste StreamString arguments_str; 480254721Semaste 481254721Semaste if (cmd) 482254721Semaste { 483254721Semaste name = cmd->GetCommandName(); 484254721Semaste cmd->GetFormattedCommandArguments (arguments_str); 485254721Semaste } 486254721Semaste else 487254721Semaste name = ""; 488254721Semaste 489254721Semaste strm.PutCString ("\nCommand Options Usage:\n"); 490254721Semaste 491254721Semaste strm.IndentMore(2); 492254721Semaste 493254721Semaste // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] 494254721Semaste // <cmd> [options-for-level-1] 495254721Semaste // etc. 496254721Semaste 497254721Semaste const uint32_t num_options = NumCommandOptions(); 498254721Semaste if (num_options == 0) 499254721Semaste return; 500254721Semaste 501254721Semaste uint32_t num_option_sets = GetRequiredOptions().size(); 502254721Semaste 503254721Semaste uint32_t i; 504254721Semaste 505254721Semaste for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) 506254721Semaste { 507254721Semaste uint32_t opt_set_mask; 508254721Semaste 509254721Semaste opt_set_mask = 1 << opt_set; 510254721Semaste if (opt_set > 0) 511254721Semaste strm.Printf ("\n"); 512254721Semaste strm.Indent (name); 513254721Semaste 514254721Semaste // Different option sets may require different args. 515254721Semaste StreamString args_str; 516254721Semaste if (cmd) 517254721Semaste cmd->GetFormattedCommandArguments(args_str, opt_set_mask); 518254721Semaste 519254721Semaste // First go through and print all options that take no arguments as 520254721Semaste // a single string. If a command has "-a" "-b" and "-c", this will show 521254721Semaste // up as [-abc] 522254721Semaste 523254721Semaste std::set<int> options; 524254721Semaste std::set<int>::const_iterator options_pos, options_end; 525254721Semaste for (i = 0; i < num_options; ++i) 526254721Semaste { 527254721Semaste if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) 528254721Semaste { 529254721Semaste // Add current option to the end of out_stream. 530254721Semaste 531254721Semaste if (opt_defs[i].required == true && 532263363Semaste opt_defs[i].option_has_arg == OptionParser::eNoArgument) 533254721Semaste { 534254721Semaste options.insert (opt_defs[i].short_option); 535254721Semaste } 536254721Semaste } 537254721Semaste } 538254721Semaste 539254721Semaste if (options.empty() == false) 540254721Semaste { 541254721Semaste // We have some required options with no arguments 542254721Semaste strm.PutCString(" -"); 543254721Semaste for (i=0; i<2; ++i) 544254721Semaste for (options_pos = options.begin(), options_end = options.end(); 545254721Semaste options_pos != options_end; 546254721Semaste ++options_pos) 547254721Semaste { 548254721Semaste if (i==0 && ::islower (*options_pos)) 549254721Semaste continue; 550254721Semaste if (i==1 && ::isupper (*options_pos)) 551254721Semaste continue; 552254721Semaste strm << (char)*options_pos; 553254721Semaste } 554254721Semaste } 555254721Semaste 556254721Semaste for (i = 0, options.clear(); i < num_options; ++i) 557254721Semaste { 558254721Semaste if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) 559254721Semaste { 560254721Semaste // Add current option to the end of out_stream. 561254721Semaste 562254721Semaste if (opt_defs[i].required == false && 563263363Semaste opt_defs[i].option_has_arg == OptionParser::eNoArgument) 564254721Semaste { 565254721Semaste options.insert (opt_defs[i].short_option); 566254721Semaste } 567254721Semaste } 568254721Semaste } 569254721Semaste 570254721Semaste if (options.empty() == false) 571254721Semaste { 572254721Semaste // We have some required options with no arguments 573254721Semaste strm.PutCString(" [-"); 574254721Semaste for (i=0; i<2; ++i) 575254721Semaste for (options_pos = options.begin(), options_end = options.end(); 576254721Semaste options_pos != options_end; 577254721Semaste ++options_pos) 578254721Semaste { 579254721Semaste if (i==0 && ::islower (*options_pos)) 580254721Semaste continue; 581254721Semaste if (i==1 && ::isupper (*options_pos)) 582254721Semaste continue; 583254721Semaste strm << (char)*options_pos; 584254721Semaste } 585254721Semaste strm.PutChar(']'); 586254721Semaste } 587254721Semaste 588254721Semaste // First go through and print the required options (list them up front). 589254721Semaste 590254721Semaste for (i = 0; i < num_options; ++i) 591254721Semaste { 592254721Semaste if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option)) 593254721Semaste { 594263363Semaste if (opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) 595254721Semaste PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm); 596254721Semaste } 597254721Semaste } 598254721Semaste 599254721Semaste // Now go through again, and this time only print the optional options. 600254721Semaste 601254721Semaste for (i = 0; i < num_options; ++i) 602254721Semaste { 603254721Semaste if (opt_defs[i].usage_mask & opt_set_mask) 604254721Semaste { 605254721Semaste // Add current option to the end of out_stream. 606254721Semaste 607263363Semaste if (!opt_defs[i].required && opt_defs[i].option_has_arg != OptionParser::eNoArgument) 608254721Semaste PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm); 609254721Semaste } 610254721Semaste } 611254721Semaste 612254721Semaste if (args_str.GetSize() > 0) 613254721Semaste { 614254721Semaste if (cmd->WantsRawCommandString()) 615254721Semaste strm.Printf(" --"); 616254721Semaste 617254721Semaste strm.Printf (" %s", args_str.GetData()); 618254721Semaste } 619254721Semaste } 620254721Semaste 621254721Semaste if (cmd && 622254721Semaste cmd->WantsRawCommandString() && 623254721Semaste arguments_str.GetSize() > 0) 624254721Semaste { 625254721Semaste strm.PutChar('\n'); 626254721Semaste strm.Indent(name); 627254721Semaste strm.Printf(" %s", arguments_str.GetData()); 628254721Semaste } 629254721Semaste 630254721Semaste strm.Printf ("\n\n"); 631254721Semaste 632254721Semaste // Now print out all the detailed information about the various options: long form, short form and help text: 633254721Semaste // --long_name <argument> ( -short <argument> ) 634254721Semaste // help text 635254721Semaste 636254721Semaste // This variable is used to keep track of which options' info we've printed out, because some options can be in 637254721Semaste // more than one usage level, but we only want to print the long form of its information once. 638254721Semaste 639254721Semaste std::multimap<int, uint32_t> options_seen; 640254721Semaste strm.IndentMore (5); 641254721Semaste 642254721Semaste // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option) 643254721Semaste // when writing out detailed help for each option. 644254721Semaste 645254721Semaste for (i = 0; i < num_options; ++i) 646254721Semaste options_seen.insert(std::make_pair(opt_defs[i].short_option, i)); 647254721Semaste 648254721Semaste // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option 649254721Semaste // and write out the detailed help information for that option. 650254721Semaste 651254721Semaste bool first_option_printed = false;; 652254721Semaste 653254721Semaste for (auto pos : options_seen) 654254721Semaste { 655254721Semaste i = pos.second; 656254721Semaste //Print out the help information for this option. 657254721Semaste 658254721Semaste // Put a newline separation between arguments 659254721Semaste if (first_option_printed) 660254721Semaste strm.EOL(); 661254721Semaste else 662254721Semaste first_option_printed = true; 663254721Semaste 664254721Semaste CommandArgumentType arg_type = opt_defs[i].argument_type; 665254721Semaste 666254721Semaste StreamString arg_name_str; 667254721Semaste arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type)); 668254721Semaste 669254721Semaste strm.Indent (); 670254721Semaste if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option)) 671254721Semaste { 672254721Semaste PrintOption (opt_defs[i], eDisplayShortOption, NULL, NULL, false, strm); 673254721Semaste PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm); 674254721Semaste } 675254721Semaste else 676254721Semaste { 677254721Semaste // Short option is not printable, just print long option 678254721Semaste PrintOption (opt_defs[i], eDisplayLongOption, NULL, NULL, false, strm); 679254721Semaste } 680254721Semaste strm.EOL(); 681254721Semaste 682254721Semaste strm.IndentMore (5); 683254721Semaste 684254721Semaste if (opt_defs[i].usage_text) 685254721Semaste OutputFormattedUsageText (strm, 686254721Semaste opt_defs[i].usage_text, 687254721Semaste screen_width); 688254721Semaste if (opt_defs[i].enum_values != NULL) 689254721Semaste { 690254721Semaste strm.Indent (); 691254721Semaste strm.Printf("Values: "); 692254721Semaste for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++) 693254721Semaste { 694254721Semaste if (k == 0) 695254721Semaste strm.Printf("%s", opt_defs[i].enum_values[k].string_value); 696254721Semaste else 697254721Semaste strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value); 698254721Semaste } 699254721Semaste strm.EOL(); 700254721Semaste } 701254721Semaste strm.IndentLess (5); 702254721Semaste } 703254721Semaste 704254721Semaste // Restore the indent level 705254721Semaste strm.SetIndentLevel (save_indent_level); 706254721Semaste} 707254721Semaste 708254721Semaste// This function is called when we have been given a potentially incomplete set of 709254721Semaste// options, such as when an alias has been defined (more options might be added at 710254721Semaste// at the time the alias is invoked). We need to verify that the options in the set 711254721Semaste// m_seen_options are all part of a set that may be used together, but m_seen_options 712254721Semaste// may be missing some of the "required" options. 713254721Semaste 714254721Semastebool 715254721SemasteOptions::VerifyPartialOptions (CommandReturnObject &result) 716254721Semaste{ 717254721Semaste bool options_are_valid = false; 718254721Semaste 719254721Semaste int num_levels = GetRequiredOptions().size(); 720254721Semaste if (num_levels) 721254721Semaste { 722254721Semaste for (int i = 0; i < num_levels && !options_are_valid; ++i) 723254721Semaste { 724254721Semaste // In this case we are treating all options as optional rather than required. 725254721Semaste // Therefore a set of options is correct if m_seen_options is a subset of the 726254721Semaste // union of m_required_options and m_optional_options. 727254721Semaste OptionSet union_set; 728254721Semaste OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set); 729254721Semaste if (IsASubset (m_seen_options, union_set)) 730254721Semaste options_are_valid = true; 731254721Semaste } 732254721Semaste } 733254721Semaste 734254721Semaste return options_are_valid; 735254721Semaste} 736254721Semaste 737254721Semastebool 738254721SemasteOptions::HandleOptionCompletion 739254721Semaste( 740254721Semaste Args &input, 741254721Semaste OptionElementVector &opt_element_vector, 742254721Semaste int cursor_index, 743254721Semaste int char_pos, 744254721Semaste int match_start_point, 745254721Semaste int max_return_elements, 746254721Semaste bool &word_complete, 747254721Semaste lldb_private::StringList &matches 748254721Semaste) 749254721Semaste{ 750254721Semaste word_complete = true; 751254721Semaste 752254721Semaste // For now we just scan the completions to see if the cursor position is in 753254721Semaste // an option or its argument. Otherwise we'll call HandleArgumentCompletion. 754254721Semaste // In the future we can use completion to validate options as well if we want. 755254721Semaste 756254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 757254721Semaste 758254721Semaste std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index)); 759254721Semaste cur_opt_std_str.erase(char_pos); 760254721Semaste const char *cur_opt_str = cur_opt_std_str.c_str(); 761254721Semaste 762254721Semaste for (size_t i = 0; i < opt_element_vector.size(); i++) 763254721Semaste { 764254721Semaste int opt_pos = opt_element_vector[i].opt_pos; 765254721Semaste int opt_arg_pos = opt_element_vector[i].opt_arg_pos; 766254721Semaste int opt_defs_index = opt_element_vector[i].opt_defs_index; 767254721Semaste if (opt_pos == cursor_index) 768254721Semaste { 769254721Semaste // We're completing the option itself. 770254721Semaste 771254721Semaste if (opt_defs_index == OptionArgElement::eBareDash) 772254721Semaste { 773254721Semaste // We're completing a bare dash. That means all options are open. 774254721Semaste // FIXME: We should scan the other options provided and only complete options 775254721Semaste // within the option group they belong to. 776254721Semaste char opt_str[3] = {'-', 'a', '\0'}; 777254721Semaste 778254721Semaste for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 779254721Semaste { 780254721Semaste opt_str[1] = opt_defs[j].short_option; 781254721Semaste matches.AppendString (opt_str); 782254721Semaste } 783254721Semaste return true; 784254721Semaste } 785254721Semaste else if (opt_defs_index == OptionArgElement::eBareDoubleDash) 786254721Semaste { 787254721Semaste std::string full_name ("--"); 788254721Semaste for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 789254721Semaste { 790254721Semaste full_name.erase(full_name.begin() + 2, full_name.end()); 791254721Semaste full_name.append (opt_defs[j].long_option); 792254721Semaste matches.AppendString (full_name.c_str()); 793254721Semaste } 794254721Semaste return true; 795254721Semaste } 796254721Semaste else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) 797254721Semaste { 798254721Semaste // We recognized it, if it an incomplete long option, complete it anyway (getopt_long_only is 799254721Semaste // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return 800254721Semaste // The string so the upper level code will know this is a full match and add the " ". 801254721Semaste if (cur_opt_str && strlen (cur_opt_str) > 2 802254721Semaste && cur_opt_str[0] == '-' && cur_opt_str[1] == '-' 803254721Semaste && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) 804254721Semaste { 805254721Semaste std::string full_name ("--"); 806254721Semaste full_name.append (opt_defs[opt_defs_index].long_option); 807254721Semaste matches.AppendString(full_name.c_str()); 808254721Semaste return true; 809254721Semaste } 810254721Semaste else 811254721Semaste { 812254721Semaste matches.AppendString(input.GetArgumentAtIndex(cursor_index)); 813254721Semaste return true; 814254721Semaste } 815254721Semaste } 816254721Semaste else 817254721Semaste { 818254721Semaste // FIXME - not handling wrong options yet: 819254721Semaste // Check to see if they are writing a long option & complete it. 820254721Semaste // I think we will only get in here if the long option table has two elements 821254721Semaste // that are not unique up to this point. getopt_long_only does shortest unique match 822254721Semaste // for long options already. 823254721Semaste 824254721Semaste if (cur_opt_str && strlen (cur_opt_str) > 2 825254721Semaste && cur_opt_str[0] == '-' && cur_opt_str[1] == '-') 826254721Semaste { 827254721Semaste for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 828254721Semaste { 829254721Semaste if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option) 830254721Semaste { 831254721Semaste std::string full_name ("--"); 832254721Semaste full_name.append (opt_defs[j].long_option); 833254721Semaste // The options definitions table has duplicates because of the 834254721Semaste // way the grouping information is stored, so only add once. 835254721Semaste bool duplicate = false; 836254721Semaste for (size_t k = 0; k < matches.GetSize(); k++) 837254721Semaste { 838254721Semaste if (matches.GetStringAtIndex(k) == full_name) 839254721Semaste { 840254721Semaste duplicate = true; 841254721Semaste break; 842254721Semaste } 843254721Semaste } 844254721Semaste if (!duplicate) 845254721Semaste matches.AppendString(full_name.c_str()); 846254721Semaste } 847254721Semaste } 848254721Semaste } 849254721Semaste return true; 850254721Semaste } 851254721Semaste 852254721Semaste 853254721Semaste } 854254721Semaste else if (opt_arg_pos == cursor_index) 855254721Semaste { 856254721Semaste // Okay the cursor is on the completion of an argument. 857254721Semaste // See if it has a completion, otherwise return no matches. 858254721Semaste 859254721Semaste if (opt_defs_index != -1) 860254721Semaste { 861254721Semaste HandleOptionArgumentCompletion (input, 862254721Semaste cursor_index, 863254721Semaste strlen (input.GetArgumentAtIndex(cursor_index)), 864254721Semaste opt_element_vector, 865254721Semaste i, 866254721Semaste match_start_point, 867254721Semaste max_return_elements, 868254721Semaste word_complete, 869254721Semaste matches); 870254721Semaste return true; 871254721Semaste } 872254721Semaste else 873254721Semaste { 874254721Semaste // No completion callback means no completions... 875254721Semaste return true; 876254721Semaste } 877254721Semaste 878254721Semaste } 879254721Semaste else 880254721Semaste { 881254721Semaste // Not the last element, keep going. 882254721Semaste continue; 883254721Semaste } 884254721Semaste } 885254721Semaste return false; 886254721Semaste} 887254721Semaste 888254721Semastebool 889254721SemasteOptions::HandleOptionArgumentCompletion 890254721Semaste( 891254721Semaste Args &input, 892254721Semaste int cursor_index, 893254721Semaste int char_pos, 894254721Semaste OptionElementVector &opt_element_vector, 895254721Semaste int opt_element_index, 896254721Semaste int match_start_point, 897254721Semaste int max_return_elements, 898254721Semaste bool &word_complete, 899254721Semaste lldb_private::StringList &matches 900254721Semaste) 901254721Semaste{ 902254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 903254721Semaste std::unique_ptr<SearchFilter> filter_ap; 904254721Semaste 905254721Semaste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 906254721Semaste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 907254721Semaste 908254721Semaste // See if this is an enumeration type option, and if so complete it here: 909254721Semaste 910254721Semaste OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values; 911254721Semaste if (enum_values != NULL) 912254721Semaste { 913254721Semaste bool return_value = false; 914254721Semaste std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos); 915254721Semaste for (int i = 0; enum_values[i].string_value != NULL; i++) 916254721Semaste { 917254721Semaste if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value) 918254721Semaste { 919254721Semaste matches.AppendString (enum_values[i].string_value); 920254721Semaste return_value = true; 921254721Semaste } 922254721Semaste } 923254721Semaste return return_value; 924254721Semaste } 925254721Semaste 926254721Semaste // If this is a source file or symbol type completion, and there is a 927254721Semaste // -shlib option somewhere in the supplied arguments, then make a search filter 928254721Semaste // for that shared library. 929254721Semaste // FIXME: Do we want to also have an "OptionType" so we don't have to match string names? 930254721Semaste 931254721Semaste uint32_t completion_mask = opt_defs[opt_defs_index].completion_type; 932254721Semaste 933254721Semaste if (completion_mask == 0) 934254721Semaste { 935254721Semaste lldb::CommandArgumentType option_arg_type = opt_defs[opt_defs_index].argument_type; 936254721Semaste if (option_arg_type != eArgTypeNone) 937254721Semaste { 938254721Semaste CommandObject::ArgumentTableEntry *arg_entry = CommandObject::FindArgumentDataByType (opt_defs[opt_defs_index].argument_type); 939254721Semaste if (arg_entry) 940254721Semaste completion_mask = arg_entry->completion_type; 941254721Semaste } 942254721Semaste } 943254721Semaste 944254721Semaste if (completion_mask & CommandCompletions::eSourceFileCompletion 945254721Semaste || completion_mask & CommandCompletions::eSymbolCompletion) 946254721Semaste { 947254721Semaste for (size_t i = 0; i < opt_element_vector.size(); i++) 948254721Semaste { 949254721Semaste int cur_defs_index = opt_element_vector[i].opt_defs_index; 950254721Semaste int cur_arg_pos = opt_element_vector[i].opt_arg_pos; 951254721Semaste const char *cur_opt_name = opt_defs[cur_defs_index].long_option; 952254721Semaste 953254721Semaste // If this is the "shlib" option and there was an argument provided, 954254721Semaste // restrict it to that shared library. 955269024Semaste if (cur_opt_name && strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1) 956254721Semaste { 957254721Semaste const char *module_name = input.GetArgumentAtIndex(cur_arg_pos); 958254721Semaste if (module_name) 959254721Semaste { 960254721Semaste FileSpec module_spec(module_name, false); 961254721Semaste lldb::TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 962254721Semaste // Search filters require a target... 963254721Semaste if (target_sp) 964254721Semaste filter_ap.reset (new SearchFilterByModule (target_sp, module_spec)); 965254721Semaste } 966254721Semaste break; 967254721Semaste } 968254721Semaste } 969254721Semaste } 970254721Semaste 971254721Semaste return CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 972254721Semaste completion_mask, 973254721Semaste input.GetArgumentAtIndex (opt_arg_pos), 974254721Semaste match_start_point, 975254721Semaste max_return_elements, 976254721Semaste filter_ap.get(), 977254721Semaste word_complete, 978254721Semaste matches); 979254721Semaste 980254721Semaste} 981254721Semaste 982254721Semaste 983254721Semastevoid 984254721SemasteOptionGroupOptions::Append (OptionGroup* group) 985254721Semaste{ 986254721Semaste const OptionDefinition* group_option_defs = group->GetDefinitions (); 987254721Semaste const uint32_t group_option_count = group->GetNumDefinitions(); 988254721Semaste for (uint32_t i=0; i<group_option_count; ++i) 989254721Semaste { 990254721Semaste m_option_infos.push_back (OptionInfo (group, i)); 991254721Semaste m_option_defs.push_back (group_option_defs[i]); 992254721Semaste } 993254721Semaste} 994254721Semaste 995263363Semasteconst OptionGroup* 996263363SemasteOptionGroupOptions::GetGroupWithOption (char short_opt) 997263363Semaste{ 998263363Semaste for (uint32_t i = 0; i < m_option_defs.size(); i++) 999263363Semaste { 1000263363Semaste OptionDefinition opt_def = m_option_defs[i]; 1001263363Semaste if (opt_def.short_option == short_opt) 1002263363Semaste return m_option_infos[i].option_group; 1003263363Semaste } 1004263363Semaste return NULL; 1005263363Semaste} 1006263363Semaste 1007254721Semastevoid 1008254721SemasteOptionGroupOptions::Append (OptionGroup* group, 1009254721Semaste uint32_t src_mask, 1010254721Semaste uint32_t dst_mask) 1011254721Semaste{ 1012254721Semaste const OptionDefinition* group_option_defs = group->GetDefinitions (); 1013254721Semaste const uint32_t group_option_count = group->GetNumDefinitions(); 1014254721Semaste for (uint32_t i=0; i<group_option_count; ++i) 1015254721Semaste { 1016254721Semaste if (group_option_defs[i].usage_mask & src_mask) 1017254721Semaste { 1018254721Semaste m_option_infos.push_back (OptionInfo (group, i)); 1019254721Semaste m_option_defs.push_back (group_option_defs[i]); 1020254721Semaste m_option_defs.back().usage_mask = dst_mask; 1021254721Semaste } 1022254721Semaste } 1023254721Semaste} 1024254721Semaste 1025254721Semastevoid 1026254721SemasteOptionGroupOptions::Finalize () 1027254721Semaste{ 1028254721Semaste m_did_finalize = true; 1029254721Semaste OptionDefinition empty_option_def = { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }; 1030254721Semaste m_option_defs.push_back (empty_option_def); 1031254721Semaste} 1032254721Semaste 1033254721SemasteError 1034254721SemasteOptionGroupOptions::SetOptionValue (uint32_t option_idx, 1035254721Semaste const char *option_value) 1036254721Semaste{ 1037254721Semaste // After calling OptionGroupOptions::Append(...), you must finalize the groups 1038254721Semaste // by calling OptionGroupOptions::Finlize() 1039254721Semaste assert (m_did_finalize); 1040254721Semaste assert (m_option_infos.size() + 1 == m_option_defs.size()); 1041254721Semaste Error error; 1042254721Semaste if (option_idx < m_option_infos.size()) 1043254721Semaste { 1044254721Semaste error = m_option_infos[option_idx].option_group->SetOptionValue (m_interpreter, 1045254721Semaste m_option_infos[option_idx].option_index, 1046254721Semaste option_value); 1047254721Semaste 1048254721Semaste } 1049254721Semaste else 1050254721Semaste { 1051254721Semaste error.SetErrorString ("invalid option index"); // Shouldn't happen... 1052254721Semaste } 1053254721Semaste return error; 1054254721Semaste} 1055254721Semaste 1056254721Semastevoid 1057254721SemasteOptionGroupOptions::OptionParsingStarting () 1058254721Semaste{ 1059254721Semaste std::set<OptionGroup*> group_set; 1060254721Semaste OptionInfos::iterator pos, end = m_option_infos.end(); 1061254721Semaste for (pos = m_option_infos.begin(); pos != end; ++pos) 1062254721Semaste { 1063254721Semaste OptionGroup* group = pos->option_group; 1064254721Semaste if (group_set.find(group) == group_set.end()) 1065254721Semaste { 1066254721Semaste group->OptionParsingStarting (m_interpreter); 1067254721Semaste group_set.insert(group); 1068254721Semaste } 1069254721Semaste } 1070254721Semaste} 1071254721SemasteError 1072254721SemasteOptionGroupOptions::OptionParsingFinished () 1073254721Semaste{ 1074254721Semaste std::set<OptionGroup*> group_set; 1075254721Semaste Error error; 1076254721Semaste OptionInfos::iterator pos, end = m_option_infos.end(); 1077254721Semaste for (pos = m_option_infos.begin(); pos != end; ++pos) 1078254721Semaste { 1079254721Semaste OptionGroup* group = pos->option_group; 1080254721Semaste if (group_set.find(group) == group_set.end()) 1081254721Semaste { 1082254721Semaste error = group->OptionParsingFinished (m_interpreter); 1083254721Semaste group_set.insert(group); 1084254721Semaste if (error.Fail()) 1085254721Semaste return error; 1086254721Semaste } 1087254721Semaste } 1088254721Semaste return error; 1089254721Semaste} 1090