1e8d8bef9SDimitry Andric #include "CommandObjectSession.h" 2e8d8bef9SDimitry Andric #include "lldb/Host/OptionParser.h" 3e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 4fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h" 5e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 6e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h" 7e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValue.h" 8e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h" 9e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueString.h" 10e8d8bef9SDimitry Andric #include "lldb/Interpreter/OptionValueUInt64.h" 11e8d8bef9SDimitry Andric #include "lldb/Interpreter/Options.h" 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric using namespace lldb; 14e8d8bef9SDimitry Andric using namespace lldb_private; 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric class CommandObjectSessionSave : public CommandObjectParsed { 17e8d8bef9SDimitry Andric public: 18e8d8bef9SDimitry Andric CommandObjectSessionSave(CommandInterpreter &interpreter) 19e8d8bef9SDimitry Andric : CommandObjectParsed(interpreter, "session save", 20e8d8bef9SDimitry Andric "Save the current session transcripts to a file.\n" 21e8d8bef9SDimitry Andric "If no file if specified, transcripts will be " 22e8d8bef9SDimitry Andric "saved to a temporary file.", 23e8d8bef9SDimitry Andric "session save [file]") { 24*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypePath, eArgRepeatOptional); 25e8d8bef9SDimitry Andric } 26e8d8bef9SDimitry Andric 27e8d8bef9SDimitry Andric ~CommandObjectSessionSave() override = default; 28e8d8bef9SDimitry Andric 29e8d8bef9SDimitry Andric protected: 305f757f3fSDimitry Andric void DoExecute(Args &args, CommandReturnObject &result) override { 31e8d8bef9SDimitry Andric llvm::StringRef file_path; 32e8d8bef9SDimitry Andric 33e8d8bef9SDimitry Andric if (!args.empty()) 34e8d8bef9SDimitry Andric file_path = args[0].ref(); 35e8d8bef9SDimitry Andric 36e8d8bef9SDimitry Andric if (m_interpreter.SaveTranscript(result, file_path.str())) 37e8d8bef9SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 38e8d8bef9SDimitry Andric else 39e8d8bef9SDimitry Andric result.SetStatus(eReturnStatusFailed); 40e8d8bef9SDimitry Andric } 41e8d8bef9SDimitry Andric }; 42e8d8bef9SDimitry Andric 43e8d8bef9SDimitry Andric #define LLDB_OPTIONS_history 44e8d8bef9SDimitry Andric #include "CommandOptions.inc" 45e8d8bef9SDimitry Andric 46e8d8bef9SDimitry Andric class CommandObjectSessionHistory : public CommandObjectParsed { 47e8d8bef9SDimitry Andric public: 48e8d8bef9SDimitry Andric CommandObjectSessionHistory(CommandInterpreter &interpreter) 49e8d8bef9SDimitry Andric : CommandObjectParsed(interpreter, "session history", 50e8d8bef9SDimitry Andric "Dump the history of commands in this session.\n" 51e8d8bef9SDimitry Andric "Commands in the history list can be run again " 52e8d8bef9SDimitry Andric "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " 53e8d8bef9SDimitry Andric "the command that is <OFFSET> commands from the end" 54e8d8bef9SDimitry Andric " of the list (counting the current command).", 5504eeddc0SDimitry Andric nullptr) {} 56e8d8bef9SDimitry Andric 57e8d8bef9SDimitry Andric ~CommandObjectSessionHistory() override = default; 58e8d8bef9SDimitry Andric 59e8d8bef9SDimitry Andric Options *GetOptions() override { return &m_options; } 60e8d8bef9SDimitry Andric 61e8d8bef9SDimitry Andric protected: 62e8d8bef9SDimitry Andric class CommandOptions : public Options { 63e8d8bef9SDimitry Andric public: 64e8d8bef9SDimitry Andric CommandOptions() 6504eeddc0SDimitry Andric : m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {} 66e8d8bef9SDimitry Andric 67e8d8bef9SDimitry Andric ~CommandOptions() override = default; 68e8d8bef9SDimitry Andric 69e8d8bef9SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 70e8d8bef9SDimitry Andric ExecutionContext *execution_context) override { 71e8d8bef9SDimitry Andric Status error; 72e8d8bef9SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 73e8d8bef9SDimitry Andric 74e8d8bef9SDimitry Andric switch (short_option) { 75e8d8bef9SDimitry Andric case 'c': 76e8d8bef9SDimitry Andric error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 77e8d8bef9SDimitry Andric break; 78e8d8bef9SDimitry Andric case 's': 79e8d8bef9SDimitry Andric if (option_arg == "end") { 80e8d8bef9SDimitry Andric m_start_idx.SetCurrentValue(UINT64_MAX); 81e8d8bef9SDimitry Andric m_start_idx.SetOptionWasSet(); 82e8d8bef9SDimitry Andric } else 83e8d8bef9SDimitry Andric error = m_start_idx.SetValueFromString(option_arg, 84e8d8bef9SDimitry Andric eVarSetOperationAssign); 85e8d8bef9SDimitry Andric break; 86e8d8bef9SDimitry Andric case 'e': 87e8d8bef9SDimitry Andric error = 88e8d8bef9SDimitry Andric m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 89e8d8bef9SDimitry Andric break; 90e8d8bef9SDimitry Andric case 'C': 91e8d8bef9SDimitry Andric m_clear.SetCurrentValue(true); 92e8d8bef9SDimitry Andric m_clear.SetOptionWasSet(); 93e8d8bef9SDimitry Andric break; 94e8d8bef9SDimitry Andric default: 95e8d8bef9SDimitry Andric llvm_unreachable("Unimplemented option"); 96e8d8bef9SDimitry Andric } 97e8d8bef9SDimitry Andric 98e8d8bef9SDimitry Andric return error; 99e8d8bef9SDimitry Andric } 100e8d8bef9SDimitry Andric 101e8d8bef9SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 102e8d8bef9SDimitry Andric m_start_idx.Clear(); 103e8d8bef9SDimitry Andric m_stop_idx.Clear(); 104e8d8bef9SDimitry Andric m_count.Clear(); 105e8d8bef9SDimitry Andric m_clear.Clear(); 106e8d8bef9SDimitry Andric } 107e8d8bef9SDimitry Andric 108e8d8bef9SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 109bdd1243dSDimitry Andric return llvm::ArrayRef(g_history_options); 110e8d8bef9SDimitry Andric } 111e8d8bef9SDimitry Andric 112e8d8bef9SDimitry Andric // Instance variables to hold the values for command options. 113e8d8bef9SDimitry Andric 114e8d8bef9SDimitry Andric OptionValueUInt64 m_start_idx; 115e8d8bef9SDimitry Andric OptionValueUInt64 m_stop_idx; 116e8d8bef9SDimitry Andric OptionValueUInt64 m_count; 117e8d8bef9SDimitry Andric OptionValueBoolean m_clear; 118e8d8bef9SDimitry Andric }; 119e8d8bef9SDimitry Andric 1205f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 121e8d8bef9SDimitry Andric if (m_options.m_clear.GetCurrentValue() && 122e8d8bef9SDimitry Andric m_options.m_clear.OptionWasSet()) { 123e8d8bef9SDimitry Andric m_interpreter.GetCommandHistory().Clear(); 124e8d8bef9SDimitry Andric result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 125e8d8bef9SDimitry Andric } else { 126e8d8bef9SDimitry Andric if (m_options.m_start_idx.OptionWasSet() && 127e8d8bef9SDimitry Andric m_options.m_stop_idx.OptionWasSet() && 128e8d8bef9SDimitry Andric m_options.m_count.OptionWasSet()) { 129e8d8bef9SDimitry Andric result.AppendError("--count, --start-index and --end-index cannot be " 130e8d8bef9SDimitry Andric "all specified in the same invocation"); 131e8d8bef9SDimitry Andric result.SetStatus(lldb::eReturnStatusFailed); 132e8d8bef9SDimitry Andric } else { 133e8d8bef9SDimitry Andric std::pair<bool, uint64_t> start_idx( 134e8d8bef9SDimitry Andric m_options.m_start_idx.OptionWasSet(), 135e8d8bef9SDimitry Andric m_options.m_start_idx.GetCurrentValue()); 136e8d8bef9SDimitry Andric std::pair<bool, uint64_t> stop_idx( 137e8d8bef9SDimitry Andric m_options.m_stop_idx.OptionWasSet(), 138e8d8bef9SDimitry Andric m_options.m_stop_idx.GetCurrentValue()); 139e8d8bef9SDimitry Andric std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 140e8d8bef9SDimitry Andric m_options.m_count.GetCurrentValue()); 141e8d8bef9SDimitry Andric 142e8d8bef9SDimitry Andric const CommandHistory &history(m_interpreter.GetCommandHistory()); 143e8d8bef9SDimitry Andric 144e8d8bef9SDimitry Andric if (start_idx.first && start_idx.second == UINT64_MAX) { 145e8d8bef9SDimitry Andric if (count.first) { 146e8d8bef9SDimitry Andric start_idx.second = history.GetSize() - count.second; 147e8d8bef9SDimitry Andric stop_idx.second = history.GetSize() - 1; 148e8d8bef9SDimitry Andric } else if (stop_idx.first) { 149e8d8bef9SDimitry Andric start_idx.second = stop_idx.second; 150e8d8bef9SDimitry Andric stop_idx.second = history.GetSize() - 1; 151e8d8bef9SDimitry Andric } else { 152e8d8bef9SDimitry Andric start_idx.second = 0; 153e8d8bef9SDimitry Andric stop_idx.second = history.GetSize() - 1; 154e8d8bef9SDimitry Andric } 155e8d8bef9SDimitry Andric } else { 156e8d8bef9SDimitry Andric if (!start_idx.first && !stop_idx.first && !count.first) { 157e8d8bef9SDimitry Andric start_idx.second = 0; 158e8d8bef9SDimitry Andric stop_idx.second = history.GetSize() - 1; 159e8d8bef9SDimitry Andric } else if (start_idx.first) { 160e8d8bef9SDimitry Andric if (count.first) { 161e8d8bef9SDimitry Andric stop_idx.second = start_idx.second + count.second - 1; 162e8d8bef9SDimitry Andric } else if (!stop_idx.first) { 163e8d8bef9SDimitry Andric stop_idx.second = history.GetSize() - 1; 164e8d8bef9SDimitry Andric } 165e8d8bef9SDimitry Andric } else if (stop_idx.first) { 166e8d8bef9SDimitry Andric if (count.first) { 167e8d8bef9SDimitry Andric if (stop_idx.second >= count.second) 168e8d8bef9SDimitry Andric start_idx.second = stop_idx.second - count.second + 1; 169e8d8bef9SDimitry Andric else 170e8d8bef9SDimitry Andric start_idx.second = 0; 171e8d8bef9SDimitry Andric } 172e8d8bef9SDimitry Andric } else /* if (count.first) */ 173e8d8bef9SDimitry Andric { 174e8d8bef9SDimitry Andric start_idx.second = 0; 175e8d8bef9SDimitry Andric stop_idx.second = count.second - 1; 176e8d8bef9SDimitry Andric } 177e8d8bef9SDimitry Andric } 178e8d8bef9SDimitry Andric history.Dump(result.GetOutputStream(), start_idx.second, 179e8d8bef9SDimitry Andric stop_idx.second); 180e8d8bef9SDimitry Andric } 181e8d8bef9SDimitry Andric } 182e8d8bef9SDimitry Andric } 183e8d8bef9SDimitry Andric 184e8d8bef9SDimitry Andric CommandOptions m_options; 185e8d8bef9SDimitry Andric }; 186e8d8bef9SDimitry Andric 187e8d8bef9SDimitry Andric CommandObjectSession::CommandObjectSession(CommandInterpreter &interpreter) 188e8d8bef9SDimitry Andric : CommandObjectMultiword(interpreter, "session", 189e8d8bef9SDimitry Andric "Commands controlling LLDB session.", 190e8d8bef9SDimitry Andric "session <subcommand> [<command-options>]") { 191e8d8bef9SDimitry Andric LoadSubCommand("save", 192e8d8bef9SDimitry Andric CommandObjectSP(new CommandObjectSessionSave(interpreter))); 193e8d8bef9SDimitry Andric LoadSubCommand("history", 194e8d8bef9SDimitry Andric CommandObjectSP(new CommandObjectSessionHistory(interpreter))); 195e8d8bef9SDimitry Andric } 196