[Lldb-commits] [lldb] r125807 - in /lldb/trunk: include/lldb/Breakpoint/BreakpointOptions.h include/lldb/Core/StringList.h include/lldb/Interpreter/CommandInterpreter.h source/Commands/CommandObjectBreakpointCommand.cpp source/Commands/CommandObjectBreakpointCommand.h source/Commands/CommandObjectCommands.cpp source/Commands/CommandObjectImage.cpp source/Core/StringList.cpp source/Interpreter/CommandInterpreter.cpp source/Interpreter/CommandObject.cpp
Jim Ingham
jingham at apple.com
Thu Feb 17 16:54:25 PST 2011
Author: jingham
Date: Thu Feb 17 18:54:25 2011
New Revision: 125807
URL: http://llvm.org/viewvc/llvm-project?rev=125807&view=rev
Log:
Factor all the code that does "Execute a list of lldb command interpreter commands" into a single function in the Interpreter, and then use that in all the places that used to do this by hand.
Modified:
lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
lldb/trunk/include/lldb/Core/StringList.h
lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
lldb/trunk/source/Commands/CommandObjectBreakpointCommand.h
lldb/trunk/source/Commands/CommandObjectCommands.cpp
lldb/trunk/source/Commands/CommandObjectImage.cpp
lldb/trunk/source/Core/StringList.cpp
lldb/trunk/source/Interpreter/CommandInterpreter.cpp
lldb/trunk/source/Interpreter/CommandObject.cpp
Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointOptions.h Thu Feb 17 18:54:25 2011
@@ -211,7 +211,8 @@
{
CommandData () :
user_source(),
- script_source()
+ script_source(),
+ stop_on_error(true)
{
}
@@ -221,6 +222,7 @@
StringList user_source;
StringList script_source;
+ bool stop_on_error;
};
class CommandBaton : public Baton
Modified: lldb/trunk/include/lldb/Core/StringList.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StringList.h?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/StringList.h (original)
+++ lldb/trunk/include/lldb/Core/StringList.h Thu Feb 17 18:54:25 2011
@@ -12,6 +12,7 @@
#include "lldb/Core/STLUtils.h"
+#include "lldb/lldb-forward.h"
namespace lldb_private {
@@ -24,7 +25,7 @@
StringList (const char *str);
StringList (const char **strv, int strc);
-
+
virtual
~StringList ();
@@ -40,6 +41,9 @@
void
AppendList (StringList strings);
+ bool
+ ReadFileLines (FileSpec &input_file);
+
uint32_t
GetSize ();
Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Thu Feb 17 18:54:25 2011
@@ -95,7 +95,68 @@
HandleCommand (const char *command_line,
bool add_to_history,
CommandReturnObject &result,
- ExecutionContext *override_context = NULL);
+ ExecutionContext *override_context = NULL,
+ bool repeat_on_empty_command = true);
+
+ //------------------------------------------------------------------
+ /// Execute a list of commands in sequence.
+ ///
+ /// @param[in] commands
+ /// The list of commands to execute.
+ /// @param[in/out] context
+ /// The execution context in which to run the commands. Can be NULL in which case the default
+ /// context will be used.
+ /// @param[in] stop_on_continue
+ /// If \b true execution will end on the first command that causes the process in the
+ /// execution context to continue. If \false, we won't check the execution status.
+ /// @param[in] stop_on_error
+ /// If \b true execution will end on the first command that causes an error.
+ /// @param[in] echo_commands
+ /// If \b true echo the command before executing it. If \false, execute silently.
+ /// @param[in] print_results
+ /// If \b true print the results of the command after executing it. If \false, execute silently.
+ /// @param[out] result
+ /// This is marked as succeeding with no output if all commands execute safely,
+ /// and failed with some explanation if we aborted executing the commands at some point.
+ //------------------------------------------------------------------
+ void
+ HandleCommands (StringList &commands,
+ ExecutionContext *context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_commands,
+ bool print_results,
+ CommandReturnObject &result);
+
+ //------------------------------------------------------------------
+ /// Execute a list of commands from a file.
+ ///
+ /// @param[in] file
+ /// The file from which to read in commands.
+ /// @param[in/out] context
+ /// The execution context in which to run the commands. Can be NULL in which case the default
+ /// context will be used.
+ /// @param[in] stop_on_continue
+ /// If \b true execution will end on the first command that causes the process in the
+ /// execution context to continue. If \false, we won't check the execution status.
+ /// @param[in] stop_on_error
+ /// If \b true execution will end on the first command that causes an error.
+ /// @param[in] echo_commands
+ /// If \b true echo the command before executing it. If \false, execute silently.
+ /// @param[in] print_results
+ /// If \b true print the results of the command after executing it. If \false, execute silently.
+ /// @param[out] result
+ /// This is marked as succeeding with no output if all commands execute safely,
+ /// and failed with some explanation if we aborted executing the commands at some point.
+ //------------------------------------------------------------------
+ void
+ HandleCommandsFromFile (FileSpec &file,
+ ExecutionContext *context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_commands,
+ bool print_results,
+ CommandReturnObject &result);
CommandObject *
GetCommandObjectForCommand (std::string &command_line);
@@ -263,6 +324,7 @@
std::vector<std::string> m_command_history;
std::string m_repeat_command; // Stores the command that will be executed for an empty command string.
std::auto_ptr<ScriptInterpreter> m_script_interpreter_ap;
+ char m_comment_char;
};
Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.cpp Thu Feb 17 18:54:25 2011
@@ -45,20 +45,29 @@
{
}
+// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
+// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
+
+static lldb::OptionEnumValueElement
+g_script_option_enumeration[4] =
+{
+ { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
+ { eScriptLanguagePython, "python", "Commands are in the Python language."},
+ { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
+ { 0, NULL, NULL }
+};
+
lldb::OptionDefinition
CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
"Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_1, true, "script", 's', no_argument, NULL, NULL, eArgTypeNone,
- "Write the breakpoint command script in the default scripting language."},
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean,
+ "Specify whether breakpoint command execution should terminate on error." },
- { LLDB_OPT_SET_2, true, "python", 'p', no_argument, NULL, NULL, eArgTypeNone,
- "Write the breakpoint command script in the Python scripting language."},
-
- { LLDB_OPT_SET_3, true, "commands", 'c', no_argument, NULL, NULL, eArgTypeNone,
- "Write the breakpoint command script using standard debugger commands."},
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone,
+ "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
@@ -83,26 +92,42 @@
switch (short_option)
{
case 'o':
- m_use_one_liner = true;
- m_one_liner = option_arg;
- break;
+ m_use_one_liner = true;
+ m_one_liner = option_arg;
+ break;
+ break;
case 's':
- m_use_commands = false;
- m_use_script_language = true;
- m_script_language = eScriptLanguageDefault;
- break;
- case 'p':
- m_use_commands = false;
- m_use_script_language = true;
- m_script_language = eScriptLanguagePython;
- break;
- case 'c':
- m_use_commands = true;
- m_use_script_language = false;
- m_script_language = eScriptLanguageNone;
- break;
+ {
+ bool found_one = false;
+ m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
+ g_option_table[option_idx].enum_values,
+ eScriptLanguageNone,
+ &found_one);
+ if (!found_one)
+ error.SetErrorStringWithFormat("Invalid enumeration value '%s' for option '%c'.\n",
+ option_arg,
+ short_option);
+
+ if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
+ {
+ m_use_commands = false;
+ m_use_script_language = true;
+ }
+ else
+ {
+ m_use_commands = true;
+ m_use_script_language = false;
+ }
+ }
+ break;
+ case 'e':
+ bool success_ptr;
+ m_stop_on_error = Args::StringToBoolean(option_arg, false, &success_ptr);
+ if (!success_ptr)
+ error.SetErrorStringWithFormat("Invalid value for stop-on-error: \"%s\".\n", option_arg);
+ break;
default:
- break;
+ break;
}
return error;
}
@@ -112,11 +137,12 @@
{
Options::ResetOptionValues();
- m_use_commands = false;
+ m_use_commands = true;
m_use_script_language = false;
m_script_language = eScriptLanguageNone;
m_use_one_liner = false;
+ m_stop_on_error = true;
m_one_liner.clear();
}
@@ -173,13 +199,13 @@
\n\
Example Python one-line breakpoint command: \n\
\n\
-(lldb) breakpoint command add -p 1 \n\
+(lldb) breakpoint command add -s python 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> print \"Hit this breakpoint!\" \n\
> DONE \n\
\n\
As a convenience, this also works for a short Python one-liner: \n\
-(lldb) breakpoint command add -p 1 -o \"import time; print time.asctime()\" \n\
+(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
(lldb) run \n\
Launching '.../a.out' (x86_64) \n\
(lldb) Fri Sep 10 12:17:45 2010 \n\
@@ -196,7 +222,7 @@
\n\
Example multiple line Python breakpoint command, using function definition: \n\
\n\
-(lldb) breakpoint command add -p 1 \n\
+(lldb) breakpoint command add -s python 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> def breakpoint_output (bp_no): \n\
> out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
@@ -208,7 +234,7 @@
\n\
Example multiple line Python breakpoint command, using 'loose' Python: \n\
\n\
-(lldb) breakpoint command add -p 1 \n\
+(lldb) breakpoint command add -s p 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> global bp_count \n\
> bp_count = bp_count + 1 \n\
@@ -309,7 +335,7 @@
bp_options = bp_loc_sp->GetLocationOptions();
}
- // Skip this breakpoiont if bp_options is not good.
+ // Skip this breakpoint if bp_options is not good.
if (bp_options == NULL) continue;
// If we are using script language, get the script interpreter
@@ -401,6 +427,7 @@
// while the latter is used for Python to interpret during the actual callback.
data_ap->user_source.AppendString (oneliner);
data_ap->script_source.AppendString (oneliner);
+ data_ap->stop_on_error = m_options.m_stop_on_error;
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
@@ -686,7 +713,9 @@
if (bp_options)
{
StreamString id_str;
- BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
+ BreakpointID::GetCanonicalReference (&id_str,
+ cur_bp_id.GetBreakpointID(),
+ cur_bp_id.GetLocationID());
const Baton *baton = bp_options->GetBaton();
if (baton)
{
@@ -697,7 +726,8 @@
}
else
{
- result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n", id_str.GetData());
+ result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
+ id_str.GetData());
}
}
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -763,55 +793,31 @@
if (commands.GetSize() > 0)
{
- uint32_t num_commands = commands.GetSize();
CommandReturnObject result;
if (context->exe_ctx.target)
{
Debugger &debugger = context->exe_ctx.target->GetDebugger();
- CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
-
- File &out_file = debugger.GetOutputFile();
- File &err_file = debugger.GetErrorFile();
-
- uint32_t i;
- for (i = 0; i < num_commands; ++i)
+
+ bool stop_on_continue = true;
+ bool echo_commands = false;
+ bool print_results = true;
+
+ debugger.GetCommandInterpreter().HandleCommands (commands,
+ &(context->exe_ctx),
+ stop_on_continue,
+ data->stop_on_error,
+ echo_commands,
+ print_results,
+ result);
+ // Now dump the commands to the debugger's output:
+ if (!result.Succeeded())
{
-
- // First time through we use the context from the stoppoint, after that we use whatever
- // has been set by the previous command.
-
- if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &context->exe_ctx))
- break;
-
- // FIXME: This isn't really the right way to do this. We should be able to peek at the public
- // to see if there is any new events, but that is racey, since the internal process thread has to run and
- // deliver the event to the public queue before a run will show up. So for now we check
- // the internal thread state.
-
- lldb::StateType internal_state = context->exe_ctx.process->GetPrivateState();
- if (internal_state != eStateStopped)
- {
- if (i < num_commands - 1)
- {
- out_file.Printf ("Short-circuiting command execution because target state changed to %s."
- " last command: \"%s\"\n", StateAsCString(internal_state),
- commands.GetStringAtIndex(i));
- }
- break;
- }
-
- out_file.Printf ("%s", result.GetErrorStream().GetData());
- err_file.Printf ("%s", result.GetOutputStream().GetData());
- result.Clear();
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ debugger.GetErrorFile().Printf ("%s", result.GetErrorStream().GetData());
}
+
+ debugger.GetOutputFile().Printf ("%s", result.GetOutputStream().GetData());
- if (!result.Succeeded() && i < num_commands)
- err_file.Printf ("Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
-
- out_file.Printf ("%s", result.GetErrorStream().GetData());
- err_file.Printf ("%s", result.GetOutputStream().GetData());
}
}
return ret_value;
Modified: lldb/trunk/source/Commands/CommandObjectBreakpointCommand.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectBreakpointCommand.h?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectBreakpointCommand.h (original)
+++ lldb/trunk/source/Commands/CommandObjectBreakpointCommand.h Thu Feb 17 18:54:25 2011
@@ -122,6 +122,7 @@
// Instance variables to hold the values for one_liner options.
bool m_use_one_liner;
std::string m_one_liner;
+ bool m_stop_on_error;
};
private:
Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Thu Feb 17 18:54:25 2011
@@ -22,14 +22,87 @@
using namespace lldb;
using namespace lldb_private;
-const char *k_space_characters = "\t\n\v\f\r ";
-
//-------------------------------------------------------------------------
// CommandObjectCommandsSource
//-------------------------------------------------------------------------
class CommandObjectCommandsSource : public CommandObject
{
+private:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (){}
+
+ virtual
+ ~CommandOptions (){}
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ bool success;
+
+ switch (short_option)
+ {
+ case 'e':
+ m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
+ break;
+ case 'c':
+ m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+
+ m_stop_on_error = true;
+ m_stop_on_continue = true;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_stop_on_error;
+ bool m_stop_on_continue;
+ };
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ CommandOptions m_options;
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
public:
CommandObjectCommandsSource(CommandInterpreter &interpreter) :
CommandObject (interpreter,
@@ -66,68 +139,21 @@
if (argc == 1)
{
const char *filename = args.GetArgumentAtIndex(0);
- bool success = true;
result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
FileSpec cmd_file (filename, true);
- if (cmd_file.Exists())
- {
- STLStringArray commands;
- success = cmd_file.ReadFileLines (commands);
-
- STLStringArray::iterator pos = commands.begin();
-
- // Trim out any empty lines or lines that start with the comment
- // char '#'
- while (pos != commands.end())
- {
- size_t non_space = pos->find_first_not_of (k_space_characters);
- // Check for empty line or comment line (lines whose first
- // non-space character is a '#')
- if (non_space == std::string::npos || (*pos)[non_space] == '#')
- pos = commands.erase(pos);
- else
- ++pos;
- }
-
- if (commands.size() > 0)
- {
- const size_t num_commands = commands.size();
- size_t i;
- for (i = 0; i<num_commands; ++i)
- {
- result.GetOutputStream().Printf ("%s %s\n",
- m_interpreter.GetPrompt(),
- commands[i].c_str());
- if (!m_interpreter.HandleCommand(commands[i].c_str(), false, result))
- break;
- }
-
- if (i < num_commands)
- {
- result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n",
- filename, commands[i].c_str());
- result.SetStatus (eReturnStatusSuccessFinishResult);
- }
- else
- {
- success = true;
- result.SetStatus (eReturnStatusFailed);
- }
- }
- }
- else
- {
- result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
- result.SetStatus (eReturnStatusFailed);
- success = false;
- }
-
- if (success)
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
+ ExecutionContext *exe_ctx = NULL; // Just use the default context.
+ bool echo_commands = true;
+ bool print_results = true;
+
+ m_interpreter.HandleCommandsFromFile (cmd_file,
+ exe_ctx,
+ m_options.m_stop_on_continue,
+ m_options.m_stop_on_error,
+ echo_commands,
+ print_results,
+ result);
}
else
{
@@ -139,6 +165,14 @@
}
};
+lldb::OptionDefinition
+CommandObjectCommandsSource::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
+{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
+{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
#pragma mark CommandObjectCommandsAlias
//-------------------------------------------------------------------------
// CommandObjectCommandsAlias
Modified: lldb/trunk/source/Commands/CommandObjectImage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectImage.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectImage.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectImage.cpp Thu Feb 17 18:54:25 2011
@@ -784,7 +784,7 @@
CommandOptions m_options;
};
-lldb::OptionEnumValueElement
+static lldb::OptionEnumValueElement
g_sort_option_enumeration[4] =
{
{ eSortOrderNone, "none", "No sorting, use the original symbol table order."},
Modified: lldb/trunk/source/Core/StringList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StringList.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Core/StringList.cpp (original)
+++ lldb/trunk/source/Core/StringList.cpp Thu Feb 17 18:54:25 2011
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/StringList.h"
+#include "lldb/Host/FileSpec.h"
#include <string>
@@ -72,6 +73,12 @@
m_strings.push_back (strings.GetStringAtIndex(i));
}
+bool
+StringList::ReadFileLines (FileSpec &input_file)
+{
+ return input_file.ReadFileLines (m_strings);
+}
+
uint32_t
StringList::GetSize ()
{
Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Thu Feb 17 18:54:25 2011
@@ -67,7 +67,8 @@
m_debugger (debugger),
m_synchronous_execution (synchronous_execution),
m_skip_lldbinit_files (false),
- m_script_interpreter_ap ()
+ m_script_interpreter_ap (),
+ m_comment_char ('#')
{
const char *dbg_name = debugger.GetInstanceName().AsCString();
std::string lang_name = ScriptInterpreter::LanguageToString (script_language);
@@ -700,8 +701,11 @@
CommandInterpreter::HandleCommand (const char *command_line,
bool add_to_history,
CommandReturnObject &result,
- ExecutionContext *override_context)
+ ExecutionContext *override_context,
+ bool repeat_on_empty_command)
+
{
+
bool done = false;
CommandObject *cmd_obj = NULL;
std::string next_word;
@@ -722,26 +726,56 @@
m_debugger.UpdateExecutionContext (override_context);
- if (command_line == NULL || command_line[0] == '\0')
+ bool empty_command = false;
+ bool comment_command = false;
+ if (command_string.empty())
+ empty_command = true;
+ else
{
- if (m_command_history.empty())
- {
- result.AppendError ("empty command");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- else
+ const char *k_space_characters = "\t\n\v\f\r ";
+
+ size_t non_space = command_string.find_first_not_of (k_space_characters);
+ // Check for empty line or comment line (lines whose first
+ // non-space character is the comment character for this interpreter)
+ if (non_space == std::string::npos)
+ empty_command = true;
+ else if (command_string[non_space] == m_comment_char)
+ comment_command = true;
+ }
+
+ if (empty_command)
+ {
+ if (repeat_on_empty_command)
{
- command_line = m_repeat_command.c_str();
- command_string = command_line;
- if (m_repeat_command.empty())
+ if (m_command_history.empty())
{
- result.AppendErrorWithFormat("No auto repeat.\n");
- result.SetStatus (eReturnStatusFailed);
+ result.AppendError ("empty command");
+ result.SetStatus(eReturnStatusFailed);
return false;
}
+ else
+ {
+ command_line = m_repeat_command.c_str();
+ command_string = command_line;
+ if (m_repeat_command.empty())
+ {
+ result.AppendErrorWithFormat("No auto repeat.\n");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ add_to_history = false;
}
- add_to_history = false;
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ }
+ else if (comment_command)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
}
// Phase 1.
@@ -1458,11 +1492,13 @@
if (init_file.Exists())
{
- char path[PATH_MAX];
- init_file.GetPath(path, sizeof(path));
- StreamString source_command;
- source_command.Printf ("command source '%s'", path);
- HandleCommand (source_command.GetData(), false, result);
+ ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
+ bool stop_on_continue = true;
+ bool stop_on_error = false;
+ bool echo_commands = false;
+ bool print_results = false;
+
+ HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, result);
}
else
{
@@ -1471,6 +1507,138 @@
}
}
+void
+CommandInterpreter::HandleCommands (StringList &commands,
+ ExecutionContext *override_context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_commands,
+ bool print_results,
+ CommandReturnObject &result)
+{
+ size_t num_lines = commands.GetSize();
+ CommandReturnObject tmp_result;
+
+ // If we are going to continue past a "continue" then we need to run the commands synchronously.
+ // Make sure you reset this value anywhere you return from the function.
+
+ bool old_async_execution = m_debugger.GetAsyncExecution();
+
+ // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
+ // cause series of commands that change the context, then do an operation that relies on that context to fail.
+
+ if (override_context != NULL)
+ m_debugger.UpdateExecutionContext (override_context);
+
+ if (!stop_on_continue)
+ {
+ m_debugger.SetAsyncExecution (false);
+ }
+
+ for (int idx = 0; idx < num_lines; idx++)
+ {
+ const char *cmd = commands.GetStringAtIndex(idx);
+ if (cmd[0] == '\0')
+ continue;
+
+ tmp_result.Clear();
+ if (echo_commands)
+ {
+ result.AppendMessageWithFormat ("%s %s\n",
+ GetPrompt(),
+ cmd);
+ }
+
+ bool success = HandleCommand(cmd, false, tmp_result, NULL);
+
+ if (print_results)
+ {
+ if (tmp_result.Succeeded())
+ result.AppendMessageWithFormat("%s", tmp_result.GetOutputStream().GetData());
+ }
+
+ if (!success || !tmp_result.Succeeded())
+ {
+ if (stop_on_error)
+ {
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' failed.\n",
+ idx, cmd);
+ result.SetStatus (eReturnStatusFailed);
+ m_debugger.SetAsyncExecution (old_async_execution);
+ return;
+ }
+ else if (print_results)
+ {
+ result.AppendMessageWithFormat ("Command #%d '%s' failed with error: %s.\n",
+ idx + 1,
+ cmd,
+ tmp_result.GetErrorStream().GetData());
+ }
+ }
+
+ // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
+ // could be running (for instance in Breakpoint Commands.
+ // So we check the return value to see if it is has running in it.
+ if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
+ || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
+ {
+ if (stop_on_continue)
+ {
+ // If we caused the target to proceed, and we're going to stop in that case, set the
+ // status in our real result before returning. This is an error if the continue was not the
+ // last command in the set of commands to be run.
+ if (idx != num_lines - 1)
+ result.AppendErrorWithFormat("Aborting reading of commands after command #%d: '%s' continued the target.\n",
+ idx + 1, cmd);
+ else
+ result.AppendMessageWithFormat ("Command #%d '%s' continued the target.\n", idx + 1, cmd);
+
+ result.SetStatus(tmp_result.GetStatus());
+ m_debugger.SetAsyncExecution (old_async_execution);
+
+ return;
+ }
+ }
+
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ m_debugger.SetAsyncExecution (old_async_execution);
+
+ return;
+}
+
+void
+CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
+ ExecutionContext *context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_command,
+ bool print_result,
+ CommandReturnObject &result)
+{
+ if (cmd_file.Exists())
+ {
+ bool success;
+ StringList commands;
+ success = commands.ReadFileLines(cmd_file);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+ HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, result);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
+ cmd_file.GetFilename().AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return;
+ }
+}
+
ScriptInterpreter *
CommandInterpreter::GetScriptInterpreter ()
{
Modified: lldb/trunk/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=125807&r1=125806&r2=125807&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObject.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Feb 17 18:54:25 2011
@@ -616,7 +616,7 @@
{ eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
{ eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
{ eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, NULL, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
- { eArgTypeFilename, "filename", CommandCompletions::eNoCompletion, NULL, "The name of a file (can include path)." },
+ { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, NULL, "The name of a file (can include path)." },
{ eArgTypeFormat, "format", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
{ eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, NULL, "Index into a thread's list of frames." },
{ eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
More information about the lldb-commits
mailing list