diff options
author | emaste <emaste@FreeBSD.org> | 2014-07-23 19:35:02 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2014-07-23 19:35:02 +0000 |
commit | aa794b38fedea0f2e99519975acab0b289714b41 (patch) | |
tree | d542e0aa192601387eab969343acfada413521e6 /contrib/llvm/tools/lldb/source/Commands | |
parent | 35d9abcb8d9ec0494bd89b56ca40aa22b6206e54 (diff) | |
download | FreeBSD-src-aa794b38fedea0f2e99519975acab0b289714b41.zip FreeBSD-src-aa794b38fedea0f2e99519975acab0b289714b41.tar.gz |
MFC r262528: Update LLDB snapshot to upstream r202189
Highlights include (upstream revs in parens):
- Improvements to the remote GDB protocol client
(r196610, r197579, r197857, r200072, and others)
- Bug fixes for big-endian targets
(r196808)
- Initial support for libdispatch (GCD) queues in the debuggee
(r197190)
- Add "step-avoid-libraries" setting
(r199943)
- IO subsystem improvements (including initial work on a curses gui)
(r200263)
- Support hardware watchpoints on FreeBSD
(r201706)
- Improved unwinding through hand-written assembly functions
(r201839)
- Handle DW_TAG_unspecified_parameters for variadic functions
(r202061)
- Fix Ctrl+C interrupting a running inferior process
(r202086, r202154)
- Various bug fixes for memory leaks, LLDB segfaults, the C++ demangler,
ELF core files, DWARF debug info, and others.
Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands')
17 files changed, 1018 insertions, 1345 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index e540461..532d6ce 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -16,6 +16,7 @@ #include "CommandObjectBreakpointCommand.h" #include "CommandObjectBreakpoint.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" @@ -34,7 +35,9 @@ using namespace lldb_private; //------------------------------------------------------------------------- -class CommandObjectBreakpointCommandAdd : public CommandObjectParsed +class CommandObjectBreakpointCommandAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: @@ -43,6 +46,7 @@ public: "add", "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.", NULL), + IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand), m_options (interpreter) { SetHelpLong ( @@ -207,42 +211,47 @@ one command per line.\n" ); return &m_options; } - void - CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, - CommandReturnObject &result) + virtual void + IOHandlerActivated (IOHandler &io_handler) { - InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - if (reader_sp && data_ap.get()) + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); - - Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback, - bp_options, // baton - eInputReaderGranularityLine, // token size, to pass to callback function - "DONE", // end token - "> ", // prompt - true)); // echo input - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } + output_sp->PutCString(g_reader_instructions); + output_sp->Flush(); } - else + } + + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + { + io_handler.SetIsDone(true); + + BreakpointOptions *bp_options = (BreakpointOptions *) io_handler.GetUserData(); + if (bp_options) { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); + std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); + if (data_ap.get()) + { + data_ap->user_source.SplitIntoLines (line.c_str(), line.size()); + BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); + bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp); + } } } + void + CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, + CommandReturnObject &result) + { + m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + bp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } + /// Set a one-liner as the callback for the breakpoint. void SetBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -262,93 +271,6 @@ one command per line.\n" ); return; } - - static size_t - GenerateBreakpointCommandCallback (void *baton, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len) - { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - - switch (notification) - { - case eInputReaderActivate: - if (!batch_mode) - { - out_stream->Printf ("%s\n", g_reader_instructions); - if (reader.GetPrompt()) - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderDeactivate: - break; - - case eInputReaderReactivate: - if (reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderAsynchronousOutputWritten: - break; - - case eInputReaderGotToken: - if (bytes && bytes_len && baton) - { - BreakpointOptions *bp_options = (BreakpointOptions *) baton; - if (bp_options) - { - Baton *bp_options_baton = bp_options->GetBaton(); - if (bp_options_baton) - ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); - } - } - if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderInterrupt: - { - // Finish, and cancel the breakpoint command. - reader.SetIsDone (true); - BreakpointOptions *bp_options = (BreakpointOptions *) baton; - if (bp_options) - { - Baton *bp_options_baton = bp_options->GetBaton (); - if (bp_options_baton) - { - ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear(); - ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear(); - } - } - if (!batch_mode) - { - out_stream->Printf ("Warning: No command attached to breakpoint.\n"); - out_stream->Flush(); - } - } - break; - - case eInputReaderEndOfFile: - reader.SetIsDone (true); - break; - - case eInputReaderDone: - break; - } - - return bytes_len; - } static bool BreakpointOptionsCallbackFunction (void *baton, @@ -623,7 +545,7 @@ private: }; const char * -CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end."; +CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n"; // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h index afedb76..e917907 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.h @@ -19,7 +19,6 @@ #include "lldb/lldb-types.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Core/InputReader.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp index 6824ead..7bfdec0 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp @@ -18,8 +18,7 @@ // Project includes #include "lldb/Core/Debugger.h" -#include "lldb/Core/InputReader.h" -#include "lldb/Core/InputReaderEZ.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Core/StringList.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandHistory.h" @@ -309,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) { } @@ -321,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; @@ -350,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* @@ -367,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 @@ -379,22 +378,40 @@ protected: { const char *filename = command.GetArgumentAtIndex(0); - 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 { @@ -423,7 +440,7 @@ CommandObjectCommandsSource::CommandOptions::g_option_table[] = static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" "You must define a Python function with this signature:\n" - "def my_command_impl(debugger, args, result, internal_dict):"; + "def my_command_impl(debugger, args, result, internal_dict):\n"; class CommandObjectCommandsAlias : public CommandObjectRaw @@ -856,7 +873,9 @@ protected: //------------------------------------------------------------------------- #pragma mark CommandObjectCommandsAddRegex -class CommandObjectCommandsAddRegex : public CommandObjectParsed +class CommandObjectCommandsAddRegex : + public CommandObjectParsed, + public IOHandlerDelegate { public: CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : @@ -864,6 +883,7 @@ public: "command regex", "Allow the user to create a regular expression command.", "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), + IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), m_options (interpreter) { SetHelpLong( @@ -899,6 +919,97 @@ public: protected: + + virtual void + IOHandlerActivated (IOHandler &io_handler) + { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) + { + output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n"); + output_sp->Flush(); + } + } + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + { + io_handler.SetIsDone(true); + if (m_regex_cmd_ap.get()) + { + StringList lines; + if (lines.SplitIntoLines (data)) + { + const size_t num_lines = lines.GetSize(); + bool check_only = false; + for (size_t i=0; i<num_lines; ++i) + { + printf ("regex[%zu] = %s\n", i, lines[i].c_str()); + llvm::StringRef bytes_strref (lines[i]); + Error error = AppendRegexSubstitution (bytes_strref, check_only); + if (error.Fail()) + { + if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) + { + StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream(); + out_stream->Printf("error: %s\n", error.AsCString()); + } + } + } + } + if (m_regex_cmd_ap->HasRegexEntries()) + { + CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); + m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); + } + } + } + + virtual LineStatus + IOHandlerLinesUpdated (IOHandler &io_handler, + StringList &lines, + uint32_t line_idx, + Error &error) + { + if (line_idx == UINT32_MAX) + { + // Return true to indicate we are done getting lines (this + // is a "fake" line - the real terminating blank line was + // removed during a previous call with the code below) + error.Clear(); + return LineStatus::Done; + } + else + { + const size_t num_lines = lines.GetSize(); + if (line_idx + 1 == num_lines) + { + // The last line was edited, if this line is empty, then we are done + // getting our multiple lines. + if (lines[line_idx].empty()) + { + // Remove the last empty line from "lines" so it doesn't appear + // in our final expression and return true to indicate we are done + // getting lines + lines.PopBack(); + return LineStatus::Done; + } + } + // Check the current line to make sure it is formatted correctly + bool check_only = true; + llvm::StringRef regex_sed(lines[line_idx]); + error = AppendRegexSubstitution (regex_sed, check_only); + if (error.Fail()) + { + return LineStatus::Error; + } + else + { + return LineStatus::Success; + } + } + } + bool DoExecute (Args& command, CommandReturnObject &result) { @@ -920,21 +1031,18 @@ protected: if (argc == 1) { - InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); - if (reader_sp) + Debugger &debugger = m_interpreter.GetDebugger(); + const bool multiple_lines = true; // Get multiple lines + IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + "lldb", // Name of input reader for history + "\033[K> ", // Prompt and clear line + multiple_lines, + *this)); + + if (io_handler_sp) { - error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback, - this, // baton - eInputReaderGranularityLine, // token size, to pass to callback function - NULL, // end token - "> ", // prompt - true); // echo input - if (error.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - return true; - } + debugger.PushIOHandler(io_handler_sp); + result.SetStatus (eReturnStatusSuccessFinishNoResult); } } else @@ -942,7 +1050,8 @@ protected: for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) { llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx)); - error = AppendRegexSubstitution (arg_strref); + bool check_only = false; + error = AppendRegexSubstitution (arg_strref, check_only); if (error.Fail()) break; } @@ -963,7 +1072,7 @@ protected: } Error - AppendRegexSubstitution (const llvm::StringRef ®ex_sed) + AppendRegexSubstitution (const llvm::StringRef ®ex_sed, bool check_only) { Error error; @@ -1053,10 +1162,14 @@ protected: regex_sed.data()); return error; } - std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); - std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); - m_regex_cmd_ap->AddRegexCommand (regex.c_str(), - subst.c_str()); + + if (check_only == false) + { + std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); + std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); + m_regex_cmd_ap->AddRegexCommand (regex.c_str(), + subst.c_str()); + } return error; } @@ -1073,89 +1186,6 @@ protected: } } - void - InputReaderDidCancel() - { - m_regex_cmd_ap.reset(); - } - - static size_t - InputReaderCallback (void *baton, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len) - { - CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton; - bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - - switch (notification) - { - case eInputReaderActivate: - if (!batch_mode) - { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream (); - out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:"); - out_stream->Flush(); - } - break; - case eInputReaderReactivate: - break; - - case eInputReaderDeactivate: - break; - - case eInputReaderAsynchronousOutputWritten: - break; - - case eInputReaderGotToken: - while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n')) - --bytes_len; - if (bytes_len == 0) - reader.SetIsDone(true); - else if (bytes) - { - llvm::StringRef bytes_strref (bytes, bytes_len); - Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref)); - if (error.Fail()) - { - if (!batch_mode) - { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); - out_stream->Printf("error: %s\n", error.AsCString()); - out_stream->Flush(); - } - add_regex_cmd->InputReaderDidCancel (); - reader.SetIsDone (true); - } - } - break; - - case eInputReaderInterrupt: - { - reader.SetIsDone (true); - if (!batch_mode) - { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); - out_stream->PutCString("Regular expression command creations was cancelled.\n"); - out_stream->Flush(); - } - add_regex_cmd->InputReaderDidCancel (); - } - break; - - case eInputReaderEndOfFile: - reader.SetIsDone (true); - break; - - case eInputReaderDone: - add_regex_cmd->AddRegexCommandToInterpreter(); - break; - } - - return bytes_len; - } - private: std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; @@ -1526,7 +1556,9 @@ CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = // CommandObjectCommandsScriptAdd //------------------------------------------------------------------------- -class CommandObjectCommandsScriptAdd : public CommandObjectParsed +class CommandObjectCommandsScriptAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : @@ -1534,6 +1566,7 @@ public: "command script add", "Add a scripted function as an LLDB command.", NULL), + IOHandlerDelegateMultiline ("DONE"), m_options (interpreter) { CommandArgumentEntry arg1; @@ -1567,7 +1600,7 @@ protected: public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter) { } @@ -1586,7 +1619,7 @@ protected: m_funct_name = std::string(option_arg); break; case 's': - m_synchronous = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); + m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); if (!error.Success()) error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg); break; @@ -1602,7 +1635,7 @@ protected: OptionParsingStarting () { m_funct_name = ""; - m_synchronous = eScriptedCommandSynchronicitySynchronous; + m_synchronicity = eScriptedCommandSynchronicitySynchronous; } const OptionDefinition* @@ -1618,128 +1651,81 @@ protected: // Instance variables to hold the values for command options. std::string m_funct_name; - ScriptedCommandSynchronicity m_synchronous; + ScriptedCommandSynchronicity m_synchronicity; }; -private: - class PythonAliasReader : public InputReaderEZ + virtual void + IOHandlerActivated (IOHandler &io_handler) { - private: - CommandInterpreter& m_interpreter; - std::string m_cmd_name; - ScriptedCommandSynchronicity m_synchronous; - StringList m_user_input; - DISALLOW_COPY_AND_ASSIGN (PythonAliasReader); - public: - PythonAliasReader(Debugger& debugger, - CommandInterpreter& interpreter, - std::string cmd_name, - ScriptedCommandSynchronicity synch) : - InputReaderEZ(debugger), - m_interpreter(interpreter), - m_cmd_name(cmd_name), - m_synchronous(synch), - m_user_input() - {} - - virtual - ~PythonAliasReader() + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { + output_sp->PutCString(g_python_command_instructions); + output_sp->Flush(); } + } + + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - virtual void ActivateHandler(HandlerData& data) + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (!batch_mode) - { - out_stream->Printf ("%s\n", g_python_command_instructions); - if (data.reader.GetPrompt()) - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void ReactivateHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (data.reader.GetPrompt() && !batch_mode) + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void GotTokenHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (data.bytes && data.bytes_len) - { - m_user_input.AppendString(data.bytes, data.bytes_len); - } - if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); + std::string funct_name_str; + if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str)) + { + if (funct_name_str.empty()) + { + error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n"); + error_sp->Flush(); + } + else + { + // everything should be fine now, let's add this alias + + CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter, + m_cmd_name, + funct_name_str.c_str(), + m_synchronicity)); + + if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) + { + error_sp->Printf ("error: unable to add selected command, didn't add python command.\n"); + error_sp->Flush(); + } + } + } + else + { + error_sp->Printf ("error: unable to create function, didn't add python command.\n"); + error_sp->Flush(); + } } - } - virtual void InterruptHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - data.reader.SetIsDone (true); - if (!batch_mode) + else { - out_stream->Printf ("Warning: No script attached.\n"); - out_stream->Flush(); + error_sp->Printf ("error: empty function, didn't add python command.\n"); + error_sp->Flush(); } } - virtual void EOFHandler(HandlerData& data) + else { - data.reader.SetIsDone (true); + error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); } - virtual void DoneHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - - ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (!interpreter) - { - out_stream->Printf ("Script interpreter missing: no script attached.\n"); - out_stream->Flush(); - return; - } - std::string funct_name_str; - if (!interpreter->GenerateScriptAliasFunction (m_user_input, - funct_name_str)) - { - out_stream->Printf ("Unable to create function: no script attached.\n"); - out_stream->Flush(); - return; - } - if (funct_name_str.empty()) - { - out_stream->Printf ("Unable to obtain a function name: no script attached.\n"); - out_stream->Flush(); - return; - } - // everything should be fine now, let's add this alias - - CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter, - m_cmd_name, - funct_name_str.c_str(), - m_synchronous)); - - if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true)) - { - out_stream->Printf ("Unable to add selected command: no script attached.\n"); - out_stream->Flush(); - return; - } - } - }; - + + io_handler.SetIsDone(true); + + + } + protected: bool DoExecute (Args& command, CommandReturnObject &result) @@ -1761,45 +1747,24 @@ protected: return false; } - std::string cmd_name = command.GetArgumentAtIndex(0); + // Store the command name and synchronicity in case we get multi-line input + m_cmd_name = command.GetArgumentAtIndex(0); + m_synchronicity = m_options.m_synchronicity; if (m_options.m_funct_name.empty()) { - InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(), - m_interpreter, - cmd_name, - m_options.m_synchronous)); - - if (reader_sp) - { - - InputReaderEZ::InitializationParameters ipr; - - Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" "))); - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); - } + m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions } else { CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, - cmd_name, + m_cmd_name, m_options.m_funct_name, - m_options.m_synchronous)); - if (m_interpreter.AddUserCommand(cmd_name, new_cmd, true)) + m_synchronicity)); + if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { result.SetStatus (eReturnStatusSuccessFinishNoResult); } @@ -1815,6 +1780,8 @@ protected: } CommandOptions m_options; + std::string m_cmd_name; + ScriptedCommandSynchronicity m_synchronicity; }; static OptionEnumValueElement g_script_synchro_type[] = diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp index fc148b1..f9c683b 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -27,6 +27,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp index 5ca44ff..c772a2e 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp @@ -17,7 +17,6 @@ // Project includes #include "lldb/Interpreter/Args.h" #include "lldb/Core/Value.h" -#include "lldb/Core/InputReader.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Expression/ClangExpressionVariable.h" @@ -197,6 +196,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", NULL, eFlagProcessMustBePaused | eFlagTryTargetAPILock), + IOHandlerDelegate (IOHandlerDelegate::Completion::Expression), m_option_group (interpreter), m_format_options (eFormatDefault), m_command_options (), @@ -254,87 +254,6 @@ CommandObjectExpression::GetOptions () return &m_option_group; } -size_t -CommandObjectExpression::MultiLineExpressionCallback -( - void *baton, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len -) -{ - CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; - bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - - switch (notification) - { - case eInputReaderActivate: - if (!batch_mode) - { - StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream()); - if (async_strm_sp) - { - async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); - async_strm_sp->Flush(); - } - } - // Fall through - case eInputReaderReactivate: - break; - - case eInputReaderDeactivate: - break; - - case eInputReaderAsynchronousOutputWritten: - break; - - case eInputReaderGotToken: - ++cmd_object_expr->m_expr_line_count; - if (bytes && bytes_len) - { - cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); - } - - if (bytes_len == 0) - reader.SetIsDone(true); - break; - - case eInputReaderInterrupt: - cmd_object_expr->m_expr_lines.clear(); - reader.SetIsDone (true); - if (!batch_mode) - { - StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream()); - if (async_strm_sp) - { - async_strm_sp->PutCString("Expression evaluation cancelled.\n"); - async_strm_sp->Flush(); - } - } - break; - - case eInputReaderEndOfFile: - reader.SetIsDone (true); - break; - - case eInputReaderDone: - if (cmd_object_expr->m_expr_lines.size() > 0) - { - StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream(); - StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream(); - cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), - output_stream.get(), - error_stream.get()); - output_stream->Flush(); - error_stream->Flush(); - } - break; - } - - return bytes_len; -} - bool CommandObjectExpression::EvaluateExpression ( @@ -373,6 +292,8 @@ CommandObjectExpression::EvaluateExpression if (m_command_options.timeout > 0) options.SetTimeoutUsec(m_command_options.timeout); + else + options.SetTimeoutUsec(0); exe_results = target->EvaluateExpression (expr, exe_ctx.GetFramePtr(), @@ -443,6 +364,48 @@ CommandObjectExpression::EvaluateExpression return true; } +void +CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) +{ + io_handler.SetIsDone(true); +// StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream(); +// StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + + EvaluateExpression (line.c_str(), + output_sp.get(), + error_sp.get()); + if (output_sp) + output_sp->Flush(); + if (error_sp) + error_sp->Flush(); +} + +LineStatus +CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler, + StringList &lines, + uint32_t line_idx, + Error &error) +{ + if (line_idx == UINT32_MAX) + { + // Remove the last line from "lines" so it doesn't appear + // in our final expression + lines.PopBack(); + error.Clear(); + return LineStatus::Done; + } + else if (line_idx + 1 == lines.GetSize()) + { + // The last line was edited, if this line is empty, then we are done + // getting our multiple lines. + if (lines[line_idx].empty()) + return LineStatus::Done; + } + return LineStatus::Success; +} + bool CommandObjectExpression::DoExecute ( @@ -459,31 +422,21 @@ CommandObjectExpression::DoExecute m_expr_lines.clear(); m_expr_line_count = 0; - InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); - if (reader_sp) - { - Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, - this, // baton - eInputReaderGranularityLine, // token size, to pass to callback function - NULL, // end token - NULL, // prompt - true)); // echo input - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else + Debugger &debugger = GetCommandInterpreter().GetDebugger(); + const bool multiple_lines = true; // Get multiple lines + IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, + "lldb-expr", // Name of input reader for history + NULL, // No prompt + multiple_lines, + *this)); + + StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); + if (output_sp) { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); + output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n"); + output_sp->Flush(); } + debugger.PushIOHandler(io_handler_sp); return result.Succeeded(); } diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h index e0703a2..c943f0e 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.h @@ -14,6 +14,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" @@ -21,7 +22,9 @@ namespace lldb_private { -class CommandObjectExpression : public CommandObjectRaw +class CommandObjectExpression : + public CommandObjectRaw, + public IOHandlerDelegate { public: @@ -71,17 +74,23 @@ public: GetOptions (); protected: + + //------------------------------------------------------------------ + // IOHandler::Delegate functions + //------------------------------------------------------------------ + virtual void + IOHandlerInputComplete (IOHandler &io_handler, + std::string &line); + + virtual LineStatus + IOHandlerLinesUpdated (IOHandler &io_handler, + StringList &lines, + uint32_t line_idx, + Error &error); virtual bool DoExecute (const char *command, CommandReturnObject &result); - static size_t - MultiLineExpressionCallback (void *baton, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len); - bool EvaluateExpression (const char *expr, Stream *output_stream, diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.cpp new file mode 100644 index 0000000..3d05335 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.cpp @@ -0,0 +1,61 @@ +//===-- CommandObjectGUI.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/lldb-python.h" + +#include "CommandObjectGUI.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------- +// CommandObjectGUI +//------------------------------------------------------------------------- + +CommandObjectGUI::CommandObjectGUI (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, "gui", "Switch into the curses based GUI mode.", "gui") +{ +} + +CommandObjectGUI::~CommandObjectGUI () +{ +} + +bool +CommandObjectGUI::DoExecute (Args& args, CommandReturnObject &result) +{ +#ifndef LLDB_DISABLE_CURSES + if (args.GetArgumentCount() == 0) + { + Debugger &debugger = m_interpreter.GetDebugger(); + IOHandlerSP io_handler_sp (new IOHandlerCursesGUI (debugger)); + if (io_handler_sp) + debugger.PushIOHandler(io_handler_sp); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError("the gui command takes no arguments."); + result.SetStatus (eReturnStatusFailed); + } + return true; +#else + result.AppendError("lldb was not build with gui support"); + return false; +#endif +} + diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h new file mode 100644 index 0000000..72ddb96 --- /dev/null +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectGUI.h @@ -0,0 +1,43 @@ +//===-- CommandObjectGUI.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CommandObjectGUI_h_ +#define liblldb_CommandObjectGUI_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// CommandObjectGUI +//------------------------------------------------------------------------- + +class CommandObjectGUI : public CommandObjectParsed +{ +public: + + CommandObjectGUI (CommandInterpreter &interpreter); + + virtual + ~CommandObjectGUI (); + +protected: + virtual bool + DoExecute (Args& args, + CommandReturnObject &result); + +}; + +} // namespace lldb_private + +#endif // liblldb_CommandObjectGUI_h_ diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp index f84b401..69b178d 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp @@ -235,18 +235,19 @@ CommandObjectMultiword::HandleCompletion // completers will override this. word_complete = true; + const char *arg0 = input.GetArgumentAtIndex(0); if (cursor_index == 0) { CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, - input.GetArgumentAtIndex(0), + arg0, matches); if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != NULL - && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) + && strcmp (arg0, matches.GetStringAtIndex(0)) == 0) { StringList temp_matches; - CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0), + CommandObject *cmd_obj = GetSubcommandObject (arg0, &temp_matches); if (cmd_obj != NULL) { @@ -270,7 +271,7 @@ CommandObjectMultiword::HandleCompletion } else { - CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0), + CommandObject *sub_command_object = GetSubcommandObject (arg0, &matches); if (sub_command_object == NULL) { diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp index 2933c78..49a3922 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectProcess.cpp @@ -49,7 +49,7 @@ public: virtual ~CommandObjectProcessLaunchOrAttach () {} protected: bool - StopProcessIfNecessary (Process *&process, StateType &state, CommandReturnObject &result) + StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result) { state = eStateInvalid; if (process) @@ -187,12 +187,10 @@ protected: { Debugger &debugger = m_interpreter.GetDebugger(); Target *target = debugger.GetSelectedTarget().get(); - Error error; // If our listener is NULL, users aren't allows to launch - char filename[PATH_MAX]; - const Module *exe_module = target->GetExecutableModulePointer(); + ModuleSP exe_module_sp = target->GetExecutableModule(); - if (exe_module == NULL) + if (exe_module_sp == NULL) { result.AppendError ("no file in target, create a debug target using the 'target create' command"); result.SetStatus (eReturnStatusFailed); @@ -200,23 +198,31 @@ protected: } StateType state = eStateInvalid; - Process *process = m_exe_ctx.GetProcessPtr(); - if (!StopProcessIfNecessary(process, state, result)) + if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) return false; const char *target_settings_argv0 = target->GetArg0(); - exe_module->GetFileSpec().GetPath (filename, sizeof(filename)); + if (target->GetDisableASLR()) + m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); + + if (target->GetDisableSTDIO()) + m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); + Args environment; + target->GetEnvironmentAsArgs (environment); + if (environment.GetArgumentCount() > 0) + m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); + if (target_settings_argv0) { m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0); - m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), false); + m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false); } else { - m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); + m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true); } if (launch_args.GetArgumentCount() == 0) @@ -228,122 +234,33 @@ protected: else { m_options.launch_info.GetArguments().AppendArguments (launch_args); - // Save the arguments for subsequent runs in the current target. target->SetRunArguments (launch_args); } - if (target->GetDisableASLR()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); - - if (target->GetDisableSTDIO()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); - - m_options.launch_info.GetFlags().Set (eLaunchFlagDebug); - - Args environment; - target->GetEnvironmentAsArgs (environment); - if (environment.GetArgumentCount() > 0) - m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); - - // Get the value of synchronous execution here. If you wait till after you have started to - // run, then you could have hit a breakpoint, whose command might switch the value, and - // then you'll pick up that incorrect value. - bool synchronous_execution = m_interpreter.GetSynchronous (); - - PlatformSP platform_sp (target->GetPlatform()); - - // Finalize the file actions, and if none were given, default to opening - // up a pseudo terminal - const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false; - m_options.launch_info.FinalizeFileActions (target, default_to_use_pty); - - if (state == eStateConnected) - { - if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) - { - result.AppendWarning("can't launch in tty when launching through a remote connection"); - m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY); - } - } - - if (!m_options.launch_info.GetArchitecture().IsValid()) - m_options.launch_info.GetArchitecture() = target->GetArchitecture(); + Error error = target->Launch(debugger.GetListener(), m_options.launch_info); - if (platform_sp && platform_sp->CanDebugProcess ()) - { - process = target->GetPlatform()->DebugProcess (m_options.launch_info, - debugger, - target, - debugger.GetListener(), - error).get(); - } - else - { - const char *plugin_name = m_options.launch_info.GetProcessPluginName(); - process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get(); - if (process) - error = process->Launch (m_options.launch_info); - } - - if (process == NULL) - { - result.SetError (error, "failed to launch or debug process"); - return false; - } - - if (error.Success()) { - const char *archname = exe_module->GetArchitecture().GetArchitectureName(); - - result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process->GetID(), filename, archname); - result.SetDidChangeProcessState (true); - if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false) + const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); + ProcessSP process_sp (target->GetProcessSP()); + if (process_sp) { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - StateType state = process->WaitForProcessToStop (NULL, NULL, false); - - if (state == eStateStopped) - { - error = process->Resume(); - if (error.Success()) - { - if (synchronous_execution) - { - state = process->WaitForProcessToStop (NULL); - const bool must_be_alive = true; - if (!StateIsStoppedState(state, must_be_alive)) - { - result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state)); - } - result.SetDidChangeProcessState (true); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - } - else - { - result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state)); - result.SetStatus (eReturnStatusFailed); - } + result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); + result.SetStatus (eReturnStatusSuccessFinishResult); + result.SetDidChangeProcessState (true); + } + else + { + result.AppendError("no error returned from Target::Launch, and target has no process"); + result.SetStatus (eReturnStatusFailed); } } else { - result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString()); + result.AppendError(error.AsCString()); result.SetStatus (eReturnStatusFailed); } - return result.Succeeded(); } @@ -615,37 +532,36 @@ protected: if (error.Success()) { + ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); + m_options.attach_info.SetHijackListener(listener_sp); + process->HijackProcessEvents(listener_sp.get()); error = process->Attach (m_options.attach_info); if (error.Success()) { result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - else - { - result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); - return false; - } - // If we're synchronous, wait for the stopped event and report that. - // Otherwise just return. - // FIXME: in the async case it will now be possible to get to the command - // interpreter with a state eStateAttaching. Make sure we handle that correctly. - StateType state = process->WaitForProcessToStop (NULL); - - result.SetDidChangeProcessState (true); + StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); - if (state == eStateStopped) - { - result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); - result.SetStatus (eReturnStatusSuccessFinishNoResult); + process->RestoreProcessEvents(); + + result.SetDidChangeProcessState (true); + + if (state == eStateStopped) + { + result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); + process->Destroy(); + result.SetStatus (eReturnStatusFailed); + } } else { - result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); - process->Destroy(); + result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); result.SetStatus (eReturnStatusFailed); - return false; } } } @@ -1170,7 +1086,7 @@ protected: if (process) { - error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url); + error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url); if (error.Fail()) { diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp index d04ecdd..ffe2a92 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectQuit.cpp @@ -92,7 +92,8 @@ CommandObjectQuit::DoExecute (Args& command, CommandReturnObject &result) return false; } } - m_interpreter.BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived); + const uint32_t event_type = CommandInterpreter::eBroadcastBitQuitCommandReceived; + m_interpreter.BroadcastEvent (event_type); result.SetStatus (eReturnStatusQuit); return true; } diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp index 7cbfaa5..deaf2ab 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectRegister.cpp @@ -29,6 +29,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Thread.h" using namespace lldb; diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp index 1f68736..bf2a42e 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectSource.cpp @@ -28,6 +28,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/TargetList.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/Options.h" diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp index 8e7e68a..308b72f 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectTarget.cpp @@ -19,7 +19,7 @@ // Project includes #include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/InputReader.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/Section.h" @@ -49,6 +49,7 @@ #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" @@ -2893,7 +2894,8 @@ protected: if (m_slide_option.GetOptionValue().OptionWasSet()) { const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue(); - module->SetLoadAddress (*target, slide, changed); + const bool slide_is_offset = true; + module->SetLoadAddress (*target, slide, slide_is_offset, changed); } else { @@ -4758,7 +4760,9 @@ private: // CommandObjectTargetStopHookAdd //------------------------------------------------------------------------- -class CommandObjectTargetStopHookAdd : public CommandObjectParsed +class CommandObjectTargetStopHookAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: @@ -4925,9 +4929,10 @@ public: CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, - "target stop-hook add ", + "target stop-hook add", "Add a hook to be executed when the target stops.", "target stop-hook add"), + IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand), m_options (interpreter) { } @@ -4936,102 +4941,61 @@ public: { } - static size_t - ReadCommandsCallbackFunction (void *baton, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len) +protected: + + virtual void + IOHandlerActivated (IOHandler &io_handler) { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); - Target::StopHook *new_stop_hook = ((Target::StopHook *) baton); - static bool got_interrupted; - bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - - switch (notification) + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { - case eInputReaderActivate: - if (!batch_mode) - { - out_stream->Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end."); - if (reader.GetPrompt()) - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - got_interrupted = false; - break; - - case eInputReaderDeactivate: - break; - - case eInputReaderReactivate: - if (reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - got_interrupted = false; - break; - - case eInputReaderAsynchronousOutputWritten: - break; - - case eInputReaderGotToken: - if (bytes && bytes_len && baton) + output_sp->PutCString("Enter your stop hook command(s). Type 'DONE' to end.\n"); + output_sp->Flush(); + } + } + + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + { + if (m_stop_hook_sp) + { + if (line.empty()) { - StringList *commands = new_stop_hook->GetCommandPointer(); - if (commands) + StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + if (error_sp) { - commands->AppendString (bytes, bytes_len); + error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", m_stop_hook_sp->GetID()); + error_sp->Flush(); } + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target) + target->RemoveStopHookByID(m_stop_hook_sp->GetID()); } - if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderInterrupt: + else { - // Finish, and cancel the stop hook. - new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID()); - if (!batch_mode) + m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line); + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { - out_stream->Printf ("Stop hook cancelled.\n"); - out_stream->Flush(); + output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID()); + output_sp->Flush(); } - - reader.SetIsDone (true); } - got_interrupted = true; - break; - - case eInputReaderEndOfFile: - reader.SetIsDone (true); - break; - - case eInputReaderDone: - if (!got_interrupted && !batch_mode) - { - out_stream->Printf ("Stop hook #%" PRIu64 " added.\n", new_stop_hook->GetID()); - out_stream->Flush(); - } - break; + m_stop_hook_sp.reset(); } - - return bytes_len; + io_handler.SetIsDone(true); } - -protected: + bool DoExecute (Args& command, CommandReturnObject &result) { + m_stop_hook_sp.reset(); + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) { - Target::StopHookSP new_hook_sp; - target->AddStopHook (new_hook_sp); + Target::StopHookSP new_hook_sp = target->CreateStopHook(); // First step, make the specifier. std::unique_ptr<SymbolContextSpecifier> specifier_ap; @@ -5104,31 +5068,12 @@ protected: } else { - // Otherwise gather up the command list, we'll push an input reader and suck the data from that directly into - // the new stop hook's command string. - InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); - if (!reader_sp) - { - result.AppendError("out of memory\n"); - result.SetStatus (eReturnStatusFailed); - target->RemoveStopHookByID (new_hook_sp->GetID()); - return false; - } - - Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction, - new_hook_sp.get(), // baton - eInputReaderGranularityLine, // token size, to pass to callback function - "DONE", // end token - "> ", // prompt - true)); // echo input - if (!err.Success()) - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - target->RemoveStopHookByID (new_hook_sp->GetID()); - return false; - } - m_interpreter.GetDebugger().PushInputReader (reader_sp); + m_stop_hook_sp = new_hook_sp; + m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } result.SetStatus (eReturnStatusSuccessFinishNoResult); } @@ -5142,6 +5087,7 @@ protected: } private: CommandOptions m_options; + Target::StopHookSP m_stop_hook_sp; }; OptionDefinition diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp index 1c695b3..f1b1d2c 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectType.cpp @@ -19,7 +19,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/InputReaderEZ.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/State.h" #include "lldb/Core/StringList.h" @@ -42,7 +42,6 @@ public: TypeSummaryImpl::Flags m_flags; StringList m_target_types; - StringList m_user_source; bool m_regex; @@ -74,7 +73,6 @@ public: bool m_skip_references; bool m_cascade; bool m_regex; - StringList m_user_source; StringList m_target_types; std::string m_category; @@ -88,7 +86,6 @@ public: m_skip_references(sref), m_cascade(casc), m_regex(regx), - m_user_source(), m_target_types(), m_category(catg) { @@ -98,9 +95,36 @@ public: }; +static bool +WarnOnPotentialUnquotedUnsignedType (Args& command, CommandReturnObject &result) +{ + for (int idx = 0; idx < command.GetArgumentCount(); idx++) + { + const char* arg = command.GetArgumentAtIndex(idx); + if (idx+1 < command.GetArgumentCount()) + { + if (arg && 0 == strcmp(arg,"unsigned")) + { + const char* next = command.GetArgumentAtIndex(idx+1); + if (next && + (0 == strcmp(next, "int") || + 0 == strcmp(next, "short") || + 0 == strcmp(next, "char") || + 0 == strcmp(next, "long"))) + { + result.AppendWarningWithFormat("%s %s being treated as two types. if you meant the combined type name use quotes, as in \"%s %s\"\n", + arg,next,arg,next); + return true; + } + } + } + } + return false; +} - -class CommandObjectTypeSummaryAdd : public CommandObjectParsed +class CommandObjectTypeSummaryAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { private: @@ -153,10 +177,6 @@ private: return &m_options; } - void - CollectPythonScript(ScriptAddOptions *options, - CommandReturnObject &result); - bool Execute_ScriptSummary (Args& command, CommandReturnObject &result); @@ -178,6 +198,147 @@ public: { } + virtual void + IOHandlerActivated (IOHandler &io_handler) + { + static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" + "def function (valobj,internal_dict):\n" + " \"\"\"valobj: an SBValue which you want to provide a summary for\n" + " internal_dict: an LLDB support object not to be used\"\"\""; + + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) + { + output_sp->PutCString(g_summary_addreader_instructions); + output_sp->Flush(); + } + } + + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + +#ifndef LLDB_DISABLE_PYTHON + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) + { + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) + { + ScriptAddOptions *options_ptr = ((ScriptAddOptions*)io_handler.GetUserData()); + if (options_ptr) + { + ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) + { + std::string funct_name_str; + if (interpreter->GenerateTypeScriptFunction (lines, funct_name_str)) + { + if (funct_name_str.empty()) + { + error_sp->Printf ("unable to obtain a valid function name from the script interpreter.\n"); + error_sp->Flush(); + } + else + { + // now I have a valid function name, let's add this as script for every type in the list + + TypeSummaryImplSP script_format; + script_format.reset(new ScriptSummaryFormat(options->m_flags, + funct_name_str.c_str(), + lines.CopyList(" ").c_str())); + + Error error; + + for (size_t i = 0; i < options->m_target_types.GetSize(); i++) + { + const char *type_name = options->m_target_types.GetStringAtIndex(i); + CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), + script_format, + (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), + options->m_category, + &error); + if (error.Fail()) + { + error_sp->Printf ("error: %s", error.AsCString()); + error_sp->Flush(); + } + } + + if (options->m_name) + { + CommandObjectTypeSummaryAdd::AddSummary (options->m_name, + script_format, + CommandObjectTypeSummaryAdd::eNamedSummary, + options->m_category, + &error); + if (error.Fail()) + { + CommandObjectTypeSummaryAdd::AddSummary (options->m_name, + script_format, + CommandObjectTypeSummaryAdd::eNamedSummary, + options->m_category, + &error); + if (error.Fail()) + { + error_sp->Printf ("error: %s", error.AsCString()); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: %s", error.AsCString()); + error_sp->Flush(); + } + } + else + { + if (error.AsCString()) + { + error_sp->Printf ("error: %s", error.AsCString()); + error_sp->Flush(); + } + } + } + } + else + { + error_sp->Printf ("error: unable to generate a function.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: no script interpreter.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: internal synchronization information missing or invalid.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: empty function, didn't add python command.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); + } +#endif // #ifndef LLDB_DISABLE_PYTHON + io_handler.SetIsDone(true); + } + static bool AddSummary(ConstString type_name, lldb::TypeSummaryImplSP entry, @@ -190,7 +351,19 @@ protected: }; -class CommandObjectTypeSynthAdd : public CommandObjectParsed +static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" +"You must define a Python class with these methods:\n" +" def __init__(self, valobj, dict):\n" +" def num_children(self):\n" +" def get_child_at_index(self, index):\n" +" def get_child_index(self, name):\n" +" def update(self):\n" +" '''Optional'''\n" +"class synthProvider:\n"; + +class CommandObjectTypeSynthAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { private: @@ -200,7 +373,7 @@ private: public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter) { } @@ -296,9 +469,6 @@ private: return &m_options; } - void - CollectPythonScript (SynthAddOptions *options, - CommandReturnObject &result); bool Execute_HandwritePython (Args& command, CommandReturnObject &result); @@ -307,8 +477,139 @@ private: protected: bool - DoExecute (Args& command, CommandReturnObject &result); + DoExecute (Args& command, CommandReturnObject &result) + { + WarnOnPotentialUnquotedUnsignedType(command, result); + + if (m_options.handwrite_python) + return Execute_HandwritePython(command, result); + else if (m_options.is_class_based) + return Execute_PythonClass(command, result); + else + { + result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + virtual void + IOHandlerActivated (IOHandler &io_handler) + { + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) + { + output_sp->PutCString(g_synth_addreader_instructions); + output_sp->Flush(); + } + } + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + +#ifndef LLDB_DISABLE_PYTHON + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) + { + StringList lines; + lines.SplitIntoLines(data); + if (lines.GetSize() > 0) + { + SynthAddOptions *options_ptr = ((SynthAddOptions*)io_handler.GetUserData()); + if (options_ptr) + { + SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope + + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (interpreter) + { + std::string class_name_str; + if (interpreter->GenerateTypeSynthClass (lines, class_name_str)) + { + if (class_name_str.empty()) + { + error_sp->Printf ("error: unable to obtain a proper name for the class.\n"); + error_sp->Flush(); + } + else + { + // everything should be fine now, let's add the synth provider class + + SyntheticChildrenSP synth_provider; + synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade). + SetSkipPointers(options->m_skip_pointers). + SetSkipReferences(options->m_skip_references), + class_name_str.c_str())); + + + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); + + Error error; + + for (size_t i = 0; i < options->m_target_types.GetSize(); i++) + { + const char *type_name = options->m_target_types.GetStringAtIndex(i); + ConstString const_type_name(type_name); + if (const_type_name) + { + if (!CommandObjectTypeSynthAdd::AddSynth(const_type_name, + synth_provider, + options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, + options->m_category, + &error)) + { + error_sp->Printf("error: %s\n", error.AsCString()); + error_sp->Flush(); + break; + } + } + else + { + error_sp->Printf ("error: invalid type name.\n"); + error_sp->Flush(); + break; + } + } + } + } + else + { + error_sp->Printf ("error: unable to generate a class.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: no script interpreter.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: internal synchronization data missing.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: empty function, didn't add python command.\n"); + error_sp->Flush(); + } + } + else + { + error_sp->Printf ("error: script interpreter missing, didn't add python command.\n"); + error_sp->Flush(); + } + +#endif // #ifndef LLDB_DISABLE_PYTHON + io_handler.SetIsDone(true); + } + public: enum SynthFormatType @@ -371,6 +672,7 @@ private: m_skip_references = false; m_regex = false; m_category.assign("default"); + m_custom_type_name.clear(); } virtual Error SetOptionValue (CommandInterpreter &interpreter, @@ -400,6 +702,9 @@ private: case 'x': m_regex = true; break; + case 't': + m_custom_type_name.assign(option_value); + break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -419,6 +724,7 @@ private: bool m_skip_pointers; bool m_regex; std::string m_category; + std::string m_custom_type_name; }; OptionGroupOptions m_option_group; @@ -480,7 +786,7 @@ public: ); // Add the "--format" to all options groups - m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_ALL); + m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1); m_option_group.Append (&m_command_options); m_option_group.Finalize(); @@ -504,7 +810,7 @@ protected: } const Format format = m_format_options.GetFormat(); - if (format == eFormatInvalid) + if (format == eFormatInvalid && m_command_options.m_custom_type_name.empty()) { result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); @@ -513,10 +819,16 @@ protected: TypeFormatImplSP entry; - entry.reset(new TypeFormatImpl(format, - TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). - SetSkipPointers(m_command_options.m_skip_pointers). - SetSkipReferences(m_command_options.m_skip_references))); + if (m_command_options.m_custom_type_name.empty()) + entry.reset(new TypeFormatImpl_Format(format, + TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). + SetSkipPointers(m_command_options.m_skip_pointers). + SetSkipReferences(m_command_options.m_skip_references))); + else + entry.reset(new TypeFormatImpl_EnumType(ConstString(m_command_options.m_custom_type_name.c_str()), + TypeFormatImpl::Flags().SetCascades(m_command_options.m_cascade). + SetSkipPointers(m_command_options.m_skip_pointers). + SetSkipReferences(m_command_options.m_skip_references))); // now I have a valid format, let's add it to every type @@ -525,6 +837,8 @@ protected: if (!category_sp) return false; + WarnOnPotentialUnquotedUnsignedType(command, result); + for (size_t i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); @@ -540,11 +854,11 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } - category_sp->GetRegexSummaryNavigator()->Delete(typeCS); - category_sp->GetRegexValueNavigator()->Add(typeRX, entry); + category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); + category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); } else - category_sp->GetValueNavigator()->Add(typeCS, entry); + category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); } else { @@ -562,11 +876,12 @@ protected: OptionDefinition CommandObjectTypeFormatAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, - { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, - { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, + { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, + { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Format variables as if they were of this type."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -817,8 +1132,8 @@ private: PerCategoryCallback(void* param, const lldb::TypeCategoryImplSP& cate) { - cate->GetValueNavigator()->Clear(); - cate->GetRegexValueNavigator()->Clear(); + cate->GetTypeFormatsContainer()->Clear(); + cate->GetRegexTypeFormatsContainer()->Clear(); return true; } @@ -996,6 +1311,7 @@ protected: param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex); DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); + delete param; if (cate_regex) delete cate_regex; @@ -1029,12 +1345,12 @@ private: cate_name, (cate->IsEnabled() ? "enabled" : "disabled")); - cate->GetValueNavigator()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp); + cate->GetTypeFormatsContainer()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp); - if (cate->GetRegexSummaryNavigator()->GetCount() > 0) + if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) { result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); - cate->GetRegexValueNavigator()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp); + cate->GetRegexTypeFormatsContainer()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp); } return true; } @@ -1089,176 +1405,6 @@ CommandObjectTypeFormatList::CommandOptions::g_option_table[] = // CommandObjectTypeSummaryAdd //------------------------------------------------------------------------- -static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" - "def function (valobj,internal_dict):\n" - " \"\"\"valobj: an SBValue which you want to provide a summary for\n" - " internal_dict: an LLDB support object not to be used\"\"\""; - -class TypeScriptAddInputReader : public InputReaderEZ -{ -private: - DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); -public: - TypeScriptAddInputReader(Debugger& debugger) : - InputReaderEZ(debugger) - {} - - virtual - ~TypeScriptAddInputReader() - { - } - - virtual void ActivateHandler(HandlerData& data) - { - StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - if (!batch_mode) - { - out_stream->Printf ("%s\n", g_summary_addreader_instructions); - if (data.reader.GetPrompt()) - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - - virtual void ReactivateHandler(HandlerData& data) - { - StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - if (data.reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void GotTokenHandler(HandlerData& data) - { - StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - if (data.bytes && data.bytes_len && data.baton) - { - ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); - } - if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void InterruptHandler(HandlerData& data) - { - StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - data.reader.SetIsDone (true); - if (!batch_mode) - { - out_stream->Printf ("Warning: No command attached to breakpoint.\n"); - out_stream->Flush(); - } - } - virtual void EOFHandler(HandlerData& data) - { - data.reader.SetIsDone (true); - } - virtual void DoneHandler(HandlerData& data) - { - StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); - ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); - if (!options_ptr) - { - out_stream->Printf ("internal synchronization information missing or invalid.\n"); - out_stream->Flush(); - return; - } - - ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope - - ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (!interpreter) - { - out_stream->Printf ("no script interpreter.\n"); - out_stream->Flush(); - return; - } - std::string funct_name_str; - if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, - funct_name_str)) - { - out_stream->Printf ("unable to generate a function.\n"); - out_stream->Flush(); - return; - } - if (funct_name_str.empty()) - { - out_stream->Printf ("unable to obtain a valid function name from the script interpreter.\n"); - out_stream->Flush(); - return; - } - // now I have a valid function name, let's add this as script for every type in the list - - TypeSummaryImplSP script_format; - script_format.reset(new ScriptSummaryFormat(options->m_flags, - funct_name_str.c_str(), - options->m_user_source.CopyList(" ").c_str())); - - Error error; - - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) - { - const char *type_name = options->m_target_types.GetStringAtIndex(i); - CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), - script_format, - (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), - options->m_category, - &error); - if (error.Fail()) - { - out_stream->Printf ("%s", error.AsCString()); - out_stream->Flush(); - return; - } - } - - if (options->m_name) - { - CommandObjectTypeSummaryAdd::AddSummary (options->m_name, - script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, - &error); - if (error.Fail()) - { - CommandObjectTypeSummaryAdd::AddSummary (options->m_name, - script_format, - CommandObjectTypeSummaryAdd::eNamedSummary, - options->m_category, - &error); - if (error.Fail()) - { - out_stream->Printf ("%s", error.AsCString()); - out_stream->Flush(); - return; - } - } - else - { - out_stream->Printf ("%s", error.AsCString()); - out_stream->Flush(); - return; - } - } - else - { - if (error.AsCString()) - { - out_stream->PutCString (error.AsCString()); - out_stream->Flush(); - } - return; - } - } -}; - #endif // #ifndef LLDB_DISABLE_PYTHON Error @@ -1339,35 +1485,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () m_category = "default"; } + + #ifndef LLDB_DISABLE_PYTHON -void -CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options, - CommandReturnObject &result) -{ - InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); - if (reader_sp && options) - { - - InputReaderEZ::InitializationParameters ipr; - - Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); - } -} bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) @@ -1393,7 +1513,7 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn return false; } - std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); + std::string code = (" " + m_options.m_python_function + "(valobj,internal_dict)"); script_format.reset(new ScriptSummaryFormat(m_options.m_flags, funct_name, @@ -1432,14 +1552,15 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn return false; } - std::string code = " " + m_options.m_python_script; + std::string code = " " + m_options.m_python_script; script_format.reset(new ScriptSummaryFormat(m_options.m_flags, funct_name_str.c_str(), code.c_str())); } - else // use an InputReader to grab Python code from the user - { + else + { + // Use an IOHandler to grab Python code from the user ScriptAddOptions *options = new ScriptAddOptions(m_options.m_flags, m_options.m_regex, m_options.m_name, @@ -1458,7 +1579,12 @@ CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturn } } - CollectPythonScript(options,result); + m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); } @@ -1590,6 +1716,7 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in "type summary add", "Add a new summary style for a type.", NULL), + IOHandlerDelegateMultiline ("DONE"), m_options (interpreter) { CommandArgumentEntry type_arg; @@ -1671,6 +1798,8 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in bool CommandObjectTypeSummaryAdd::DoExecute (Args& command, CommandReturnObject &result) { + WarnOnPotentialUnquotedUnsignedType(command, result); + if (m_options.m_is_add_script) { #ifndef LLDB_DISABLE_PYTHON @@ -1720,8 +1849,8 @@ CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, return false; } - category->GetRegexSummaryNavigator()->Delete(type_name); - category->GetRegexSummaryNavigator()->Add(typeRX, entry); + category->GetRegexTypeSummariesContainer()->Delete(type_name); + category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); return true; } @@ -1733,7 +1862,7 @@ CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, } else { - category->GetSummaryNavigator()->Add(type_name, entry); + category->GetTypeSummariesContainer()->Add(type_name, entry); return true; } } @@ -1994,8 +2123,8 @@ private: PerCategoryCallback(void* param, const lldb::TypeCategoryImplSP& cate) { - cate->GetSummaryNavigator()->Clear(); - cate->GetRegexSummaryNavigator()->Clear(); + cate->GetTypeSummariesContainer()->Clear(); + cate->GetRegexTypeSummariesContainer()->Clear(); return true; } @@ -2178,7 +2307,8 @@ protected: param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - + delete param; + if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { result.GetOutputStream().Printf("Named summaries:\n"); @@ -2226,12 +2356,12 @@ private: cate_name, (cate->IsEnabled() ? "enabled" : "disabled")); - cate->GetSummaryNavigator()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); + cate->GetTypeSummariesContainer()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); - if (cate->GetRegexSummaryNavigator()->GetCount() > 0) + if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) { result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); - cate->GetRegexSummaryNavigator()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); + cate->GetRegexTypeSummariesContainer()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); } return true; } @@ -2741,6 +2871,7 @@ protected: param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex); DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); + delete param; if (cate_regex) delete cate_regex; @@ -2774,12 +2905,12 @@ private: cate_name, (cate->IsEnabled() ? "enabled" : "disabled")); - cate->GetFilterNavigator()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); + cate->GetTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); - if (cate->GetRegexFilterNavigator()->GetCount() > 0) + if (cate->GetRegexTypeFiltersContainer()->GetCount() > 0) { result->GetOutputStream().Printf("Regex-based filters (slower):\n"); - cate->GetRegexFilterNavigator()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); + cate->GetRegexTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); } return true; @@ -2955,7 +3086,8 @@ protected: param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex); DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - + delete param; + if (cate_regex) delete cate_regex; @@ -2988,12 +3120,12 @@ private: cate_name, (cate->IsEnabled() ? "enabled" : "disabled")); - cate->GetSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); + cate->GetTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); - if (cate->GetRegexSyntheticNavigator()->GetCount() > 0) + if (cate->GetRegexTypeSyntheticsContainer()->GetCount() > 0) { result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n"); - cate->GetRegexSyntheticNavigator()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); + cate->GetRegexTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); } return true; @@ -3179,8 +3311,8 @@ protected: lldb::TypeCategoryImplSP category; DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - bool delete_category = category->GetFilterNavigator()->Delete(typeCS); - delete_category = category->GetRegexFilterNavigator()->Delete(typeCS) || delete_category; + bool delete_category = category->GetTypeFiltersContainer()->Delete(typeCS); + delete_category = category->GetRegexTypeFiltersContainer()->Delete(typeCS) || delete_category; if (delete_category) { @@ -3345,8 +3477,8 @@ protected: lldb::TypeCategoryImplSP category; DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - bool delete_category = category->GetSyntheticNavigator()->Delete(typeCS); - delete_category = category->GetRegexSyntheticNavigator()->Delete(typeCS) || delete_category; + bool delete_category = category->GetTypeSyntheticsContainer()->Delete(typeCS); + delete_category = category->GetRegexTypeSyntheticsContainer()->Delete(typeCS) || delete_category; if (delete_category) { @@ -3484,8 +3616,8 @@ protected: } else DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->GetFilterNavigator()->Clear(); - category->GetRegexFilterNavigator()->Clear(); + category->GetTypeFiltersContainer()->Clear(); + category->GetRegexTypeFiltersContainer()->Clear(); } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -3613,8 +3745,8 @@ protected: } else DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->GetSyntheticNavigator()->Clear(); - category->GetRegexSyntheticNavigator()->Clear(); + category->GetTypeSyntheticsContainer()->Clear(); + category->GetRegexTypeSyntheticsContainer()->Clear(); } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -3631,193 +3763,6 @@ CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = }; -//------------------------------------------------------------------------- -// TypeSynthAddInputReader -//------------------------------------------------------------------------- - -static const char *g_synth_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" - "You must define a Python class with these methods:\n" - " def __init__(self, valobj, dict):\n" - " def num_children(self):\n" - " def get_child_at_index(self, index):\n" - " def get_child_index(self, name):\n" - "Optionally, you can also define a method:\n" - " def update(self):\n" - "if your synthetic provider is holding on to any per-object state variables (currently, this is not implemented because of the way LLDB handles instances of SBValue and you should not rely on object persistence and per-object state)\n" - "class synthProvider:"; - -class TypeSynthAddInputReader : public InputReaderEZ -{ -public: - TypeSynthAddInputReader(Debugger& debugger) : - InputReaderEZ(debugger) - {} - - virtual - ~TypeSynthAddInputReader() - { - } - - virtual void ActivateHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (!batch_mode) - { - out_stream->Printf ("%s\n", g_synth_addreader_instructions); - if (data.reader.GetPrompt()) - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - - virtual void ReactivateHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (data.reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void GotTokenHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - if (data.bytes && data.bytes_len && data.baton) - { - ((SynthAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); - } - if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", data.reader.GetPrompt()); - out_stream->Flush(); - } - } - virtual void InterruptHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - bool batch_mode = data.GetBatchMode(); - data.reader.SetIsDone (true); - if (!batch_mode) - { - out_stream->Printf ("Warning: No command attached to breakpoint.\n"); - out_stream->Flush(); - } - } - virtual void EOFHandler(HandlerData& data) - { - data.reader.SetIsDone (true); - } - virtual void DoneHandler(HandlerData& data) - { - StreamSP out_stream = data.GetOutStream(); - SynthAddOptions *options_ptr = ((SynthAddOptions*)data.baton); - if (!options_ptr) - { - out_stream->Printf ("internal synchronization data missing.\n"); - out_stream->Flush(); - return; - } - - SynthAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope - - ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (!interpreter) - { - out_stream->Printf ("no script interpreter.\n"); - out_stream->Flush(); - return; - } - std::string class_name_str; - if (!interpreter->GenerateTypeSynthClass (options->m_user_source, - class_name_str)) - { - out_stream->Printf ("unable to generate a class.\n"); - out_stream->Flush(); - return; - } - if (class_name_str.empty()) - { - out_stream->Printf ("unable to obtain a proper name for the class.\n"); - out_stream->Flush(); - return; - } - - // everything should be fine now, let's add the synth provider class - - SyntheticChildrenSP synth_provider; - synth_provider.reset(new ScriptedSyntheticChildren(SyntheticChildren::Flags().SetCascades(options->m_cascade). - SetSkipPointers(options->m_skip_pointers). - SetSkipReferences(options->m_skip_references), - class_name_str.c_str())); - - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(options->m_category.c_str()), category); - - Error error; - - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) - { - const char *type_name = options->m_target_types.GetStringAtIndex(i); - ConstString typeCS(type_name); - if (typeCS) - { - if (!CommandObjectTypeSynthAdd::AddSynth(typeCS, - synth_provider, - options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, - options->m_category, - &error)) - { - out_stream->Printf("%s\n", error.AsCString()); - out_stream->Flush(); - return; - } - } - else - { - out_stream->Printf ("invalid type name.\n"); - out_stream->Flush(); - return; - } - } - } - -private: - DISALLOW_COPY_AND_ASSIGN (TypeSynthAddInputReader); -}; - -void -CommandObjectTypeSynthAdd::CollectPythonScript (SynthAddOptions *options, - CommandReturnObject &result) -{ - InputReaderSP reader_sp (new TypeSynthAddInputReader(m_interpreter.GetDebugger())); - if (reader_sp && options) - { - - InputReaderEZ::InitializationParameters ipr; - - Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else - { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); - } -} - bool CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) { @@ -3842,7 +3787,11 @@ CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturn } } - CollectPythonScript(options,result); + m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } @@ -3921,6 +3870,7 @@ CommandObjectTypeSynthAdd::CommandObjectTypeSynthAdd (CommandInterpreter &interp "type synthetic add", "Add a new synthetic provider for a type.", NULL), + IOHandlerDelegateMultiline ("DONE"), m_options (interpreter) { CommandArgumentEntry type_arg; @@ -3979,32 +3929,17 @@ CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, return false; } - category->GetRegexSyntheticNavigator()->Delete(type_name); - category->GetRegexSyntheticNavigator()->Add(typeRX, entry); + category->GetRegexTypeSyntheticsContainer()->Delete(type_name); + category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); return true; } else { - category->GetSyntheticNavigator()->Add(type_name, entry); + category->GetTypeSyntheticsContainer()->Add(type_name, entry); return true; } } - -bool -CommandObjectTypeSynthAdd::DoExecute (Args& command, CommandReturnObject &result) -{ - if (m_options.handwrite_python) - return Execute_HandwritePython(command, result); - else if (m_options.is_class_based) - return Execute_PythonClass(command, result); - else - { - result.AppendError("must either provide a children list, a Python class name, or use -P and type a Python class line-by-line"); - result.SetStatus(eReturnStatusFailed); - return false; - } -} OptionDefinition CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = @@ -4173,14 +4108,14 @@ private: return false; } - category->GetRegexFilterNavigator()->Delete(type_name); - category->GetRegexFilterNavigator()->Add(typeRX, entry); + category->GetRegexTypeFiltersContainer()->Delete(type_name); + category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); return true; } else { - category->GetFilterNavigator()->Add(type_name, entry); + category->GetTypeFiltersContainer()->Add(type_name, entry); return true; } } @@ -4279,6 +4214,8 @@ protected: Error error; + WarnOnPotentialUnquotedUnsignedType(command, result); + for (size_t i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index e19216d..0083ff1 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -16,6 +16,7 @@ #include "CommandObjectWatchpointCommand.h" #include "CommandObjectWatchpoint.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" @@ -34,7 +35,9 @@ using namespace lldb_private; //------------------------------------------------------------------------- -class CommandObjectWatchpointCommandAdd : public CommandObjectParsed +class CommandObjectWatchpointCommandAdd : + public CommandObjectParsed, + public IOHandlerDelegateMultiline { public: @@ -43,6 +46,7 @@ public: "add", "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.", NULL), + IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand), m_options (interpreter) { SetHelpLong ( @@ -185,40 +189,45 @@ but do NOT enter more than one command per line. \n" ); return &m_options; } - void - CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result) + virtual void + IOHandlerActivated (IOHandler &io_handler) { - InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); - std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); - if (reader_sp && data_ap.get()) + StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + if (output_sp) { - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp); - - Error err (reader_sp->Initialize (CommandObjectWatchpointCommandAdd::GenerateWatchpointCommandCallback, - wp_options, // callback_data - eInputReaderGranularityLine, // token size, to pass to callback function - "DONE", // end token - "> ", // prompt - true)); // echo input - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } + output_sp->PutCString("Enter your debugger command(s). Type 'DONE' to end.\n"); + output_sp->Flush(); } - else + } + + + virtual void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + { + io_handler.SetIsDone(true); + + // The WatchpointOptions object is owned by the watchpoint or watchpoint location + WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData(); + if (wp_options) { - result.AppendError("out of memory"); - result.SetStatus (eReturnStatusFailed); + std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); + if (data_ap.get()) + { + data_ap->user_source.SplitIntoLines(line); + BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); + wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp); + } } + } + void + CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, + CommandReturnObject &result) + { + m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + wp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions } /// Set a one-liner as the callback for the watchpoint. @@ -240,93 +249,6 @@ but do NOT enter more than one command per line. \n" ); return; } - - static size_t - GenerateWatchpointCommandCallback (void *callback_data, - InputReader &reader, - lldb::InputReaderAction notification, - const char *bytes, - size_t bytes_len) - { - StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); - bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); - - switch (notification) - { - case eInputReaderActivate: - if (!batch_mode) - { - out_stream->Printf ("%s\n", g_reader_instructions); - if (reader.GetPrompt()) - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderDeactivate: - break; - - case eInputReaderReactivate: - if (reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderAsynchronousOutputWritten: - break; - - case eInputReaderGotToken: - if (bytes && bytes_len && callback_data) - { - WatchpointOptions *wp_options = (WatchpointOptions *) callback_data; - if (wp_options) - { - Baton *wp_options_baton = wp_options->GetBaton(); - if (wp_options_baton) - ((WatchpointOptions::CommandData *)wp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len); - } - } - if (!reader.IsDone() && reader.GetPrompt() && !batch_mode) - { - out_stream->Printf ("%s", reader.GetPrompt()); - out_stream->Flush(); - } - break; - - case eInputReaderInterrupt: - { - // Finish, and cancel the watchpoint command. - reader.SetIsDone (true); - WatchpointOptions *wp_options = (WatchpointOptions *) callback_data; - if (wp_options) - { - Baton *wp_options_baton = wp_options->GetBaton (); - if (wp_options_baton) - { - ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->user_source.Clear(); - ((WatchpointOptions::CommandData *) wp_options_baton->m_data)->script_source.clear(); - } - } - if (!batch_mode) - { - out_stream->Printf ("Warning: No command attached to watchpoint.\n"); - out_stream->Flush(); - } - } - break; - - case eInputReaderEndOfFile: - reader.SetIsDone (true); - break; - - case eInputReaderDone: - break; - } - - return bytes_len; - } static bool WatchpointOptionsCallbackFunction (void *baton, @@ -579,12 +501,8 @@ protected: private: CommandOptions m_options; - static const char *g_reader_instructions; - }; -const char * -CommandObjectWatchpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end."; // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper. diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h index c2faf71..3bc9b35 100644 --- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h +++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectWatchpointCommand.h @@ -19,9 +19,6 @@ #include "lldb/lldb-types.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Core/InputReader.h" -#include "lldb/Interpreter/CommandObject.h" -#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" |