forked from OSchip/llvm-project
Add a "Confirm" function to the CommandInterpreter so you can confirm potentially dangerous operations in a generic way.
llvm-svn: 115546
This commit is contained in:
parent
308363336b
commit
97a6dc7e16
|
@ -15,6 +15,7 @@
|
|||
#include "lldb/lldb-include.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Host/Predicate.h"
|
||||
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -88,6 +89,11 @@ public:
|
|||
|
||||
void
|
||||
RefreshPrompt();
|
||||
|
||||
// If you want to read from an input reader synchronously, then just initialize the
|
||||
// reader and then call WaitOnReaderIsDone, which will return when the reader is popped.
|
||||
void
|
||||
WaitOnReaderIsDone ();
|
||||
|
||||
protected:
|
||||
friend class Debugger;
|
||||
|
@ -104,6 +110,7 @@ protected:
|
|||
bool m_done;
|
||||
bool m_echo;
|
||||
bool m_active;
|
||||
Predicate<bool> m_reader_done;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (InputReader);
|
||||
|
|
|
@ -157,7 +157,16 @@ public:
|
|||
|
||||
void
|
||||
SetPrompt (const char *);
|
||||
|
||||
|
||||
bool Confirm (const char *message, bool default_answer);
|
||||
|
||||
static size_t
|
||||
GetConfirmationInputReaderCallback (void *baton,
|
||||
InputReader &reader,
|
||||
lldb::InputReaderAction action,
|
||||
const char *bytes,
|
||||
size_t bytes_len);
|
||||
|
||||
void
|
||||
LoadCommandDictionary ();
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ InputReader::InputReader (Debugger &debugger) :
|
|||
m_granularity (eInputReaderGranularityInvalid),
|
||||
m_done (true),
|
||||
m_echo (true),
|
||||
m_active (false)
|
||||
m_active (false),
|
||||
m_reader_done (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -315,6 +316,7 @@ InputReader::Notify (InputReaderAction notification)
|
|||
case eInputReaderActivate:
|
||||
case eInputReaderReactivate:
|
||||
m_active = true;
|
||||
m_reader_done.SetValue(false, eBroadcastAlways);
|
||||
break;
|
||||
|
||||
case eInputReaderDeactivate:
|
||||
|
@ -327,4 +329,12 @@ InputReader::Notify (InputReaderAction notification)
|
|||
}
|
||||
if (m_callback)
|
||||
m_callback (m_callback_baton, *this, notification, NULL, 0);
|
||||
if (notification == eInputReaderDone)
|
||||
m_reader_done.SetValue(true, eBroadcastAlways);
|
||||
}
|
||||
|
||||
void
|
||||
InputReader::WaitOnReaderIsDone ()
|
||||
{
|
||||
m_reader_done.WaitForValueEqualTo (true);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/InputReader.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
@ -778,6 +779,98 @@ CommandInterpreter::SetPrompt (const char *new_prompt)
|
|||
m_debugger.SetPrompt (new_prompt);
|
||||
}
|
||||
|
||||
size_t
|
||||
CommandInterpreter::GetConfirmationInputReaderCallback (void *baton,
|
||||
InputReader &reader,
|
||||
lldb::InputReaderAction action,
|
||||
const char *bytes,
|
||||
size_t bytes_len)
|
||||
{
|
||||
FILE *out_fh = reader.GetDebugger().GetOutputFileHandle();
|
||||
bool *response_ptr = (bool *) baton;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case eInputReaderActivate:
|
||||
if (out_fh)
|
||||
{
|
||||
if (reader.GetPrompt())
|
||||
::fprintf (out_fh, "%s", reader.GetPrompt());
|
||||
}
|
||||
break;
|
||||
|
||||
case eInputReaderDeactivate:
|
||||
break;
|
||||
|
||||
case eInputReaderReactivate:
|
||||
if (out_fh && reader.GetPrompt())
|
||||
::fprintf (out_fh, "%s", reader.GetPrompt());
|
||||
break;
|
||||
|
||||
case eInputReaderGotToken:
|
||||
if (bytes_len == 0)
|
||||
{
|
||||
reader.SetIsDone(true);
|
||||
}
|
||||
else if (bytes[0] == 'y')
|
||||
{
|
||||
*response_ptr = true;
|
||||
reader.SetIsDone(true);
|
||||
}
|
||||
else if (bytes[0] == 'n')
|
||||
{
|
||||
*response_ptr = false;
|
||||
reader.SetIsDone(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out_fh && !reader.IsDone() && reader.GetPrompt())
|
||||
{
|
||||
::fprintf (out_fh, "Please answer \"y\" or \"n\"\n");
|
||||
::fprintf (out_fh, "%s", reader.GetPrompt());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eInputReaderDone:
|
||||
break;
|
||||
}
|
||||
|
||||
return bytes_len;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
CommandInterpreter::Confirm (const char *message, bool default_answer)
|
||||
{
|
||||
// The default interpretation just pushes a new input reader and lets it get the answer:
|
||||
InputReaderSP reader_sp (new InputReader(GetDebugger()));
|
||||
bool response = default_answer;
|
||||
if (reader_sp)
|
||||
{
|
||||
std::string prompt(message);
|
||||
prompt.append(": [");
|
||||
if (default_answer)
|
||||
prompt.append ("Y/n] ");
|
||||
else
|
||||
prompt.append ("y/N] ");
|
||||
|
||||
Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback,
|
||||
&response, // baton
|
||||
eInputReaderGranularityLine, // token size, to pass to callback function
|
||||
NULL, // end token
|
||||
prompt.c_str(), // prompt
|
||||
true)); // echo input
|
||||
if (err.Success())
|
||||
{
|
||||
GetDebugger().PushInputReader (reader_sp);
|
||||
}
|
||||
reader_sp->WaitOnReaderIsDone();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue