summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r--lldb/source/Commands/CMakeLists.txt1
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp156
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.h1
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp450
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp170
-rw-r--r--lldb/source/Commands/CommandObjectExpression.h28
-rw-r--r--lldb/source/Commands/CommandObjectGUI.cpp56
-rw-r--r--lldb/source/Commands/CommandObjectGUI.h43
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp43
-rw-r--r--lldb/source/Commands/CommandObjectQuit.cpp3
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp156
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp729
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.cpp158
-rw-r--r--lldb/source/Commands/CommandObjectWatchpointCommand.h3
14 files changed, 841 insertions, 1156 deletions
diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt
index 1f287d57243..cee8146bee2 100644
--- a/lldb/source/Commands/CMakeLists.txt
+++ b/lldb/source/Commands/CMakeLists.txt
@@ -10,6 +10,7 @@ add_lldb_library(lldbCommands
CommandObjectDisassemble.cpp
CommandObjectExpression.cpp
CommandObjectFrame.cpp
+ CommandObjectGUI.cpp
CommandObjectHelp.cpp
CommandObjectLog.cpp
CommandObjectMemory.cpp
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
index e540461dada..532d6cedc83 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -16,6 +16,7 @@
#include "CommandObjectBreakpointCommand.h"
#include "CommandObjectBreakpoint.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
@@ -34,7 +35,9 @@ using namespace lldb_private;
//-------------------------------------------------------------------------
-class CommandObjectBreakpointCommandAdd : public CommandObjectParsed
+class CommandObjectBreakpointCommandAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
public:
@@ -43,6 +46,7 @@ public:
"add",
"Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
NULL),
+ IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong (
@@ -207,42 +211,47 @@ one command per line.\n" );
return &m_options;
}
- void
- CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
- CommandReturnObject &result)
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
{
- InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
- std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
- if (reader_sp && data_ap.get())
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
{
- BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
- bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
-
- Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
- bp_options, // baton
- eInputReaderGranularityLine, // token size, to pass to callback function
- "DONE", // end token
- "> ", // prompt
- true)); // echo input
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
+ output_sp->PutCString(g_reader_instructions);
+ output_sp->Flush();
}
- else
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ {
+ io_handler.SetIsDone(true);
+
+ BreakpointOptions *bp_options = (BreakpointOptions *) io_handler.GetUserData();
+ if (bp_options)
{
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ if (data_ap.get())
+ {
+ data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+ }
}
}
+ void
+ CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CommandReturnObject &result)
+ {
+ m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ bp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ }
+
/// Set a one-liner as the callback for the breakpoint.
void
SetBreakpointCommandCallback (BreakpointOptions *bp_options,
@@ -262,93 +271,6 @@ one command per line.\n" );
return;
}
-
- static size_t
- GenerateBreakpointCommandCallback (void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len)
- {
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
- switch (notification)
- {
- case eInputReaderActivate:
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", g_reader_instructions);
- if (reader.GetPrompt())
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderReactivate:
- if (reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
-
- case eInputReaderGotToken:
- if (bytes && bytes_len && baton)
- {
- BreakpointOptions *bp_options = (BreakpointOptions *) baton;
- if (bp_options)
- {
- Baton *bp_options_baton = bp_options->GetBaton();
- if (bp_options_baton)
- ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
- }
- }
- if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderInterrupt:
- {
- // Finish, and cancel the breakpoint command.
- reader.SetIsDone (true);
- BreakpointOptions *bp_options = (BreakpointOptions *) baton;
- if (bp_options)
- {
- Baton *bp_options_baton = bp_options->GetBaton ();
- if (bp_options_baton)
- {
- ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
- ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
- }
- }
- if (!batch_mode)
- {
- out_stream->Printf ("Warning: No command attached to breakpoint.\n");
- out_stream->Flush();
- }
- }
- break;
-
- case eInputReaderEndOfFile:
- reader.SetIsDone (true);
- break;
-
- case eInputReaderDone:
- break;
- }
-
- return bytes_len;
- }
static bool
BreakpointOptionsCallbackFunction (void *baton,
@@ -623,7 +545,7 @@ private:
};
const char *
-CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
+CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n";
// 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.
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h
index afedb7602cd..e9179077951 100644
--- a/lldb/source/Commands/CommandObjectBreakpointCommand.h
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h
@@ -19,7 +19,6 @@
#include "lldb/lldb-types.h"
#include "lldb/Interpreter/Options.h"
-#include "lldb/Core/InputReader.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 6824ead0d9e..9cd89b4870b 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -18,8 +18,7 @@
// Project includes
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
-#include "lldb/Core/InputReaderEZ.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Core/StringList.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandHistory.h"
@@ -379,7 +378,8 @@ protected:
{
const char *filename = command.GetArgumentAtIndex(0);
- result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
+ if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
+ result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
FileSpec cmd_file (filename, true);
ExecutionContext *exe_ctx = NULL; // Just use the default context.
@@ -423,7 +423,7 @@ CommandObjectCommandsSource::CommandOptions::g_option_table[] =
static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
"You must define a Python function with this signature:\n"
- "def my_command_impl(debugger, args, result, internal_dict):";
+ "def my_command_impl(debugger, args, result, internal_dict):\n";
class CommandObjectCommandsAlias : public CommandObjectRaw
@@ -856,7 +856,9 @@ protected:
//-------------------------------------------------------------------------
#pragma mark CommandObjectCommandsAddRegex
-class CommandObjectCommandsAddRegex : public CommandObjectParsed
+class CommandObjectCommandsAddRegex :
+ public CommandObjectParsed,
+ public IOHandlerDelegate
{
public:
CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
@@ -864,6 +866,7 @@ public:
"command regex",
"Allow the user to create a regular expression command.",
"command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
+ IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong(
@@ -899,6 +902,97 @@ public:
protected:
+
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
+ {
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n");
+ output_sp->Flush();
+ }
+ }
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ {
+ io_handler.SetIsDone(true);
+ if (m_regex_cmd_ap.get())
+ {
+ StringList lines;
+ if (lines.SplitIntoLines (data))
+ {
+ const size_t num_lines = lines.GetSize();
+ bool check_only = false;
+ for (size_t i=0; i<num_lines; ++i)
+ {
+ printf ("regex[%zu] = %s\n", i, lines[i].c_str());
+ llvm::StringRef bytes_strref (lines[i]);
+ Error error = AppendRegexSubstitution (bytes_strref, check_only);
+ if (error.Fail())
+ {
+ if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
+ {
+ StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
+ out_stream->Printf("error: %s\n", error.AsCString());
+ }
+ }
+ }
+ }
+ if (m_regex_cmd_ap->HasRegexEntries())
+ {
+ CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
+ m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
+ }
+ }
+ }
+
+ virtual LineStatus
+ IOHandlerLinesUpdated (IOHandler &io_handler,
+ StringList &lines,
+ uint32_t line_idx,
+ Error &error)
+ {
+ if (line_idx == UINT32_MAX)
+ {
+ // Return true to indicate we are done getting lines (this
+ // is a "fake" line - the real terminating blank line was
+ // removed during a previous call with the code below)
+ error.Clear();
+ return LineStatus::Done;
+ }
+ else
+ {
+ const size_t num_lines = lines.GetSize();
+ if (line_idx + 1 == num_lines)
+ {
+ // The last line was edited, if this line is empty, then we are done
+ // getting our multiple lines.
+ if (lines[line_idx].empty())
+ {
+ // Remove the last empty line from "lines" so it doesn't appear
+ // in our final expression and return true to indicate we are done
+ // getting lines
+ lines.PopBack();
+ return LineStatus::Done;
+ }
+ }
+ // Check the current line to make sure it is formatted correctly
+ bool check_only = true;
+ llvm::StringRef regex_sed(lines[line_idx]);
+ error = AppendRegexSubstitution (regex_sed, check_only);
+ if (error.Fail())
+ {
+ return LineStatus::Error;
+ }
+ else
+ {
+ return LineStatus::Success;
+ }
+ }
+ }
+
bool
DoExecute (Args& command, CommandReturnObject &result)
{
@@ -920,21 +1014,18 @@ protected:
if (argc == 1)
{
- InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
- if (reader_sp)
+ Debugger &debugger = m_interpreter.GetDebugger();
+ const bool multiple_lines = true; // Get multiple lines
+ IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ "lldb", // Name of input reader for history
+ "\033[K> ", // Prompt and clear line
+ multiple_lines,
+ *this));
+
+ if (io_handler_sp)
{
- error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
- this, // baton
- eInputReaderGranularityLine, // token size, to pass to callback function
- NULL, // end token
- "> ", // prompt
- true); // echo input
- if (error.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- return true;
- }
+ debugger.PushIOHandler(io_handler_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
}
else
@@ -942,7 +1033,8 @@ protected:
for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
{
llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
- error = AppendRegexSubstitution (arg_strref);
+ bool check_only = false;
+ error = AppendRegexSubstitution (arg_strref, check_only);
if (error.Fail())
break;
}
@@ -963,7 +1055,7 @@ protected:
}
Error
- AppendRegexSubstitution (const llvm::StringRef &regex_sed)
+ AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
{
Error error;
@@ -1053,10 +1145,14 @@ protected:
regex_sed.data());
return error;
}
- std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
- std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
- m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
- subst.c_str());
+
+ if (check_only == false)
+ {
+ std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
+ std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
+ m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
+ subst.c_str());
+ }
return error;
}
@@ -1073,89 +1169,6 @@ protected:
}
}
- void
- InputReaderDidCancel()
- {
- m_regex_cmd_ap.reset();
- }
-
- static size_t
- InputReaderCallback (void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len)
- {
- CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
- switch (notification)
- {
- case eInputReaderActivate:
- if (!batch_mode)
- {
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
- out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
- out_stream->Flush();
- }
- break;
- case eInputReaderReactivate:
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
-
- case eInputReaderGotToken:
- while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
- --bytes_len;
- if (bytes_len == 0)
- reader.SetIsDone(true);
- else if (bytes)
- {
- llvm::StringRef bytes_strref (bytes, bytes_len);
- Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
- if (error.Fail())
- {
- if (!batch_mode)
- {
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- out_stream->Printf("error: %s\n", error.AsCString());
- out_stream->Flush();
- }
- add_regex_cmd->InputReaderDidCancel ();
- reader.SetIsDone (true);
- }
- }
- break;
-
- case eInputReaderInterrupt:
- {
- reader.SetIsDone (true);
- if (!batch_mode)
- {
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- out_stream->PutCString("Regular expression command creations was cancelled.\n");
- out_stream->Flush();
- }
- add_regex_cmd->InputReaderDidCancel ();
- }
- break;
-
- case eInputReaderEndOfFile:
- reader.SetIsDone (true);
- break;
-
- case eInputReaderDone:
- add_regex_cmd->AddRegexCommandToInterpreter();
- break;
- }
-
- return bytes_len;
- }
-
private:
std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
@@ -1526,7 +1539,9 @@ CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
// CommandObjectCommandsScriptAdd
//-------------------------------------------------------------------------
-class CommandObjectCommandsScriptAdd : public CommandObjectParsed
+class CommandObjectCommandsScriptAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
public:
CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
@@ -1534,6 +1549,7 @@ public:
"command script add",
"Add a scripted function as an LLDB command.",
NULL),
+ IOHandlerDelegateMultiline ("DONE"),
m_options (interpreter)
{
CommandArgumentEntry arg1;
@@ -1567,7 +1583,7 @@ protected:
public:
CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
+ Options (interpreter)
{
}
@@ -1586,7 +1602,7 @@ protected:
m_funct_name = std::string(option_arg);
break;
case 's':
- m_synchronous = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
+ m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
if (!error.Success())
error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
break;
@@ -1602,7 +1618,7 @@ protected:
OptionParsingStarting ()
{
m_funct_name = "";
- m_synchronous = eScriptedCommandSynchronicitySynchronous;
+ m_synchronicity = eScriptedCommandSynchronicitySynchronous;
}
const OptionDefinition*
@@ -1618,128 +1634,81 @@ protected:
// Instance variables to hold the values for command options.
std::string m_funct_name;
- ScriptedCommandSynchronicity m_synchronous;
+ ScriptedCommandSynchronicity m_synchronicity;
};
-private:
- class PythonAliasReader : public InputReaderEZ
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
{
- private:
- CommandInterpreter& m_interpreter;
- std::string m_cmd_name;
- ScriptedCommandSynchronicity m_synchronous;
- StringList m_user_input;
- DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
- public:
- PythonAliasReader(Debugger& debugger,
- CommandInterpreter& interpreter,
- std::string cmd_name,
- ScriptedCommandSynchronicity synch) :
- InputReaderEZ(debugger),
- m_interpreter(interpreter),
- m_cmd_name(cmd_name),
- m_synchronous(synch),
- m_user_input()
- {}
-
- virtual
- ~PythonAliasReader()
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
{
+ output_sp->PutCString(g_python_command_instructions);
+ output_sp->Flush();
}
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
- virtual void ActivateHandler(HandlerData& data)
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+ if (interpreter)
{
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", g_python_command_instructions);
- if (data.reader.GetPrompt())
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void ReactivateHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (data.reader.GetPrompt() && !batch_mode)
+ StringList lines;
+ lines.SplitIntoLines(data);
+ if (lines.GetSize() > 0)
{
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void GotTokenHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (data.bytes && data.bytes_len)
- {
- m_user_input.AppendString(data.bytes, data.bytes_len);
- }
- if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
+ std::string funct_name_str;
+ if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
+ {
+ if (funct_name_str.empty())
+ {
+ error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
+ error_sp->Flush();
+ }
+ else
+ {
+ // everything should be fine now, let's add this alias
+
+ CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
+ m_cmd_name,
+ funct_name_str.c_str(),
+ m_synchronicity));
+
+ if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
+ {
+ error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
+ error_sp->Flush();
+ }
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: unable to create function, didn't add python command.\n");
+ error_sp->Flush();
+ }
}
- }
- virtual void InterruptHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- data.reader.SetIsDone (true);
- if (!batch_mode)
+ else
{
- out_stream->Printf ("Warning: No script attached.\n");
- out_stream->Flush();
+ error_sp->Printf ("error: empty function, didn't add python command.\n");
+ error_sp->Flush();
}
}
- virtual void EOFHandler(HandlerData& data)
- {
- data.reader.SetIsDone (true);
- }
- virtual void DoneHandler(HandlerData& data)
+ else
{
- StreamSP out_stream = data.GetOutStream();
-
- ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (!interpreter)
- {
- out_stream->Printf ("Script interpreter missing: no script attached.\n");
- out_stream->Flush();
- return;
- }
- std::string funct_name_str;
- if (!interpreter->GenerateScriptAliasFunction (m_user_input,
- funct_name_str))
- {
- out_stream->Printf ("Unable to create function: no script attached.\n");
- out_stream->Flush();
- return;
- }
- if (funct_name_str.empty())
- {
- out_stream->Printf ("Unable to obtain a function name: no script attached.\n");
- out_stream->Flush();
- return;
- }
- // everything should be fine now, let's add this alias
-
- CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
- m_cmd_name,
- funct_name_str.c_str(),
- m_synchronous));
-
- if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
- {
- out_stream->Printf ("Unable to add selected command: no script attached.\n");
- out_stream->Flush();
- return;
- }
+ error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+ error_sp->Flush();
}
- };
-
+
+ io_handler.SetIsDone(true);
+
+
+ }
+
protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
@@ -1761,45 +1730,24 @@ protected:
return false;
}
- std::string cmd_name = command.GetArgumentAtIndex(0);
+ // Store the command name and synchronicity in case we get multi-line input
+ m_cmd_name = command.GetArgumentAtIndex(0);
+ m_synchronicity = m_options.m_synchronicity;
if (m_options.m_funct_name.empty())
{
- InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
- m_interpreter,
- cmd_name,
- m_options.m_synchronous));
-
- if (reader_sp)
- {
-
- InputReaderEZ::InitializationParameters ipr;
-
- Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- else
- {
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
- }
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
}
else
{
CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
- cmd_name,
+ m_cmd_name,
m_options.m_funct_name,
- m_options.m_synchronous));
- if (m_interpreter.AddUserCommand(cmd_name, new_cmd, true))
+ m_synchronicity));
+ if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
@@ -1815,6 +1763,8 @@ protected:
}
CommandOptions m_options;
+ std::string m_cmd_name;
+ ScriptedCommandSynchronicity m_synchronicity;
};
static OptionEnumValueElement g_script_synchro_type[] =
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 18d144c57a1..b3651640ec0 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -17,7 +17,6 @@
// Project includes
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Value.h"
-#include "lldb/Core/InputReader.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/ClangExpressionVariable.h"
@@ -197,6 +196,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
"Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
NULL,
eFlagProcessMustBePaused | eFlagTryTargetAPILock),
+ IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
m_option_group (interpreter),
m_format_options (eFormatDefault),
m_command_options (),
@@ -254,87 +254,6 @@ CommandObjectExpression::GetOptions ()
return &m_option_group;
}
-size_t
-CommandObjectExpression::MultiLineExpressionCallback
-(
- void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len
-)
-{
- CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
- switch (notification)
- {
- case eInputReaderActivate:
- if (!batch_mode)
- {
- StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
- if (async_strm_sp)
- {
- async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
- async_strm_sp->Flush();
- }
- }
- // Fall through
- case eInputReaderReactivate:
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
-
- case eInputReaderGotToken:
- ++cmd_object_expr->m_expr_line_count;
- if (bytes && bytes_len)
- {
- cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
- }
-
- if (bytes_len == 0)
- reader.SetIsDone(true);
- break;
-
- case eInputReaderInterrupt:
- cmd_object_expr->m_expr_lines.clear();
- reader.SetIsDone (true);
- if (!batch_mode)
- {
- StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
- if (async_strm_sp)
- {
- async_strm_sp->PutCString("Expression evaluation cancelled.\n");
- async_strm_sp->Flush();
- }
- }
- break;
-
- case eInputReaderEndOfFile:
- reader.SetIsDone (true);
- break;
-
- case eInputReaderDone:
- if (cmd_object_expr->m_expr_lines.size() > 0)
- {
- StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream();
- StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream();
- cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(),
- output_stream.get(),
- error_stream.get());
- output_stream->Flush();
- error_stream->Flush();
- }
- break;
- }
-
- return bytes_len;
-}
-
bool
CommandObjectExpression::EvaluateExpression
(
@@ -445,6 +364,60 @@ CommandObjectExpression::EvaluateExpression
return true;
}
+void
+CommandObjectExpression::IOHandlerActivated (IOHandler &io_handler)
+{
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
+ output_sp->Flush();
+ }
+}
+
+
+void
+CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+{
+ io_handler.SetIsDone(true);
+// StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
+// StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+
+ EvaluateExpression (line.c_str(),
+ output_sp.get(),
+ error_sp.get());
+ if (output_sp)
+ output_sp->Flush();
+ if (error_sp)
+ error_sp->Flush();
+}
+
+LineStatus
+CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
+ StringList &lines,
+ uint32_t line_idx,
+ Error &error)
+{
+ if (line_idx == UINT32_MAX)
+ {
+ // Remove the last line from "lines" so it doesn't appear
+ // in our final expression
+ lines.PopBack();
+ error.Clear();
+ return LineStatus::Done;
+ }
+ else if (line_idx + 1 == lines.GetSize())
+ {
+ // The last line was edited, if this line is empty, then we are done
+ // getting our multiple lines.
+ if (lines[line_idx].empty())
+ return LineStatus::Done;
+ }
+ return LineStatus::Success;
+}
+
bool
CommandObjectExpression::DoExecute
(
@@ -461,31 +434,14 @@ CommandObjectExpression::DoExecute
m_expr_lines.clear();
m_expr_line_count = 0;
- InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
- if (reader_sp)
- {
- Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
- this, // baton
- eInputReaderGranularityLine, // token size, to pass to callback function
- NULL, // end token
- NULL, // prompt
- true)); // echo input
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- else
- {
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
- }
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+ const bool multiple_lines = true; // Get multiple lines
+ IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
+ "lldb-expr", // Name of input reader for history
+ NULL, // No prompt
+ multiple_lines,
+ *this));
+ debugger.PushIOHandler(io_handler_sp);
return result.Succeeded();
}
diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h
index e0703a22a4c..4b5162fc67f 100644
--- a/lldb/source/Commands/CommandObjectExpression.h
+++ b/lldb/source/Commands/CommandObjectExpression.h
@@ -14,6 +14,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
@@ -21,7 +22,9 @@
namespace lldb_private {
-class CommandObjectExpression : public CommandObjectRaw
+class CommandObjectExpression :
+ public CommandObjectRaw,
+ public IOHandlerDelegate
{
public:
@@ -71,17 +74,26 @@ public:
GetOptions ();
protected:
+
+ //------------------------------------------------------------------
+ // IOHandler::Delegate functions
+ //------------------------------------------------------------------
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler);
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler,
+ std::string &line);
+
+ virtual LineStatus
+ IOHandlerLinesUpdated (IOHandler &io_handler,
+ StringList &lines,
+ uint32_t line_idx,
+ Error &error);
virtual bool
DoExecute (const char *command,
CommandReturnObject &result);
- static size_t
- MultiLineExpressionCallback (void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len);
-
bool
EvaluateExpression (const char *expr,
Stream *output_stream,
diff --git a/lldb/source/Commands/CommandObjectGUI.cpp b/lldb/source/Commands/CommandObjectGUI.cpp
new file mode 100644
index 00000000000..0fe6cdcd8b0
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectGUI.cpp
@@ -0,0 +1,56 @@
+//===-- CommandObjectGUI.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "CommandObjectGUI.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectGUI
+//-------------------------------------------------------------------------
+
+CommandObjectGUI::CommandObjectGUI (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter, "gui", "Switch into the curses based GUI mode.", "gui")
+{
+}
+
+CommandObjectGUI::~CommandObjectGUI ()
+{
+}
+
+bool
+CommandObjectGUI::DoExecute (Args& args, CommandReturnObject &result)
+{
+ if (args.GetArgumentCount() == 0)
+ {
+ Debugger &debugger = m_interpreter.GetDebugger();
+ IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger));
+ if (io_handler_sp)
+ debugger.PushIOHandler(io_handler_sp);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError("the gui command takes no arguments.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return true;
+}
+
diff --git a/lldb/source/Commands/CommandObjectGUI.h b/lldb/source/Commands/CommandObjectGUI.h
new file mode 100644
index 00000000000..72ddb961c26
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectGUI.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectGUI.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectGUI_h_
+#define liblldb_CommandObjectGUI_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectGUI
+//-------------------------------------------------------------------------
+
+class CommandObjectGUI : public CommandObjectParsed
+{
+public:
+
+ CommandObjectGUI (CommandInterpreter &interpreter);
+
+ virtual
+ ~CommandObjectGUI ();
+
+protected:
+ virtual bool
+ DoExecute (Args& args,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectGUI_h_
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 7c72ab8c347..49a392286c6 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -532,37 +532,36 @@ protected:
if (error.Success())
{
+ ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack"));
+ m_options.attach_info.SetHijackListener(listener_sp);
+ process->HijackProcessEvents(listener_sp.get());
error = process->Attach (m_options.attach_info);
if (error.Success())
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
- }
- else
- {
- result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
- // If we're synchronous, wait for the stopped event and report that.
- // Otherwise just return.
- // FIXME: in the async case it will now be possible to get to the command
- // interpreter with a state eStateAttaching. Make sure we handle that correctly.
- StateType state = process->WaitForProcessToStop (NULL);
-
- result.SetDidChangeProcessState (true);
+ StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get());
- if (state == eStateStopped)
- {
- result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ process->RestoreProcessEvents();
+
+ result.SetDidChangeProcessState (true);
+
+ if (state == eStateStopped)
+ {
+ result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
+ process->Destroy();
+ result.SetStatus (eReturnStatusFailed);
+ }
}
else
{
- result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
- process->Destroy();
+ result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
result.SetStatus (eReturnStatusFailed);
- return false;
}
}
}
@@ -1087,7 +1086,7 @@ protected:
if (process)
{
- error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
+ error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url);
if (error.Fail())
{
diff --git a/lldb/source/Commands/CommandObjectQuit.cpp b/lldb/source/Commands/CommandObjectQuit.cpp
index d04ecdd9885..ffe2a924072 100644
--- a/lldb/source/Commands/CommandObjectQuit.cpp
+++ b/lldb/source/Commands/CommandObjectQuit.cpp
@@ -92,7 +92,8 @@ CommandObjectQuit::DoExecute (Args& command, CommandReturnObject &result)
return false;
}
}
- m_interpreter.BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived);
+ const uint32_t event_type = CommandInterpreter::eBroadcastBitQuitCommandReceived;
+ m_interpreter.BroadcastEvent (event_type);
result.SetStatus (eReturnStatusQuit);
return true;
}
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index ff6a7235378..7a46d1cb782 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -19,7 +19,7 @@
// Project includes
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReader.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
@@ -4759,7 +4759,9 @@ private:
// CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
-class CommandObjectTargetStopHookAdd : public CommandObjectParsed
+class CommandObjectTargetStopHookAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
public:
@@ -4926,9 +4928,10 @@ public:
CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
- "target stop-hook add ",
+ "target stop-hook add",
"Add a hook to be executed when the target stops.",
"target stop-hook add"),
+ IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
}
@@ -4937,102 +4940,61 @@ public:
{
}
- static size_t
- ReadCommandsCallbackFunction (void *baton,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len)
+protected:
+
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
{
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- Target::StopHook *new_stop_hook = ((Target::StopHook *) baton);
- static bool got_interrupted;
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
- switch (notification)
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
{
- case eInputReaderActivate:
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end.");
- if (reader.GetPrompt())
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- got_interrupted = false;
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderReactivate:
- if (reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- got_interrupted = false;
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
-
- case eInputReaderGotToken:
- if (bytes && bytes_len && baton)
+ output_sp->PutCString("Enter your stop hook command(s). Type 'DONE' to end.\n");
+ output_sp->Flush();
+ }
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ {
+ if (m_stop_hook_sp)
+ {
+ if (line.empty())
{
- StringList *commands = new_stop_hook->GetCommandPointer();
- if (commands)
+ StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+ if (error_sp)
{
- commands->AppendString (bytes, bytes_len);
+ error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", m_stop_hook_sp->GetID());
+ error_sp->Flush();
}
+ Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ if (target)
+ target->RemoveStopHookByID(m_stop_hook_sp->GetID());
}
- if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderInterrupt:
+ else
{
- // Finish, and cancel the stop hook.
- new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID());
- if (!batch_mode)
+ m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
{
- out_stream->Printf ("Stop hook cancelled.\n");
- out_stream->Flush();
+ output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID());
+ output_sp->Flush();
}
-
- reader.SetIsDone (true);
}
- got_interrupted = true;
- break;
-
- case eInputReaderEndOfFile:
- reader.SetIsDone (true);
- break;
-
- case eInputReaderDone:
- if (!got_interrupted && !batch_mode)
- {
- out_stream->Printf ("Stop hook #%" PRIu64 " added.\n", new_stop_hook->GetID());
- out_stream->Flush();
- }
- break;
+ m_stop_hook_sp.reset();
}
-
- return bytes_len;
+ io_handler.SetIsDone(true);
}
-
-protected:
+
bool
DoExecute (Args& command, CommandReturnObject &result)
{
+ m_stop_hook_sp.reset();
+
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target)
{
- Target::StopHookSP new_hook_sp;
- target->AddStopHook (new_hook_sp);
+ Target::StopHookSP new_hook_sp = target->CreateStopHook();
// First step, make the specifier.
std::unique_ptr<SymbolContextSpecifier> specifier_ap;
@@ -5105,31 +5067,12 @@ protected:
}
else
{
- // Otherwise gather up the command list, we'll push an input reader and suck the data from that directly into
- // the new stop hook's command string.
- InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
- if (!reader_sp)
- {
- result.AppendError("out of memory\n");
- result.SetStatus (eReturnStatusFailed);
- target->RemoveStopHookByID (new_hook_sp->GetID());
- return false;
- }
-
- Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction,
- new_hook_sp.get(), // baton
- eInputReaderGranularityLine, // token size, to pass to callback function
- "DONE", // end token
- "> ", // prompt
- true)); // echo input
- if (!err.Success())
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- target->RemoveStopHookByID (new_hook_sp->GetID());
- return false;
- }
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
+ m_stop_hook_sp = new_hook_sp;
+ m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+
}
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
@@ -5143,6 +5086,7 @@ protected:
}
private:
CommandOptions m_options;
+ Target::StopHookSP m_stop_hook_sp;
};
OptionDefinition
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index 2aa77c6729c..caf5429084e 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/InputReaderEZ.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StringList.h"
@@ -42,7 +42,6 @@ public:
TypeSummaryImpl::Flags m_flags;
StringList m_target_types;
- StringList m_user_source;
bool m_regex;
@@ -74,7 +73,6 @@ public:
bool m_skip_references;
bool m_cascade;
bool m_regex;
- StringList m_user_source;
StringList m_target_types;
std::string m_category;
@@ -88,7 +86,6 @@ public:
m_skip_references(sref),
m_cascade(casc),
m_regex(regx),
- m_user_source(),
m_target_types(),
m_category(catg)
{
@@ -100,7 +97,9 @@ public:
-class CommandObjectTypeSummaryAdd : public CommandObjectParsed
+class CommandObjectTypeSummaryAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
private:
@@ -153,10 +152,6 @@ private:
return &m_options;
}
- void
- CollectPythonScript(ScriptAddOptions *options,
- CommandReturnObject &result);
-
bool
Execute_ScriptSummary (Args& command, CommandReturnObject &result);
@@ -178,6 +173,146 @@ public:
{
}
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
+ {
+ static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+ "def function (valobj,internal_dict):\n"
+ " \"\"\"valobj: an SBValue which you want to provide a summary for\n"
+ " internal_dict: an LLDB support object not to be used\"\"\"";
+
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString(g_summary_addreader_instructions);
+ output_sp->Flush();
+ }
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+ if (interpreter)
+ {
+ StringList lines;
+ lines.SplitIntoLines(data);
+ if (lines.GetSize() > 0)
+ {
+ ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData());
+ if (options_ptr)
+ {
+ ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
+
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+ if (interpreter)
+ {
+ std::string funct_name_str;
+ if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str))
+ {
+ if (funct_name_str.empty())
+ {
+ error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n");
+ error_sp->Flush();
+ }
+ else
+ {
+ // now I have a valid function name, let's add this as script for every type in the list
+
+ TypeSummaryImplSP script_format;
+ script_format.reset(new ScriptSummaryFormat(options->m_flags,
+ funct_name_str.c_str(),
+ lines.CopyList(" ").c_str()));
+
+ Error error;
+
+ for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
+ {
+ const char *type_name = options->m_target_types.GetStringAtIndex(i);
+ CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
+ script_format,
+ (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
+ options->m_category,
+ &error);
+ if (error.Fail())
+ {
+ error_sp->Printf ("error: %s", error.AsCString());
+ error_sp->Flush();
+ }
+ }
+
+ if (options->m_name)
+ {
+ CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
+ script_format,
+ CommandObjectTypeSummaryAdd::eNamedSummary,
+ options->m_category,
+ &error);
+ if (error.Fail())
+ {
+ CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
+ script_format,
+ CommandObjectTypeSummaryAdd::eNamedSummary,
+ options->m_category,
+ &error);
+ if (error.Fail())
+ {
+ error_sp->Printf ("error: %s", error.AsCString());
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: %s", error.AsCString());
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ if (error.AsCString())
+ {
+ error_sp->Printf ("error: %s", error.AsCString());
+ error_sp->Flush();
+ }
+ }
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: unable to generate a function.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: no script interpreter.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: internal synchronization information missing or invalid.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: empty function, didn't add python command.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+ error_sp->Flush();
+ }
+
+ io_handler.SetIsDone(true);
+ }
+
static bool
AddSummary(ConstString type_name,
lldb::TypeSummaryImplSP entry,
@@ -190,7 +325,19 @@ protected:
};
-class CommandObjectTypeSynthAdd : public CommandObjectParsed
+static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+"You must define a Python class with these methods:\n"
+" def __init__(self, valobj, dict):\n"
+" def num_children(self):\n"
+" def get_child_at_index(self, index):\n"
+" def get_child_index(self, name):\n"
+" def update(self):\n"
+" '''Optional'''\n"
+"class synthProvider:\n";
+
+class CommandObjectTypeSynthAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
private:
@@ -200,7 +347,7 @@ private:
public:
CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
+ Options (interpreter)
{
}
@@ -296,9 +443,6 @@ private:
return &m_options;
}
- void
- CollectPythonScript (SynthAddOptions *options,
- CommandReturnObject &result);
bool
Execute_HandwritePython (Args& command, CommandReturnObject &result);
@@ -307,8 +451,137 @@ private:
protected:
bool
- DoExecute (Args& command, CommandReturnObject &result);
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ if (m_options.handwrite_python)
+ return Execute_HandwritePython(command, result);
+ else if (m_options.is_class_based)
+ return Execute_PythonClass(command, result);
+ else
+ {
+ result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
+ {
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString(g_synth_addreader_instructions);
+ output_sp->Flush();
+ }
+ }
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+ if (interpreter)
+ {
+ StringList lines;
+ lines.SplitIntoLines(data);
+ if (lines.GetSize() > 0)
+ {
+ SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData());
+ if (options_ptr)
+ {
+ SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
+
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+ if (interpreter)
+ {
+ std::string class_name_str;
+ if (interpreter->GenerateTypeSynthClass (lines, class_name_str))
+ {
+ if (class_name_str.empty())
+ {
+ error_sp->Printf ("error: unable to obtain a proper name for the class.\n");
+ error_sp->Flush();
+ }
+ else
+ {
+ // everything should be fine now, let's add the synth provider class
+
+ SyntheticChildrenSP synth_provider;
+ synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade).
+ SetSkipPointers(options->m_skip_pointers).
+ SetSkipReferences(options->m_skip_references),
+ class_name_str.c_str()));
+
+
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
+
+ Error error;
+
+ for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
+ {
+ const char *type_name = options->m_target_types.GetStringAtIndex(i);
+ ConstString const_type_name(type_name);
+ if (const_type_name)
+ {
+ if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name,
+ synth_provider,
+ options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
+ options->m_category,
+ &error))
+ {
+ error_sp->Printf("error: %s\n", error.AsCString());
+ error_sp->Flush();
+ break;
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: invalid type name.\n");
+ error_sp->Flush();
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: unable to generate a class.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: no script interpreter.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: internal synchronization data missing.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: empty function, didn't add python command.\n");
+ error_sp->Flush();
+ }
+ }
+ else
+ {
+ error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
+ error_sp->Flush();
+ }
+
+ io_handler.SetIsDone(true);
+
+
+ }
+
public:
enum SynthFormatType
@@ -1102,176 +1375,6 @@ CommandObjectTypeFormatList::CommandOptions::g_option_table[] =
// CommandObjectTypeSummaryAdd
//-------------------------------------------------------------------------
-static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
- "def function (valobj,internal_dict):\n"
- " \"\"\"valobj: an SBValue which you want to provide a summary for\n"
- " internal_dict: an LLDB support object not to be used\"\"\"";
-
-class TypeScriptAddInputReader : public InputReaderEZ
-{
-private:
- DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader);
-public:
- TypeScriptAddInputReader(Debugger& debugger) :
- InputReaderEZ(debugger)
- {}
-
- virtual
- ~TypeScriptAddInputReader()
- {
- }
-
- virtual void ActivateHandler(HandlerData& data)
- {
- StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", g_summary_addreader_instructions);
- if (data.reader.GetPrompt())
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
-
- virtual void ReactivateHandler(HandlerData& data)
- {
- StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
- if (data.reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void GotTokenHandler(HandlerData& data)
- {
- StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
- if (data.bytes && data.bytes_len && data.baton)
- {
- ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
- }
- if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void InterruptHandler(HandlerData& data)
- {
- StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
- data.reader.SetIsDone (true);
- if (!batch_mode)
- {
- out_stream->Printf ("Warning: No command attached to breakpoint.\n");
- out_stream->Flush();
- }
- }
- virtual void EOFHandler(HandlerData& data)
- {
- data.reader.SetIsDone (true);
- }
- virtual void DoneHandler(HandlerData& data)
- {
- StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream();
- ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton);
- if (!options_ptr)
- {
- out_stream->Printf ("internal synchronization information missing or invalid.\n");
- out_stream->Flush();
- return;
- }
-
- ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
-
- ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (!interpreter)
- {
- out_stream->Printf ("no script interpreter.\n");
- out_stream->Flush();
- return;
- }
- std::string funct_name_str;
- if (!interpreter->GenerateTypeScriptFunction (options->m_user_source,
- funct_name_str))
- {
- out_stream->Printf ("unable to generate a function.\n");
- out_stream->Flush();
- return;
- }
- if (funct_name_str.empty())
- {
- out_stream->Printf ("unable to obtain a valid function name from the script interpreter.\n");
- out_stream->Flush();
- return;
- }
- // now I have a valid function name, let's add this as script for every type in the list
-
- TypeSummaryImplSP script_format;
- script_format.reset(new ScriptSummaryFormat(options->m_flags,
- funct_name_str.c_str(),
- options->m_user_source.CopyList(" ").c_str()));
-
- Error error;
-
- for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
- {
- const char *type_name = options->m_target_types.GetStringAtIndex(i);
- CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name),
- script_format,
- (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary),
- options->m_category,
- &error);
- if (error.Fail())
- {
- out_stream->Printf ("%s", error.AsCString());
- out_stream->Flush();
- return;
- }
- }
-
- if (options->m_name)
- {
- CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
- script_format,
- CommandObjectTypeSummaryAdd::eNamedSummary,
- options->m_category,
- &error);
- if (error.Fail())
- {
- CommandObjectTypeSummaryAdd::AddSummary (options->m_name,
- script_format,
- CommandObjectTypeSummaryAdd::eNamedSummary,
- options->m_category,
- &error);
- if (error.Fail())
- {
- out_stream->Printf ("%s", error.AsCString());
- out_stream->Flush();
- return;
- }
- }
- else
- {
- out_stream->Printf ("%s", error.AsCString());
- out_stream->Flush();
- return;
- }
- }
- else
- {
- if (error.AsCString())
- {
- out_stream->PutCString (error.AsCString());
- out_stream->Flush();
- }
- return;
- }
- }
-};
-
#endif // #ifndef LLDB_DISABLE_PYTHON
Error
@@ -1352,35 +1455,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting ()
m_category = "default";
}
+
+
#ifndef LLDB_DISABLE_PYTHON
-void
-CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options,
- CommandReturnObject &result)
-{
- InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger()));
- if (reader_sp && options)
- {
-
- InputReaderEZ::InitializationParameters ipr;
-
- Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" ")));
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- else
- {
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
- }
-}
bool
CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result)
@@ -1406,7 +1483,7 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn
return false;
}
- std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)");
+ std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)");
script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
funct_name,
@@ -1445,14 +1522,15 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn
return false;
}
- std::string code = " " + m_options.m_python_script;
+ std::string code = " " + m_options.m_python_script;
script_format.reset(new ScriptSummaryFormat(m_options.m_flags,
funct_name_str.c_str(),
code.c_str()));
}
- else // use an InputReader to grab Python code from the user
- {
+ else
+ {
+ // Use an IOHandler to grab Python code from the user
ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags,
m_options.m_regex,
m_options.m_name,
@@ -1471,7 +1549,12 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn
}
}
- CollectPythonScript(options,result);
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+
return result.Succeeded();
}
@@ -1603,6 +1686,7 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in
"type summary add",
"Add a new summary style for a type.",
NULL),
+ IOHandlerDelegateMultiline ("DONE"),
m_options (interpreter)
{
CommandArgumentEntry type_arg;
@@ -3647,193 +3731,6 @@ CommandObjectTypeSynthClear::CommandOptions::g_option_table[] =
};
-//-------------------------------------------------------------------------
-// TypeSynthAddInputReader
-//-------------------------------------------------------------------------
-
-static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
- "You must define a Python class with these methods:\n"
- " def __init__(self, valobj, dict):\n"
- " def num_children(self):\n"
- " def get_child_at_index(self, index):\n"
- " def get_child_index(self, name):\n"
- "Optionally, you can also define a method:\n"
- " def update(self):\n"
- "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n"
- "class synthProvider:";
-
-class TypeSynthAddInputReader : public InputReaderEZ
-{
-public:
- TypeSynthAddInputReader(Debugger& debugger) :
- InputReaderEZ(debugger)
- {}
-
- virtual
- ~TypeSynthAddInputReader()
- {
- }
-
- virtual void ActivateHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", g_synth_addreader_instructions);
- if (data.reader.GetPrompt())
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
-
- virtual void ReactivateHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (data.reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void GotTokenHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- if (data.bytes && data.bytes_len && data.baton)
- {
- ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len);
- }
- if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", data.reader.GetPrompt());
- out_stream->Flush();
- }
- }
- virtual void InterruptHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- bool batch_mode = data.GetBatchMode();
- data.reader.SetIsDone (true);
- if (!batch_mode)
- {
- out_stream->Printf ("Warning: No command attached to breakpoint.\n");
- out_stream->Flush();
- }
- }
- virtual void EOFHandler(HandlerData& data)
- {
- data.reader.SetIsDone (true);
- }
- virtual void DoneHandler(HandlerData& data)
- {
- StreamSP out_stream = data.GetOutStream();
- SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton);
- if (!options_ptr)
- {
- out_stream->Printf ("internal synchronization data missing.\n");
- out_stream->Flush();
- return;
- }
-
- SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope
-
- ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- if (!interpreter)
- {
- out_stream->Printf ("no script interpreter.\n");
- out_stream->Flush();
- return;
- }
- std::string class_name_str;
- if (!interpreter->GenerateTypeSynthClass (options->m_user_source,
- class_name_str))
- {
- out_stream->Printf ("unable to generate a class.\n");
- out_stream->Flush();
- return;
- }
- if (class_name_str.empty())
- {
- out_stream->Printf ("unable to obtain a proper name for the class.\n");
- out_stream->Flush();
- return;
- }
-
- // everything should be fine now, let's add the synth provider class
-
- SyntheticChildrenSP synth_provider;
- synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade).
- SetSkipPointers(options->m_skip_pointers).
- SetSkipReferences(options->m_skip_references),
- class_name_str.c_str()));
-
-
- lldb::TypeCategoryImplSP category;
- DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category);
-
- Error error;
-
- for (size_t i = 0; i < options->m_target_types.GetSize(); i++)
- {
- const char *type_name = options->m_target_types.GetStringAtIndex(i);
- ConstString typeCS(type_name);
- if (typeCS)
- {
- if (!CommandObjectTypeSynthAdd::AddSynth(typeCS,
- synth_provider,
- options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth,
- options->m_category,
- &error))
- {
- out_stream->Printf("%s\n", error.AsCString());
- out_stream->Flush();
- return;
- }
- }
- else
- {
- out_stream->Printf ("invalid type name.\n");
- out_stream->Flush();
- return;
- }
- }
- }
-
-private:
- DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader);
-};
-
-void
-CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options,
- CommandReturnObject &result)
-{
- InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger()));
- if (reader_sp && options)
- {
-
- InputReaderEZ::InitializationParameters ipr;
-
- Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" ")));
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
- }
- else
- {
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
- }
-}
-
bool
CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result)
{
@@ -3858,7 +3755,11 @@ CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturn
}
}
- CollectPythonScript(options,result);
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
return result.Succeeded();
}
@@ -3937,6 +3838,7 @@ CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interp
"type synthetic add",
"Add a new synthetic provider for a type.",
NULL),
+ IOHandlerDelegateMultiline ("DONE"),
m_options (interpreter)
{
CommandArgumentEntry type_arg;
@@ -4006,21 +3908,6 @@ CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
return true;
}
}
-
-bool
-CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result)
-{
- if (m_options.handwrite_python)
- return Execute_HandwritePython(command, result);
- else if (m_options.is_class_based)
- return Execute_PythonClass(command, result);
- else
- {
- result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-}
OptionDefinition
CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] =
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
index e19216d74fc..0083ff140e5 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -16,6 +16,7 @@
#include "CommandObjectWatchpointCommand.h"
#include "CommandObjectWatchpoint.h"
+#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
@@ -34,7 +35,9 @@ using namespace lldb_private;
//-------------------------------------------------------------------------
-class CommandObjectWatchpointCommandAdd : public CommandObjectParsed
+class CommandObjectWatchpointCommandAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
{
public:
@@ -43,6 +46,7 @@ public:
"add",
"Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
NULL),
+ IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong (
@@ -185,40 +189,45 @@ but do NOT enter more than one command per line. \n" );
return &m_options;
}
- void
- CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
- CommandReturnObject &result)
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
{
- InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
- std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
- if (reader_sp && data_ap.get())
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
{
- BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
- wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
-
- Error err (reader_sp->Initialize (CommandObjectWatchpointCommandAdd::GenerateWatchpointCommandCallback,
- wp_options, // callback_data
- eInputReaderGranularityLine, // token size, to pass to callback function
- "DONE", // end token
- "> ", // prompt
- true)); // echo input
- if (err.Success())
- {
- m_interpreter.GetDebugger().PushInputReader (reader_sp);
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
- {
- result.AppendError (err.AsCString());
- result.SetStatus (eReturnStatusFailed);
- }
+ output_sp->PutCString("Enter your debugger command(s). Type 'DONE' to end.\n");
+ output_sp->Flush();
}
- else
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ {
+ io_handler.SetIsDone(true);
+
+ // The WatchpointOptions object is owned by the watchpoint or watchpoint location
+ WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData();
+ if (wp_options)
{
- result.AppendError("out of memory");
- result.SetStatus (eReturnStatusFailed);
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+ if (data_ap.get())
+ {
+ data_ap->user_source.SplitIntoLines(line);
+ BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+ wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
+ }
}
+ }
+ void
+ CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
+ CommandReturnObject &result)
+ {
+ m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ wp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
}
/// Set a one-liner as the callback for the watchpoint.
@@ -240,93 +249,6 @@ but do NOT enter more than one command per line. \n" );
return;
}
-
- static size_t
- GenerateWatchpointCommandCallback (void *callback_data,
- InputReader &reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len)
- {
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
- switch (notification)
- {
- case eInputReaderActivate:
- if (!batch_mode)
- {
- out_stream->Printf ("%s\n", g_reader_instructions);
- if (reader.GetPrompt())
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderReactivate:
- if (reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- break;
-
- case eInputReaderGotToken:
- if (bytes && bytes_len && callback_data)
- {
- WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
- if (wp_options)
- {
- Baton *wp_options_baton = wp_options->GetBaton();
- if (wp_options_baton)
- ((WatchpointOptions::CommandData *)wp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
- }
- }
- if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
- {
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush();
- }
- break;
-
- case eInputReaderInterrupt:
- {
- // Finish, and cancel the watchpoint command.
- reader.SetIsDone (true);
- WatchpointOptions *wp_options = (WatchpointOptions *) callback_data;
- if (wp_options)
- {
- Baton *wp_options_baton = wp_options->GetBaton ();
- if (wp_options_baton)
- {
- ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->user_source.Clear();
- ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->script_source.clear();
- }
- }
- if (!batch_mode)
- {
- out_stream->Printf ("Warning: No command attached to watchpoint.\n");
- out_stream->Flush();
- }
- }
- break;
-
- case eInputReaderEndOfFile:
- reader.SetIsDone (true);
- break;
-
- case eInputReaderDone:
- break;
- }
-
- return bytes_len;
- }
static bool
WatchpointOptionsCallbackFunction (void *baton,
@@ -579,12 +501,8 @@ protected:
private:
CommandOptions m_options;
- static const char *g_reader_instructions;
-
};
-const char *
-CommandObjectWatchpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
// 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.
diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.h b/lldb/source/Commands/CommandObjectWatchpointCommand.h
index c2faf7187db..3bc9b3537db 100644
--- a/lldb/source/Commands/CommandObjectWatchpointCommand.h
+++ b/lldb/source/Commands/CommandObjectWatchpointCommand.h
@@ -19,9 +19,6 @@
#include "lldb/lldb-types.h"
#include "lldb/Interpreter/Options.h"
-#include "lldb/Core/InputReader.h"
-#include "lldb/Interpreter/CommandObject.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
OpenPOWER on IntegriCloud