xref: /freebsd-src/contrib/llvm-project/lldb/source/Commands/CommandObjectSession.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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