forked from OSchip/llvm-project
Fixed an issue where "command source" would not do the right thing:
- empty lines in init files would repeat previous command and cause errors to be displayed - all options to control showing the command, its output, if it should stop on error or continue, weren't being obeyed. llvm-svn: 200860
This commit is contained in:
parent
9b8aa38e45
commit
340b0309b5
|
@ -18,6 +18,7 @@
|
|||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Flags.h"
|
||||
#include "lldb/Core/StringList.h"
|
||||
#include "lldb/Core/ValueObjectList.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
@ -38,7 +39,8 @@ namespace lldb_private {
|
|||
IOHandler (Debugger &debugger,
|
||||
const lldb::StreamFileSP &input_sp,
|
||||
const lldb::StreamFileSP &output_sp,
|
||||
const lldb::StreamFileSP &error_sp);
|
||||
const lldb::StreamFileSP &error_sp,
|
||||
uint32_t flags);
|
||||
|
||||
virtual
|
||||
~IOHandler ();
|
||||
|
@ -162,11 +164,45 @@ namespace lldb_private {
|
|||
m_user_data = user_data;
|
||||
}
|
||||
|
||||
Flags &
|
||||
GetFlags ()
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
const Flags &
|
||||
GetFlags () const
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check if the input is being supplied interactively by a user
|
||||
///
|
||||
/// This will return true if the input stream is a terminal (tty or
|
||||
/// pty) and can cause IO handlers to do different things (like
|
||||
/// for a comfirmation when deleting all breakpoints).
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
GetIsInteractive ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check if the input is coming from a real terminal.
|
||||
///
|
||||
/// A real terminal has a valid size with a certain number of rows
|
||||
/// and colums. If this function returns true, then terminal escape
|
||||
/// sequences are expected to work (cursor movement escape sequences,
|
||||
/// clearning lines, etc).
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
GetIsRealTerminal ();
|
||||
|
||||
protected:
|
||||
Debugger &m_debugger;
|
||||
lldb::StreamFileSP m_input_sp;
|
||||
lldb::StreamFileSP m_output_sp;
|
||||
lldb::StreamFileSP m_error_sp;
|
||||
Flags m_flags;
|
||||
void *m_user_data;
|
||||
bool m_done;
|
||||
bool m_active;
|
||||
|
@ -340,6 +376,7 @@ namespace lldb_private {
|
|||
const lldb::StreamFileSP &input_sp,
|
||||
const lldb::StreamFileSP &output_sp,
|
||||
const lldb::StreamFileSP &error_sp,
|
||||
uint32_t flags,
|
||||
const char *editline_name, // Used for saving history files
|
||||
const char *prompt,
|
||||
bool multi_line,
|
||||
|
@ -408,9 +445,7 @@ namespace lldb_private {
|
|||
std::unique_ptr<Editline> m_editline_ap;
|
||||
IOHandlerDelegate &m_delegate;
|
||||
std::string m_prompt;
|
||||
bool m_multi_line;
|
||||
bool m_interactive;
|
||||
|
||||
bool m_multi_line;
|
||||
};
|
||||
|
||||
class IOHandlerConfirm :
|
||||
|
|
|
@ -52,7 +52,9 @@ public:
|
|||
m_stream (kInvalidStream),
|
||||
m_options (0),
|
||||
m_own_stream (false),
|
||||
m_own_descriptor (false)
|
||||
m_own_descriptor (false),
|
||||
m_is_interactive (eLazyBoolCalculate),
|
||||
m_is_real_terminal (eLazyBoolCalculate)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -61,7 +63,9 @@ public:
|
|||
m_stream (fh),
|
||||
m_options (0),
|
||||
m_own_stream (transfer_ownership),
|
||||
m_own_descriptor (false)
|
||||
m_own_descriptor (false),
|
||||
m_is_interactive (eLazyBoolCalculate),
|
||||
m_is_real_terminal (eLazyBoolCalculate)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -462,6 +466,32 @@ public:
|
|||
static uint32_t
|
||||
GetPermissions (const char *path, Error &error);
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return true if this file is interactive.
|
||||
///
|
||||
/// @return
|
||||
/// True if this file is a terminal (tty or pty), false
|
||||
/// otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
GetIsInteractive ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return true if this file from a real terminal.
|
||||
///
|
||||
/// Just knowing a file is a interactive isn't enough, we also need
|
||||
/// to know if the terminal has a width and height so we can do
|
||||
/// cursor movement and other terminal maninpulations by sending
|
||||
/// escape sequences.
|
||||
///
|
||||
/// @return
|
||||
/// True if this file is a terminal (tty, not a pty) that has
|
||||
/// a non-zero width and height, false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
GetIsRealTerminal ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Output printf formatted output to the stream.
|
||||
///
|
||||
|
@ -501,6 +531,9 @@ protected:
|
|||
return m_stream != kInvalidStream;
|
||||
}
|
||||
|
||||
void
|
||||
CalculateInteractiveAndTerminal ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Member variables
|
||||
//------------------------------------------------------------------
|
||||
|
@ -509,6 +542,8 @@ protected:
|
|||
uint32_t m_options;
|
||||
bool m_own_stream;
|
||||
bool m_own_descriptor;
|
||||
LazyBool m_is_interactive;
|
||||
LazyBool m_is_real_terminal;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -215,10 +215,10 @@ public:
|
|||
void
|
||||
HandleCommandsFromFile (FileSpec &file,
|
||||
ExecutionContext *context,
|
||||
bool stop_on_continue,
|
||||
bool stop_on_error,
|
||||
bool echo_commands,
|
||||
bool print_results,
|
||||
LazyBool stop_on_continue,
|
||||
LazyBool stop_on_error,
|
||||
LazyBool echo_commands,
|
||||
LazyBool print_results,
|
||||
LazyBool add_to_history,
|
||||
CommandReturnObject &result);
|
||||
|
||||
|
@ -515,6 +515,7 @@ private:
|
|||
bool m_batch_command_mode;
|
||||
ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told
|
||||
uint32_t m_command_source_depth;
|
||||
std::vector<uint32_t> m_command_source_flags;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -308,7 +308,9 @@ protected:
|
|||
|
||||
CommandOptions (CommandInterpreter &interpreter) :
|
||||
Options (interpreter),
|
||||
m_stop_on_error (true)
|
||||
m_stop_on_error (true),
|
||||
m_silent_run (false),
|
||||
m_stop_on_continue (true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -320,23 +322,21 @@ protected:
|
|||
{
|
||||
Error error;
|
||||
const int short_option = m_getopt_table[option_idx].val;
|
||||
bool success;
|
||||
|
||||
switch (short_option)
|
||||
{
|
||||
case 'e':
|
||||
error = m_stop_on_error.SetValueFromCString(option_arg);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat("invalid value for stop-on-continue: %s", option_arg);
|
||||
error = m_stop_on_continue.SetValueFromCString(option_arg);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
m_silent_run = Args::StringToBoolean(option_arg, true, &success);
|
||||
if (!success)
|
||||
error.SetErrorStringWithFormat("invalid value for silent-run: %s", option_arg);
|
||||
error = m_silent_run.SetValueFromCString(option_arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
|
||||
break;
|
||||
|
@ -349,8 +349,8 @@ protected:
|
|||
OptionParsingStarting ()
|
||||
{
|
||||
m_stop_on_error.Clear();
|
||||
m_silent_run = false;
|
||||
m_stop_on_continue = true;
|
||||
m_silent_run.Clear();
|
||||
m_stop_on_continue.Clear();
|
||||
}
|
||||
|
||||
const OptionDefinition*
|
||||
|
@ -366,8 +366,8 @@ protected:
|
|||
// Instance variables to hold the values for command options.
|
||||
|
||||
OptionValueBoolean m_stop_on_error;
|
||||
bool m_silent_run;
|
||||
bool m_stop_on_continue;
|
||||
OptionValueBoolean m_silent_run;
|
||||
OptionValueBoolean m_stop_on_continue;
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -378,23 +378,42 @@ protected:
|
|||
{
|
||||
const char *filename = command.GetArgumentAtIndex(0);
|
||||
|
||||
if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
|
||||
result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
|
||||
result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
|
||||
|
||||
FileSpec cmd_file (filename, true);
|
||||
ExecutionContext *exe_ctx = NULL; // Just use the default context.
|
||||
bool echo_commands = !m_options.m_silent_run;
|
||||
bool print_results = true;
|
||||
bool stop_on_error = m_options.m_stop_on_error.OptionWasSet() ? (bool)m_options.m_stop_on_error : m_interpreter.GetStopCmdSourceOnError();
|
||||
|
||||
m_interpreter.HandleCommandsFromFile (cmd_file,
|
||||
exe_ctx,
|
||||
m_options.m_stop_on_continue,
|
||||
stop_on_error,
|
||||
echo_commands,
|
||||
print_results,
|
||||
eLazyBoolCalculate,
|
||||
result);
|
||||
|
||||
// If any options were set, then use them
|
||||
if (m_options.m_stop_on_error.OptionWasSet() ||
|
||||
m_options.m_silent_run.OptionWasSet() ||
|
||||
m_options.m_stop_on_continue.OptionWasSet())
|
||||
{
|
||||
// Use user set settings
|
||||
LazyBool print_command = m_options.m_silent_run.GetCurrentValue() ? eLazyBoolNo : eLazyBoolYes;
|
||||
m_interpreter.HandleCommandsFromFile (cmd_file,
|
||||
exe_ctx,
|
||||
m_options.m_stop_on_continue.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on continue
|
||||
m_options.m_stop_on_error.GetCurrentValue() ? eLazyBoolYes : eLazyBoolNo, // Stop on error
|
||||
print_command, // Echo command
|
||||
print_command, // Print command output
|
||||
eLazyBoolCalculate, // Add to history
|
||||
result);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// No options were set, inherit any settings from nested "command source" commands,
|
||||
// or set to sane default settings...
|
||||
m_interpreter.HandleCommandsFromFile (cmd_file,
|
||||
exe_ctx,
|
||||
eLazyBoolCalculate, // Stop on continue
|
||||
eLazyBoolCalculate, // Stop on error
|
||||
eLazyBoolCalculate, // Echo command
|
||||
eLazyBoolCalculate, // Print command output
|
||||
eLazyBoolCalculate, // Add to history
|
||||
result);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -10,12 +10,6 @@
|
|||
|
||||
#include "lldb/lldb-python.h"
|
||||
|
||||
#include <stdio.h> /* ioctl, TIOCGWINSZ */
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/ioctl.h> /* ioctl, TIOCGWINSZ */
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "lldb/Breakpoint/BreakpointLocation.h"
|
||||
|
@ -43,9 +37,10 @@ using namespace lldb_private;
|
|||
|
||||
IOHandler::IOHandler (Debugger &debugger) :
|
||||
IOHandler (debugger,
|
||||
StreamFileSP(), // Adopt STDIN from top input reader
|
||||
StreamFileSP(), // Adopt STDOUT from top input reader
|
||||
StreamFileSP()) // Adopt STDERR from top input reader
|
||||
StreamFileSP(), // Adopt STDIN from top input reader
|
||||
StreamFileSP(), // Adopt STDOUT from top input reader
|
||||
StreamFileSP(), // Adopt STDERR from top input reader
|
||||
0) // Flags
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -53,11 +48,13 @@ IOHandler::IOHandler (Debugger &debugger) :
|
|||
IOHandler::IOHandler (Debugger &debugger,
|
||||
const lldb::StreamFileSP &input_sp,
|
||||
const lldb::StreamFileSP &output_sp,
|
||||
const lldb::StreamFileSP &error_sp) :
|
||||
const lldb::StreamFileSP &error_sp,
|
||||
uint32_t flags) :
|
||||
m_debugger (debugger),
|
||||
m_input_sp (input_sp),
|
||||
m_output_sp (output_sp),
|
||||
m_error_sp (error_sp),
|
||||
m_flags (flags),
|
||||
m_user_data (NULL),
|
||||
m_done (false),
|
||||
m_active (false)
|
||||
|
@ -141,6 +138,17 @@ IOHandler::GetErrorStreamFile()
|
|||
return m_error_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
IOHandler::GetIsInteractive ()
|
||||
{
|
||||
return GetInputStreamFile()->GetFile().GetIsInteractive ();
|
||||
}
|
||||
|
||||
bool
|
||||
IOHandler::GetIsRealTerminal ()
|
||||
{
|
||||
return GetInputStreamFile()->GetFile().GetIsRealTerminal();
|
||||
}
|
||||
|
||||
IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
|
||||
const char *prompt,
|
||||
|
@ -308,6 +316,7 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
|
|||
StreamFileSP(), // Inherit input from top input reader
|
||||
StreamFileSP(), // Inherit output from top input reader
|
||||
StreamFileSP(), // Inherit error from top input reader
|
||||
0, // Flags
|
||||
editline_name, // Used for saving history files
|
||||
prompt,
|
||||
multi_line,
|
||||
|
@ -319,32 +328,23 @@ IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
|
|||
const lldb::StreamFileSP &input_sp,
|
||||
const lldb::StreamFileSP &output_sp,
|
||||
const lldb::StreamFileSP &error_sp,
|
||||
uint32_t flags,
|
||||
const char *editline_name, // Used for saving history files
|
||||
const char *prompt,
|
||||
bool multi_line,
|
||||
IOHandlerDelegate &delegate) :
|
||||
IOHandler (debugger, input_sp, output_sp, error_sp),
|
||||
IOHandler (debugger, input_sp, output_sp, error_sp, flags),
|
||||
m_editline_ap (),
|
||||
m_delegate (delegate),
|
||||
m_prompt (),
|
||||
m_multi_line (multi_line),
|
||||
m_interactive (false)
|
||||
m_multi_line (multi_line)
|
||||
{
|
||||
SetPrompt(prompt);
|
||||
|
||||
bool use_editline = false;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
const int in_fd = GetInputFD();
|
||||
struct winsize window_size;
|
||||
if (isatty (in_fd))
|
||||
{
|
||||
m_interactive = true;
|
||||
if (::ioctl (in_fd, TIOCGWINSZ, &window_size) == 0)
|
||||
{
|
||||
if (window_size.ws_col > 0)
|
||||
use_editline = true;
|
||||
}
|
||||
}
|
||||
use_editline = m_input_sp->GetFile().GetIsRealTerminal();
|
||||
#else
|
||||
use_editline = true;
|
||||
#endif
|
||||
|
@ -382,7 +382,7 @@ IOHandlerEditline::GetLine (std::string &line)
|
|||
FILE *in = GetInputFILE();
|
||||
if (in)
|
||||
{
|
||||
if (m_interactive)
|
||||
if (GetIsInteractive())
|
||||
{
|
||||
const char *prompt = GetPrompt();
|
||||
if (prompt && prompt[0])
|
||||
|
@ -432,7 +432,7 @@ IOHandlerEditline::GetLine (std::string &line)
|
|||
// No more input file, we are done...
|
||||
SetIsDone(true);
|
||||
}
|
||||
return !line.empty();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "lldb/Host/windows/windows.h"
|
||||
|
@ -78,7 +80,9 @@ File::File(const char *path, uint32_t options, uint32_t permissions) :
|
|||
m_stream (kInvalidStream),
|
||||
m_options (),
|
||||
m_own_stream (false),
|
||||
m_own_descriptor (false)
|
||||
m_own_descriptor (false),
|
||||
m_is_interactive (eLazyBoolCalculate),
|
||||
m_is_real_terminal (eLazyBoolCalculate)
|
||||
{
|
||||
Open (path, options, permissions);
|
||||
}
|
||||
|
@ -90,7 +94,10 @@ File::File (const FileSpec& filespec,
|
|||
m_stream (kInvalidStream),
|
||||
m_options (0),
|
||||
m_own_stream (false),
|
||||
m_own_descriptor (false)
|
||||
m_own_descriptor (false),
|
||||
m_is_interactive (eLazyBoolCalculate),
|
||||
m_is_real_terminal (eLazyBoolCalculate)
|
||||
|
||||
{
|
||||
if (filespec)
|
||||
{
|
||||
|
@ -103,7 +110,9 @@ File::File (const File &rhs) :
|
|||
m_stream (kInvalidStream),
|
||||
m_options (0),
|
||||
m_own_stream (false),
|
||||
m_own_descriptor (false)
|
||||
m_own_descriptor (false),
|
||||
m_is_interactive (eLazyBoolCalculate),
|
||||
m_is_real_terminal (eLazyBoolCalculate)
|
||||
{
|
||||
Duplicate (rhs);
|
||||
}
|
||||
|
@ -371,6 +380,8 @@ File::Close ()
|
|||
m_options = 0;
|
||||
m_own_stream = false;
|
||||
m_own_descriptor = false;
|
||||
m_is_interactive = eLazyBoolCalculate;
|
||||
m_is_real_terminal = eLazyBoolCalculate;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -866,3 +877,41 @@ File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
|
|||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void
|
||||
File::CalculateInteractiveAndTerminal ()
|
||||
{
|
||||
const int fd = GetDescriptor();
|
||||
if (fd >= 0)
|
||||
{
|
||||
m_is_interactive = eLazyBoolNo;
|
||||
m_is_real_terminal = eLazyBoolNo;
|
||||
if (isatty(fd))
|
||||
{
|
||||
m_is_interactive = eLazyBoolYes;
|
||||
struct winsize window_size;
|
||||
if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0)
|
||||
{
|
||||
if (window_size.ws_col > 0)
|
||||
m_is_real_terminal = eLazyBoolYes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
File::GetIsInteractive ()
|
||||
{
|
||||
if (m_is_interactive == eLazyBoolCalculate)
|
||||
CalculateInteractiveAndTerminal ();
|
||||
return m_is_interactive == eLazyBoolYes;
|
||||
}
|
||||
|
||||
bool
|
||||
File::GetIsRealTerminal ()
|
||||
{
|
||||
if (m_is_real_terminal == eLazyBoolCalculate)
|
||||
CalculateInteractiveAndTerminal();
|
||||
return m_is_real_terminal == eLazyBoolYes;
|
||||
}
|
||||
|
||||
|
|
|
@ -2390,14 +2390,15 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
|
|||
|
||||
if (init_file.Exists())
|
||||
{
|
||||
ExecutionContext *exe_ctx = NULL; // We don't have any context yet.
|
||||
bool stop_on_continue = true;
|
||||
bool stop_on_error = false;
|
||||
bool echo_commands = false;
|
||||
bool print_results = false;
|
||||
|
||||
const bool saved_batch = SetBatchCommandMode (true);
|
||||
HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result);
|
||||
HandleCommandsFromFile (init_file,
|
||||
NULL, // Execution context
|
||||
eLazyBoolYes, // Stop on continue
|
||||
eLazyBoolNo, // Stop on error
|
||||
eLazyBoolNo, // Don't echo commands
|
||||
eLazyBoolNo, // Don't print command output
|
||||
eLazyBoolNo, // Don't add the commands that are sourced into the history buffer
|
||||
result);
|
||||
SetBatchCommandMode (saved_batch);
|
||||
}
|
||||
else
|
||||
|
@ -2546,13 +2547,21 @@ CommandInterpreter::HandleCommands (const StringList &commands,
|
|||
return;
|
||||
}
|
||||
|
||||
// Make flags that we can pass into the IOHandler so our delegates can do the right thing
|
||||
enum {
|
||||
eHandleCommandFlagStopOnContinue = (1u << 0),
|
||||
eHandleCommandFlagStopOnError = (1u << 1),
|
||||
eHandleCommandFlagEchoCommand = (1u << 2),
|
||||
eHandleCommandFlagPrintResult = (1u << 3)
|
||||
};
|
||||
|
||||
void
|
||||
CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
|
||||
ExecutionContext *context,
|
||||
bool stop_on_continue,
|
||||
bool stop_on_error,
|
||||
bool echo_command,
|
||||
bool print_result,
|
||||
LazyBool stop_on_continue,
|
||||
LazyBool stop_on_error,
|
||||
LazyBool echo_command,
|
||||
LazyBool print_result,
|
||||
LazyBool add_to_history,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
|
@ -2567,15 +2576,93 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
|
|||
{
|
||||
Debugger &debugger = GetDebugger();
|
||||
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (stop_on_continue == eLazyBoolCalculate)
|
||||
{
|
||||
if (m_command_source_flags.empty())
|
||||
{
|
||||
// Echo command by default
|
||||
flags |= eHandleCommandFlagStopOnContinue;
|
||||
}
|
||||
else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
|
||||
{
|
||||
flags |= eHandleCommandFlagStopOnContinue;
|
||||
}
|
||||
}
|
||||
else if (stop_on_continue == eLazyBoolYes)
|
||||
{
|
||||
flags |= eHandleCommandFlagStopOnContinue;
|
||||
}
|
||||
|
||||
if (stop_on_error == eLazyBoolCalculate)
|
||||
{
|
||||
if (m_command_source_flags.empty())
|
||||
{
|
||||
if (GetStopCmdSourceOnError())
|
||||
flags |= eHandleCommandFlagStopOnError;
|
||||
}
|
||||
else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
|
||||
{
|
||||
flags |= eHandleCommandFlagStopOnError;
|
||||
}
|
||||
}
|
||||
else if (stop_on_error == eLazyBoolYes)
|
||||
{
|
||||
flags |= eHandleCommandFlagStopOnError;
|
||||
}
|
||||
|
||||
if (echo_command == eLazyBoolCalculate)
|
||||
{
|
||||
if (m_command_source_flags.empty())
|
||||
{
|
||||
// Echo command by default
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
|
||||
{
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
}
|
||||
else if (echo_command == eLazyBoolYes)
|
||||
{
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
|
||||
if (print_result == eLazyBoolCalculate)
|
||||
{
|
||||
if (m_command_source_flags.empty())
|
||||
{
|
||||
// Echo command by default
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
|
||||
{
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
}
|
||||
else if (print_result == eLazyBoolYes)
|
||||
{
|
||||
flags |= eHandleCommandFlagEchoCommand;
|
||||
}
|
||||
|
||||
// Used for inheriting the right settings when "command source" might have
|
||||
// nested "command source" commands
|
||||
m_command_source_flags.push_back(flags);
|
||||
IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
|
||||
input_file_sp,
|
||||
debugger.GetOutputFile(),
|
||||
debugger.GetErrorFile(),
|
||||
flags,
|
||||
NULL, // Pass in NULL for "editline_name" so no history is saved, or written
|
||||
m_debugger.GetPrompt(),
|
||||
false, // Not multi-line
|
||||
*this));
|
||||
m_command_source_depth++;
|
||||
m_debugger.RunIOHandler(io_handler_sp);
|
||||
if (!m_command_source_flags.empty())
|
||||
m_command_source_flags.pop_back();
|
||||
m_command_source_depth--;
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
|
@ -2583,21 +2670,6 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
|
|||
result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool success;
|
||||
StringList commands;
|
||||
success = commands.ReadFileLines(cmd_file);
|
||||
if (!success)
|
||||
{
|
||||
result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return;
|
||||
}
|
||||
m_command_source_depth++;
|
||||
HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result);
|
||||
m_command_source_depth--;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2886,31 +2958,59 @@ CommandInterpreter::GetProcessOutput ()
|
|||
void
|
||||
CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
|
||||
{
|
||||
const bool is_interactive = io_handler.GetIsInteractive();
|
||||
if (is_interactive == false)
|
||||
{
|
||||
// When we are not interactive, don't execute blank lines. This will happen
|
||||
// sourcing a commands file. We don't want blank lines to repeat the previous
|
||||
// command and cause any errors to occur (like redefining an alias, get an error
|
||||
// and stop parsing the commands file).
|
||||
if (line.empty())
|
||||
return;
|
||||
|
||||
// When using a non-interactive file handle (like when sourcing commands from a file)
|
||||
// we need to echo the command out so we don't just see the command output and no
|
||||
// command...
|
||||
if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
|
||||
io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
|
||||
}
|
||||
|
||||
lldb_private::CommandReturnObject result;
|
||||
HandleCommand(line.c_str(), eLazyBoolCalculate, result);
|
||||
|
||||
// Display any STDOUT/STDERR _prior_ to emitting the command result text
|
||||
GetProcessOutput ();
|
||||
|
||||
// Now emit the command output text from the command we just executed
|
||||
const char *output = result.GetOutputData();
|
||||
if (output && output[0])
|
||||
io_handler.GetOutputStreamFile()->PutCString(output);
|
||||
if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
|
||||
{
|
||||
// Display any STDOUT/STDERR _prior_ to emitting the command result text
|
||||
GetProcessOutput ();
|
||||
|
||||
const char *output = result.GetOutputData();
|
||||
if (output && output[0])
|
||||
io_handler.GetOutputStreamFile()->PutCString(output);
|
||||
|
||||
// Now emit the command error text from the command we just executed
|
||||
const char *error = result.GetErrorData();
|
||||
if (error && error[0])
|
||||
io_handler.GetErrorStreamFile()->PutCString(error);
|
||||
// Now emit the command error text from the command we just executed
|
||||
const char *error = result.GetErrorData();
|
||||
if (error && error[0])
|
||||
io_handler.GetErrorStreamFile()->PutCString(error);
|
||||
}
|
||||
|
||||
switch (result.GetStatus())
|
||||
{
|
||||
case eReturnStatusInvalid:
|
||||
case eReturnStatusSuccessFinishNoResult:
|
||||
case eReturnStatusSuccessFinishResult:
|
||||
case eReturnStatusStarted:
|
||||
break;
|
||||
|
||||
case eReturnStatusSuccessContinuingNoResult:
|
||||
case eReturnStatusSuccessContinuingResult:
|
||||
case eReturnStatusStarted:
|
||||
if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
|
||||
io_handler.SetIsDone(true);
|
||||
break;
|
||||
|
||||
case eReturnStatusFailed:
|
||||
if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
|
||||
io_handler.SetIsDone(true);
|
||||
break;
|
||||
|
||||
case eReturnStatusQuit:
|
||||
|
@ -2984,6 +3084,7 @@ CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
|
|||
m_debugger.GetInputFile(),
|
||||
m_debugger.GetOutputFile(),
|
||||
m_debugger.GetErrorFile(),
|
||||
eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult,
|
||||
"lldb",
|
||||
m_debugger.GetPrompt(),
|
||||
multiple_lines,
|
||||
|
|
Loading…
Reference in New Issue