aboutsummaryrefslogtreecommitdiff
path: root/tools/driver
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2014-02-18 16:23:10 +0000
committerEd Maste <emaste@FreeBSD.org>2014-02-18 16:23:10 +0000
commit866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (patch)
tree95cb16075f0af1b3a05b9b84eb18dda8e6c903e9 /tools/driver
parentde889deb2c386f2a7831befaf226e5c86685fa53 (diff)
downloadsrc-866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec.tar.gz
src-866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec.zip
Import lldb as of SVN r201577 (git 2bdc2f6)vendor/lldb/lldb-r201577
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
Notes
Notes: svn path=/vendor/lldb/dist/; revision=262182 svn path=/vendor/lldb/lldb-r201577/; revision=262183; tag=vendor/lldb/lldb-r201577
Diffstat (limited to 'tools/driver')
-rw-r--r--tools/driver/Driver.cpp984
-rw-r--r--tools/driver/Driver.h80
-rw-r--r--tools/driver/ELWrapper.cpp422
-rw-r--r--tools/driver/ELWrapper.h122
-rw-r--r--tools/driver/GetOptWrapper.cpp33
-rw-r--r--tools/driver/GetOptWrapper.h49
-rw-r--r--tools/driver/IOChannel.cpp656
-rw-r--r--tools/driver/IOChannel.h154
-rw-r--r--tools/driver/Platform.h3
9 files changed, 122 insertions, 2381 deletions
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index e2742425dd4c..78d3a7e1c037 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -18,7 +18,6 @@
#include <string>
#include <thread>
-#include "IOChannel.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
@@ -83,20 +82,12 @@ static OptionDefinition g_options[] =
"Tells the debugger to use the file <filename> as the program to be debugged." },
{ LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename,
"Tells the debugger to use the fullpath to <path> as the core file." },
+ { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
+ "Tells the debugger to attach to a process with the given pid." },
{ LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName,
"Tells the debugger to attach to a process with the given name." },
{ LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone,
"Tells the debugger to wait for a process with the given pid or name to launch before attaching." },
- { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid,
- "Tells the debugger to attach to a process with the given pid." },
- { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
- "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
- "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
- "extensions have been implemented." },
- { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
- "Tells the debugger to print out extra information for debugging itself." },
- { LLDB_3_TO_5, false, "source-quietly" , 'b', no_argument , 0, eArgTypeNone,
- "Tells the debugger to print out extra information for debugging itself." },
{ LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename,
"Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." },
{ LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone,
@@ -105,6 +96,8 @@ static OptionDefinition g_options[] =
"Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." },
{ LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone,
"Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." },
+ { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone,
+ "Tells the debugger suppress output from commands provided in the -s, -S, -O and -o commands." },
{ LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone,
"Tells the debugger to open source files using the host's \"external editor\" mechanism." },
{ LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
@@ -113,6 +106,12 @@ static OptionDefinition g_options[] =
"Do not use colors." },
{ LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
"Prints out the path to the lldb.py file for this version of lldb." },
+ { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang,
+ "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. "
+ "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python "
+ "extensions have been implemented." },
+ { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone,
+ "Tells the debugger to print out extra information for debugging itself." },
{ 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
};
@@ -121,14 +120,7 @@ static const uint32_t last_option_set_with_args = 2;
Driver::Driver () :
SBBroadcaster ("Driver"),
m_debugger (SBDebugger::Create(false)),
- m_editline_pty (),
- m_editline_slave_fh (NULL),
- m_editline_reader (),
- m_io_channel_ap (),
- m_option_data (),
- m_executing_user_command (false),
- m_waiting_for_command (false),
- m_done(false)
+ m_option_data ()
{
// We want to be able to handle CTRL+D in the terminal to have it terminate
// certain input
@@ -145,24 +137,6 @@ Driver::~Driver ()
g_debugger_name = NULL;
}
-void
-Driver::CloseIOChannelFile ()
-{
- // Write an End of File sequence to the file descriptor to ensure any
- // read functions can exit.
- char eof_str[] = "\x04";
- int mfd = m_editline_pty.GetMasterFileDescriptor();
- if (mfd != -1)
- ::write (m_editline_pty.GetMasterFileDescriptor(), eof_str, strlen(eof_str));
-
- m_editline_pty.CloseMasterFileDescriptor();
-
- if (m_editline_slave_fh)
- {
- ::fclose (m_editline_slave_fh);
- m_editline_slave_fh = NULL;
- }
-}
// This function takes INDENT, which tells how many spaces to output at the front
// of each line; TEXT, which is the text that is to be output. It outputs the
@@ -346,7 +320,11 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
}
indent_level -= 5;
-
+
+ fprintf (out, "\n%*sNotes:\n",
+ indent_level, "");
+ indent_level += 5;
+
fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed from left to right in order, "
"\n%*swith the source files and commands interleaved. The same is true of the \"-S\" and \"-O\" options."
"\n%*sThe before file and after file sets can intermixed freely, the command parser will sort them out."
@@ -356,9 +334,9 @@ ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data)
indent_level, "",
indent_level, "");
- fprintf (out, "\n%*s(If you don't provide -f then the first argument will be the file to be debugged"
- "\n%*s so '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
- "\n%*s Remember to end the options with \"--\" if any of your arguments have a \"-\" in them.)\n\n",
+ fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be debugged"
+ "\n%*swhich means that '%s -- <filename> [<ARG1> [<ARG2>]]' also works."
+ "\n%*sBut remember to end the options with \"--\" if any of your arguments have a \"-\" in them.\n\n",
indent_level, "",
indent_level, "",
name,
@@ -521,7 +499,7 @@ Driver::ExecuteInitialCommands (bool before_file)
const char *executed_command = command;
if (is_file)
{
- ::snprintf (command_string, sizeof(command_string), "command source '%s'", command);
+ ::snprintf (command_string, sizeof(command_string), "command source -s %i '%s'", m_option_data.m_source_quietly, command);
executed_command = command_string;
}
@@ -530,23 +508,27 @@ Driver::ExecuteInitialCommands (bool before_file)
{
const size_t output_size = result.GetOutputSize();
if (output_size > 0)
- m_io_channel_ap->OutWrite (result.GetOutput(dump_stream_only_if_no_immediate), output_size, NO_ASYNC);
+ {
+ const char *cstr = result.GetOutput(dump_stream_only_if_no_immediate);
+ if (cstr)
+ printf ("%s", cstr);
+ }
const size_t error_size = result.GetErrorSize();
if (error_size > 0)
- m_io_channel_ap->OutWrite (result.GetError(dump_stream_only_if_no_immediate), error_size, NO_ASYNC);
+ {
+ const char *cstr = result.GetError(dump_stream_only_if_no_immediate);
+ if (cstr)
+ printf ("%s", cstr);
+ }
}
if (result.Succeeded() == false)
{
- char error_buffer[1024];
- size_t error_size;
const char *type = before_file ? "before file" : "after_file";
if (is_file)
- error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command file: '%s' failed.\n", type, command);
+ ::fprintf(stderr, "Aborting %s command execution, command file: '%s' failed.\n", type, command);
else
- error_size = ::snprintf(error_buffer, sizeof(error_buffer), "Aborting %s command execution, command: '%s' failed.\n", type, command);
-
- m_io_channel_ap->OutWrite(error_buffer, error_size, NO_ASYNC);
+ ::fprintf(stderr, "Aborting %s command execution, command: '%s' failed.\n", type, command);
break;
}
result.Clear();
@@ -747,7 +729,7 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
m_option_data.m_debug_mode = true;
break;
- case 'q':
+ case 'Q':
m_option_data.m_source_quietly = true;
break;
@@ -861,524 +843,9 @@ Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting)
return error;
}
-size_t
-Driver::GetProcessSTDOUT ()
-{
- // The process has stuff waiting for stdout; get it and write it out to the appropriate place.
- char stdio_buffer[1024];
- size_t len;
- size_t total_bytes = 0;
- while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0)
- {
- m_io_channel_ap->OutWrite (stdio_buffer, len, NO_ASYNC);
- total_bytes += len;
- }
- return total_bytes;
-}
-
-size_t
-Driver::GetProcessSTDERR ()
-{
- // The process has stuff waiting for stderr; get it and write it out to the appropriate place.
- char stdio_buffer[1024];
- size_t len;
- size_t total_bytes = 0;
- while ((len = m_debugger.GetSelectedTarget().GetProcess().GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0)
- {
- m_io_channel_ap->ErrWrite (stdio_buffer, len, NO_ASYNC);
- total_bytes += len;
- }
- return total_bytes;
-}
-
-void
-Driver::UpdateSelectedThread ()
-{
- using namespace lldb;
- SBProcess process(m_debugger.GetSelectedTarget().GetProcess());
- if (process.IsValid())
- {
- SBThread curr_thread (process.GetSelectedThread());
- SBThread thread;
- StopReason curr_thread_stop_reason = eStopReasonInvalid;
- curr_thread_stop_reason = curr_thread.GetStopReason();
-
- if (!curr_thread.IsValid() ||
- curr_thread_stop_reason == eStopReasonInvalid ||
- curr_thread_stop_reason == eStopReasonNone)
- {
- // Prefer a thread that has just completed its plan over another thread as current thread.
- SBThread plan_thread;
- SBThread other_thread;
- const size_t num_threads = process.GetNumThreads();
- size_t i;
- for (i = 0; i < num_threads; ++i)
- {
- thread = process.GetThreadAtIndex(i);
- StopReason thread_stop_reason = thread.GetStopReason();
- switch (thread_stop_reason)
- {
- case eStopReasonInvalid:
- case eStopReasonNone:
- break;
-
- case eStopReasonTrace:
- case eStopReasonBreakpoint:
- case eStopReasonWatchpoint:
- case eStopReasonSignal:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonThreadExiting:
- if (!other_thread.IsValid())
- other_thread = thread;
- break;
- case eStopReasonPlanComplete:
- if (!plan_thread.IsValid())
- plan_thread = thread;
- break;
- }
- }
- if (plan_thread.IsValid())
- process.SetSelectedThread (plan_thread);
- else if (other_thread.IsValid())
- process.SetSelectedThread (other_thread);
- else
- {
- if (curr_thread.IsValid())
- thread = curr_thread;
- else
- thread = process.GetThreadAtIndex(0);
-
- if (thread.IsValid())
- process.SetSelectedThread (thread);
- }
- }
- }
-}
-
-// This function handles events that were broadcast by the process.
-void
-Driver::HandleBreakpointEvent (const SBEvent &event)
-{
- using namespace lldb;
- const uint32_t event_type = SBBreakpoint::GetBreakpointEventTypeFromEvent (event);
-
- if (event_type & eBreakpointEventTypeAdded
- || event_type & eBreakpointEventTypeRemoved
- || event_type & eBreakpointEventTypeEnabled
- || event_type & eBreakpointEventTypeDisabled
- || event_type & eBreakpointEventTypeCommandChanged
- || event_type & eBreakpointEventTypeConditionChanged
- || event_type & eBreakpointEventTypeIgnoreChanged
- || event_type & eBreakpointEventTypeLocationsResolved)
- {
- // Don't do anything about these events, since the breakpoint commands already echo these actions.
- }
- else if (event_type & eBreakpointEventTypeLocationsAdded)
- {
- char message[256];
- uint32_t num_new_locations = SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
- if (num_new_locations > 0)
- {
- SBBreakpoint breakpoint = SBBreakpoint::GetBreakpointFromEvent(event);
- int message_len = ::snprintf (message, sizeof(message), "%d location%s added to breakpoint %d\n",
- num_new_locations,
- num_new_locations == 1 ? "" : "s",
- breakpoint.GetID());
- m_io_channel_ap->OutWrite(message, message_len, ASYNC);
- }
- }
- else if (event_type & eBreakpointEventTypeLocationsRemoved)
- {
- // These locations just get disabled, not sure it is worth spamming folks about this on the command line.
- }
- else if (event_type & eBreakpointEventTypeLocationsResolved)
- {
- // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy.
- }
-}
-
-// This function handles events that were broadcast by the process.
-void
-Driver::HandleProcessEvent (const SBEvent &event)
-{
- using namespace lldb;
- const uint32_t event_type = event.GetType();
-
- if (event_type & SBProcess::eBroadcastBitSTDOUT)
- {
- // The process has stdout available, get it and write it out to the
- // appropriate place.
- GetProcessSTDOUT ();
- }
- else if (event_type & SBProcess::eBroadcastBitSTDERR)
- {
- // The process has stderr available, get it and write it out to the
- // appropriate place.
- GetProcessSTDERR ();
- }
- else if (event_type & SBProcess::eBroadcastBitStateChanged)
- {
- // Drain all stout and stderr so we don't see any output come after
- // we print our prompts
- GetProcessSTDOUT ();
- GetProcessSTDERR ();
- // Something changed in the process; get the event and report the process's current status and location to
- // the user.
- StateType event_state = SBProcess::GetStateFromEvent (event);
- if (event_state == eStateInvalid)
- return;
-
- SBProcess process (SBProcess::GetProcessFromEvent (event));
- assert (process.IsValid());
-
- switch (event_state)
- {
- case eStateInvalid:
- case eStateUnloaded:
- case eStateConnected:
- case eStateAttaching:
- case eStateLaunching:
- case eStateStepping:
- case eStateDetached:
- {
- char message[1024];
- int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " %s\n", process.GetProcessID(),
- m_debugger.StateAsCString (event_state));
- m_io_channel_ap->OutWrite(message, message_len, ASYNC);
- }
- break;
-
- case eStateRunning:
- // Don't be chatty when we run...
- break;
-
- case eStateExited:
- {
- SBCommandReturnObject result;
- m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
- m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
- m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
- }
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- // Make sure the program hasn't been auto-restarted:
- if (SBProcess::GetRestartedFromEvent (event))
- {
- size_t num_reasons = SBProcess::GetNumRestartedReasonsFromEvent(event);
- if (num_reasons > 0)
- {
- // FIXME: Do we want to report this, or would that just be annoyingly chatty?
- if (num_reasons == 1)
- {
- char message[1024];
- const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, 0);
- int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted: %s\n",
- process.GetProcessID(), reason ? reason : "<UNKNOWN REASON>");
- m_io_channel_ap->OutWrite(message, message_len, ASYNC);
- }
- else
- {
- char message[1024];
- int message_len = ::snprintf (message, sizeof(message), "Process %" PRIu64 " stopped and restarted, reasons:\n",
- process.GetProcessID());
- m_io_channel_ap->OutWrite(message, message_len, ASYNC);
- for (size_t i = 0; i < num_reasons; i++)
- {
- const char *reason = SBProcess::GetRestartedReasonAtIndexFromEvent (event, i);
- int message_len = ::snprintf(message, sizeof(message), "\t%s\n", reason ? reason : "<UNKNOWN REASON>");
- m_io_channel_ap->OutWrite(message, message_len, ASYNC);
- }
- }
- }
- }
- else
- {
- if (GetDebugger().GetSelectedTarget() == process.GetTarget())
- {
- SBCommandReturnObject result;
- UpdateSelectedThread ();
- m_debugger.GetCommandInterpreter().HandleCommand("process status", result, false);
- m_io_channel_ap->ErrWrite (result.GetError(), result.GetErrorSize(), ASYNC);
- m_io_channel_ap->OutWrite (result.GetOutput(), result.GetOutputSize(), ASYNC);
- }
- else
- {
- SBStream out_stream;
- uint32_t target_idx = GetDebugger().GetIndexOfTarget(process.GetTarget());
- if (target_idx != UINT32_MAX)
- out_stream.Printf ("Target %d: (", target_idx);
- else
- out_stream.Printf ("Target <unknown index>: (");
- process.GetTarget().GetDescription (out_stream, eDescriptionLevelBrief);
- out_stream.Printf (") stopped.\n");
- m_io_channel_ap->OutWrite (out_stream.GetData(), out_stream.GetSize(), ASYNC);
- }
- }
- break;
- }
- }
-}
-
-void
-Driver::HandleThreadEvent (const SBEvent &event)
-{
- // At present the only thread event we handle is the Frame Changed event, and all we do for that is just
- // reprint the thread status for that thread.
- using namespace lldb;
- const uint32_t event_type = event.GetType();
- if (event_type == SBThread::eBroadcastBitStackChanged
- || event_type == SBThread::eBroadcastBitThreadSelected)
- {
- SBThread thread = SBThread::GetThreadFromEvent (event);
- if (thread.IsValid())
- {
- SBStream out_stream;
- thread.GetStatus(out_stream);
- m_io_channel_ap->OutWrite (out_stream.GetData (), out_stream.GetSize (), ASYNC);
- }
- }
-}
-
-// This function handles events broadcast by the IOChannel (HasInput, UserInterrupt, or ThreadShouldExit).
-
-bool
-Driver::HandleIOEvent (const SBEvent &event)
-{
- bool quit = false;
-
- const uint32_t event_type = event.GetType();
-
- if (event_type & IOChannel::eBroadcastBitHasUserInput)
- {
- // We got some input (i.e. a command string) from the user; pass it off to the command interpreter for
- // handling.
-
- const char *command_string = SBEvent::GetCStringFromEvent(event);
- if (command_string == NULL)
- command_string = "";
- SBCommandReturnObject result;
-
- // We don't want the result to bypass the OutWrite function in IOChannel, as this can result in odd
- // output orderings and problems with the prompt.
-
- // Note that we are in the process of executing a command
- m_executing_user_command = true;
-
- m_debugger.GetCommandInterpreter().HandleCommand (command_string, result, true);
-
- // Note that we are back from executing a user command
- m_executing_user_command = false;
-
- // Display any STDOUT/STDERR _prior_ to emitting the command result text
- GetProcessSTDOUT ();
- GetProcessSTDERR ();
-
- const bool only_if_no_immediate = true;
-
- // Now emit the command output text from the command we just executed
- const size_t output_size = result.GetOutputSize();
- if (output_size > 0)
- m_io_channel_ap->OutWrite (result.GetOutput(only_if_no_immediate), output_size, NO_ASYNC);
-
- // Now emit the command error text from the command we just executed
- const size_t error_size = result.GetErrorSize();
- if (error_size > 0)
- m_io_channel_ap->OutWrite (result.GetError(only_if_no_immediate), error_size, NO_ASYNC);
-
- // We are done getting and running our command, we can now clear the
- // m_waiting_for_command so we can get another one.
- m_waiting_for_command = false;
-
- // If our editline input reader is active, it means another input reader
- // got pushed onto the input reader and caused us to become deactivated.
- // When the input reader above us gets popped, we will get re-activated
- // and our prompt will refresh in our callback
- if (m_editline_reader.IsActive())
- {
- ReadyForCommand ();
- }
- }
- else if (event_type & IOChannel::eBroadcastBitUserInterrupt)
- {
- // This is here to handle control-c interrupts from the user. It has not yet really been implemented.
- // TO BE DONE: PROPERLY HANDLE CONTROL-C FROM USER
- //m_io_channel_ap->CancelInput();
- // Anything else? Send Interrupt to process?
- }
- else if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
- (event_type & IOChannel::eBroadcastBitThreadDidExit))
- {
- // If the IOChannel thread is trying to go away, then it is definitely
- // time to end the debugging session.
- quit = true;
- }
-
- return quit;
-}
-
-void
-Driver::MasterThreadBytesReceived (void *baton, const void *src, size_t src_len)
-{
- Driver *driver = (Driver*)baton;
- driver->GetFromMaster ((const char *)src, src_len);
-}
-
-void
-Driver::GetFromMaster (const char *src, size_t src_len)
-{
- // Echo the characters back to the Debugger's stdout, that way if you
- // type characters while a command is running, you'll see what you've typed.
- FILE *out_fh = m_debugger.GetOutputFileHandle();
- if (out_fh)
- ::fwrite (src, 1, src_len, out_fh);
-}
-
-size_t
-Driver::EditLineInputReaderCallback
-(
- void *baton,
- SBInputReader *reader,
- InputReaderAction notification,
- const char *bytes,
- size_t bytes_len
-)
-{
- Driver *driver = (Driver *)baton;
-
- switch (notification)
- {
- case eInputReaderActivate:
- break;
-
- case eInputReaderReactivate:
- if (driver->m_executing_user_command == false)
- driver->ReadyForCommand();
- break;
-
- case eInputReaderDeactivate:
- break;
-
- case eInputReaderAsynchronousOutputWritten:
- if (driver->m_io_channel_ap.get() != NULL)
- driver->m_io_channel_ap->RefreshPrompt();
- break;
-
- case eInputReaderInterrupt:
- if (driver->m_io_channel_ap.get() != NULL)
- {
- SBProcess process(driver->GetDebugger().GetSelectedTarget().GetProcess());
- if (!driver->m_io_channel_ap->EditLineHasCharacters()
- && process.IsValid()
- && (process.GetState() == lldb::eStateRunning || process.GetState() == lldb::eStateAttaching))
- {
- process.SendAsyncInterrupt ();
- }
- else
- {
- driver->m_io_channel_ap->OutWrite ("^C\n", 3, NO_ASYNC);
- // I wish I could erase the entire input line, but there's no public API for that.
- driver->m_io_channel_ap->EraseCharsBeforeCursor();
- driver->m_io_channel_ap->RefreshPrompt();
- }
- }
- break;
-
- case eInputReaderEndOfFile:
- if (driver->m_io_channel_ap.get() != NULL)
- {
- driver->m_io_channel_ap->OutWrite ("^D\n", 3, NO_ASYNC);
- driver->m_io_channel_ap->RefreshPrompt ();
- }
- write (driver->m_editline_pty.GetMasterFileDescriptor(), "quit\n", 5);
- break;
-
- case eInputReaderGotToken:
- write (driver->m_editline_pty.GetMasterFileDescriptor(), bytes, bytes_len);
- break;
-
- case eInputReaderDone:
- break;
- }
- return bytes_len;
-}
-
void
Driver::MainLoop ()
{
-#if defined(_MSC_VER)
- m_editline_slave_fh = stdin;
- FILE *editline_output_slave_fh = stdout;
- lldb_utility::PseudoTerminal editline_output_pty;
-#else
-
- char error_str[1024];
- if (m_editline_pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, error_str, sizeof(error_str)) == false)
- {
- ::fprintf (stderr, "error: failed to open driver pseudo terminal : %s", error_str);
- exit(1);
- }
- else
- {
- const char *driver_slave_name = m_editline_pty.GetSlaveName (error_str, sizeof(error_str));
- if (driver_slave_name == NULL)
- {
- ::fprintf (stderr, "error: failed to get slave name for driver pseudo terminal : %s", error_str);
- exit(2);
- }
- else
- {
- m_editline_slave_fh = ::fopen (driver_slave_name, "r+");
- if (m_editline_slave_fh == NULL)
- {
- SBError error;
- error.SetErrorToErrno();
- ::fprintf (stderr, "error: failed to get open slave for driver pseudo terminal : %s",
- error.GetCString());
- exit(3);
- }
-
- ::setbuf (m_editline_slave_fh, NULL);
- }
- }
-
- lldb_utility::PseudoTerminal editline_output_pty;
- FILE *editline_output_slave_fh = NULL;
-
- if (editline_output_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str, sizeof (error_str)) == false)
- {
- ::fprintf (stderr, "error: failed to open output pseudo terminal : %s", error_str);
- exit(1);
- }
- else
- {
- const char *output_slave_name = editline_output_pty.GetSlaveName (error_str, sizeof(error_str));
- if (output_slave_name == NULL)
- {
- ::fprintf (stderr, "error: failed to get slave name for output pseudo terminal : %s", error_str);
- exit(2);
- }
- else
- {
- editline_output_slave_fh = ::fopen (output_slave_name, "r+");
- if (editline_output_slave_fh == NULL)
- {
- SBError error;
- error.SetErrorToErrno();
- ::fprintf (stderr, "error: failed to get open slave for output pseudo terminal : %s",
- error.GetCString());
- exit(3);
- }
- ::setbuf (editline_output_slave_fh, NULL);
- }
- }
-#endif
-
- // struct termios stdin_termios;
-
if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0)
{
g_old_stdin_termios_is_valid = true;
@@ -1394,43 +861,6 @@ Driver::MainLoop ()
m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
- // You have to drain anything that comes to the master side of the PTY. master_out_comm is
- // for that purpose. The reason you need to do this is a curious reason... editline will echo
- // characters to the PTY when it gets characters while el_gets is not running, and then when
- // you call el_gets (or el_getc) it will try to reset the terminal back to raw mode which blocks
- // if there are unconsumed characters in the out buffer.
- // However, you don't need to do anything with the characters, since editline will dump these
- // unconsumed characters after printing the prompt again in el_gets.
-
- SBCommunication master_out_comm("driver.editline");
- master_out_comm.SetCloseOnEOF (false);
- master_out_comm.AdoptFileDesriptor(m_editline_pty.GetMasterFileDescriptor(), false);
- master_out_comm.SetReadThreadBytesReceivedCallback(Driver::MasterThreadBytesReceived, this);
-
- if (master_out_comm.ReadThreadStart () == false)
- {
- ::fprintf (stderr, "error: failed to start master out read thread");
- exit(5);
- }
-
- SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
-
- m_io_channel_ap.reset (new IOChannel(m_editline_slave_fh, editline_output_slave_fh, stdout, stderr, this));
-
-#if !defined (_MSC_VER)
- SBCommunication out_comm_2("driver.editline_output");
- out_comm_2.SetCloseOnEOF (false);
- out_comm_2.AdoptFileDesriptor (editline_output_pty.GetMasterFileDescriptor(), false);
- out_comm_2.SetReadThreadBytesReceivedCallback (IOChannel::LibeditOutputBytesReceived, m_io_channel_ap.get());
-
- if (out_comm_2.ReadThreadStart () == false)
- {
- ::fprintf (stderr, "error: failed to start libedit output read thread");
- exit (5);
- }
-#endif
-
-
struct winsize window_size;
if (isatty (STDIN_FILENO)
&& ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0)
@@ -1439,286 +869,114 @@ Driver::MainLoop ()
m_debugger.SetTerminalWidth (window_size.ws_col);
}
- // Since input can be redirected by the debugger, we must insert our editline
- // input reader in the queue so we know when our reader should be active
- // and so we can receive bytes only when we are supposed to.
- SBError err (m_editline_reader.Initialize (m_debugger,
- Driver::EditLineInputReaderCallback, // callback
- this, // baton
- eInputReaderGranularityByte, // token_size
- NULL, // end token - NULL means never done
- NULL, // prompt - taken care of elsewhere
- false)); // echo input - don't need Debugger
- // to do this, we handle it elsewhere
+ SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter();
- if (err.Fail())
+ // Before we handle any options from the command line, we parse the
+ // .lldbinit file in the user's home directory.
+ SBCommandReturnObject result;
+ sb_interpreter.SourceInitFileInHomeDirectory(result);
+ if (GetDebugMode())
{
- ::fprintf (stderr, "error: %s", err.GetCString());
- exit (6);
+ result.PutError (m_debugger.GetErrorFileHandle());
+ result.PutOutput (m_debugger.GetOutputFileHandle());
}
-
- m_debugger.PushInputReader (m_editline_reader);
- SBListener listener(m_debugger.GetListener());
- if (listener.IsValid())
+ // Now we handle options we got from the command line
+ // First source in the commands specified to be run before the file arguments are processed.
+ ExecuteInitialCommands(true);
+
+ // Was there a core file specified?
+ std::string core_file_spec("");
+ if (!m_option_data.m_core_file.empty())
+ core_file_spec.append("--core ").append(m_option_data.m_core_file);
+
+ char command_string[PATH_MAX * 2];
+ const size_t num_args = m_option_data.m_args.size();
+ if (num_args > 0)
{
-
- listener.StartListeningForEventClass(m_debugger,
- SBTarget::GetBroadcasterClassName(),
- SBTarget::eBroadcastBitBreakpointChanged);
- listener.StartListeningForEventClass(m_debugger,
- SBThread::GetBroadcasterClassName(),
- SBThread::eBroadcastBitStackChanged |
- SBThread::eBroadcastBitThreadSelected);
- listener.StartListeningForEvents (*m_io_channel_ap,
- IOChannel::eBroadcastBitHasUserInput |
- IOChannel::eBroadcastBitUserInterrupt |
- IOChannel::eBroadcastBitThreadShouldExit |
- IOChannel::eBroadcastBitThreadDidStart |
- IOChannel::eBroadcastBitThreadDidExit);
-
- if (m_io_channel_ap->Start ())
+ char arch_name[64];
+ if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
+ ::snprintf (command_string,
+ sizeof (command_string),
+ "target create --arch=%s %s \"%s\"",
+ arch_name,
+ core_file_spec.c_str(),
+ m_option_data.m_args[0].c_str());
+ else
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "target create %s \"%s\"",
+ core_file_spec.c_str(),
+ m_option_data.m_args[0].c_str());
+
+ m_debugger.HandleCommand (command_string);
+
+ if (num_args > 1)
{
- bool iochannel_thread_exited = false;
-
- listener.StartListeningForEvents (sb_interpreter.GetBroadcaster(),
- SBCommandInterpreter::eBroadcastBitQuitCommandReceived |
- SBCommandInterpreter::eBroadcastBitAsynchronousOutputData |
- SBCommandInterpreter::eBroadcastBitAsynchronousErrorData);
-
- // Before we handle any options from the command line, we parse the
- // .lldbinit file in the user's home directory.
- SBCommandReturnObject result;
- sb_interpreter.SourceInitFileInHomeDirectory(result);
- if (GetDebugMode())
- {
- result.PutError (m_debugger.GetErrorFileHandle());
- result.PutOutput (m_debugger.GetOutputFileHandle());
- }
-
- // Now we handle options we got from the command line
- // First source in the commands specified to be run before the file arguments are processed.
- ExecuteInitialCommands(true);
-
- // Was there a core file specified?
- std::string core_file_spec("");
- if (!m_option_data.m_core_file.empty())
- core_file_spec.append("--core ").append(m_option_data.m_core_file);
-
- char command_string[PATH_MAX * 2];
- const size_t num_args = m_option_data.m_args.size();
- if (num_args > 0)
- {
- char arch_name[64];
- if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name)))
- ::snprintf (command_string,
- sizeof (command_string),
- "target create --arch=%s %s \"%s\"",
- arch_name,
- core_file_spec.c_str(),
- m_option_data.m_args[0].c_str());
- else
- ::snprintf (command_string,
- sizeof(command_string),
- "target create %s \"%s\"",
- core_file_spec.c_str(),
- m_option_data.m_args[0].c_str());
-
- m_debugger.HandleCommand (command_string);
-
- if (num_args > 1)
- {
- m_debugger.HandleCommand ("settings clear target.run-args");
- char arg_cstr[1024];
- for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
- {
- ::snprintf (arg_cstr,
- sizeof(arg_cstr),
- "settings append target.run-args \"%s\"",
- m_option_data.m_args[arg_idx].c_str());
- m_debugger.HandleCommand (arg_cstr);
- }
- }
- }
- else if (!core_file_spec.empty())
- {
- ::snprintf (command_string,
- sizeof(command_string),
- "target create %s",
- core_file_spec.c_str());
- m_debugger.HandleCommand (command_string);;
- }
-
- // Now that all option parsing is done, we try and parse the .lldbinit
- // file in the current working directory
- sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
- if (GetDebugMode())
- {
- result.PutError(m_debugger.GetErrorFileHandle());
- result.PutOutput(m_debugger.GetOutputFileHandle());
- }
-
- // Now execute the commands specified for after the file arguments are processed.
- ExecuteInitialCommands(false);
-
- SBEvent event;
-
- // Make sure the IO channel is started up before we try to tell it we
- // are ready for input
- listener.WaitForEventForBroadcasterWithType (UINT32_MAX,
- *m_io_channel_ap,
- IOChannel::eBroadcastBitThreadDidStart,
- event);
- // If we were asked to attach, then do that here:
- // I'm going to use the command string rather than directly
- // calling the API's because then I don't have to recode the
- // event handling here.
- if (!m_option_data.m_process_name.empty()
- || m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
+ m_debugger.HandleCommand ("settings clear target.run-args");
+ char arg_cstr[1024];
+ for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx)
{
- std::string command_str("process attach ");
- if (m_option_data.m_process_pid != LLDB_INVALID_PROCESS_ID)
- {
- command_str.append("-p ");
- char pid_buffer[32];
- ::snprintf (pid_buffer, sizeof(pid_buffer), "%" PRIu64, m_option_data.m_process_pid);
- command_str.append(pid_buffer);
- }
- else
- {
- command_str.append("-n \"");
- command_str.append(m_option_data.m_process_name);
- command_str.push_back('\"');
- if (m_option_data.m_wait_for)
- command_str.append(" -w");
- }
-
- if (m_debugger.GetOutputFileHandle())
- ::fprintf (m_debugger.GetOutputFileHandle(),
- "Attaching to process with:\n %s\n",
- command_str.c_str());
-
- // Force the attach to be synchronous:
- bool orig_async = m_debugger.GetAsync();
- m_debugger.SetAsync(true);
- m_debugger.HandleCommand(command_str.c_str());
- m_debugger.SetAsync(orig_async);
+ ::snprintf (arg_cstr,
+ sizeof(arg_cstr),
+ "settings append target.run-args \"%s\"",
+ m_option_data.m_args[arg_idx].c_str());
+ m_debugger.HandleCommand (arg_cstr);
}
-
- ReadyForCommand ();
-
- while (!GetIsDone())
- {
- listener.WaitForEvent (UINT32_MAX, event);
- if (event.IsValid())
- {
- if (event.GetBroadcaster().IsValid())
- {
- uint32_t event_type = event.GetType();
- if (event.BroadcasterMatchesRef (*m_io_channel_ap))
- {
- if ((event_type & IOChannel::eBroadcastBitThreadShouldExit) ||
- (event_type & IOChannel::eBroadcastBitThreadDidExit))
- {
- SetIsDone();
- if (event_type & IOChannel::eBroadcastBitThreadDidExit)
- iochannel_thread_exited = true;
- }
- else
- {
- if (HandleIOEvent (event))
- SetIsDone();
- }
- }
- else if (SBProcess::EventIsProcessEvent (event))
- {
- HandleProcessEvent (event);
- }
- else if (SBBreakpoint::EventIsBreakpointEvent (event))
- {
- HandleBreakpointEvent (event);
- }
- else if (SBThread::EventIsThreadEvent (event))
- {
- HandleThreadEvent (event);
- }
- 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)
- {
- SetIsDone();
- }
- else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousErrorData)
- {
- const char *data = SBEvent::GetCStringFromEvent (event);
- m_io_channel_ap->ErrWrite (data, strlen(data), ASYNC);
- }
- else if (event_type & SBCommandInterpreter::eBroadcastBitAsynchronousOutputData)
- {
- const char *data = SBEvent::GetCStringFromEvent (event);
- m_io_channel_ap->OutWrite (data, strlen(data), ASYNC);
- }
- }
- }
- }
- }
-
- master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
- master_out_comm.Disconnect();
- master_out_comm.ReadThreadStop();
-
-#if !defined(_MSC_VER)
- out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
- out_comm_2.Disconnect();
- out_comm_2.ReadThreadStop();
-#endif
-
- editline_output_pty.CloseMasterFileDescriptor();
- reset_stdin_termios();
- fclose (stdin);
-
- CloseIOChannelFile ();
-
- if (!iochannel_thread_exited)
- {
- event.Clear();
- listener.GetNextEventForBroadcasterWithType (*m_io_channel_ap,
- IOChannel::eBroadcastBitThreadDidExit,
- event);
- if (!event.IsValid())
- {
- // Send end EOF to the driver file descriptor
- m_io_channel_ap->Stop();
- }
- }
-
- SBDebugger::Destroy (m_debugger);
}
}
-}
+ else if (!core_file_spec.empty())
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "target create %s",
+ core_file_spec.c_str());
+ m_debugger.HandleCommand (command_string);;
+ }
+ else if (!m_option_data.m_process_name.empty())
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "process attach --name '%s'%s",
+ m_option_data.m_process_name.c_str(),
+ m_option_data.m_wait_for ? " --waitfor" : "");
+ m_debugger.HandleCommand (command_string);
+ }
+ else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid)
+ {
+ ::snprintf (command_string,
+ sizeof(command_string),
+ "process attach --pid %" PRIu64,
+ m_option_data.m_process_pid);
+ m_debugger.HandleCommand (command_string);
+ }
+ ExecuteInitialCommands(false);
-void
-Driver::ReadyForCommand ()
-{
- if (m_waiting_for_command == false)
+ // Now that all option parsing is done, we try and parse the .lldbinit
+ // file in the current working directory
+ sb_interpreter.SourceInitFileInCurrentWorkingDirectory (result);
+ if (GetDebugMode())
{
- m_waiting_for_command = true;
- BroadcastEventByType (Driver::eBroadcastBitReadyForInput, true);
+ result.PutError(m_debugger.GetErrorFileHandle());
+ result.PutOutput(m_debugger.GetOutputFileHandle());
}
+
+ bool handle_events = true;
+ bool spawn_thread = false;
+ m_debugger.RunCommandInterpreter(handle_events, spawn_thread);
+
+ reset_stdin_termios();
+ fclose (stdin);
+
+ SBDebugger::Destroy (m_debugger);
}
+
void
Driver::ResizeWindow (unsigned short col)
{
GetDebugger().SetTerminalWidth (col);
- if (m_io_channel_ap.get() != NULL)
- {
- m_io_channel_ap->ElResize();
- }
}
void
diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h
index dcfd5ed11cd1..699244685d06 100644
--- a/tools/driver/Driver.h
+++ b/tools/driver/Driver.h
@@ -22,27 +22,15 @@
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
-#include "lldb/API/SBInputReader.h"
#define ASYNC true
#define NO_ASYNC false
class IOChannel;
-namespace lldb
-{
- class SBInputReader;
-}
-
-
class Driver : public lldb::SBBroadcaster
{
public:
- enum {
- eBroadcastBitReadyForInput = (1 << 0),
- eBroadcastBitThreadShouldExit = (1 << 1)
- };
-
Driver ();
virtual
@@ -51,24 +39,6 @@ public:
void
MainLoop ();
- void
- PutSTDIN (const char *src, size_t src_len);
-
- void
- GetFromMaster (const char *src, size_t src_len);
-
- bool
- HandleIOEvent (const lldb::SBEvent &event);
-
- void
- HandleProcessEvent (const lldb::SBEvent &event);
-
- void
- HandleBreakpointEvent (const lldb::SBEvent &event);
-
- void
- HandleThreadEvent (const lldb::SBEvent &event);
-
lldb::SBError
ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit);
@@ -137,66 +107,16 @@ public:
return m_debugger;
}
- bool
- EditlineReaderIsTop ()
- {
- return m_debugger.InputReaderIsTopReader (m_editline_reader);
- }
-
- bool
- GetIsDone () const
- {
- return m_done;
- }
-
- void
- SetIsDone ()
- {
- m_done = true;
- }
-
void
ResizeWindow (unsigned short col);
private:
lldb::SBDebugger m_debugger;
- lldb_utility::PseudoTerminal m_editline_pty;
- FILE *m_editline_slave_fh;
- lldb::SBInputReader m_editline_reader;
- std::unique_ptr<IOChannel> m_io_channel_ap;
OptionData m_option_data;
- bool m_executing_user_command;
- bool m_waiting_for_command;
- bool m_done;
void
ResetOptionValues ();
- size_t
- GetProcessSTDOUT ();
-
- size_t
- GetProcessSTDERR ();
-
- void
- UpdateSelectedThread ();
-
- void
- CloseIOChannelFile ();
-
- static size_t
- EditLineInputReaderCallback (void *baton,
- lldb::SBInputReader *reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len);
-
- static void
- ReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
- static void
- MasterThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
void
ReadyForCommand ();
};
diff --git a/tools/driver/ELWrapper.cpp b/tools/driver/ELWrapper.cpp
deleted file mode 100644
index 258f47e5169c..000000000000
--- a/tools/driver/ELWrapper.cpp
+++ /dev/null
@@ -1,422 +0,0 @@
-//===-- ELWrapper.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// this file is only relevant for Visual C++
-#if defined( _MSC_VER )
-
-#include "lldb/Host/windows/windows.h"
-
-#include "ELWrapper.h"
-#include <vector>
-#include <assert.h>
-
-// index one of the variable arguments
-// presuming "(EditLine *el, ..." is first in the argument list
-#define GETARG( X ) ( (void* ) *( ( (int**) &el ) + ((X) + 2) ) )
-
-// edit line EL_ADDFN function pointer type
-typedef unsigned char (*el_addfn_func)(EditLine *e, int ch);
-
-// edit line wrapper binding container
-struct el_binding
-{
- //
- const char *name;
- const char *help;
- // function pointer to callback routine
- el_addfn_func func;
- // ascii key this function is bound to
- const char *key;
-};
-
-// stored key bindings
-static std::vector<el_binding*> _bindings;
-
-//TODO: this should infact be related to the exact edit line context we create
-static void *clientData = NULL;
-
-// store the current prompt string
-// default to what we expect to receive anyway
-static const char *_prompt = "(lldb) ";
-
-#if !defined( _WIP_INPUT_METHOD )
-
-static char *
-el_get_s (char *buffer, int chars)
-{
- return gets_s(buffer, chars);
-}
-#else
-
-static void
-con_output (char _in)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get the cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // output this char
- WriteConsoleOutputCharacterA( hout, &_in, 1, info.dwCursorPosition, &written );
- // advance cursor position
- info.dwCursorPosition.X++;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
-}
-
-static void
-con_backspace (void)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // nudge cursor backwards
- info.dwCursorPosition.X--;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
- // blank out the last character
- WriteConsoleOutputCharacterA( hout, " ", 1, info.dwCursorPosition, &written );
-}
-
-static void
-con_return (void)
-{
- HANDLE hout = GetStdHandle( STD_OUTPUT_HANDLE );
- DWORD written = 0;
- // get cursor position
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo( hout, &info );
- // move onto the new line
- info.dwCursorPosition.X = 0;
- info.dwCursorPosition.Y++;
- SetConsoleCursorPosition( hout, info.dwCursorPosition );
-}
-
-static bool
-runBind (char _key)
-{
- for ( int i=0; i<_bindings.size(); i++ )
- {
- el_binding *bind = _bindings[i];
- if ( bind->key[0] == _key )
- {
- bind->func( (EditLine*) -1, _key );
- return true;
- }
- }
- return false;
-}
-
-// replacement get_s which is EL_BIND aware
-static char *
-el_get_s (char *buffer, int chars)
-{
- //
- char *head = buffer;
- //
- for ( ;; Sleep( 10 ) )
- {
- //
- INPUT_RECORD _record;
- //
- DWORD _read = 0;
- if ( ReadConsoleInputA( GetStdHandle( STD_INPUT_HANDLE ), &_record, 1, &_read ) == FALSE )
- break;
- // if we didnt read a key
- if ( _read == 0 )
- continue;
- // only interested in key events
- if ( _record.EventType != KEY_EVENT )
- continue;
- // is the key down
- if (! _record.Event.KeyEvent.bKeyDown )
- continue;
- // read the ascii key character
- char _key = _record.Event.KeyEvent.uChar.AsciiChar;
- // non ascii conformant key press
- if ( _key == 0 )
- {
- // check the scan code
- // if VK_UP scroll back through history
- // if VK_DOWN scroll forward through history
- continue;
- }
- // try to execute any bind this key may have
- if ( runBind( _key ) )
- continue;
- // if we read a return key
- if ( _key == '\n' || _key == '\r' )
- {
- con_return( );
- break;
- }
- // key is backspace
- if ( _key == 0x8 )
- {
- // avoid deleting past beginning
- if ( head > buffer )
- {
- con_backspace( );
- head--;
- }
- continue;
- }
-
- // add this key to the input buffer
- if ( (head-buffer) < (chars-1) )
- {
- con_output( _key );
- *(head++) = _key;
- }
- }
- // insert end of line character
- *head = '\0';
-
- return buffer;
-}
-#endif
-
-// edit line initalise
-EditLine *
-el_init (const char *, FILE *, FILE *, FILE *)
-{
- //
- SetConsoleTitleA( "lldb" );
- // return dummy handle
- return (EditLine*) -1;
-}
-
-const char *
-el_gets (EditLine *el, int *length)
-{
- // print the prompt if we have one
- if ( _prompt != NULL )
- printf( _prompt );
- // create a buffer for the user input
- char *buffer = new char[ MAX_PATH ];
- // try to get user input string
- if ( el_get_s( buffer, MAX_PATH ) )
- {
- // get the string length in 'length'
- while ( buffer[ *length ] != '\0' )
- (*length)++;
- // return the input buffer
- // remember that this memory has the be free'd somewhere
- return buffer;
- }
- else
- {
- // on error
- delete [] buffer;
- return NULL;
- }
-}
-
-int
-el_set (EditLine *el, int code, ...)
-{
- int **arg = (int**) &el;
- //
- switch ( code )
- {
- // edit line set prompt message
- case ( EL_PROMPT ):
- {
- // EL_PROMPT, char *(*f)( EditLine *)
- // define a prompt printing function as 'f', which is to return a string that
- // contains the prompt.
-
- // get the function pointer from the arg list
- void *func_vp = (void*) *(arg+2);
- // cast to suitable prototype
- const char* (*func_fp)(EditLine*) = (const char*(*)(EditLine *)) func_vp;
- // call to get the prompt as a string
- _prompt = func_fp( el );
- }
- break;
- case ( EL_EDITOR ):
- {
- // EL_EDITOR, const char *mode
- // set editing mode to "emacs" or "vi"
- }
- break;
- case ( EL_HIST ):
- {
- // EL_HIST, History *(*fun)(History *, int op, ... ), const char *ptr
- // defines which histroy function to use, which is usualy history(). Ptr should be the
- // value returned by history_init().
- }
- break;
- case ( EL_ADDFN ):
- {
- // EL_ADDFN, const char *name, const char *help, unsigned char (*func)(EditLine *e, int ch)
- // add a user defined function, func), referred to as 'name' which is invoked when a key which is bound to 'name' is
- // entered. 'help' is a description of 'name'. at involcation time, 'ch' is the key which caused the invocation. the
- // return value of 'func()' should be one of:
- // CC_NORM add a normal character
- // CC_NEWLINE end of line was entered
- // CC_EOF EOF was entered
- // CC_ARGHACK expecting further command input as arguments, do nothing visually.
- // CC_REFRESH refresh display.
- // CC_REFRESH_BEEP refresh display and beep.
- // CC_CURSOR cursor moved so update and perform CC_REFRESH
- // CC_REDISPLAY redisplay entire input line. this is usefull if a key binding outputs extra information.
- // CC_ERROR an error occured. beep and flush tty.
- // CC_FATAL fatal error, reset tty to known state.
-
- el_binding *binding = new el_binding;
- binding->name = (const char *) GETARG( 0 );
- binding->help = (const char *) GETARG( 1 );
- binding->func = (el_addfn_func) GETARG( 2 );
- binding->key = 0;
- // add this to the bindings list
- _bindings.push_back( binding );
- }
- break;
- case ( EL_BIND ):
- {
- // EL_BIND, const char *, ..., NULL
- // perform the BIND buildin command. Refer to editrc(5) for more information.
-
- const char *name = (const char*) GETARG( 1 );
-
- for ( int i=0; i<_bindings.size(); i++ )
- {
- el_binding *bind = _bindings[i];
- if ( strcmp( bind->name, name ) == 0 )
- {
- bind->key = (const char *) GETARG( 0 );
- break;
- }
- }
-
- }
- break;
- case ( EL_CLIENTDATA ):
- {
- clientData = GETARG( 0 );
- }
- break;
- default:
- assert( !"Not Implemented!" );
- }
- return 0;
-}
-
-void
-el_end (EditLine *el)
-{
- assert( !"Not implemented!" );
-}
-
-void
-el_reset (EditLine *)
-{
- assert( !"Not implemented!" );
-}
-
-int
-el_getc (EditLine *, char *)
-{
- assert( !"Not implemented!" );
- return 0;
-}
-
-void
-el_push (EditLine *, char *)
-{
- assert( !"Not implemented!" );
-}
-
-void
-el_beep (EditLine *)
-{
- Beep( 1000, 500 );
-}
-
-int
-el_parse (EditLine *, int, const char **)
-{
- assert( !"Not implemented!" );
- return 0;
-}
-
-int
-el_get (EditLine *el, int code, ...)
-{
- switch ( code )
- {
- case ( EL_CLIENTDATA ):
- {
- void **dout = (void**) GETARG( 0 );
- *dout = clientData;
- }
- break;
- default:
- assert( !"Not implemented!" );
- }
- return 0;
-}
-
-int
-el_source (EditLine *el, const char *file)
-{
- // init edit line by reading the contents of 'file'
- // nothing to do here on windows...
- return 0;
-}
-
-void
-el_resize (EditLine *)
-{
- assert( !"Not implemented!" );
-}
-
-const LineInfo *
-el_line (EditLine *el)
-{
- assert( !"Not implemented!" );
- return 0;
-}
-
-int
-el_insertstr (EditLine *, const char *)
-{
- assert( !"Not implemented!" );
- return 0;
-}
-
-void
-el_deletestr (EditLine *, int)
-{
- assert( !"Not implemented!" );
-}
-
-History *
-history_init (void)
-{
- // return dummy handle
- return (History*) -1;
-}
-
-void
-history_end (History *)
-{
- assert( !"Not implemented!" );
-}
-
-int
-history (History *, HistEvent *, int op, ...)
-{
- // perform operation 'op' on the history list with optional argumetns as needed by
- // the operation.
- return 0;
-}
-
-#endif
diff --git a/tools/driver/ELWrapper.h b/tools/driver/ELWrapper.h
deleted file mode 100644
index a30182d948b1..000000000000
--- a/tools/driver/ELWrapper.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//===-- ELWrapper.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#include <stdio.h>
-
-// EditLine editor function return codes.
-// For user-defined function interface
-#define CC_NORM 0
-#define CC_NEWLINE 1
-#define CC_EOF 2
-#define CC_ARGHACK 3
-#define CC_REFRESH 4
-#define CC_CURSOR 5
-#define CC_ERROR 6
-#define CC_FATAL 7
-#define CC_REDISPLAY 8
-#define CC_REFRESH_BEEP 9
-
-// el_set/el_get parameters
-#define EL_PROMPT 0 // , el_pfunc_t
-#define EL_TERMINAL 1 // , const char *
-#define EL_EDITOR 2 // , const char *
-#define EL_SIGNAL 3 // , int);
-#define EL_BIND 4 // , const char *, ..., NULL
-#define EL_TELLTC 5 // , const char *, ..., NULL
-#define EL_SETTC 6 // , const char *, ..., NULL
-#define EL_ECHOTC 7 // , const char *, ..., NULL
-#define EL_SETTY 8 // , const char *, ..., NULL
-#define EL_ADDFN 9 // , const char *, const char *, el_func_t
-#define EL_HIST 10 // , hist_fun_t, const char *
-#define EL_EDITMODE 11 // , int
-#define EL_RPROMPT 12 // , el_pfunc_t
-#define EL_GETCFN 13 // , el_rfunc_t
-#define EL_CLIENTDATA 14 // , void *
-#define EL_UNBUFFERED 15 // , int
-#define EL_PREP_TERM 16 // , int
-#define EL_GETTC 17 // , const char *, ..., NULL
-#define EL_GETFP 18 // , int, FILE **
-#define EL_SETFP 19 // , int, FILE *
-#define EL_REFRESH 20 // , void
-
-#define EL_BUILTIN_GETCFN (NULL)
-
-// history defines
-#define H_FUNC 0 // , UTSL
-#define H_SETSIZE 1 // , const int
-#define H_GETSIZE 2 // , void
-#define H_FIRST 3 // , void
-#define H_LAST 4 // , void
-#define H_PREV 5 // , void
-#define H_NEXT 6 // , void
-#define H_CURR 8 // , const int
-#define H_SET 7 // , int
-#define H_ADD 9 // , const char *
-#define H_ENTER 10 // , const char *
-#define H_APPEND 11 // , const char *
-#define H_END 12 // , void
-#define H_NEXT_STR 13 // , const char *
-#define H_PREV_STR 14 // , const char *
-#define H_NEXT_EVENT 15 // , const int
-#define H_PREV_EVENT 16 // , const int
-#define H_LOAD 17 // , const char *
-#define H_SAVE 18 // , const char *
-#define H_CLEAR 19 // , void
-#define H_SETUNIQUE 20 // , int
-#define H_GETUNIQUE 21 // , void
-#define H_DEL 22 // , int
-
-struct EditLine
-{
-};
-
-struct LineInfo
-{
- const char *buffer;
- const char *cursor;
- const char *lastchar;
-};
-
-struct History
-{
-};
-
-struct HistEvent
-{
- int num;
- const char *str;
-};
-
-extern "C"
-{
- // edit line API
- EditLine *el_init ( const char *, FILE *, FILE *, FILE * );
- const char *el_gets ( EditLine *, int * );
- int el_set ( EditLine *, int, ... );
-
- void el_end ( EditLine * );
- void el_reset ( EditLine * );
- int el_getc ( EditLine *, char * );
- void el_push ( EditLine *, char * );
- void el_beep ( EditLine * );
- int el_parse ( EditLine *, int, const char ** );
- int el_get ( EditLine *, int, ... );
- int el_source ( EditLine *, const char * );
- void el_resize ( EditLine * );
- const LineInfo *el_line ( EditLine * );
- int el_insertstr( EditLine *, const char * );
- void el_deletestr( EditLine *, int );
-
- // history API
- History *history_init( void );
- void history_end ( History * );
- int history ( History *, HistEvent *, int, ... );
-}; \ No newline at end of file
diff --git a/tools/driver/GetOptWrapper.cpp b/tools/driver/GetOptWrapper.cpp
deleted file mode 100644
index e7cdfd786c6e..000000000000
--- a/tools/driver/GetOptWrapper.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===-- GetOptWrapper.cpp ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// this file is only relevant for Visual C++
-#if defined( _MSC_VER )
-
-#include "GetOptWrapper.h"
-
-/*
-
-// already defined in lldbHostCommon.lib due to 'getopt.inc'
-
-extern int
-getopt_long_only
-(
- int ___argc,
- char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts,
- int *__longind
-)
-{
- return -1;
-}
-*/
-
-#endif \ No newline at end of file
diff --git a/tools/driver/GetOptWrapper.h b/tools/driver/GetOptWrapper.h
deleted file mode 100644
index 9c9cf03d7626..000000000000
--- a/tools/driver/GetOptWrapper.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===-- GetOptWrapper.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_GetOptWrapper_h_
-#define lldb_GetOptWrapper_h_
-
-// from getopt.h
-#define no_argument 0
-#define required_argument 1
-#define optional_argument 2
-
-// defined int unistd.h
-extern int optreset;
-
-// from getopt.h
-extern char *optarg;
-extern int optind;
-extern int opterr;
-extern int optopt;
-
-// option structure
-struct option
-{
- const char *name;
- // has_arg can't be an enum because some compilers complain about
- // type mismatches in all the code that assumes it is an int.
- int has_arg;
- int *flag;
- int val;
-};
-
-//
-extern int
-getopt_long_only
-(
- int ___argc,
- char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts,
- int *__longind
-);
-
-#endif // lldb_GetOptWrapper_h_ \ No newline at end of file
diff --git a/tools/driver/IOChannel.cpp b/tools/driver/IOChannel.cpp
deleted file mode 100644
index 7cba73aaae8c..000000000000
--- a/tools/driver/IOChannel.cpp
+++ /dev/null
@@ -1,656 +0,0 @@
-//===-- IOChannel.cpp -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Platform.h"
-#include "IOChannel.h"
-
-#include <map>
-
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBError.h"
-#include "lldb/API/SBEvent.h"
-#include "lldb/API/SBFileSpec.h"
-#include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBStringList.h"
-
-#include <string.h>
-#include <limits.h>
-
-using namespace lldb;
-
-typedef std::map<EditLine *, std::string> PromptMap;
-const char *g_default_prompt = "(lldb) ";
-PromptMap g_prompt_map;
-
-// Printing the following string causes libedit to back up to the beginning of the line & blank it out.
-const char undo_prompt_string[4] = { (char) 13, (char) 27, (char) 91, (char) 75};
-
-static const char*
-el_prompt(EditLine *el)
-{
- PromptMap::const_iterator pos = g_prompt_map.find (el);
- if (pos == g_prompt_map.end())
- return g_default_prompt;
- return pos->second.c_str();
-}
-
-const char *
-IOChannel::GetPrompt ()
-{
- PromptMap::const_iterator pos = g_prompt_map.find (m_edit_line);
- if (pos == g_prompt_map.end())
- return g_default_prompt;
- return pos->second.c_str();
-}
-
-bool
-IOChannel::EditLineHasCharacters ()
-{
- const LineInfo *line_info = el_line(m_edit_line);
- if (line_info)
- {
- // Sometimes we get called after the user has submitted the line, but before editline has
- // cleared the buffer. In that case the cursor will be pointing at the newline. That's
- // equivalent to having no characters on the line, since it has already been submitted.
- if (*line_info->cursor == '\n')
- return false;
- else
- return line_info->cursor != line_info->buffer;
- }
- else
- return false;
-}
-
-
-void
-IOChannel::EraseCharsBeforeCursor ()
-{
- const LineInfo *line_info = el_line(m_edit_line);
- if (line_info != NULL)
- el_deletestr(m_edit_line, line_info->cursor - line_info->buffer);
-}
-
-unsigned char
-IOChannel::ElCompletionFn (EditLine *e, int ch)
-{
- IOChannel *io_channel;
- if (el_get(e, EL_CLIENTDATA, &io_channel) == 0)
- {
- return io_channel->HandleCompletion (e, ch);
- }
- else
- {
- return CC_ERROR;
- }
-}
-
-void
-IOChannel::ElResize()
-{
- el_resize(m_edit_line);
-}
-
-unsigned char
-IOChannel::HandleCompletion (EditLine *e, int ch)
-{
- assert (e == m_edit_line);
-
- const LineInfo *line_info = el_line(m_edit_line);
- SBStringList completions;
- int page_size = 40;
-
- int num_completions = m_driver->GetDebugger().GetCommandInterpreter().HandleCompletion (line_info->buffer,
- line_info->cursor,
- line_info->lastchar,
- 0,
- -1,
- completions);
-
- if (num_completions == -1)
- {
- el_insertstr (m_edit_line, m_completion_key);
- return CC_REDISPLAY;
- }
- else if (num_completions == -2)
- {
- el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
- el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
- return CC_REDISPLAY;
- }
-
- // If we get a longer match display that first.
- const char *completion_str = completions.GetStringAtIndex(0);
- if (completion_str != NULL && *completion_str != '\0')
- {
- el_insertstr (m_edit_line, completion_str);
- return CC_REDISPLAY;
- }
-
- if (num_completions > 1)
- {
- const char *comment = "\nAvailable completions:";
-
- int num_elements = num_completions + 1;
- OutWrite(comment, strlen (comment), NO_ASYNC);
- if (num_completions < page_size)
- {
- for (int i = 1; i < num_elements; i++)
- {
- completion_str = completions.GetStringAtIndex(i);
- OutWrite("\n\t", 2, NO_ASYNC);
- OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
- }
- OutWrite ("\n", 1, NO_ASYNC);
- }
- else
- {
- int cur_pos = 1;
- char reply;
- int got_char;
- while (cur_pos < num_elements)
- {
- int endpoint = cur_pos + page_size;
- if (endpoint > num_elements)
- endpoint = num_elements;
- for (; cur_pos < endpoint; cur_pos++)
- {
- completion_str = completions.GetStringAtIndex(cur_pos);
- OutWrite("\n\t", 2, NO_ASYNC);
- OutWrite(completion_str, strlen (completion_str), NO_ASYNC);
- }
-
- if (cur_pos >= num_elements)
- {
- OutWrite("\n", 1, NO_ASYNC);
- break;
- }
-
- OutWrite("\nMore (Y/n/a): ", strlen ("\nMore (Y/n/a): "), NO_ASYNC);
- reply = 'n';
- got_char = el_getc(m_edit_line, &reply);
- if (got_char == -1 || reply == 'n')
- break;
- if (reply == 'a')
- page_size = num_elements - cur_pos;
- }
- }
-
- }
-
- if (num_completions == 0)
- return CC_REFRESH_BEEP;
- else
- return CC_REDISPLAY;
-}
-
-IOChannel::IOChannel
-(
- FILE *editline_in,
- FILE *editline_out,
- FILE *out,
- FILE *err,
- Driver *driver
-) :
- SBBroadcaster ("IOChannel"),
- m_output_mutex (),
- m_enter_elgets_time (),
- m_driver (driver),
- m_read_thread (LLDB_INVALID_HOST_THREAD),
- m_read_thread_should_exit (false),
- m_out_file (out),
- m_err_file (err),
- m_editline_out (editline_out),
- m_command_queue (),
- m_completion_key ("\t"),
- m_edit_line (::el_init (SBHostOS::GetProgramFileSpec().GetFilename(), editline_in, editline_out, editline_out)),
- m_history (history_init()),
- m_history_event(),
- m_getting_command (false),
- m_expecting_prompt (false),
- m_prompt_str (),
- m_refresh_request_pending (false)
-{
- assert (m_edit_line);
- el_set (m_edit_line, EL_PROMPT, el_prompt);
- el_set (m_edit_line, EL_EDITOR, "emacs");
- el_set (m_edit_line, EL_HIST, history, m_history);
- el_set (m_edit_line, EL_ADDFN, "lldb_complete", "LLDB completion function", IOChannel::ElCompletionFn);
- el_set (m_edit_line, EL_BIND, m_completion_key, "lldb_complete", NULL);
- el_set (m_edit_line, EL_BIND, "^r", "em-inc-search-prev", NULL); // Cycle through backwards search, entering string
- el_set (m_edit_line, EL_BIND, "^w", "ed-delete-prev-word", NULL); // Delete previous word, behave like bash does.
- el_set (m_edit_line, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); // Fix the delete key.
- el_set (m_edit_line, EL_CLIENTDATA, this);
-
- // Source $PWD/.editrc then $HOME/.editrc
- el_source (m_edit_line, NULL);
-
- assert (m_history);
- history (m_history, &m_history_event, H_SETSIZE, 800);
- history (m_history, &m_history_event, H_SETUNIQUE, 1);
- // Load history
- HistorySaveLoad (false);
-
- // Initialize time that ::el_gets was last called.
- m_enter_elgets_time.tv_sec = 0;
- m_enter_elgets_time.tv_usec = 0;
-
- // set the initial state to non flushed
- m_output_flushed = false;
-}
-
-IOChannel::~IOChannel ()
-{
- // Save history
- HistorySaveLoad (true);
-
- if (m_history != NULL)
- {
- ::history_end (m_history);
- m_history = NULL;
- }
-
- if (m_edit_line != NULL)
- {
- ::el_end (m_edit_line);
- m_edit_line = NULL;
- }
-}
-
-void
-IOChannel::HistorySaveLoad (bool save)
-{
- if (m_history != NULL)
- {
- char history_path[PATH_MAX];
- ::snprintf (history_path, sizeof(history_path), "~/.%s-history", SBHostOS::GetProgramFileSpec().GetFilename());
- if ((size_t)SBFileSpec::ResolvePath (history_path, history_path, sizeof(history_path)) < sizeof(history_path) - 1)
- {
- const char *path_ptr = history_path;
- if (save)
- ::history (m_history, &m_history_event, H_SAVE, path_ptr);
- else
- ::history (m_history, &m_history_event, H_LOAD, path_ptr);
- }
- }
-}
-
-void
-IOChannel::LibeditOutputBytesReceived (void *baton, const void *src, size_t src_len)
-{
- IOChannel *io_channel = (IOChannel *) baton;
- std::lock_guard<std::recursive_mutex> locker(io_channel->m_output_mutex);
- const char *bytes = (const char *) src;
-
- bool flush = false;
-
- // See if we have a 'flush' synchronization point in there.
- // this is performed from 'fputc ('\0', m_editline_out);' in LibeditGetInput()
- if (src_len > 0 && bytes[src_len-1] == '\0')
- {
- src_len--;
- flush = true;
- }
-
- if (io_channel->IsGettingCommand() && io_channel->m_expecting_prompt)
- {
- io_channel->m_prompt_str.append (bytes, src_len);
- // Log this to make sure the prompt is really what you think it is.
- if (io_channel->m_prompt_str.find (el_prompt(io_channel->m_edit_line)) == 0)
- {
- io_channel->m_expecting_prompt = false;
- io_channel->m_refresh_request_pending = false;
- io_channel->OutWrite (io_channel->m_prompt_str.c_str(),
- io_channel->m_prompt_str.size(), NO_ASYNC);
- io_channel->m_prompt_str.clear();
- }
- }
- else
- {
- if (io_channel->m_prompt_str.size() > 0)
- io_channel->m_prompt_str.clear();
- std::string tmp_str (bytes, src_len);
- if (tmp_str.find (el_prompt (io_channel->m_edit_line)) == 0)
- io_channel->m_refresh_request_pending = false;
- io_channel->OutWrite (bytes, src_len, NO_ASYNC);
- }
-
-#if !defined (_MSC_VER)
- if (flush)
- {
- io_channel->m_output_flushed = true;
- io_channel->m_output_cond.notify_all();
- }
-#endif
-
-}
-
-IOChannel::LibeditGetInputResult
-IOChannel::LibeditGetInput (std::string &new_line)
-{
- IOChannel::LibeditGetInputResult retval = IOChannel::eLibeditGetInputResultUnknown;
- if (m_edit_line != NULL)
- {
- int line_len = 0;
-
- // Set boolean indicating whether or not el_gets is trying to get input (i.e. whether or not to attempt
- // to refresh the prompt after writing data).
- SetGettingCommand (true);
- m_expecting_prompt = true;
-
- // Call el_gets to prompt the user and read the user's input.
- const char *line = ::el_gets (m_edit_line, &line_len);
-
-#if !defined (_MSC_VER)
- // Force the piped output from el_gets to finish processing.
- // el_gets does an fflush internally, which is not sufficient here; it only
- // writes the data into m_editline_out, but doesn't affect whether our worker
- // thread will read that data yet. So we block here manually.
- {
- std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
- m_output_flushed = false;
-
- // Write a synchronization point into the stream, so we can guarantee
- // LibeditOutputBytesReceived has processed everything up till that mark.
- fputc ('\0', m_editline_out);
-
- while (!m_output_flushed)
- {
- // wait until the condition variable is signaled
- m_output_cond.wait(m_output_mutex);
- }
- }
-#endif
-
- // Re-set the boolean indicating whether or not el_gets is trying to get input.
- SetGettingCommand (false);
-
- if (line)
- {
- retval = IOChannel::eLibeditGetInputValid;
- // strip any newlines off the end of the string...
- while (line_len > 0 && (line[line_len - 1] == '\n' || line[line_len - 1] == '\r'))
- --line_len;
- if (line_len > 0)
- {
- ::history (m_history, &m_history_event, H_ENTER, line);
- new_line.assign (line, line_len); // Omit the newline
- }
- else
- {
- retval = IOChannel::eLibeditGetInputEmpty;
- // Someone just hit ENTER, return the empty string
- new_line.clear();
- }
- // Return true to indicate success even if a string is empty
- return retval;
- }
- else
- {
- retval = (line_len == 0 ? IOChannel::eLibeditGetInputEOF : IOChannel::eLibeditGetInputResultError);
- }
- }
- // Return false to indicate failure. This can happen when the file handle
- // is closed (EOF).
- new_line.clear();
- return retval;
-}
-
-thread_result_t
-IOChannel::IOReadThread (void *ptr)
-{
- IOChannel *myself = static_cast<IOChannel *> (ptr);
- myself->Run();
- return NULL;
-}
-
-void
-IOChannel::Run ()
-{
- SBListener listener("IOChannel::Run");
- std::string new_line;
-
- SBBroadcaster interpreter_broadcaster (m_driver->GetDebugger().GetCommandInterpreter().GetBroadcaster());
- listener.StartListeningForEvents (interpreter_broadcaster,
- SBCommandInterpreter::eBroadcastBitResetPrompt |
- SBCommandInterpreter::eBroadcastBitThreadShouldExit |
- SBCommandInterpreter::eBroadcastBitQuitCommandReceived);
-
- listener.StartListeningForEvents (*this,
- IOChannel::eBroadcastBitThreadShouldExit);
-
- listener.StartListeningForEvents (*m_driver,
- Driver::eBroadcastBitReadyForInput |
- Driver::eBroadcastBitThreadShouldExit);
-
- // Let anyone know that the IO channel is up and listening and ready for events
- BroadcastEventByType (eBroadcastBitThreadDidStart);
- bool done = false;
- while (!done)
- {
- SBEvent event;
-
- listener.WaitForEvent (UINT32_MAX, event);
- if (!event.IsValid())
- continue;
-
- const uint32_t event_type = event.GetType();
-
- if (event.GetBroadcaster().IsValid())
- {
- if (event.BroadcasterMatchesPtr (m_driver))
- {
- if (event_type & Driver::eBroadcastBitReadyForInput)
- {
- std::string line;
-
- if (CommandQueueIsEmpty())
- {
- IOChannel::LibeditGetInputResult getline_result = LibeditGetInput(line);
- if (getline_result == IOChannel::eLibeditGetInputEOF)
- {
- // EOF occurred
- // pretend that a quit was typed so the user gets a potential
- // chance to confirm
- line.assign("quit");
- }
- else if (getline_result == IOChannel::eLibeditGetInputResultError || getline_result == IOChannel::eLibeditGetInputResultUnknown)
- {
- // some random error occurred, exit and don't ask because the state might be corrupt
- done = true;
- continue;
- }
- }
- else
- {
- GetCommandFromQueue (line);
- }
-
- // TO BE DONE: FIGURE OUT WHICH COMMANDS SHOULD NOT BE REPEATED IF USER PRESSES PLAIN 'RETURN'
- // AND TAKE CARE OF THAT HERE.
-
- SBEvent line_event(IOChannel::eBroadcastBitHasUserInput,
- line.c_str(),
- line.size());
- BroadcastEvent (line_event);
- }
- else if (event_type & Driver::eBroadcastBitThreadShouldExit)
- {
- done = true;
- continue;
- }
- }
- else if (event.BroadcasterMatchesRef (interpreter_broadcaster))
- {
- switch (event_type)
- {
- case SBCommandInterpreter::eBroadcastBitResetPrompt:
- {
- const char *new_prompt = SBEvent::GetCStringFromEvent (event);
- if (new_prompt)
- g_prompt_map[m_edit_line] = new_prompt;
- }
- break;
-
- case SBCommandInterpreter::eBroadcastBitThreadShouldExit:
- case SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
- done = true;
- break;
- }
- }
- else if (event.BroadcasterMatchesPtr (this))
- {
- if (event_type & IOChannel::eBroadcastBitThreadShouldExit)
- {
- done = true;
- continue;
- }
- }
- }
- }
- BroadcastEventByType (IOChannel::eBroadcastBitThreadDidExit);
- m_driver = NULL;
- m_read_thread = 0;
-}
-
-bool
-IOChannel::Start ()
-{
- if (IS_VALID_LLDB_HOST_THREAD(m_read_thread))
- return true;
-
- m_read_thread = SBHostOS::ThreadCreate("<lldb.driver.commandline_io>", (lldb::thread_func_t) IOChannel::IOReadThread, this, NULL);
-
- return (IS_VALID_LLDB_HOST_THREAD(m_read_thread));
-}
-
-bool
-IOChannel::Stop ()
-{
- if (!IS_VALID_LLDB_HOST_THREAD(m_read_thread))
- return true;
-
- BroadcastEventByType (eBroadcastBitThreadShouldExit);
-
- // Don't call Host::ThreadCancel since el_gets won't respond to this
- // function call -- the thread will just die and all local variables in
- // IOChannel::Run() won't get destructed down which is bad since there is
- // a local listener holding onto broadcasters... To ensure proper shutdown,
- // a ^D (control-D) sequence (0x04) should be written to other end of the
- // the "in" file handle that was passed into the contructor as closing the
- // file handle doesn't seem to make el_gets() exit....
- return SBHostOS::ThreadJoin (m_read_thread, NULL, NULL);
-}
-
-void
-IOChannel::RefreshPrompt ()
-{
- // If we are not in the middle of getting input from the user, there is no need to
- // refresh the prompt.
- std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
- if (! IsGettingCommand())
- return;
-
- // If we haven't finished writing the prompt, there's no need to refresh it.
- if (m_expecting_prompt)
- return;
-
- if (m_refresh_request_pending)
- return;
-
- ::el_set (m_edit_line, EL_REFRESH);
- m_refresh_request_pending = true;
-}
-
-void
-IOChannel::OutWrite (const char *buffer, size_t len, bool asynchronous)
-{
- if (len == 0 || buffer == NULL)
- return;
-
- // We're in the process of exiting -- IOChannel::Run() has already completed
- // and set m_driver to NULL - it is time for us to leave now. We might not
- // print the final ^D to stdout in this case. We need to do some re-work on
- // how the I/O streams are managed at some point.
- if (m_driver == NULL)
- {
- return;
- }
-
- // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
- if (m_driver->EditlineReaderIsTop() && asynchronous)
- ::fwrite (undo_prompt_string, 1, 4, m_out_file);
- ::fwrite (buffer, 1, len, m_out_file);
- if (asynchronous)
- m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
-}
-
-void
-IOChannel::ErrWrite (const char *buffer, size_t len, bool asynchronous)
-{
- if (len == 0 || buffer == NULL)
- return;
-
- // Use the mutex to make sure OutWrite and ErrWrite do not interfere with each other's output.
- std::lock_guard<std::recursive_mutex> locker(m_output_mutex);
- if (asynchronous)
- ::fwrite (undo_prompt_string, 1, 4, m_err_file);
- ::fwrite (buffer, 1, len, m_err_file);
- if (asynchronous)
- m_driver->GetDebugger().NotifyTopInputReader (eInputReaderAsynchronousOutputWritten);
-}
-
-void
-IOChannel::AddCommandToQueue (const char *command)
-{
- m_command_queue.push (std::string(command));
-}
-
-bool
-IOChannel::GetCommandFromQueue (std::string &cmd)
-{
- if (m_command_queue.empty())
- return false;
- cmd.swap(m_command_queue.front());
- m_command_queue.pop ();
- return true;
-}
-
-int
-IOChannel::CommandQueueSize () const
-{
- return m_command_queue.size();
-}
-
-void
-IOChannel::ClearCommandQueue ()
-{
- while (!m_command_queue.empty())
- m_command_queue.pop();
-}
-
-bool
-IOChannel::CommandQueueIsEmpty () const
-{
- return m_command_queue.empty();
-}
-
-bool
-IOChannel::IsGettingCommand () const
-{
- return m_getting_command;
-}
-
-void
-IOChannel::SetGettingCommand (bool new_value)
-{
- m_getting_command = new_value;
-}
diff --git a/tools/driver/IOChannel.h b/tools/driver/IOChannel.h
deleted file mode 100644
index 3788673da972..000000000000
--- a/tools/driver/IOChannel.h
+++ /dev/null
@@ -1,154 +0,0 @@
-//===-- IOChannel.h ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef lldb_IOChannel_h_
-#define lldb_IOChannel_h_
-
-#include <thread>
-#include <mutex>
-#include <atomic>
-#include <condition_variable>
-
-#include <string>
-#include <queue>
-#include "Driver.h"
-
-class IOChannel : public lldb::SBBroadcaster
-{
-public:
- enum {
- eBroadcastBitHasUserInput = (1 << 0),
- eBroadcastBitUserInterrupt = (1 << 1),
- eBroadcastBitThreadShouldExit = (1 << 2),
- eBroadcastBitThreadDidExit = (1 << 3),
- eBroadcastBitThreadDidStart = (1 << 4),
- eBroadcastBitsSTDOUT = (1 << 5),
- eBroadcastBitsSTDERR = (1 << 6),
- eBroadcastBitsSTDIN = (1 << 7),
- eAllEventBits = 0xffffffff
- };
-
- enum LibeditGetInputResult
- {
- eLibeditGetInputEOF = 0,
- eLibeditGetInputValid = 1,
- eLibeditGetInputEmpty = 2,
- eLibeditGetInputResultError = 4,
- eLibeditGetInputResultUnknown = 0xffffffff
- };
-
- IOChannel (FILE *editline_in,
- FILE *editline_out,
- FILE *out,
- FILE *err,
- Driver *driver = NULL);
-
- virtual
- ~IOChannel ();
-
- bool
- Start ();
-
- bool
- Stop ();
-
- static lldb::thread_result_t
- IOReadThread (void *);
-
- void
- Run ();
-
- void
- OutWrite (const char *buffer, size_t len, bool asynchronous);
-
- void
- ErrWrite (const char *buffer, size_t len, bool asynchronous);
-
- LibeditGetInputResult
- LibeditGetInput (std::string &);
-
- static void
- LibeditOutputBytesReceived (void *baton, const void *src,size_t src_len);
-
- void
- SetPrompt ();
-
- void
- RefreshPrompt ();
-
- void
- AddCommandToQueue (const char *command);
-
- bool
- GetCommandFromQueue (std::string &cmd);
-
- int
- CommandQueueSize () const;
-
- void
- ClearCommandQueue ();
-
- bool
- CommandQueueIsEmpty () const;
-
- const char *
- GetPrompt ();
-
- bool
- EditLineHasCharacters ();
-
- void
- EraseCharsBeforeCursor ();
-
- static unsigned char
- ElCompletionFn (EditLine *e, int ch);
-
- void
- ElResize();
-
-protected:
-
- bool
- IsGettingCommand () const;
-
- void
- SetGettingCommand (bool new_value);
-
-private:
-
- std::recursive_mutex m_output_mutex;
- std::condition_variable_any m_output_cond;
- struct timeval m_enter_elgets_time;
-
- Driver *m_driver;
- lldb::thread_t m_read_thread;
- bool m_read_thread_should_exit;
- FILE *m_out_file;
- FILE *m_err_file;
- FILE *m_editline_out;
- std::queue<std::string> m_command_queue;
- const char *m_completion_key;
-
- EditLine *m_edit_line;
- History *m_history;
- HistEvent m_history_event;
- bool m_getting_command;
- bool m_expecting_prompt;
- bool m_output_flushed;
- std::string m_prompt_str; // for accumlating the prompt as it gets written out by editline
- bool m_refresh_request_pending;
-
- void
- HistorySaveLoad (bool save);
-
- unsigned char
- HandleCompletion (EditLine *e, int ch);
-};
-
-#endif // lldb_IOChannel_h_
diff --git a/tools/driver/Platform.h b/tools/driver/Platform.h
index f1fe1e4aac18..faa2991bf6f3 100644
--- a/tools/driver/Platform.h
+++ b/tools/driver/Platform.h
@@ -18,9 +18,8 @@
#include <io.h>
#include <eh.h>
#include <inttypes.h>
- #include "ELWrapper.h"
#include "lldb/Host/windows/Windows.h"
- #include "GetOptWrapper.h"
+ #include "lldb/Host/HostGetOpt.h"
struct timeval
{