| #include "CommandObjectSession.h" | |
| #include "lldb/Host/OptionParser.h" | |
| #include "lldb/Interpreter/CommandInterpreter.h" | |
| #include "lldb/Interpreter/CommandOptionArgumentTable.h" | |
| #include "lldb/Interpreter/CommandReturnObject.h" | |
| #include "lldb/Interpreter/OptionArgParser.h" | |
| #include "lldb/Interpreter/OptionValue.h" | |
| #include "lldb/Interpreter/OptionValueBoolean.h" | |
| #include "lldb/Interpreter/OptionValueString.h" | |
| #include "lldb/Interpreter/OptionValueUInt64.h" | |
| #include "lldb/Interpreter/Options.h" | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| class CommandObjectSessionSave : public CommandObjectParsed { | |
| public: | |
| CommandObjectSessionSave(CommandInterpreter &interpreter) | |
| : CommandObjectParsed(interpreter, "session save", | |
| "Save the current session transcripts to a file.\n" | |
| "If no file if specified, transcripts will be " | |
| "saved to a temporary file.\n" | |
| "Note: transcripts will only be saved if " | |
| "interpreter.save-transcript is true.\n", | |
| "session save [file]") { | |
| AddSimpleArgumentList(eArgTypePath, eArgRepeatOptional); | |
| } | |
| ~CommandObjectSessionSave() override = default; | |
| protected: | |
| void DoExecute(Args &args, CommandReturnObject &result) override { | |
| llvm::StringRef file_path; | |
| if (!args.empty()) | |
| file_path = args[0].ref(); | |
| if (m_interpreter.SaveTranscript(result, file_path.str())) | |
| result.SetStatus(eReturnStatusSuccessFinishNoResult); | |
| else | |
| result.SetStatus(eReturnStatusFailed); | |
| } | |
| }; | |
| #define LLDB_OPTIONS_history | |
| #include "CommandOptions.inc" | |
| class CommandObjectSessionHistory : public CommandObjectParsed { | |
| public: | |
| CommandObjectSessionHistory(CommandInterpreter &interpreter) | |
| : CommandObjectParsed(interpreter, "session history", | |
| "Dump the history of commands in this session.\n" | |
| "Commands in the history list can be run again " | |
| "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " | |
| "the command that is <OFFSET> commands from the end" | |
| " of the list (counting the current command).", | |
| nullptr) {} | |
| ~CommandObjectSessionHistory() override = default; | |
| Options *GetOptions() override { return &m_options; } | |
| protected: | |
| class CommandOptions : public Options { | |
| public: | |
| CommandOptions() | |
| : m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {} | |
| ~CommandOptions() override = default; | |
| Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, | |
| ExecutionContext *execution_context) override { | |
| Status error; | |
| const int short_option = m_getopt_table[option_idx].val; | |
| switch (short_option) { | |
| case 'c': | |
| error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); | |
| break; | |
| case 's': | |
| if (option_arg == "end") { | |
| m_start_idx.SetCurrentValue(UINT64_MAX); | |
| m_start_idx.SetOptionWasSet(); | |
| } else | |
| error = m_start_idx.SetValueFromString(option_arg, | |
| eVarSetOperationAssign); | |
| break; | |
| case 'e': | |
| error = | |
| m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); | |
| break; | |
| case 'C': | |
| m_clear.SetCurrentValue(true); | |
| m_clear.SetOptionWasSet(); | |
| break; | |
| default: | |
| llvm_unreachable("Unimplemented option"); | |
| } | |
| return error; | |
| } | |
| void OptionParsingStarting(ExecutionContext *execution_context) override { | |
| m_start_idx.Clear(); | |
| m_stop_idx.Clear(); | |
| m_count.Clear(); | |
| m_clear.Clear(); | |
| } | |
| llvm::ArrayRef<OptionDefinition> GetDefinitions() override { | |
| return llvm::ArrayRef(g_history_options); | |
| } | |
| // Instance variables to hold the values for command options. | |
| OptionValueUInt64 m_start_idx; | |
| OptionValueUInt64 m_stop_idx; | |
| OptionValueUInt64 m_count; | |
| OptionValueBoolean m_clear; | |
| }; | |
| void DoExecute(Args &command, CommandReturnObject &result) override { | |
| if (m_options.m_clear.GetCurrentValue() && | |
| m_options.m_clear.OptionWasSet()) { | |
| m_interpreter.GetCommandHistory().Clear(); | |
| result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); | |
| } else { | |
| if (m_options.m_start_idx.OptionWasSet() && | |
| m_options.m_stop_idx.OptionWasSet() && | |
| m_options.m_count.OptionWasSet()) { | |
| result.AppendError("--count, --start-index and --end-index cannot be " | |
| "all specified in the same invocation"); | |
| result.SetStatus(lldb::eReturnStatusFailed); | |
| } else { | |
| std::pair<bool, uint64_t> start_idx( | |
| m_options.m_start_idx.OptionWasSet(), | |
| m_options.m_start_idx.GetCurrentValue()); | |
| std::pair<bool, uint64_t> stop_idx( | |
| m_options.m_stop_idx.OptionWasSet(), | |
| m_options.m_stop_idx.GetCurrentValue()); | |
| std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), | |
| m_options.m_count.GetCurrentValue()); | |
| const CommandHistory &history(m_interpreter.GetCommandHistory()); | |
| if (start_idx.first && start_idx.second == UINT64_MAX) { | |
| if (count.first) { | |
| start_idx.second = history.GetSize() - count.second; | |
| stop_idx.second = history.GetSize() - 1; | |
| } else if (stop_idx.first) { | |
| start_idx.second = stop_idx.second; | |
| stop_idx.second = history.GetSize() - 1; | |
| } else { | |
| start_idx.second = 0; | |
| stop_idx.second = history.GetSize() - 1; | |
| } | |
| } else { | |
| if (!start_idx.first && !stop_idx.first && !count.first) { | |
| start_idx.second = 0; | |
| stop_idx.second = history.GetSize() - 1; | |
| } else if (start_idx.first) { | |
| if (count.first) { | |
| stop_idx.second = start_idx.second + count.second - 1; | |
| } else if (!stop_idx.first) { | |
| stop_idx.second = history.GetSize() - 1; | |
| } | |
| } else if (stop_idx.first) { | |
| if (count.first) { | |
| if (stop_idx.second >= count.second) | |
| start_idx.second = stop_idx.second - count.second + 1; | |
| else | |
| start_idx.second = 0; | |
| } | |
| } else /* if (count.first) */ | |
| { | |
| start_idx.second = 0; | |
| stop_idx.second = count.second - 1; | |
| } | |
| } | |
| history.Dump(result.GetOutputStream(), start_idx.second, | |
| stop_idx.second); | |
| result.SetStatus(lldb::eReturnStatusSuccessFinishResult); | |
| } | |
| } | |
| } | |
| CommandOptions m_options; | |
| }; | |
| CommandObjectSession::CommandObjectSession(CommandInterpreter &interpreter) | |
| : CommandObjectMultiword(interpreter, "session", | |
| "Commands controlling LLDB session.", | |
| "session <subcommand> [<command-options>]") { | |
| LoadSubCommand("save", | |
| CommandObjectSP(new CommandObjectSessionSave(interpreter))); | |
| LoadSubCommand("history", | |
| CommandObjectSP(new CommandObjectSessionHistory(interpreter))); | |
| } |