diff options
author | Caroline Tice <ctice@apple.com> | 2010-12-07 19:58:26 +0000 |
---|---|---|
committer | Caroline Tice <ctice@apple.com> | 2010-12-07 19:58:26 +0000 |
commit | d9d63369dfd1b31e0eb89ce38d6be12cffdb7274 (patch) | |
tree | 607386f6a51e64cdec6fe99cd64b2ab034dddb6a /lldb/source | |
parent | f844b3b2275fd71a0751c92b432651b64a984786 (diff) | |
download | bcm5719-llvm-d9d63369dfd1b31e0eb89ce38d6be12cffdb7274.tar.gz bcm5719-llvm-d9d63369dfd1b31e0eb89ce38d6be12cffdb7274.zip |
- Fix alias-building & resolving to properly handle optional arguments for command options.
- Add logging for command resolution ('log enable lldb commands')
- Fix alias resolution to properly handle commands that take raw input (resolve the alias, but
don't muck up the raw arguments).
Net result: Among other things, 'expr' command can now take strings with escaped characters and
not have the command handling & alias resolution code muck up the escaped characters. E.g.
'expr printf ("\n\n\tHello there!")' should now work properly.
Not working yet: Creating aliases with raw input for commands that take raw input. Working on that.
e.g. 'command alias print_hi expr printf ("\n\tHi!")' does not work yet.
llvm-svn: 121171
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Commands/CommandObjectCommands.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectHelp.cpp | 4 | ||||
-rw-r--r-- | lldb/source/Interpreter/Args.cpp | 84 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 141 | ||||
-rw-r--r-- | lldb/source/lldb-log.cpp | 2 |
5 files changed, 197 insertions, 42 deletions
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index ea4ae03939b..0ca50b0ff65 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -336,9 +336,11 @@ public: argc = args.GetArgumentCount(); for (size_t i = 0; i < argc; ++i) - if (strcmp (args.GetArgumentAtIndex (i), "") != 0) - option_arg_vector->push_back (OptionArgPair ("<argument>", - std::string (args.GetArgumentAtIndex (i)))); + if (strcmp (args.GetArgumentAtIndex (i), "") != 0) + option_arg_vector->push_back + (OptionArgPair ("<argument>", + OptionArgValue (-1, + std::string (args.GetArgumentAtIndex (i))))); } // Create the alias. diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp index 416bdd542ba..98fe2ad58c2 100644 --- a/lldb/source/Commands/CommandObjectHelp.cpp +++ b/lldb/source/Commands/CommandObjectHelp.cpp @@ -146,6 +146,10 @@ CommandObjectHelp::Execute (Args& command, CommandReturnObject &result) && (strlen (long_help) > 0)) output_strm.Printf ("\n%s", long_help); // Mark this help command with a success status. + if (sub_cmd_obj->WantsRawCommandString()) + { + m_interpreter.OutputFormattedHelpText (output_strm, "", "", "\nIMPORTANT NOTE: Because this command takes 'raw' input, if you use any command options you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1); + } result.SetStatus (eReturnStatusSuccessFinishNoResult); } else if (sub_cmd_obj->IsMultiwordObject()) diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp index c04c4aa7c8a..8bc7d97b582 100644 --- a/lldb/source/Interpreter/Args.cpp +++ b/lldb/source/Interpreter/Args.cpp @@ -801,6 +801,51 @@ Args::LongestCommonPrefix (std::string &common_prefix) } } +size_t +Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index) +{ + char short_buffer[3]; + char long_buffer[255]; + ::snprintf (short_buffer, sizeof (short_buffer), "-%c", (char) long_options[long_options_index].val); + ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name); + size_t end = GetArgumentCount (); + size_t idx = 0; + while (idx < end) + { + if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0) + || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0)) + { + return idx; + } + ++idx; + } + + return end; +} + +bool +Args::IsPositionalArgument (const char *arg) +{ + if (arg == NULL) + return false; + + bool is_positional = true; + char *cptr = (char *) arg; + + if (cptr[0] == '%') + { + ++cptr; + while (isdigit (cptr[0])) + ++cptr; + if (cptr[0] != '\0') + is_positional = false; + } + else + is_positional = false; + + return is_positional; +} + void Args::ParseAliasOptions (Options &options, CommandReturnObject &result, @@ -889,14 +934,16 @@ Args::ParseAliasOptions (Options &options, switch (long_options[long_options_index].has_arg) { case no_argument: - option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), "<no-argument>")); + option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), + OptionArgValue (no_argument, "<no-argument>"))); result.SetStatus (eReturnStatusSuccessFinishNoResult); break; case required_argument: if (optarg != NULL) { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - std::string (optarg))); + OptionArgValue (required_argument, + std::string (optarg)))); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -910,13 +957,14 @@ Args::ParseAliasOptions (Options &options, if (optarg != NULL) { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - std::string (optarg))); + OptionArgValue (optional_argument, + std::string (optarg)))); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else { option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), - "<no-argument>")); + OptionArgValue (optional_argument, "<no-argument>"))); result.SetStatus (eReturnStatusSuccessFinishNoResult); } break; @@ -938,24 +986,16 @@ Args::ParseAliasOptions (Options &options, { // Find option in the argument list; also see if it was supposed to take an argument and if one was // supplied. Remove option (and argument, if given) from the argument list. - StreamString short_opt_str; - StreamString long_opt_str; - short_opt_str.Printf ("-%c", (char) long_options[long_options_index].val); - long_opt_str.Printf ("-%s", long_options[long_options_index].name); - bool found = false; - size_t end = GetArgumentCount(); - for (size_t i = 0; i < end && !found; ++i) - if ((strcmp (GetArgumentAtIndex (i), short_opt_str.GetData()) == 0) - || (strcmp (GetArgumentAtIndex (i), long_opt_str.GetData()) == 0)) - { - found = true; - ReplaceArgumentAtIndex (i, ""); - if ((long_options[long_options_index].has_arg != no_argument) - && (optarg != NULL) - && (i+1 < end) - && (strcmp (optarg, GetArgumentAtIndex(i+1)) == 0)) - ReplaceArgumentAtIndex (i+1, ""); - } + size_t idx = FindArgumentIndexForOption (long_options, long_options_index); + if (idx < GetArgumentCount()) + { + ReplaceArgumentAtIndex (idx, ""); + if ((long_options[long_options_index].has_arg != no_argument) + && (optarg != NULL) + && (idx+1 < GetArgumentCount()) + && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0)) + ReplaceArgumentAtIndex (idx+1, ""); + } } if (!result.Succeeded()) diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 86a635a6b2b..feb496332c1 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -406,7 +406,8 @@ CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_na { OptionArgPair cur_option = (*options)[i]; std::string opt = cur_option.first; - std::string value = cur_option.second; + OptionArgValue value_pair = cur_option.second; + std::string value = value_pair.second; if (opt.compare("<argument>") == 0) { help_string.Printf (" %s", value.c_str()); @@ -502,6 +503,7 @@ CommandInterpreter::HandleCommand ExecutionContext *override_context ) { + LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); // FIXME: there should probably be a mutex to make sure only one thread can // run the interpreter at a time. @@ -542,10 +544,16 @@ CommandInterpreter::HandleCommand add_to_history = false; } + if (log) + log->Printf ("CommandInterpreter::HandleCommand, command_line = '%s'", command_line); + Args command_args(command_line); if (command_args.GetArgumentCount() > 0) { + std::string raw_command_string (command_line); // For commands that take raw input but may be aliased or + // have command options. + const char *command_cstr = command_args.GetArgumentAtIndex(0); if (command_cstr) { @@ -556,20 +564,54 @@ CommandInterpreter::HandleCommand if (command_obj != NULL) { + // Strip command name from the raw_command_string. + if (raw_command_string.find (command_cstr) == 0) + { + // The command name is at the front of the string (where it should be) so strip it off. + raw_command_string = raw_command_string.substr (strlen (command_cstr)); + } + + std::string aliased_cmd_str; if (command_obj->IsAlias()) { - BuildAliasCommandArgs (command_obj, command_cstr, command_args, result); + if (log) + log->Printf ("Command '%s' is an alias. Building alias command args.", command_cstr); + BuildAliasCommandArgs (command_obj, command_cstr, command_args, raw_command_string, result); if (!result.Succeeded()) + { + if (log) + log->Printf ("Building alias command args failed."); return false; + } else { // We need to transfer the newly constructed args back into the command_line, in case // this happens to be an alias for a command that takes raw input. if (command_args.GetCommandString (aliased_cmd_str)) { + if (log) + log->Printf ("Result string from BuildAliasCommandArgs is '%s'", aliased_cmd_str.c_str()); + if (command_obj->WantsRawCommandString()) + { + if (log) + { + log->Printf ("This command takes raw input."); + } + aliased_cmd_str.append (" "); + aliased_cmd_str.append (raw_command_string); + } + else + { + if (log) + log->Printf ("This command does NOT take raw input."); + } command_line = aliased_cmd_str.c_str(); command_cstr = command_args.GetArgumentAtIndex (0); + if (log) + { + log->Printf ("Final command line, after resolving aliases is '%s'", command_line); + } } } } @@ -594,6 +636,9 @@ CommandInterpreter::HandleCommand stripped_command += strlen(command_cstr); while (isspace(*stripped_command)) ++stripped_command; + if (log) + log->Printf ("Input string being passed to ExecuteRawCommandString for '%s' command is '%s'", + command_obj->GetCommandName(), stripped_command); command_obj->ExecuteRawCommandString (stripped_command, result); } } @@ -601,6 +646,14 @@ CommandInterpreter::HandleCommand { // Remove the command from the args. command_args.Shift(); + if (log) + { + size_t count = command_args.GetArgumentCount(); + log->Printf ("ExecuteWithOptions for '%s' command is being called with %d args:", + command_obj->GetCommandName(), count); + for (size_t k = 0; k < count; ++k) + log->Printf (" arg[%d]='%s'", k, command_args.GetArgumentAtIndex (k)); + } command_obj->ExecuteWithOptions (command_args, result); } } @@ -983,20 +1036,35 @@ void CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, + std::string &raw_input_string, CommandReturnObject &result) { OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); + + bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); + // Make sure that the alias name is the 0th element in cmd_args + std::string alias_name_str = alias_name; + if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) + cmd_args.Unshift (alias_name); + + Args new_args (alias_cmd_obj->GetCommandName()); + if (new_args.GetArgumentCount() == 2) + new_args.Shift(); + if (option_arg_vector_sp.get()) { - // Make sure that the alias name is the 0th element in cmd_args - std::string alias_name_str = alias_name; - if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) - cmd_args.Unshift (alias_name); - - Args new_args (alias_cmd_obj->GetCommandName()); - if (new_args.GetArgumentCount() == 2) - new_args.Shift(); + if (wants_raw_input) + { + // We have a command that both has command options and takes raw input. Make *sure* it has a + // " -- " in the right place in the raw_input_string. + size_t pos = raw_input_string.find(" -- "); + if (pos == std::string::npos) + { + // None found; assume it goes at the beginning of the raw input string + raw_input_string.insert (0, " -- "); + } + } OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); int old_size = cmd_args.GetArgumentCount(); @@ -1007,19 +1075,36 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, for (int i = 0; i < option_arg_vector->size(); ++i) { OptionArgPair option_pair = (*option_arg_vector)[i]; + OptionArgValue value_pair = option_pair.second; + int value_type = value_pair.first; std::string option = option_pair.first; - std::string value = option_pair.second; + std::string value = value_pair.second; if (option.compare ("<argument>") == 0) - new_args.AppendArgument (value.c_str()); + { + if (!wants_raw_input + || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice + new_args.AppendArgument (value.c_str()); + } else { - new_args.AppendArgument (option.c_str()); + if (value_type != optional_argument) + new_args.AppendArgument (option.c_str()); if (value.compare ("<no-argument>") != 0) { int index = GetOptionArgumentPosition (value.c_str()); if (index == 0) + { // value was NOT a positional argument; must be a real value - new_args.AppendArgument (value.c_str()); + if (value_type != optional_argument) + new_args.AppendArgument (value.c_str()); + else + { + char buffer[255]; + ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); + new_args.AppendArgument (buffer); + } + + } else if (index >= cmd_args.GetArgumentCount()) { result.AppendErrorWithFormat @@ -1030,7 +1115,22 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, } else { - new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); + // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string + size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); + if (strpos != std::string::npos) + { + raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); + } + + if (value_type != optional_argument) + new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); + else + { + char buffer[255]; + ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), + cmd_args.GetArgumentAtIndex (index)); + new_args.AppendArgument (buffer); + } used[index] = true; } } @@ -1039,7 +1139,7 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, for (int j = 0; j < cmd_args.GetArgumentCount(); ++j) { - if (!used[j]) + if (!used[j] && !wants_raw_input) new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); } @@ -1049,7 +1149,14 @@ CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, else { result.SetStatus (eReturnStatusSuccessFinishNoResult); - // This alias was not created with any options; nothing further needs to be done. + // This alias was not created with any options; nothing further needs to be done, unless it is a command that + // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw + // input string. + if (wants_raw_input) + { + cmd_args.Clear(); + cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); + } return; } diff --git a/lldb/source/lldb-log.cpp b/lldb/source/lldb-log.cpp index 5e4d6f545c4..dcad9cb8efc 100644 --- a/lldb/source/lldb-log.cpp +++ b/lldb/source/lldb-log.cpp @@ -116,6 +116,7 @@ lldb_private::DisableLog (Args &args, Stream *feedback_strm) if (strcasecmp(arg, "all") == 0 ) flag_bits &= ~LIBLLDB_LOG_ALL; else if (strcasecmp(arg, "api") == 0) flag_bits &= ~LIBLLDB_LOG_API; else if (strcasestr(arg, "break") == arg) flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS; + else if (strcasecmp(arg, "commands")== 0) flag_bits &= ~LIBLLDB_LOG_COMMANDS; else if (strcasecmp(arg, "default") == 0 ) flag_bits &= ~LIBLLDB_LOG_DEFAULT; else if (strcasecmp(arg, "dyld") == 0 ) flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER; else if (strcasestr(arg, "event") == arg) flag_bits &= ~LIBLLDB_LOG_EVENTS; @@ -181,6 +182,7 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &ar if (strcasecmp(arg, "all") == 0 ) flag_bits |= LIBLLDB_LOG_ALL; else if (strcasecmp(arg, "api") == 0) flag_bits |= LIBLLDB_LOG_API; else if (strcasestr(arg, "break") == arg) flag_bits |= LIBLLDB_LOG_BREAKPOINTS; + else if (strcasecmp(arg, "commands")== 0) flag_bits |= LIBLLDB_LOG_COMMANDS; else if (strcasecmp(arg, "default") == 0 ) flag_bits |= LIBLLDB_LOG_DEFAULT; else if (strcasecmp(arg, "dyld") == 0 ) flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER; else if (strcasestr(arg, "event") == arg) flag_bits |= LIBLLDB_LOG_EVENTS; |