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"
14 using namespace lldb_private
;
16 class CommandObjectSessionSave
: public CommandObjectParsed
{
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 CommandArgumentEntry arg1
;
25 arg1
.emplace_back(eArgTypePath
, eArgRepeatOptional
);
26 m_arguments
.push_back(arg1
);
29 ~CommandObjectSessionSave() override
= default;
32 HandleArgumentCompletion(CompletionRequest
&request
,
33 OptionElementVector
&opt_element_vector
) override
{
34 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
35 GetCommandInterpreter(), lldb::eDiskFileCompletion
, request
, nullptr);
39 void DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
40 llvm::StringRef file_path
;
43 file_path
= args
[0].ref();
45 if (m_interpreter
.SaveTranscript(result
, file_path
.str()))
46 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
48 result
.SetStatus(eReturnStatusFailed
);
52 #define LLDB_OPTIONS_history
53 #include "CommandOptions.inc"
55 class CommandObjectSessionHistory
: public CommandObjectParsed
{
57 CommandObjectSessionHistory(CommandInterpreter
&interpreter
)
58 : CommandObjectParsed(interpreter
, "session history",
59 "Dump the history of commands in this session.\n"
60 "Commands in the history list can be run again "
61 "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run "
62 "the command that is <OFFSET> commands from the end"
63 " of the list (counting the current command).",
66 ~CommandObjectSessionHistory() override
= default;
68 Options
*GetOptions() override
{ return &m_options
; }
71 class CommandOptions
: public Options
{
74 : m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {}
76 ~CommandOptions() override
= default;
78 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
79 ExecutionContext
*execution_context
) override
{
81 const int short_option
= m_getopt_table
[option_idx
].val
;
83 switch (short_option
) {
85 error
= m_count
.SetValueFromString(option_arg
, eVarSetOperationAssign
);
88 if (option_arg
== "end") {
89 m_start_idx
.SetCurrentValue(UINT64_MAX
);
90 m_start_idx
.SetOptionWasSet();
92 error
= m_start_idx
.SetValueFromString(option_arg
,
93 eVarSetOperationAssign
);
97 m_stop_idx
.SetValueFromString(option_arg
, eVarSetOperationAssign
);
100 m_clear
.SetCurrentValue(true);
101 m_clear
.SetOptionWasSet();
104 llvm_unreachable("Unimplemented option");
110 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
117 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
118 return llvm::ArrayRef(g_history_options
);
121 // Instance variables to hold the values for command options.
123 OptionValueUInt64 m_start_idx
;
124 OptionValueUInt64 m_stop_idx
;
125 OptionValueUInt64 m_count
;
126 OptionValueBoolean m_clear
;
129 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
130 if (m_options
.m_clear
.GetCurrentValue() &&
131 m_options
.m_clear
.OptionWasSet()) {
132 m_interpreter
.GetCommandHistory().Clear();
133 result
.SetStatus(lldb::eReturnStatusSuccessFinishNoResult
);
135 if (m_options
.m_start_idx
.OptionWasSet() &&
136 m_options
.m_stop_idx
.OptionWasSet() &&
137 m_options
.m_count
.OptionWasSet()) {
138 result
.AppendError("--count, --start-index and --end-index cannot be "
139 "all specified in the same invocation");
140 result
.SetStatus(lldb::eReturnStatusFailed
);
142 std::pair
<bool, uint64_t> start_idx(
143 m_options
.m_start_idx
.OptionWasSet(),
144 m_options
.m_start_idx
.GetCurrentValue());
145 std::pair
<bool, uint64_t> stop_idx(
146 m_options
.m_stop_idx
.OptionWasSet(),
147 m_options
.m_stop_idx
.GetCurrentValue());
148 std::pair
<bool, uint64_t> count(m_options
.m_count
.OptionWasSet(),
149 m_options
.m_count
.GetCurrentValue());
151 const CommandHistory
&history(m_interpreter
.GetCommandHistory());
153 if (start_idx
.first
&& start_idx
.second
== UINT64_MAX
) {
155 start_idx
.second
= history
.GetSize() - count
.second
;
156 stop_idx
.second
= history
.GetSize() - 1;
157 } else if (stop_idx
.first
) {
158 start_idx
.second
= stop_idx
.second
;
159 stop_idx
.second
= history
.GetSize() - 1;
161 start_idx
.second
= 0;
162 stop_idx
.second
= history
.GetSize() - 1;
165 if (!start_idx
.first
&& !stop_idx
.first
&& !count
.first
) {
166 start_idx
.second
= 0;
167 stop_idx
.second
= history
.GetSize() - 1;
168 } else if (start_idx
.first
) {
170 stop_idx
.second
= start_idx
.second
+ count
.second
- 1;
171 } else if (!stop_idx
.first
) {
172 stop_idx
.second
= history
.GetSize() - 1;
174 } else if (stop_idx
.first
) {
176 if (stop_idx
.second
>= count
.second
)
177 start_idx
.second
= stop_idx
.second
- count
.second
+ 1;
179 start_idx
.second
= 0;
181 } else /* if (count.first) */
183 start_idx
.second
= 0;
184 stop_idx
.second
= count
.second
- 1;
187 history
.Dump(result
.GetOutputStream(), start_idx
.second
,
193 CommandOptions m_options
;
196 CommandObjectSession::CommandObjectSession(CommandInterpreter
&interpreter
)
197 : CommandObjectMultiword(interpreter
, "session",
198 "Commands controlling LLDB session.",
199 "session <subcommand> [<command-options>]") {
200 LoadSubCommand("save",
201 CommandObjectSP(new CommandObjectSessionSave(interpreter
)));
202 LoadSubCommand("history",
203 CommandObjectSP(new CommandObjectSessionHistory(interpreter
)));