1 //===-- Options.cpp ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Interpreter/Options.h" 11 12 // C Includes 13 // C++ Includes 14 #include <bitset> 15 #include <algorithm> 16 17 // Other libraries and framework includes 18 // Project includes 19 #include "lldb/Interpreter/CommandObject.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "lldb/Interpreter/CommandCompletions.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Core/StreamString.h" 24 #include "lldb/Target/Target.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //------------------------------------------------------------------------- 30 // Options 31 //------------------------------------------------------------------------- 32 Options::Options () : 33 m_getopt_table () 34 { 35 BuildValidOptionSets(); 36 } 37 38 Options::~Options () 39 { 40 } 41 42 43 void 44 Options::ResetOptionValues () 45 { 46 m_seen_options.clear(); 47 } 48 49 void 50 Options::OptionSeen (int option_idx) 51 { 52 m_seen_options.insert ((char) option_idx); 53 } 54 55 // Returns true is set_a is a subset of set_b; Otherwise returns false. 56 57 bool 58 Options::IsASubset (const OptionSet& set_a, const OptionSet& set_b) 59 { 60 bool is_a_subset = true; 61 OptionSet::const_iterator pos_a; 62 OptionSet::const_iterator pos_b; 63 64 // set_a is a subset of set_b if every member of set_a is also a member of set_b 65 66 for (pos_a = set_a.begin(); pos_a != set_a.end() && is_a_subset; ++pos_a) 67 { 68 pos_b = set_b.find(*pos_a); 69 if (pos_b == set_b.end()) 70 is_a_subset = false; 71 } 72 73 return is_a_subset; 74 } 75 76 // Returns the set difference set_a - set_b, i.e. { x | ElementOf (x, set_a) && !ElementOf (x, set_b) } 77 78 size_t 79 Options::OptionsSetDiff (const OptionSet& set_a, const OptionSet& set_b, OptionSet& diffs) 80 { 81 size_t num_diffs = 0; 82 OptionSet::const_iterator pos_a; 83 OptionSet::const_iterator pos_b; 84 85 for (pos_a = set_a.begin(); pos_a != set_a.end(); ++pos_a) 86 { 87 pos_b = set_b.find(*pos_a); 88 if (pos_b == set_b.end()) 89 { 90 ++num_diffs; 91 diffs.insert(*pos_a); 92 } 93 } 94 95 return num_diffs; 96 } 97 98 // Returns the union of set_a and set_b. Does not put duplicate members into the union. 99 100 void 101 Options::OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set) 102 { 103 OptionSet::const_iterator pos; 104 OptionSet::iterator pos_union; 105 106 // Put all the elements of set_a into the union. 107 108 for (pos = set_a.begin(); pos != set_a.end(); ++pos) 109 union_set.insert(*pos); 110 111 // Put all the elements of set_b that are not already there into the union. 112 for (pos = set_b.begin(); pos != set_b.end(); ++pos) 113 { 114 pos_union = union_set.find(*pos); 115 if (pos_union == union_set.end()) 116 union_set.insert(*pos); 117 } 118 } 119 120 bool 121 Options::VerifyOptions (CommandReturnObject &result) 122 { 123 bool options_are_valid = false; 124 125 int num_levels = GetRequiredOptions().size(); 126 if (num_levels) 127 { 128 for (int i = 0; i < num_levels && !options_are_valid; ++i) 129 { 130 // This is the correct set of options if: 1). m_seen_options contains all of m_required_options[i] 131 // (i.e. all the required options at this level are a subset of m_seen_options); AND 132 // 2). { m_seen_options - m_required_options[i] is a subset of m_options_options[i] (i.e. all the rest of 133 // m_seen_options are in the set of optional options at this level. 134 135 // Check to see if all of m_required_options[i] are a subset of m_seen_options 136 if (IsASubset (GetRequiredOptions()[i], m_seen_options)) 137 { 138 // Construct the set difference: remaining_options = {m_seen_options} - {m_required_options[i]} 139 OptionSet remaining_options; 140 OptionsSetDiff (m_seen_options, GetRequiredOptions()[i], remaining_options); 141 // Check to see if remaining_options is a subset of m_optional_options[i] 142 if (IsASubset (remaining_options, GetOptionalOptions()[i])) 143 options_are_valid = true; 144 } 145 } 146 } 147 else 148 { 149 options_are_valid = true; 150 } 151 152 if (options_are_valid) 153 { 154 result.SetStatus (eReturnStatusSuccessFinishNoResult); 155 } 156 else 157 { 158 result.AppendError ("invalid combination of options for the given command"); 159 result.SetStatus (eReturnStatusFailed); 160 } 161 162 return options_are_valid; 163 } 164 165 // This is called in the Options constructor, though we could call it lazily if that ends up being 166 // a performance problem. 167 168 void 169 Options::BuildValidOptionSets () 170 { 171 // Check to see if we already did this. 172 if (m_required_options.size() != 0) 173 return; 174 175 // Check to see if there are any options. 176 int num_options = NumCommandOptions (); 177 if (num_options == 0) 178 return; 179 180 const lldb::OptionDefinition *full_options_table = GetDefinitions(); 181 m_required_options.resize(1); 182 m_optional_options.resize(1); 183 184 // First count the number of option sets we've got. Ignore LLDB_ALL_OPTION_SETS... 185 186 uint32_t num_option_sets = 0; 187 188 for (int i = 0; i < num_options; i++) 189 { 190 uint32_t this_usage_mask = full_options_table[i].usage_mask; 191 if (this_usage_mask == LLDB_OPT_SET_ALL) 192 { 193 if (num_option_sets == 0) 194 num_option_sets = 1; 195 } 196 else 197 { 198 for (int j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) 199 { 200 if (this_usage_mask & (1 << j)) 201 { 202 if (num_option_sets <= j) 203 num_option_sets = j + 1; 204 } 205 } 206 } 207 } 208 209 if (num_option_sets > 0) 210 { 211 m_required_options.resize(num_option_sets); 212 m_optional_options.resize(num_option_sets); 213 214 for (int i = 0; i < num_options; ++i) 215 { 216 for (int j = 0; j < num_option_sets; j++) 217 { 218 if (full_options_table[i].usage_mask & 1 << j) 219 { 220 if (full_options_table[i].required) 221 m_required_options[j].insert(full_options_table[i].short_option); 222 else 223 m_optional_options[j].insert(full_options_table[i].short_option); 224 } 225 } 226 } 227 } 228 } 229 230 uint32_t 231 Options::NumCommandOptions () 232 { 233 const lldb::OptionDefinition *full_options_table = GetDefinitions (); 234 if (full_options_table == NULL) 235 return 0; 236 237 int i = 0; 238 239 if (full_options_table != NULL) 240 { 241 while (full_options_table[i].long_option != NULL) 242 ++i; 243 } 244 245 return i; 246 } 247 248 struct option * 249 Options::GetLongOptions () 250 { 251 // Check to see if this has already been done. 252 if (m_getopt_table.empty()) 253 { 254 // Check to see if there are any options. 255 const uint32_t num_options = NumCommandOptions(); 256 if (num_options == 0) 257 return NULL; 258 259 uint32_t i; 260 uint32_t j; 261 const lldb::OptionDefinition *full_options_table = GetDefinitions(); 262 263 std::bitset<256> option_seen; 264 265 m_getopt_table.resize(num_options + 1); 266 for (i = 0, j = 0; i < num_options; ++i) 267 { 268 char short_opt = full_options_table[i].short_option; 269 270 if (option_seen.test(short_opt) == false) 271 { 272 m_getopt_table[j].name = full_options_table[i].long_option; 273 m_getopt_table[j].has_arg = full_options_table[i].option_has_arg; 274 m_getopt_table[j].flag = NULL; 275 m_getopt_table[j].val = full_options_table[i].short_option; 276 option_seen.set(short_opt); 277 ++j; 278 } 279 } 280 281 //getopt_long requires a NULL final entry in the table: 282 283 m_getopt_table[j].name = NULL; 284 m_getopt_table[j].has_arg = 0; 285 m_getopt_table[j].flag = NULL; 286 m_getopt_table[j].val = 0; 287 } 288 289 if (m_getopt_table.empty()) 290 return NULL; 291 292 return &m_getopt_table.front(); 293 } 294 295 296 // This function takes INDENT, which tells how many spaces to output at the front of each line; SPACES, which is 297 // a string containing 80 spaces; and TEXT, which is the text that is to be output. It outputs the text, on 298 // multiple lines if necessary, to RESULT, with INDENT spaces at the front of each line. It breaks lines on spaces, 299 // tabs or newlines, shortening the line if necessary to not break in the middle of a word. It assumes that each 300 // output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. 301 302 303 void 304 Options::OutputFormattedUsageText 305 ( 306 Stream &strm, 307 const char *text, 308 uint32_t output_max_columns 309 ) 310 { 311 int len = strlen (text); 312 313 // Will it all fit on one line? 314 315 if ((len + strm.GetIndentLevel()) < output_max_columns) 316 { 317 // Output it as a single line. 318 strm.Indent (text); 319 strm.EOL(); 320 } 321 else 322 { 323 // We need to break it up into multiple lines. 324 325 int text_width = output_max_columns - strm.GetIndentLevel() - 1; 326 int start = 0; 327 int end = start; 328 int final_end = strlen (text); 329 int sub_len; 330 331 while (end < final_end) 332 { 333 // Don't start the 'text' on a space, since we're already outputting the indentation. 334 while ((start < final_end) && (text[start] == ' ')) 335 start++; 336 337 end = start + text_width; 338 if (end > final_end) 339 end = final_end; 340 else 341 { 342 // If we're not at the end of the text, make sure we break the line on white space. 343 while (end > start 344 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 345 end--; 346 } 347 348 sub_len = end - start; 349 if (start != 0) 350 strm.EOL(); 351 strm.Indent(); 352 assert (start < final_end); 353 assert (start + sub_len <= final_end); 354 strm.Write(text + start, sub_len); 355 start = end + 1; 356 } 357 strm.EOL(); 358 } 359 } 360 361 void 362 Options::GenerateOptionUsage 363 ( 364 CommandInterpreter &interpreter, 365 Stream &strm, 366 CommandObject *cmd 367 ) 368 { 369 const uint32_t screen_width = interpreter.GetDebugger().GetTerminalWidth(); 370 371 const lldb::OptionDefinition *full_options_table = GetDefinitions(); 372 const uint32_t save_indent_level = strm.GetIndentLevel(); 373 const char *name; 374 375 StreamString arguments_str; 376 377 if (cmd) 378 { 379 name = cmd->GetCommandName(); 380 cmd->GetFormattedCommandArguments (arguments_str); 381 } 382 else 383 name = ""; 384 385 strm.PutCString ("\nCommand Options Usage:\n"); 386 387 strm.IndentMore(2); 388 389 // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] 390 // <cmd> [options-for-level-1] 391 // etc. 392 393 const uint32_t num_options = NumCommandOptions(); 394 if (num_options == 0) 395 return; 396 397 int num_option_sets = GetRequiredOptions().size(); 398 399 uint32_t i; 400 401 for (uint32_t opt_set = 0; opt_set < num_option_sets; ++opt_set) 402 { 403 uint32_t opt_set_mask; 404 405 opt_set_mask = 1 << opt_set; 406 if (opt_set > 0) 407 strm.Printf ("\n"); 408 strm.Indent (name); 409 410 // First go through and print all options that take no arguments as 411 // a single string. If a command has "-a" "-b" and "-c", this will show 412 // up as [-abc] 413 414 std::set<char> options; 415 std::set<char>::const_iterator options_pos, options_end; 416 bool first; 417 for (i = 0, first = true; i < num_options; ++i) 418 { 419 if (full_options_table[i].usage_mask & opt_set_mask) 420 { 421 // Add current option to the end of out_stream. 422 423 if (full_options_table[i].required == true && 424 full_options_table[i].option_has_arg == no_argument) 425 { 426 options.insert (full_options_table[i].short_option); 427 } 428 } 429 } 430 431 if (options.empty() == false) 432 { 433 // We have some required options with no arguments 434 strm.PutCString(" -"); 435 for (i=0; i<2; ++i) 436 for (options_pos = options.begin(), options_end = options.end(); 437 options_pos != options_end; 438 ++options_pos) 439 { 440 if (i==0 && ::isupper (*options_pos)) 441 continue; 442 if (i==1 && ::islower (*options_pos)) 443 continue; 444 strm << *options_pos; 445 } 446 } 447 448 for (i = 0, options.clear(); i < num_options; ++i) 449 { 450 if (full_options_table[i].usage_mask & opt_set_mask) 451 { 452 // Add current option to the end of out_stream. 453 454 if (full_options_table[i].required == false && 455 full_options_table[i].option_has_arg == no_argument) 456 { 457 options.insert (full_options_table[i].short_option); 458 } 459 } 460 } 461 462 if (options.empty() == false) 463 { 464 // We have some required options with no arguments 465 strm.PutCString(" [-"); 466 for (i=0; i<2; ++i) 467 for (options_pos = options.begin(), options_end = options.end(); 468 options_pos != options_end; 469 ++options_pos) 470 { 471 if (i==0 && ::isupper (*options_pos)) 472 continue; 473 if (i==1 && ::islower (*options_pos)) 474 continue; 475 strm << *options_pos; 476 } 477 strm.PutChar(']'); 478 } 479 480 // First go through and print the required options (list them up front). 481 482 for (i = 0; i < num_options; ++i) 483 { 484 if (full_options_table[i].usage_mask & opt_set_mask) 485 { 486 // Add current option to the end of out_stream. 487 CommandArgumentType arg_type = full_options_table[i].argument_type; 488 489 if (full_options_table[i].required) 490 { 491 if (full_options_table[i].option_has_arg == required_argument) 492 { 493 strm.Printf (" -%c <%s>", 494 full_options_table[i].short_option, 495 CommandObject::GetArgumentName (arg_type)); 496 } 497 else if (full_options_table[i].option_has_arg == optional_argument) 498 { 499 strm.Printf (" -%c [<%s>]", 500 full_options_table[i].short_option, 501 CommandObject::GetArgumentName (arg_type)); 502 } 503 } 504 } 505 } 506 507 // Now go through again, and this time only print the optional options. 508 509 for (i = 0; i < num_options; ++i) 510 { 511 if (full_options_table[i].usage_mask & opt_set_mask) 512 { 513 // Add current option to the end of out_stream. 514 515 CommandArgumentType arg_type = full_options_table[i].argument_type; 516 517 if (! full_options_table[i].required) 518 { 519 if (full_options_table[i].option_has_arg == required_argument) 520 strm.Printf (" [-%c <%s>]", full_options_table[i].short_option, 521 CommandObject::GetArgumentName (arg_type)); 522 else if (full_options_table[i].option_has_arg == optional_argument) 523 strm.Printf (" [-%c [<%s>]]", full_options_table[i].short_option, 524 CommandObject::GetArgumentName (arg_type)); 525 } 526 } 527 } 528 if (arguments_str.GetSize() > 0) 529 strm.Printf (" %s", arguments_str.GetData()); 530 } 531 strm.Printf ("\n\n"); 532 533 // Now print out all the detailed information about the various options: long form, short form and help text: 534 // --long_name <argument> ( -short <argument> ) 535 // help text 536 537 // This variable is used to keep track of which options' info we've printed out, because some options can be in 538 // more than one usage level, but we only want to print the long form of its information once. 539 540 OptionSet options_seen; 541 OptionSet::iterator pos; 542 strm.IndentMore (5); 543 544 std::vector<char> sorted_options; 545 546 547 // Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option) 548 // when writing out detailed help for each option. 549 550 for (i = 0; i < num_options; ++i) 551 { 552 pos = options_seen.find (full_options_table[i].short_option); 553 if (pos == options_seen.end()) 554 { 555 options_seen.insert (full_options_table[i].short_option); 556 sorted_options.push_back (full_options_table[i].short_option); 557 } 558 } 559 560 std::sort (sorted_options.begin(), sorted_options.end()); 561 562 // Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option 563 // and write out the detailed help information for that option. 564 565 int first_option_printed = 1; 566 size_t end = sorted_options.size(); 567 for (size_t j = 0; j < end; ++j) 568 { 569 char option = sorted_options[j]; 570 bool found = false; 571 for (i = 0; i < num_options && !found; ++i) 572 { 573 if (full_options_table[i].short_option == option) 574 { 575 found = true; 576 //Print out the help information for this option. 577 578 // Put a newline separation between arguments 579 if (first_option_printed) 580 first_option_printed = 0; 581 else 582 strm.EOL(); 583 584 CommandArgumentType arg_type = full_options_table[i].argument_type; 585 586 StreamString arg_name_str; 587 arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type)); 588 589 strm.Indent (); 590 strm.Printf ("-%c", full_options_table[i].short_option); 591 if (arg_type != eArgTypeNone) 592 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type)); 593 strm.Printf (" ( --%s", full_options_table[i].long_option); 594 if (arg_type != eArgTypeNone) 595 strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type)); 596 strm.PutCString(" )\n"); 597 598 strm.IndentMore (5); 599 600 if (full_options_table[i].usage_text) 601 OutputFormattedUsageText (strm, 602 full_options_table[i].usage_text, 603 screen_width); 604 if (full_options_table[i].enum_values != NULL) 605 { 606 strm.Indent (); 607 strm.Printf("Values: "); 608 for (int k = 0; full_options_table[i].enum_values[k].string_value != NULL; k++) 609 { 610 if (k == 0) 611 strm.Printf("%s", full_options_table[i].enum_values[k].string_value); 612 else 613 strm.Printf(" | %s", full_options_table[i].enum_values[k].string_value); 614 } 615 strm.EOL(); 616 } 617 strm.IndentLess (5); 618 } 619 } 620 } 621 622 // Restore the indent level 623 strm.SetIndentLevel (save_indent_level); 624 } 625 626 // This function is called when we have been given a potentially incomplete set of 627 // options, such as when an alias has been defined (more options might be added at 628 // at the time the alias is invoked). We need to verify that the options in the set 629 // m_seen_options are all part of a set that may be used together, but m_seen_options 630 // may be missing some of the "required" options. 631 632 bool 633 Options::VerifyPartialOptions (CommandReturnObject &result) 634 { 635 bool options_are_valid = false; 636 637 int num_levels = GetRequiredOptions().size(); 638 if (num_levels) 639 { 640 for (int i = 0; i < num_levels && !options_are_valid; ++i) 641 { 642 // In this case we are treating all options as optional rather than required. 643 // Therefore a set of options is correct if m_seen_options is a subset of the 644 // union of m_required_options and m_optional_options. 645 OptionSet union_set; 646 OptionsSetUnion (GetRequiredOptions()[i], GetOptionalOptions()[i], union_set); 647 if (IsASubset (m_seen_options, union_set)) 648 options_are_valid = true; 649 } 650 } 651 652 return options_are_valid; 653 } 654 655 bool 656 Options::HandleOptionCompletion 657 ( 658 CommandInterpreter &interpreter, 659 Args &input, 660 OptionElementVector &opt_element_vector, 661 int cursor_index, 662 int char_pos, 663 int match_start_point, 664 int max_return_elements, 665 bool &word_complete, 666 lldb_private::StringList &matches 667 ) 668 { 669 word_complete = true; 670 671 // For now we just scan the completions to see if the cursor position is in 672 // an option or its argument. Otherwise we'll call HandleArgumentCompletion. 673 // In the future we can use completion to validate options as well if we want. 674 675 const OptionDefinition *opt_defs = GetDefinitions(); 676 677 std::string cur_opt_std_str (input.GetArgumentAtIndex(cursor_index)); 678 cur_opt_std_str.erase(char_pos); 679 const char *cur_opt_str = cur_opt_std_str.c_str(); 680 681 for (int i = 0; i < opt_element_vector.size(); i++) 682 { 683 int opt_pos = opt_element_vector[i].opt_pos; 684 int opt_arg_pos = opt_element_vector[i].opt_arg_pos; 685 int opt_defs_index = opt_element_vector[i].opt_defs_index; 686 if (opt_pos == cursor_index) 687 { 688 // We're completing the option itself. 689 690 if (opt_defs_index == OptionArgElement::eBareDash) 691 { 692 // We're completing a bare dash. That means all options are open. 693 // FIXME: We should scan the other options provided and only complete options 694 // within the option group they belong to. 695 char opt_str[3] = {'-', 'a', '\0'}; 696 697 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 698 { 699 opt_str[1] = opt_defs[j].short_option; 700 matches.AppendString (opt_str); 701 } 702 return true; 703 } 704 else if (opt_defs_index == OptionArgElement::eBareDoubleDash) 705 { 706 std::string full_name ("--"); 707 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 708 { 709 full_name.erase(full_name.begin() + 2, full_name.end()); 710 full_name.append (opt_defs[j].long_option); 711 matches.AppendString (full_name.c_str()); 712 } 713 return true; 714 } 715 else if (opt_defs_index != OptionArgElement::eUnrecognizedArg) 716 { 717 // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is 718 // happy with shortest unique string, but it's still a nice thing to do.) Otherwise return 719 // The string so the upper level code will know this is a full match and add the " ". 720 if (cur_opt_str && strlen (cur_opt_str) > 2 721 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-' 722 && strcmp (opt_defs[opt_defs_index].long_option, cur_opt_str) != 0) 723 { 724 std::string full_name ("--"); 725 full_name.append (opt_defs[opt_defs_index].long_option); 726 matches.AppendString(full_name.c_str()); 727 return true; 728 } 729 else 730 { 731 matches.AppendString(input.GetArgumentAtIndex(cursor_index)); 732 return true; 733 } 734 } 735 else 736 { 737 // FIXME - not handling wrong options yet: 738 // Check to see if they are writing a long option & complete it. 739 // I think we will only get in here if the long option table has two elements 740 // that are not unique up to this point. getopt_long does shortest unique match 741 // for long options already. 742 743 if (cur_opt_str && strlen (cur_opt_str) > 2 744 && cur_opt_str[0] == '-' && cur_opt_str[1] == '-') 745 { 746 for (int j = 0 ; opt_defs[j].short_option != 0 ; j++) 747 { 748 if (strstr(opt_defs[j].long_option, cur_opt_str + 2) == opt_defs[j].long_option) 749 { 750 std::string full_name ("--"); 751 full_name.append (opt_defs[j].long_option); 752 // The options definitions table has duplicates because of the 753 // way the grouping information is stored, so only add once. 754 bool duplicate = false; 755 for (int k = 0; k < matches.GetSize(); k++) 756 { 757 if (matches.GetStringAtIndex(k) == full_name) 758 { 759 duplicate = true; 760 break; 761 } 762 } 763 if (!duplicate) 764 matches.AppendString(full_name.c_str()); 765 } 766 } 767 } 768 return true; 769 } 770 771 772 } 773 else if (opt_arg_pos == cursor_index) 774 { 775 // Okay the cursor is on the completion of an argument. 776 // See if it has a completion, otherwise return no matches. 777 778 if (opt_defs_index != -1) 779 { 780 HandleOptionArgumentCompletion (interpreter, 781 input, 782 cursor_index, 783 strlen (input.GetArgumentAtIndex(cursor_index)), 784 opt_element_vector, 785 i, 786 match_start_point, 787 max_return_elements, 788 word_complete, 789 matches); 790 return true; 791 } 792 else 793 { 794 // No completion callback means no completions... 795 return true; 796 } 797 798 } 799 else 800 { 801 // Not the last element, keep going. 802 continue; 803 } 804 } 805 return false; 806 } 807 808 bool 809 Options::HandleOptionArgumentCompletion 810 ( 811 CommandInterpreter &interpreter, 812 Args &input, 813 int cursor_index, 814 int char_pos, 815 OptionElementVector &opt_element_vector, 816 int opt_element_index, 817 int match_start_point, 818 int max_return_elements, 819 bool &word_complete, 820 lldb_private::StringList &matches 821 ) 822 { 823 const OptionDefinition *opt_defs = GetDefinitions(); 824 std::auto_ptr<SearchFilter> filter_ap; 825 826 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 827 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 828 829 // See if this is an enumeration type option, and if so complete it here: 830 831 OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values; 832 if (enum_values != NULL) 833 { 834 bool return_value = false; 835 std::string match_string(input.GetArgumentAtIndex (opt_arg_pos), input.GetArgumentAtIndex (opt_arg_pos) + char_pos); 836 for (int i = 0; enum_values[i].string_value != NULL; i++) 837 { 838 if (strstr(enum_values[i].string_value, match_string.c_str()) == enum_values[i].string_value) 839 { 840 matches.AppendString (enum_values[i].string_value); 841 return_value = true; 842 } 843 } 844 return return_value; 845 } 846 847 // If this is a source file or symbol type completion, and there is a 848 // -shlib option somewhere in the supplied arguments, then make a search filter 849 // for that shared library. 850 // FIXME: Do we want to also have an "OptionType" so we don't have to match string names? 851 852 uint32_t completion_mask = opt_defs[opt_defs_index].completionType; 853 if (completion_mask & CommandCompletions::eSourceFileCompletion 854 || completion_mask & CommandCompletions::eSymbolCompletion) 855 { 856 for (int i = 0; i < opt_element_vector.size(); i++) 857 { 858 int cur_defs_index = opt_element_vector[i].opt_defs_index; 859 int cur_arg_pos = opt_element_vector[i].opt_arg_pos; 860 const char *cur_opt_name = opt_defs[cur_defs_index].long_option; 861 862 // If this is the "shlib" option and there was an argument provided, 863 // restrict it to that shared library. 864 if (strcmp(cur_opt_name, "shlib") == 0 && cur_arg_pos != -1) 865 { 866 const char *module_name = input.GetArgumentAtIndex(cur_arg_pos); 867 if (module_name) 868 { 869 FileSpec module_spec(module_name, false); 870 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget(); 871 // Search filters require a target... 872 if (target_sp != NULL) 873 filter_ap.reset (new SearchFilterByModule (target_sp, module_spec)); 874 } 875 break; 876 } 877 } 878 } 879 880 return CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, 881 completion_mask, 882 input.GetArgumentAtIndex (opt_arg_pos), 883 match_start_point, 884 max_return_elements, 885 filter_ap.get(), 886 word_complete, 887 matches); 888 889 } 890