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