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