15bb742b1SMed Ismail Bennani #include "CommandObjectSession.h" 2*85fbb08fSMed Ismail Bennani #include "lldb/Host/OptionParser.h" 35bb742b1SMed Ismail Bennani #include "lldb/Interpreter/CommandInterpreter.h" 45bb742b1SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h" 5*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionArgParser.h" 6*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValue.h" 7*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueBoolean.h" 8*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueString.h" 9*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/OptionValueUInt64.h" 10*85fbb08fSMed Ismail Bennani #include "lldb/Interpreter/Options.h" 115bb742b1SMed Ismail Bennani 125bb742b1SMed Ismail Bennani using namespace lldb; 135bb742b1SMed Ismail Bennani using namespace lldb_private; 145bb742b1SMed Ismail Bennani 155bb742b1SMed Ismail Bennani class CommandObjectSessionSave : public CommandObjectParsed { 165bb742b1SMed Ismail Bennani public: 175bb742b1SMed Ismail Bennani CommandObjectSessionSave(CommandInterpreter &interpreter) 185bb742b1SMed Ismail Bennani : CommandObjectParsed(interpreter, "session save", 195bb742b1SMed Ismail Bennani "Save the current session transcripts to a file.\n" 205bb742b1SMed Ismail Bennani "If no file if specified, transcripts will be " 215bb742b1SMed Ismail Bennani "saved to a temporary file.", 225bb742b1SMed Ismail Bennani "session save [file]") { 235bb742b1SMed Ismail Bennani CommandArgumentEntry arg1; 245bb742b1SMed Ismail Bennani arg1.emplace_back(eArgTypePath, eArgRepeatOptional); 255bb742b1SMed Ismail Bennani m_arguments.push_back(arg1); 265bb742b1SMed Ismail Bennani } 275bb742b1SMed Ismail Bennani 285bb742b1SMed Ismail Bennani ~CommandObjectSessionSave() override = default; 295bb742b1SMed Ismail Bennani 305bb742b1SMed Ismail Bennani void 315bb742b1SMed Ismail Bennani HandleArgumentCompletion(CompletionRequest &request, 325bb742b1SMed Ismail Bennani OptionElementVector &opt_element_vector) override { 335bb742b1SMed Ismail Bennani CommandCompletions::InvokeCommonCompletionCallbacks( 345bb742b1SMed Ismail Bennani GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 355bb742b1SMed Ismail Bennani request, nullptr); 365bb742b1SMed Ismail Bennani } 375bb742b1SMed Ismail Bennani 385bb742b1SMed Ismail Bennani protected: 395bb742b1SMed Ismail Bennani bool DoExecute(Args &args, CommandReturnObject &result) override { 405bb742b1SMed Ismail Bennani llvm::StringRef file_path; 415bb742b1SMed Ismail Bennani 425bb742b1SMed Ismail Bennani if (!args.empty()) 435bb742b1SMed Ismail Bennani file_path = args[0].ref(); 445bb742b1SMed Ismail Bennani 455bb742b1SMed Ismail Bennani if (m_interpreter.SaveTranscript(result, file_path.str())) 465bb742b1SMed Ismail Bennani result.SetStatus(eReturnStatusSuccessFinishNoResult); 475bb742b1SMed Ismail Bennani else 485bb742b1SMed Ismail Bennani result.SetStatus(eReturnStatusFailed); 495bb742b1SMed Ismail Bennani return result.Succeeded(); 505bb742b1SMed Ismail Bennani } 515bb742b1SMed Ismail Bennani }; 525bb742b1SMed Ismail Bennani 53*85fbb08fSMed Ismail Bennani #define LLDB_OPTIONS_history 54*85fbb08fSMed Ismail Bennani #include "CommandOptions.inc" 55*85fbb08fSMed Ismail Bennani 56*85fbb08fSMed Ismail Bennani class CommandObjectSessionHistory : public CommandObjectParsed { 57*85fbb08fSMed Ismail Bennani public: 58*85fbb08fSMed Ismail Bennani CommandObjectSessionHistory(CommandInterpreter &interpreter) 59*85fbb08fSMed Ismail Bennani : CommandObjectParsed(interpreter, "session history", 60*85fbb08fSMed Ismail Bennani "Dump the history of commands in this session.\n" 61*85fbb08fSMed Ismail Bennani "Commands in the history list can be run again " 62*85fbb08fSMed Ismail Bennani "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " 63*85fbb08fSMed Ismail Bennani "the command that is <OFFSET> commands from the end" 64*85fbb08fSMed Ismail Bennani " of the list (counting the current command).", 65*85fbb08fSMed Ismail Bennani nullptr), 66*85fbb08fSMed Ismail Bennani m_options() {} 67*85fbb08fSMed Ismail Bennani 68*85fbb08fSMed Ismail Bennani ~CommandObjectSessionHistory() override = default; 69*85fbb08fSMed Ismail Bennani 70*85fbb08fSMed Ismail Bennani Options *GetOptions() override { return &m_options; } 71*85fbb08fSMed Ismail Bennani 72*85fbb08fSMed Ismail Bennani protected: 73*85fbb08fSMed Ismail Bennani class CommandOptions : public Options { 74*85fbb08fSMed Ismail Bennani public: 75*85fbb08fSMed Ismail Bennani CommandOptions() 76*85fbb08fSMed Ismail Bennani : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 77*85fbb08fSMed Ismail Bennani } 78*85fbb08fSMed Ismail Bennani 79*85fbb08fSMed Ismail Bennani ~CommandOptions() override = default; 80*85fbb08fSMed Ismail Bennani 81*85fbb08fSMed Ismail Bennani Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 82*85fbb08fSMed Ismail Bennani ExecutionContext *execution_context) override { 83*85fbb08fSMed Ismail Bennani Status error; 84*85fbb08fSMed Ismail Bennani const int short_option = m_getopt_table[option_idx].val; 85*85fbb08fSMed Ismail Bennani 86*85fbb08fSMed Ismail Bennani switch (short_option) { 87*85fbb08fSMed Ismail Bennani case 'c': 88*85fbb08fSMed Ismail Bennani error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 89*85fbb08fSMed Ismail Bennani break; 90*85fbb08fSMed Ismail Bennani case 's': 91*85fbb08fSMed Ismail Bennani if (option_arg == "end") { 92*85fbb08fSMed Ismail Bennani m_start_idx.SetCurrentValue(UINT64_MAX); 93*85fbb08fSMed Ismail Bennani m_start_idx.SetOptionWasSet(); 94*85fbb08fSMed Ismail Bennani } else 95*85fbb08fSMed Ismail Bennani error = m_start_idx.SetValueFromString(option_arg, 96*85fbb08fSMed Ismail Bennani eVarSetOperationAssign); 97*85fbb08fSMed Ismail Bennani break; 98*85fbb08fSMed Ismail Bennani case 'e': 99*85fbb08fSMed Ismail Bennani error = 100*85fbb08fSMed Ismail Bennani m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 101*85fbb08fSMed Ismail Bennani break; 102*85fbb08fSMed Ismail Bennani case 'C': 103*85fbb08fSMed Ismail Bennani m_clear.SetCurrentValue(true); 104*85fbb08fSMed Ismail Bennani m_clear.SetOptionWasSet(); 105*85fbb08fSMed Ismail Bennani break; 106*85fbb08fSMed Ismail Bennani default: 107*85fbb08fSMed Ismail Bennani llvm_unreachable("Unimplemented option"); 108*85fbb08fSMed Ismail Bennani } 109*85fbb08fSMed Ismail Bennani 110*85fbb08fSMed Ismail Bennani return error; 111*85fbb08fSMed Ismail Bennani } 112*85fbb08fSMed Ismail Bennani 113*85fbb08fSMed Ismail Bennani void OptionParsingStarting(ExecutionContext *execution_context) override { 114*85fbb08fSMed Ismail Bennani m_start_idx.Clear(); 115*85fbb08fSMed Ismail Bennani m_stop_idx.Clear(); 116*85fbb08fSMed Ismail Bennani m_count.Clear(); 117*85fbb08fSMed Ismail Bennani m_clear.Clear(); 118*85fbb08fSMed Ismail Bennani } 119*85fbb08fSMed Ismail Bennani 120*85fbb08fSMed Ismail Bennani llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 121*85fbb08fSMed Ismail Bennani return llvm::makeArrayRef(g_history_options); 122*85fbb08fSMed Ismail Bennani } 123*85fbb08fSMed Ismail Bennani 124*85fbb08fSMed Ismail Bennani // Instance variables to hold the values for command options. 125*85fbb08fSMed Ismail Bennani 126*85fbb08fSMed Ismail Bennani OptionValueUInt64 m_start_idx; 127*85fbb08fSMed Ismail Bennani OptionValueUInt64 m_stop_idx; 128*85fbb08fSMed Ismail Bennani OptionValueUInt64 m_count; 129*85fbb08fSMed Ismail Bennani OptionValueBoolean m_clear; 130*85fbb08fSMed Ismail Bennani }; 131*85fbb08fSMed Ismail Bennani 132*85fbb08fSMed Ismail Bennani bool DoExecute(Args &command, CommandReturnObject &result) override { 133*85fbb08fSMed Ismail Bennani if (m_options.m_clear.GetCurrentValue() && 134*85fbb08fSMed Ismail Bennani m_options.m_clear.OptionWasSet()) { 135*85fbb08fSMed Ismail Bennani m_interpreter.GetCommandHistory().Clear(); 136*85fbb08fSMed Ismail Bennani result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 137*85fbb08fSMed Ismail Bennani } else { 138*85fbb08fSMed Ismail Bennani if (m_options.m_start_idx.OptionWasSet() && 139*85fbb08fSMed Ismail Bennani m_options.m_stop_idx.OptionWasSet() && 140*85fbb08fSMed Ismail Bennani m_options.m_count.OptionWasSet()) { 141*85fbb08fSMed Ismail Bennani result.AppendError("--count, --start-index and --end-index cannot be " 142*85fbb08fSMed Ismail Bennani "all specified in the same invocation"); 143*85fbb08fSMed Ismail Bennani result.SetStatus(lldb::eReturnStatusFailed); 144*85fbb08fSMed Ismail Bennani } else { 145*85fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> start_idx( 146*85fbb08fSMed Ismail Bennani m_options.m_start_idx.OptionWasSet(), 147*85fbb08fSMed Ismail Bennani m_options.m_start_idx.GetCurrentValue()); 148*85fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> stop_idx( 149*85fbb08fSMed Ismail Bennani m_options.m_stop_idx.OptionWasSet(), 150*85fbb08fSMed Ismail Bennani m_options.m_stop_idx.GetCurrentValue()); 151*85fbb08fSMed Ismail Bennani std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 152*85fbb08fSMed Ismail Bennani m_options.m_count.GetCurrentValue()); 153*85fbb08fSMed Ismail Bennani 154*85fbb08fSMed Ismail Bennani const CommandHistory &history(m_interpreter.GetCommandHistory()); 155*85fbb08fSMed Ismail Bennani 156*85fbb08fSMed Ismail Bennani if (start_idx.first && start_idx.second == UINT64_MAX) { 157*85fbb08fSMed Ismail Bennani if (count.first) { 158*85fbb08fSMed Ismail Bennani start_idx.second = history.GetSize() - count.second; 159*85fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 160*85fbb08fSMed Ismail Bennani } else if (stop_idx.first) { 161*85fbb08fSMed Ismail Bennani start_idx.second = stop_idx.second; 162*85fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 163*85fbb08fSMed Ismail Bennani } else { 164*85fbb08fSMed Ismail Bennani start_idx.second = 0; 165*85fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 166*85fbb08fSMed Ismail Bennani } 167*85fbb08fSMed Ismail Bennani } else { 168*85fbb08fSMed Ismail Bennani if (!start_idx.first && !stop_idx.first && !count.first) { 169*85fbb08fSMed Ismail Bennani start_idx.second = 0; 170*85fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 171*85fbb08fSMed Ismail Bennani } else if (start_idx.first) { 172*85fbb08fSMed Ismail Bennani if (count.first) { 173*85fbb08fSMed Ismail Bennani stop_idx.second = start_idx.second + count.second - 1; 174*85fbb08fSMed Ismail Bennani } else if (!stop_idx.first) { 175*85fbb08fSMed Ismail Bennani stop_idx.second = history.GetSize() - 1; 176*85fbb08fSMed Ismail Bennani } 177*85fbb08fSMed Ismail Bennani } else if (stop_idx.first) { 178*85fbb08fSMed Ismail Bennani if (count.first) { 179*85fbb08fSMed Ismail Bennani if (stop_idx.second >= count.second) 180*85fbb08fSMed Ismail Bennani start_idx.second = stop_idx.second - count.second + 1; 181*85fbb08fSMed Ismail Bennani else 182*85fbb08fSMed Ismail Bennani start_idx.second = 0; 183*85fbb08fSMed Ismail Bennani } 184*85fbb08fSMed Ismail Bennani } else /* if (count.first) */ 185*85fbb08fSMed Ismail Bennani { 186*85fbb08fSMed Ismail Bennani start_idx.second = 0; 187*85fbb08fSMed Ismail Bennani stop_idx.second = count.second - 1; 188*85fbb08fSMed Ismail Bennani } 189*85fbb08fSMed Ismail Bennani } 190*85fbb08fSMed Ismail Bennani history.Dump(result.GetOutputStream(), start_idx.second, 191*85fbb08fSMed Ismail Bennani stop_idx.second); 192*85fbb08fSMed Ismail Bennani } 193*85fbb08fSMed Ismail Bennani } 194*85fbb08fSMed Ismail Bennani return result.Succeeded(); 195*85fbb08fSMed Ismail Bennani } 196*85fbb08fSMed Ismail Bennani 197*85fbb08fSMed Ismail Bennani CommandOptions m_options; 198*85fbb08fSMed Ismail Bennani }; 199*85fbb08fSMed Ismail Bennani 2005bb742b1SMed Ismail Bennani CommandObjectSession::CommandObjectSession(CommandInterpreter &interpreter) 2015bb742b1SMed Ismail Bennani : CommandObjectMultiword(interpreter, "session", 2025bb742b1SMed Ismail Bennani "Commands controlling LLDB session.", 2035bb742b1SMed Ismail Bennani "session <subcommand> [<command-options>]") { 2045bb742b1SMed Ismail Bennani LoadSubCommand("save", 2055bb742b1SMed Ismail Bennani CommandObjectSP(new CommandObjectSessionSave(interpreter))); 206*85fbb08fSMed Ismail Bennani LoadSubCommand("history", 207*85fbb08fSMed Ismail Bennani CommandObjectSP(new CommandObjectSessionHistory(interpreter))); 2085bb742b1SMed Ismail Bennani } 209