15bb742b1SMed Ismail Bennani #include "CommandObjectSession.h" 285fbb08fSMed Ismail Bennani #include "lldb/Host/OptionParser.h" 35bb742b1SMed Ismail Bennani #include "lldb/Interpreter/CommandInterpreter.h" 47ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h" 55bb742b1SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h" 685fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionArgParser.h" 785fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValue.h" 885fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueBoolean.h" 985fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueString.h" 1085fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueUInt64.h" 1185fbb08fSMed Ismail Bennani #include "lldb/Interpreter/Options.h" 125bb742b1SMed Ismail Bennani 135bb742b1SMed Ismail Bennani using namespace lldb; 145bb742b1SMed Ismail Bennani using namespace lldb_private; 155bb742b1SMed Ismail Bennani 165bb742b1SMed Ismail Bennani class CommandObjectSessionSave : public CommandObjectParsed { 175bb742b1SMed Ismail Bennani public: 185bb742b1SMed Ismail Bennani CommandObjectSessionSave(CommandInterpreter &interpreter) 195bb742b1SMed Ismail Bennani : CommandObjectParsed(interpreter, "session save", 205bb742b1SMed Ismail Bennani "Save the current session transcripts to a file.\n" 215bb742b1SMed Ismail Bennani "If no file if specified, transcripts will be " 22*835b5e27STom Yang "saved to a temporary file.\n" 23*835b5e27STom Yang "Note: transcripts will only be saved if " 24*835b5e27STom Yang "interpreter.save-transcript is true.\n", 255bb742b1SMed Ismail Bennani "session save [file]") { 262d704f4bSjimingham AddSimpleArgumentList(eArgTypePath, eArgRepeatOptional); 275bb742b1SMed Ismail Bennani } 285bb742b1SMed Ismail Bennani 295bb742b1SMed Ismail Bennani ~CommandObjectSessionSave() override = default; 305bb742b1SMed Ismail Bennani 315bb742b1SMed Ismail Bennani protected: 3292d8a28cSPete Lawrence void DoExecute(Args &args, CommandReturnObject &result) override { 335bb742b1SMed Ismail Bennani llvm::StringRef file_path; 345bb742b1SMed Ismail Bennani 355bb742b1SMed Ismail Bennani if (!args.empty()) 365bb742b1SMed Ismail Bennani file_path = args[0].ref(); 375bb742b1SMed Ismail Bennani 385bb742b1SMed Ismail Bennani if (m_interpreter.SaveTranscript(result, file_path.str())) 395bb742b1SMed Ismail Bennani result.SetStatus(eReturnStatusSuccessFinishNoResult); 405bb742b1SMed Ismail Bennani else 415bb742b1SMed Ismail Bennani result.SetStatus(eReturnStatusFailed); 425bb742b1SMed Ismail Bennani } 435bb742b1SMed Ismail Bennani }; 445bb742b1SMed Ismail Bennani 4585fbb08fSMed Ismail Bennani #define LLDB_OPTIONS_history 4685fbb08fSMed Ismail Bennani #include "CommandOptions.inc" 4785fbb08fSMed Ismail Bennani 4885fbb08fSMed Ismail Bennani class CommandObjectSessionHistory : public CommandObjectParsed { 4985fbb08fSMed Ismail Bennani public: 5085fbb08fSMed Ismail Bennani CommandObjectSessionHistory(CommandInterpreter &interpreter) 5185fbb08fSMed Ismail Bennani : CommandObjectParsed(interpreter, "session history", 5285fbb08fSMed Ismail Bennani "Dump the history of commands in this session.\n" 5385fbb08fSMed Ismail Bennani "Commands in the history list can be run again " 5485fbb08fSMed Ismail Bennani "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " 5585fbb08fSMed Ismail Bennani "the command that is <OFFSET> commands from the end" 5685fbb08fSMed Ismail Bennani " of the list (counting the current command).", 57abb0ed44SKazu Hirata nullptr) {} 5885fbb08fSMed Ismail Bennani 5985fbb08fSMed Ismail Bennani ~CommandObjectSessionHistory() override = default; 6085fbb08fSMed Ismail Bennani 6185fbb08fSMed Ismail Bennani Options *GetOptions() override { return &m_options; } 6285fbb08fSMed Ismail Bennani 6385fbb08fSMed Ismail Bennani protected: 6485fbb08fSMed Ismail Bennani class CommandOptions : public Options { 6585fbb08fSMed Ismail Bennani public: 6685fbb08fSMed Ismail Bennani CommandOptions() 67abb0ed44SKazu Hirata : m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {} 6885fbb08fSMed Ismail Bennani 6985fbb08fSMed Ismail Bennani ~CommandOptions() override = default; 7085fbb08fSMed Ismail Bennani 7185fbb08fSMed Ismail Bennani Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 7285fbb08fSMed Ismail Bennani ExecutionContext *execution_context) override { 7385fbb08fSMed Ismail Bennani Status error; 7485fbb08fSMed Ismail Bennani const int short_option = m_getopt_table[option_idx].val; 7585fbb08fSMed Ismail Bennani 7685fbb08fSMed Ismail Bennani switch (short_option) { 7785fbb08fSMed Ismail Bennani case 'c': 7885fbb08fSMed Ismail Bennani error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 7985fbb08fSMed Ismail Bennani break; 8085fbb08fSMed Ismail Bennani case 's': 8185fbb08fSMed Ismail Bennani if (option_arg == "end") { 8285fbb08fSMed Ismail Bennani m_start_idx.SetCurrentValue(UINT64_MAX); 8385fbb08fSMed Ismail Bennani m_start_idx.SetOptionWasSet(); 8485fbb08fSMed Ismail Bennani } else 8585fbb08fSMed Ismail Bennani error = m_start_idx.SetValueFromString(option_arg, 8685fbb08fSMed Ismail Bennani eVarSetOperationAssign); 8785fbb08fSMed Ismail Bennani break; 8885fbb08fSMed Ismail Bennani case 'e': 8985fbb08fSMed Ismail Bennani error = 9085fbb08fSMed Ismail Bennani m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 9185fbb08fSMed Ismail Bennani break; 9285fbb08fSMed Ismail Bennani case 'C': 9385fbb08fSMed Ismail Bennani m_clear.SetCurrentValue(true); 9485fbb08fSMed Ismail Bennani m_clear.SetOptionWasSet(); 9585fbb08fSMed Ismail Bennani break; 9685fbb08fSMed Ismail Bennani default: 9785fbb08fSMed Ismail Bennani llvm_unreachable("Unimplemented option"); 9885fbb08fSMed Ismail Bennani } 9985fbb08fSMed Ismail Bennani 10085fbb08fSMed Ismail Bennani return error; 10185fbb08fSMed Ismail Bennani } 10285fbb08fSMed Ismail Bennani 10385fbb08fSMed Ismail Bennani void OptionParsingStarting(ExecutionContext *execution_context) override { 10485fbb08fSMed Ismail Bennani m_start_idx.Clear(); 10585fbb08fSMed Ismail Bennani m_stop_idx.Clear(); 10685fbb08fSMed Ismail Bennani m_count.Clear(); 10785fbb08fSMed Ismail Bennani m_clear.Clear(); 10885fbb08fSMed Ismail Bennani } 10985fbb08fSMed Ismail Bennani 11085fbb08fSMed Ismail Bennani llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 111984b800aSserge-sans-paille return llvm::ArrayRef(g_history_options); 11285fbb08fSMed Ismail Bennani } 11385fbb08fSMed Ismail Bennani 11485fbb08fSMed Ismail Bennani // Instance variables to hold the values for command options. 11585fbb08fSMed Ismail Bennani 11685fbb08fSMed Ismail Bennani OptionValueUInt64 m_start_idx; 11785fbb08fSMed Ismail Bennani OptionValueUInt64 m_stop_idx; 11885fbb08fSMed Ismail Bennani OptionValueUInt64 m_count; 11985fbb08fSMed Ismail Bennani OptionValueBoolean m_clear; 12085fbb08fSMed Ismail Bennani }; 12185fbb08fSMed Ismail Bennani 12292d8a28cSPete Lawrence void DoExecute(Args &command, CommandReturnObject &result) override { 12385fbb08fSMed Ismail Bennani if (m_options.m_clear.GetCurrentValue() && 12485fbb08fSMed Ismail Bennani m_options.m_clear.OptionWasSet()) { 12585fbb08fSMed Ismail Bennani m_interpreter.GetCommandHistory().Clear(); 12685fbb08fSMed Ismail Bennani result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 12785fbb08fSMed Ismail Bennani } else { 12885fbb08fSMed Ismail Bennani if (m_options.m_start_idx.OptionWasSet() && 12985fbb08fSMed Ismail Bennani m_options.m_stop_idx.OptionWasSet() && 13085fbb08fSMed Ismail Bennani m_options.m_count.OptionWasSet()) { 13185fbb08fSMed Ismail Bennani result.AppendError("--count, --start-index and --end-index cannot be " 13285fbb08fSMed Ismail Bennani "all specified in the same invocation"); 13385fbb08fSMed Ismail Bennani result.SetStatus(lldb::eReturnStatusFailed); 13485fbb08fSMed Ismail Bennani } else { 13585fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> start_idx( 13685fbb08fSMed Ismail Bennani m_options.m_start_idx.OptionWasSet(), 13785fbb08fSMed Ismail Bennani m_options.m_start_idx.GetCurrentValue()); 13885fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> stop_idx( 13985fbb08fSMed Ismail Bennani m_options.m_stop_idx.OptionWasSet(), 14085fbb08fSMed Ismail Bennani m_options.m_stop_idx.GetCurrentValue()); 14185fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 14285fbb08fSMed Ismail Bennani m_options.m_count.GetCurrentValue()); 14385fbb08fSMed Ismail Bennani 14485fbb08fSMed Ismail Bennani const CommandHistory &history(m_interpreter.GetCommandHistory()); 14585fbb08fSMed Ismail Bennani 14685fbb08fSMed Ismail Bennani if (start_idx.first && start_idx.second == UINT64_MAX) { 14785fbb08fSMed Ismail Bennani if (count.first) { 14885fbb08fSMed Ismail Bennani start_idx.second = history.GetSize() - count.second; 14985fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 15085fbb08fSMed Ismail Bennani } else if (stop_idx.first) { 15185fbb08fSMed Ismail Bennani start_idx.second = stop_idx.second; 15285fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 15385fbb08fSMed Ismail Bennani } else { 15485fbb08fSMed Ismail Bennani start_idx.second = 0; 15585fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 15685fbb08fSMed Ismail Bennani } 15785fbb08fSMed Ismail Bennani } else { 15885fbb08fSMed Ismail Bennani if (!start_idx.first && !stop_idx.first && !count.first) { 15985fbb08fSMed Ismail Bennani start_idx.second = 0; 16085fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 16185fbb08fSMed Ismail Bennani } else if (start_idx.first) { 16285fbb08fSMed Ismail Bennani if (count.first) { 16385fbb08fSMed Ismail Bennani stop_idx.second = start_idx.second + count.second - 1; 16485fbb08fSMed Ismail Bennani } else if (!stop_idx.first) { 16585fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 16685fbb08fSMed Ismail Bennani } 16785fbb08fSMed Ismail Bennani } else if (stop_idx.first) { 16885fbb08fSMed Ismail Bennani if (count.first) { 16985fbb08fSMed Ismail Bennani if (stop_idx.second >= count.second) 17085fbb08fSMed Ismail Bennani start_idx.second = stop_idx.second - count.second + 1; 17185fbb08fSMed Ismail Bennani else 17285fbb08fSMed Ismail Bennani start_idx.second = 0; 17385fbb08fSMed Ismail Bennani } 17485fbb08fSMed Ismail Bennani } else /* if (count.first) */ 17585fbb08fSMed Ismail Bennani { 17685fbb08fSMed Ismail Bennani start_idx.second = 0; 17785fbb08fSMed Ismail Bennani stop_idx.second = count.second - 1; 17885fbb08fSMed Ismail Bennani } 17985fbb08fSMed Ismail Bennani } 18085fbb08fSMed Ismail Bennani history.Dump(result.GetOutputStream(), start_idx.second, 18185fbb08fSMed Ismail Bennani stop_idx.second); 18285fbb08fSMed Ismail Bennani } 18385fbb08fSMed Ismail Bennani } 18485fbb08fSMed Ismail Bennani } 18585fbb08fSMed Ismail Bennani 18685fbb08fSMed Ismail Bennani CommandOptions m_options; 18785fbb08fSMed Ismail Bennani }; 18885fbb08fSMed Ismail Bennani 1895bb742b1SMed Ismail Bennani CommandObjectSession::CommandObjectSession(CommandInterpreter &interpreter) 1905bb742b1SMed Ismail Bennani : CommandObjectMultiword(interpreter, "session", 1915bb742b1SMed Ismail Bennani "Commands controlling LLDB session.", 1925bb742b1SMed Ismail Bennani "session <subcommand> [<command-options>]") { 1935bb742b1SMed Ismail Bennani LoadSubCommand("save", 1945bb742b1SMed Ismail Bennani CommandObjectSP(new CommandObjectSessionSave(interpreter))); 19585fbb08fSMed Ismail Bennani LoadSubCommand("history", 19685fbb08fSMed Ismail Bennani CommandObjectSP(new CommandObjectSessionHistory(interpreter))); 1975bb742b1SMed Ismail Bennani } 198