forked from OSchip/llvm-project
<rdar://problem/10605072>
Added the ability to override command line commands. In some cases GUI interfaces might want to intercept commands like "quit" or "process launch" (which might cause the process to re-run). They can now do so by overriding/intercepting commands by using functions added to SBCommandInterpreter using a callback function. If the callback function returns true, the command is assumed to be handled. If false is returned the command should be evaluated normally. Adopted this up in the Driver.cpp for intercepting the "quit" command. llvm-svn: 151708
This commit is contained in:
parent
e4f22dfa95
commit
a9f7b79dfe
|
@ -92,6 +92,13 @@ public:
|
|||
int max_return_elements,
|
||||
lldb::SBStringList &matches);
|
||||
|
||||
// Catch commands before they execute by registering a callback that will
|
||||
// get called when the command gets executed. This allows GUI or command
|
||||
// line interfaces to intercept a command and stop it from happening
|
||||
bool
|
||||
SetCommandOverrideCallback (const char *command_name,
|
||||
lldb::CommandOverrideCallback callback,
|
||||
void *baton);
|
||||
protected:
|
||||
|
||||
lldb_private::CommandInterpreter &
|
||||
|
|
|
@ -194,11 +194,6 @@ public:
|
|||
eFlagProcessMustBePaused = (1 << 1)
|
||||
};
|
||||
|
||||
// Do not override this
|
||||
bool
|
||||
ExecuteCommandString (const char *command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
bool
|
||||
ParseOptions (Args& args,
|
||||
CommandReturnObject &result);
|
||||
|
@ -369,6 +364,25 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
CommandOverrideCallback
|
||||
GetOverrideCallback () const
|
||||
{
|
||||
return m_command_override_callback;
|
||||
}
|
||||
|
||||
void *
|
||||
GetOverrideCallbackBaton () const
|
||||
{
|
||||
return m_command_override_baton;
|
||||
}
|
||||
|
||||
void
|
||||
SetOverrideCallback (CommandOverrideCallback callback, void *baton)
|
||||
{
|
||||
m_command_override_callback = callback;
|
||||
m_command_override_baton = baton;
|
||||
}
|
||||
|
||||
protected:
|
||||
CommandInterpreter &m_interpreter;
|
||||
std::string m_cmd_name;
|
||||
|
@ -376,9 +390,10 @@ protected:
|
|||
std::string m_cmd_help_long;
|
||||
std::string m_cmd_syntax;
|
||||
bool m_is_alias;
|
||||
Flags m_flags;
|
||||
Flags m_flags;
|
||||
std::vector<CommandArgumentEntry> m_arguments;
|
||||
|
||||
CommandOverrideCallback m_command_override_callback;
|
||||
void * m_command_override_baton;
|
||||
// Helper function to populate IDs or ID ranges as the command argument data
|
||||
// to the specified command argument entry.
|
||||
static void
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace lldb_private
|
|||
typedef ThreadPlan * (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, void *baton);
|
||||
typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch);
|
||||
typedef int (*ComparisonFunction)(const void *, const void *);
|
||||
typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
|
|
|
@ -49,32 +49,8 @@ namespace lldb {
|
|||
typedef void * thread_arg_t; // Host thread argument type
|
||||
typedef void * thread_result_t; // Host thread result type
|
||||
typedef void * (*thread_func_t)(void *); // Host thread function type
|
||||
|
||||
// The template below can be used in a few useful ways:
|
||||
//
|
||||
// // Make a single shared pointer a class Foo
|
||||
// lldb::SharePtr<Foo>::Type foo_sp;
|
||||
//
|
||||
// // Make a typedef to a Foo shared pointer
|
||||
// typedef lldb::SharePtr<Foo>::Type FooSP;
|
||||
//
|
||||
// template<typename _Tp>
|
||||
// struct SharedPtr
|
||||
// {
|
||||
// typedef lldb_private::SharingPtr<_Tp> Type;
|
||||
// };
|
||||
// template<typename _Tp>
|
||||
// struct LoggingSharedPtr
|
||||
// {
|
||||
// typedef lldb_private::LoggingSharingPtr<_Tp> Type;
|
||||
// };
|
||||
//
|
||||
// template <typename _Tp>
|
||||
// struct IntrusiveSharedPtr
|
||||
// {
|
||||
// typedef lldb_private::IntrusiveSharingPtr<_Tp> Type;
|
||||
// };
|
||||
typedef void (*LogOutputCallback) (const char *, void *baton);
|
||||
typedef void (*LogOutputCallback) (const char *, void *baton);
|
||||
typedef bool (*CommandOverrideCallback)(void *baton, const char **argv);
|
||||
} // namespace lldb
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
|
|
|
@ -310,6 +310,22 @@ SBCommandInterpreter::GetArgumentDescriptionAsCString (const lldb::CommandArgume
|
|||
return CommandObject::GetArgumentDescriptionAsCString (arg_type);
|
||||
}
|
||||
|
||||
bool
|
||||
SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name,
|
||||
lldb::CommandOverrideCallback callback,
|
||||
void *baton)
|
||||
{
|
||||
if (command_name && command_name[0] && m_opaque_ptr)
|
||||
{
|
||||
CommandObject *cmd_obj = m_opaque_ptr->GetCommandObject(command_name);
|
||||
if (cmd_obj)
|
||||
{
|
||||
cmd_obj->SetOverrideCallback (callback, baton);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef LLDB_DISABLE_PYTHON
|
||||
|
||||
|
@ -341,3 +357,4 @@ SBCommandInterpreter::InitializeSWIG ()
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1511,12 +1511,33 @@ CommandInterpreter::HandleCommand (const char *command_line,
|
|||
log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
|
||||
|
||||
|
||||
CommandOverrideCallback command_callback = cmd_obj->GetOverrideCallback();
|
||||
bool handled = false;
|
||||
if (wants_raw_input)
|
||||
cmd_obj->ExecuteRawCommandString (remainder.c_str(), result);
|
||||
{
|
||||
if (command_callback)
|
||||
{
|
||||
std::string full_command (cmd_obj->GetCommandName ());
|
||||
full_command += ' ';
|
||||
full_command += remainder;
|
||||
const char *argv[2] = { NULL, NULL };
|
||||
argv[0] = full_command.c_str();
|
||||
handled = command_callback (cmd_obj->GetOverrideCallbackBaton(), argv);
|
||||
}
|
||||
if (!handled)
|
||||
cmd_obj->ExecuteRawCommandString (remainder.c_str(), result);
|
||||
}
|
||||
else
|
||||
{
|
||||
Args cmd_args (remainder.c_str());
|
||||
cmd_obj->ExecuteWithOptions (cmd_args, result);
|
||||
if (command_callback)
|
||||
{
|
||||
Args full_args (cmd_obj->GetCommandName ());
|
||||
full_args.AppendArguments(cmd_args);
|
||||
handled = command_callback (cmd_obj->GetOverrideCallbackBaton(), full_args.GetConstArgumentVector());
|
||||
}
|
||||
if (!handled)
|
||||
cmd_obj->ExecuteWithOptions (cmd_args, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -53,7 +53,9 @@ CommandObject::CommandObject
|
|||
m_cmd_syntax (),
|
||||
m_is_alias (false),
|
||||
m_flags (flags),
|
||||
m_arguments()
|
||||
m_arguments(),
|
||||
m_command_override_callback (NULL),
|
||||
m_command_override_baton (NULL)
|
||||
{
|
||||
if (help && help[0])
|
||||
m_cmd_help_short = help;
|
||||
|
@ -162,17 +164,6 @@ CommandObject::GetFlags() const
|
|||
return m_flags;
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObject::ExecuteCommandString
|
||||
(
|
||||
const char *command_line,
|
||||
CommandReturnObject &result
|
||||
)
|
||||
{
|
||||
Args command_args(command_line);
|
||||
return ExecuteWithOptions (command_args, result);
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObject::ParseOptions
|
||||
(
|
||||
|
|
|
@ -1088,6 +1088,14 @@ Driver::EditLineInputReaderCallback
|
|||
return bytes_len;
|
||||
}
|
||||
|
||||
// Intercept when the quit command is called and tell our driver that it is done
|
||||
static bool
|
||||
QuitCommandOverrideCallback (void *baton, const char **argv)
|
||||
{
|
||||
((Driver *)baton)->SetIsDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Driver::MainLoop ()
|
||||
{
|
||||
|
@ -1190,6 +1198,10 @@ Driver::MainLoop ()
|
|||
|
||||
SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
|
||||
|
||||
// Intercept when the quit command is called and tell our driver that it is done
|
||||
bool quit_success = sb_interpreter.SetCommandOverrideCallback ("quit", QuitCommandOverrideCallback, this);
|
||||
assert (quit_success);
|
||||
|
||||
m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
|
||||
|
||||
SBCommunication out_comm_2("driver.editline_output");
|
||||
|
@ -1371,8 +1383,7 @@ Driver::MainLoop ()
|
|||
|
||||
ReadyForCommand ();
|
||||
|
||||
bool done = false;
|
||||
while (!done)
|
||||
while (!GetIsDone())
|
||||
{
|
||||
listener.WaitForEvent (UINT32_MAX, event);
|
||||
if (event.IsValid())
|
||||
|
@ -1385,12 +1396,15 @@ Driver::MainLoop ()
|
|||
if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
|
||||
(event_type & IOChannel::eBroadcastBitThreadDidExit))
|
||||
{
|
||||
done = true;
|
||||
SetIsDone();
|
||||
if (event_type & IOChannel::eBroadcastBitThreadDidExit)
|
||||
iochannel_thread_exited = true;
|
||||
}
|
||||
else
|
||||
done = HandleIOEvent (event);
|
||||
{
|
||||
if (HandleIOEvent (event))
|
||||
SetIsDone();
|
||||
}
|
||||
}
|
||||
else if (SBProcess::EventIsProcessEvent (event))
|
||||
{
|
||||
|
@ -1402,9 +1416,12 @@ Driver::MainLoop ()
|
|||
}
|
||||
else if (event.BroadcasterMatchesRef (sb_interpreter.GetBroadcaster()))
|
||||
{
|
||||
// TODO: deprecate the eBroadcastBitQuitCommandReceived event
|
||||
// now that we have SBCommandInterpreter::SetCommandOverrideCallback()
|
||||
// that can take over a command
|
||||
if (event_type & SBCommandInterpreter::eBroadcastBitQuitCommandReceived)
|
||||
{
|
||||
done = true;
|
||||
SetIsDone();
|
||||
}
|
||||
else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
|
||||
{
|
||||
|
|
|
@ -135,6 +135,18 @@ public:
|
|||
return m_debugger.InputReaderIsTopReader (m_editline_reader);
|
||||
}
|
||||
|
||||
bool
|
||||
GetIsDone () const
|
||||
{
|
||||
return m_done;
|
||||
}
|
||||
|
||||
void
|
||||
SetIsDone ()
|
||||
{
|
||||
m_done = true;
|
||||
}
|
||||
|
||||
private:
|
||||
lldb::SBDebugger m_debugger;
|
||||
lldb_utility::PseudoTerminal m_editline_pty;
|
||||
|
@ -143,6 +155,7 @@ private:
|
|||
std::auto_ptr<IOChannel> m_io_channel_ap;
|
||||
OptionData m_option_data;
|
||||
bool m_waiting_for_command;
|
||||
bool m_done;
|
||||
|
||||
void
|
||||
ResetOptionValues ();
|
||||
|
|
Loading…
Reference in New Issue