[Lldb-commits] [lldb] r121171 - in /lldb/trunk: include/lldb/Interpreter/Args.h include/lldb/Interpreter/CommandInterpreter.h include/lldb/lldb-private-log.h source/Commands/CommandObjectCommands.cpp source/Commands/CommandObjectHelp.cpp source/Interpreter/Args.cpp source/Interpreter/CommandInterpreter.cpp source/lldb-log.cpp test/set_values/TestSetValues.py
Caroline Tice
ctice at apple.com
Tue Dec 7 11:58:26 PST 2010
Author: ctice
Date: Tue Dec 7 13:58:26 2010
New Revision: 121171
URL: http://llvm.org/viewvc/llvm-project?rev=121171&view=rev
Log:
- 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.
Modified:
lldb/trunk/include/lldb/Interpreter/Args.h
lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
lldb/trunk/include/lldb/lldb-private-log.h
lldb/trunk/source/Commands/CommandObjectCommands.cpp
lldb/trunk/source/Commands/CommandObjectHelp.cpp
lldb/trunk/source/Interpreter/Args.cpp
lldb/trunk/source/Interpreter/CommandInterpreter.cpp
lldb/trunk/source/lldb-log.cpp
lldb/trunk/test/set_values/TestSetValues.py
Modified: lldb/trunk/include/lldb/Interpreter/Args.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/Args.h?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/Args.h (original)
+++ lldb/trunk/include/lldb/Interpreter/Args.h Tue Dec 7 13:58:26 2010
@@ -27,7 +27,8 @@
namespace lldb_private {
-typedef std::pair<std::string, std::string> OptionArgPair;
+typedef std::pair<int, std::string> OptionArgValue;
+typedef std::pair<std::string, OptionArgValue> OptionArgPair;
typedef std::vector<OptionArgPair> OptionArgVector;
typedef lldb::SharedPtr<OptionArgVector>::Type OptionArgVectorSP;
@@ -301,6 +302,12 @@
//------------------------------------------------------------------
Error
ParseOptions (Options &options);
+
+ size_t
+ FindArgumentIndexForOption (struct option *long_options, int long_options_index);
+
+ bool
+ IsPositionalArgument (const char *arg);
// The following works almost identically to ParseOptions, except that no option is required to have arguments,
// and it builds up the option_arg_vector as it parses the options.
Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Tue Dec 7 13:58:26 2010
@@ -193,8 +193,8 @@
HasAliasOptions ();
void
- BuildAliasCommandArgs (CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args,
- CommandReturnObject &result);
+ BuildAliasCommandArgs (CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args,
+ std::string &raw_input_string, CommandReturnObject &result);
int
GetOptionArgumentPosition (const char *in_string);
Modified: lldb/trunk/include/lldb/lldb-private-log.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-log.h?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-log.h (original)
+++ lldb/trunk/include/lldb/lldb-private-log.h Tue Dec 7 13:58:26 2010
@@ -37,6 +37,7 @@
#define LIBLLDB_LOG_UNWIND (1u << 15)
#define LIBLLDB_LOG_API (1u << 16)
#define LIBLLDB_LOG_SCRIPT (1u << 17)
+#define LIBLLDB_LOG_COMMANDS (1U << 18)
#define LIBLLDB_LOG_ALL (UINT32_MAX)
#define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\
LIBLLDB_LOG_THREAD |\
@@ -44,7 +45,8 @@
LIBLLDB_LOG_BREAKPOINTS |\
LIBLLDB_LOG_WATCHPOINTS |\
LIBLLDB_LOG_STEP |\
- LIBLLDB_LOG_STATE )
+ LIBLLDB_LOG_STATE |\
+ LIBLLDB_LOG_COMMANDS)
namespace lldb_private {
Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Tue Dec 7 13:58:26 2010
@@ -336,9 +336,11 @@
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.
Modified: lldb/trunk/source/Commands/CommandObjectHelp.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectHelp.cpp?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectHelp.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectHelp.cpp Tue Dec 7 13:58:26 2010
@@ -146,6 +146,10 @@
&& (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())
Modified: lldb/trunk/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Args.cpp?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/Args.cpp (original)
+++ lldb/trunk/source/Interpreter/Args.cpp Tue Dec 7 13:58:26 2010
@@ -801,6 +801,51 @@
}
}
+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 @@
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 @@
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 @@
{
// 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())
Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Tue Dec 7 13:58:26 2010
@@ -406,7 +406,8 @@
{
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 @@
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 @@
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 @@
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 @@
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 @@
{
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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;
}
Modified: lldb/trunk/source/lldb-log.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb-log.cpp?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/source/lldb-log.cpp (original)
+++ lldb/trunk/source/lldb-log.cpp Tue Dec 7 13:58:26 2010
@@ -116,6 +116,7 @@
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 @@
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;
Modified: lldb/trunk/test/set_values/TestSetValues.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/set_values/TestSetValues.py?rev=121171&r1=121170&r2=121171&view=diff
==============================================================================
--- lldb/trunk/test/set_values/TestSetValues.py (original)
+++ lldb/trunk/test/set_values/TestSetValues.py Tue Dec 7 13:58:26 2010
@@ -78,7 +78,7 @@
startstr = "(char) i = 'a'")
# Now set variable 'i' and check that it is correctly displayed.
- self.runCmd("expression i = \\'b\\'") # Escape the single quotes.
+ self.runCmd("expression i = 'b'") # Escape the single quotes.
self.expect("frame variable -t", VARIABLES_DISPLAYED_CORRECTLY,
startstr = "(char) i = 'b'")
More information about the lldb-commits
mailing list