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