xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- CommandObjectSettings.cpp -----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "CommandObjectSettings.h"
10f034231aSEd Maste 
11f3fbd1c0SDimitry Andric #include "llvm/ADT/StringRef.h"
12f3fbd1c0SDimitry Andric 
1374a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
1414f1b3e8SDimitry Andric #include "lldb/Interpreter/CommandCompletions.h"
15f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
164b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
185e95aa85SEd Maste #include "lldb/Interpreter/OptionValueProperties.h"
19f034231aSEd Maste 
20f034231aSEd Maste using namespace lldb;
21f034231aSEd Maste using namespace lldb_private;
22f034231aSEd Maste 
23f034231aSEd Maste // CommandObjectSettingsSet
245f29bb8aSDimitry Andric #define LLDB_OPTIONS_settings_set
255f29bb8aSDimitry Andric #include "CommandOptions.inc"
2614f1b3e8SDimitry Andric 
2714f1b3e8SDimitry Andric class CommandObjectSettingsSet : public CommandObjectRaw {
28f034231aSEd Maste public:
CommandObjectSettingsSet(CommandInterpreter & interpreter)29f3fbd1c0SDimitry Andric   CommandObjectSettingsSet(CommandInterpreter &interpreter)
3014f1b3e8SDimitry Andric       : CommandObjectRaw(interpreter, "settings set",
316f8fc217SDimitry Andric                          "Set the value of the specified debugger setting.") {
32f034231aSEd Maste     CommandArgumentEntry arg1;
33f034231aSEd Maste     CommandArgumentEntry arg2;
34f034231aSEd Maste     CommandArgumentData var_name_arg;
35f034231aSEd Maste     CommandArgumentData value_arg;
36f034231aSEd Maste 
37f034231aSEd Maste     // Define the first (and only) variant of this arg.
38f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
39f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
40f034231aSEd Maste 
4114f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
4214f1b3e8SDimitry Andric     // argument entry.
43f034231aSEd Maste     arg1.push_back(var_name_arg);
44f034231aSEd Maste 
45f034231aSEd Maste     // Define the first (and only) variant of this arg.
46f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
47f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
48f034231aSEd Maste 
4914f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
5014f1b3e8SDimitry Andric     // argument entry.
51f034231aSEd Maste     arg2.push_back(value_arg);
52f034231aSEd Maste 
53f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
54f034231aSEd Maste     m_arguments.push_back(arg1);
55f034231aSEd Maste     m_arguments.push_back(arg2);
56f034231aSEd Maste 
57f034231aSEd Maste     SetHelpLong(
58027f1c96SDimitry Andric         "\nWhen setting a dictionary or array variable, you can set multiple entries \
5914f1b3e8SDimitry Andric at once by giving the values to the set command.  For example:"
6014f1b3e8SDimitry Andric         R"(
61027f1c96SDimitry Andric 
62027f1c96SDimitry Andric (lldb) settings set target.run-args value1 value2 value3
63027f1c96SDimitry Andric (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin  SOME_ENV_VAR=12345
64027f1c96SDimitry Andric 
65027f1c96SDimitry Andric (lldb) settings show target.run-args
66027f1c96SDimitry Andric   [0]: 'value1'
67027f1c96SDimitry Andric   [1]: 'value2'
68027f1c96SDimitry Andric   [3]: 'value3'
69027f1c96SDimitry Andric (lldb) settings show target.env-vars
70027f1c96SDimitry Andric   'MYPATH=~/.:/usr/bin'
71027f1c96SDimitry Andric   'SOME_ENV_VAR=12345'
72027f1c96SDimitry Andric 
7314f1b3e8SDimitry Andric )"
7414f1b3e8SDimitry Andric         "Warning:  The 'set' command re-sets the entire array or dictionary.  If you \
75027f1c96SDimitry Andric just want to add, remove or update individual values (or add something to \
76027f1c96SDimitry Andric the end), use one of the other settings sub-commands: append, replace, \
7714f1b3e8SDimitry Andric insert-before or insert-after.");
78f034231aSEd Maste   }
79f034231aSEd Maste 
80f3fbd1c0SDimitry Andric   ~CommandObjectSettingsSet() override = default;
81f034231aSEd Maste 
8214f1b3e8SDimitry Andric   // Overrides base class's behavior where WantsCompletion =
8314f1b3e8SDimitry Andric   // !WantsRawCommandString.
WantsCompletion()8414f1b3e8SDimitry Andric   bool WantsCompletion() override { return true; }
85f034231aSEd Maste 
GetOptions()8614f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
87f034231aSEd Maste 
8814f1b3e8SDimitry Andric   class CommandOptions : public Options {
89f034231aSEd Maste   public:
90145449b1SDimitry Andric     CommandOptions() = default;
91f034231aSEd Maste 
92f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
93f034231aSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)94b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
9514f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
96b76161e4SDimitry Andric       Status error;
97f034231aSEd Maste       const int short_option = m_getopt_table[option_idx].val;
98f034231aSEd Maste 
9914f1b3e8SDimitry Andric       switch (short_option) {
10094994d37SDimitry Andric       case 'f':
10194994d37SDimitry Andric         m_force = true;
10294994d37SDimitry Andric         break;
103f034231aSEd Maste       case 'g':
104f034231aSEd Maste         m_global = true;
105f034231aSEd Maste         break;
106145449b1SDimitry Andric       case 'e':
107145449b1SDimitry Andric         m_exists = true;
108145449b1SDimitry Andric         break;
109f034231aSEd Maste       default:
110ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
111f034231aSEd Maste       }
112f034231aSEd Maste 
113f034231aSEd Maste       return error;
114f034231aSEd Maste     }
115f034231aSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)11614f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
117f034231aSEd Maste       m_global = false;
11894994d37SDimitry Andric       m_force = false;
119145449b1SDimitry Andric       m_exists = false;
120f034231aSEd Maste     }
121f034231aSEd Maste 
GetDefinitions()12214f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
123e3b55780SDimitry Andric       return llvm::ArrayRef(g_settings_set_options);
124f034231aSEd Maste     }
125f034231aSEd Maste 
126f034231aSEd Maste     // Instance variables to hold the values for command options.
127344a3780SDimitry Andric     bool m_global = false;
128145449b1SDimitry Andric     bool m_force = false;
129145449b1SDimitry Andric     bool m_exists = false;
130f034231aSEd Maste   };
131f034231aSEd Maste 
132ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)133ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
134f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
135f034231aSEd Maste 
136f73363f1SDimitry Andric     const size_t argc = request.GetParsedLine().GetArgumentCount();
137f3fbd1c0SDimitry Andric     const char *arg = nullptr;
138ead24645SDimitry Andric     size_t setting_var_idx;
139ead24645SDimitry Andric     for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {
140f73363f1SDimitry Andric       arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
141f034231aSEd Maste       if (arg && arg[0] != '-')
142f034231aSEd Maste         break; // We found our setting variable name index
143f034231aSEd Maste     }
144f73363f1SDimitry Andric     if (request.GetCursorIndex() == setting_var_idx) {
145f034231aSEd Maste       // Attempting to complete setting variable name
1467fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1477fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
1487fa27ce4SDimitry Andric           nullptr);
149ead24645SDimitry Andric       return;
150ead24645SDimitry Andric     }
151706b4fc4SDimitry Andric     arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
152f034231aSEd Maste 
153ead24645SDimitry Andric     if (!arg)
154ead24645SDimitry Andric       return;
155ead24645SDimitry Andric 
156f034231aSEd Maste     // Complete option name
157e3b55780SDimitry Andric     if (arg[0] == '-')
158ead24645SDimitry Andric       return;
159ead24645SDimitry Andric 
160f034231aSEd Maste     // Complete setting value
16114f1b3e8SDimitry Andric     const char *setting_var_name =
162f73363f1SDimitry Andric         request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
163b76161e4SDimitry Andric     Status error;
1647fa27ce4SDimitry Andric     lldb::OptionValueSP value_sp(
1657fa27ce4SDimitry Andric         GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, error));
166ead24645SDimitry Andric     if (!value_sp)
167ead24645SDimitry Andric       return;
168f73363f1SDimitry Andric     value_sp->AutoComplete(m_interpreter, request);
169f034231aSEd Maste   }
170f034231aSEd Maste 
171f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)172b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
173f73363f1SDimitry Andric                  CommandReturnObject &result) override {
174f034231aSEd Maste     Args cmd_args(command);
175f034231aSEd Maste 
176f034231aSEd Maste     // Process possible options.
177f034231aSEd Maste     if (!ParseOptions(cmd_args, result))
178b1c73532SDimitry Andric       return;
179f034231aSEd Maste 
18094994d37SDimitry Andric     const size_t min_argc = m_options.m_force ? 1 : 2;
181f034231aSEd Maste     const size_t argc = cmd_args.GetArgumentCount();
18294994d37SDimitry Andric 
18394994d37SDimitry Andric     if ((argc < min_argc) && (!m_options.m_global)) {
184f034231aSEd Maste       result.AppendError("'settings set' takes more arguments");
185b1c73532SDimitry Andric       return;
186f034231aSEd Maste     }
187f034231aSEd Maste 
188f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
18914f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
19014f1b3e8SDimitry Andric       result.AppendError(
19114f1b3e8SDimitry Andric           "'settings set' command requires a valid variable name");
192b1c73532SDimitry Andric       return;
193f034231aSEd Maste     }
194f034231aSEd Maste 
19594994d37SDimitry Andric     // A missing value corresponds to clearing the setting when "force" is
19694994d37SDimitry Andric     // specified.
19794994d37SDimitry Andric     if (argc == 1 && m_options.m_force) {
1985f29bb8aSDimitry Andric       Status error(GetDebugger().SetPropertyValue(
19994994d37SDimitry Andric           &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
20094994d37SDimitry Andric       if (error.Fail()) {
20194994d37SDimitry Andric         result.AppendError(error.AsCString());
20294994d37SDimitry Andric       }
203b1c73532SDimitry Andric       return;
20494994d37SDimitry Andric     }
20594994d37SDimitry Andric 
206f034231aSEd Maste     // Split the raw command into var_name and value pair.
207ead24645SDimitry Andric     llvm::StringRef var_value(command);
208ead24645SDimitry Andric     var_value = var_value.split(var_name).second.ltrim();
209f034231aSEd Maste 
210b76161e4SDimitry Andric     Status error;
211ead24645SDimitry Andric     if (m_options.m_global)
2125f29bb8aSDimitry Andric       error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,
213ead24645SDimitry Andric                                              var_name, var_value);
214f034231aSEd Maste 
21514f1b3e8SDimitry Andric     if (error.Success()) {
216f034231aSEd Maste       // FIXME this is the same issue as the one in commands script import
21714f1b3e8SDimitry Andric       // we could be setting target.load-script-from-symbol-file which would
218f73363f1SDimitry Andric       // cause Python scripts to be loaded, which could run LLDB commands (e.g.
219f73363f1SDimitry Andric       // settings set target.process.python-os-plugin-path) and cause a crash
220f034231aSEd Maste       // if we did not clear the command's exe_ctx first
221f034231aSEd Maste       ExecutionContext exe_ctx(m_exe_ctx);
222f034231aSEd Maste       m_exe_ctx.Clear();
2235f29bb8aSDimitry Andric       error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
224ead24645SDimitry Andric                                              var_name, var_value);
225f034231aSEd Maste     }
226f034231aSEd Maste 
227145449b1SDimitry Andric     if (error.Fail() && !m_options.m_exists) {
228f034231aSEd Maste       result.AppendError(error.AsCString());
229b1c73532SDimitry Andric       return;
230f034231aSEd Maste     }
231f034231aSEd Maste 
232145449b1SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
233f034231aSEd Maste   }
234f3fbd1c0SDimitry Andric 
235f034231aSEd Maste private:
236f034231aSEd Maste   CommandOptions m_options;
237f034231aSEd Maste };
238f034231aSEd Maste 
239f034231aSEd Maste // CommandObjectSettingsShow -- Show current values
240f034231aSEd Maste 
24114f1b3e8SDimitry Andric class CommandObjectSettingsShow : public CommandObjectParsed {
242f034231aSEd Maste public:
CommandObjectSettingsShow(CommandInterpreter & interpreter)243f3fbd1c0SDimitry Andric   CommandObjectSettingsShow(CommandInterpreter &interpreter)
24414f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "settings show",
24514f1b3e8SDimitry Andric                             "Show matching debugger settings and their current "
24614f1b3e8SDimitry Andric                             "values.  Defaults to showing all settings.",
24714f1b3e8SDimitry Andric                             nullptr) {
248ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);
249f034231aSEd Maste   }
250f034231aSEd Maste 
251f3fbd1c0SDimitry Andric   ~CommandObjectSettingsShow() override = default;
252f034231aSEd Maste 
253f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)254b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
255f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
256f034231aSEd Maste 
25714f1b3e8SDimitry Andric     if (!args.empty()) {
25814f1b3e8SDimitry Andric       for (const auto &arg : args) {
2595f29bb8aSDimitry Andric         Status error(GetDebugger().DumpPropertyValue(
260ead24645SDimitry Andric             &m_exe_ctx, result.GetOutputStream(), arg.ref(),
26114f1b3e8SDimitry Andric             OptionValue::eDumpGroupValue));
26214f1b3e8SDimitry Andric         if (error.Success()) {
263f034231aSEd Maste           result.GetOutputStream().EOL();
26414f1b3e8SDimitry Andric         } else {
265f034231aSEd Maste           result.AppendError(error.AsCString());
266f034231aSEd Maste         }
267f034231aSEd Maste       }
26814f1b3e8SDimitry Andric     } else {
2695f29bb8aSDimitry Andric       GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),
2705f29bb8aSDimitry Andric                                           OptionValue::eDumpGroupValue);
271f034231aSEd Maste     }
272f034231aSEd Maste   }
273f034231aSEd Maste };
274f034231aSEd Maste 
27594994d37SDimitry Andric // CommandObjectSettingsWrite -- Write settings to file
2765f29bb8aSDimitry Andric #define LLDB_OPTIONS_settings_write
2775f29bb8aSDimitry Andric #include "CommandOptions.inc"
27894994d37SDimitry Andric 
27994994d37SDimitry Andric class CommandObjectSettingsWrite : public CommandObjectParsed {
28094994d37SDimitry Andric public:
CommandObjectSettingsWrite(CommandInterpreter & interpreter)28194994d37SDimitry Andric   CommandObjectSettingsWrite(CommandInterpreter &interpreter)
28294994d37SDimitry Andric       : CommandObjectParsed(
28394994d37SDimitry Andric             interpreter, "settings export",
28494994d37SDimitry Andric             "Write matching debugger settings and their "
28594994d37SDimitry Andric             "current values to a file that can be read in with "
28694994d37SDimitry Andric             "\"settings read\". Defaults to writing all settings.",
2876f8fc217SDimitry Andric             nullptr) {
288ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);
28994994d37SDimitry Andric   }
29094994d37SDimitry Andric 
29194994d37SDimitry Andric   ~CommandObjectSettingsWrite() override = default;
29294994d37SDimitry Andric 
GetOptions()29394994d37SDimitry Andric   Options *GetOptions() override { return &m_options; }
29494994d37SDimitry Andric 
29594994d37SDimitry Andric   class CommandOptions : public Options {
29694994d37SDimitry Andric   public:
297145449b1SDimitry Andric     CommandOptions() = default;
29894994d37SDimitry Andric 
29994994d37SDimitry Andric     ~CommandOptions() override = default;
30094994d37SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)30194994d37SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
30294994d37SDimitry Andric                           ExecutionContext *execution_context) override {
30394994d37SDimitry Andric       Status error;
30494994d37SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
30594994d37SDimitry Andric 
30694994d37SDimitry Andric       switch (short_option) {
30794994d37SDimitry Andric       case 'f':
308cfca06d7SDimitry Andric         m_filename.assign(std::string(option_arg));
30994994d37SDimitry Andric         break;
31094994d37SDimitry Andric       case 'a':
31194994d37SDimitry Andric         m_append = true;
31294994d37SDimitry Andric         break;
31394994d37SDimitry Andric       default:
314ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
31594994d37SDimitry Andric       }
31694994d37SDimitry Andric 
31794994d37SDimitry Andric       return error;
31894994d37SDimitry Andric     }
31994994d37SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)32094994d37SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
32194994d37SDimitry Andric       m_filename.clear();
32294994d37SDimitry Andric       m_append = false;
32394994d37SDimitry Andric     }
32494994d37SDimitry Andric 
GetDefinitions()32594994d37SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
326e3b55780SDimitry Andric       return llvm::ArrayRef(g_settings_write_options);
32794994d37SDimitry Andric     }
32894994d37SDimitry Andric 
32994994d37SDimitry Andric     // Instance variables to hold the values for command options.
33094994d37SDimitry Andric     std::string m_filename;
33194994d37SDimitry Andric     bool m_append = false;
33294994d37SDimitry Andric   };
33394994d37SDimitry Andric 
33494994d37SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)335b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
33694994d37SDimitry Andric     FileSpec file_spec(m_options.m_filename);
33794994d37SDimitry Andric     FileSystem::Instance().Resolve(file_spec);
33894994d37SDimitry Andric     std::string path(file_spec.GetPath());
339c0981da4SDimitry Andric     auto options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
34094994d37SDimitry Andric     if (m_options.m_append)
341ead24645SDimitry Andric       options |= File::eOpenOptionAppend;
34294994d37SDimitry Andric     else
343ead24645SDimitry Andric       options |= File::eOpenOptionTruncate;
34494994d37SDimitry Andric 
34594994d37SDimitry Andric     StreamFile out_file(path.c_str(), options,
34694994d37SDimitry Andric                         lldb::eFilePermissionsFileDefault);
34794994d37SDimitry Andric 
34894994d37SDimitry Andric     if (!out_file.GetFile().IsValid()) {
34994994d37SDimitry Andric       result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
350b1c73532SDimitry Andric       return;
35194994d37SDimitry Andric     }
35294994d37SDimitry Andric 
35394994d37SDimitry Andric     // Exporting should not be context sensitive.
35494994d37SDimitry Andric     ExecutionContext clean_ctx;
35594994d37SDimitry Andric 
35694994d37SDimitry Andric     if (args.empty()) {
3575f29bb8aSDimitry Andric       GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,
3585f29bb8aSDimitry Andric                                           OptionValue::eDumpGroupExport);
359b1c73532SDimitry Andric       return;
36094994d37SDimitry Andric     }
36194994d37SDimitry Andric 
36294994d37SDimitry Andric     for (const auto &arg : args) {
3635f29bb8aSDimitry Andric       Status error(GetDebugger().DumpPropertyValue(
364ead24645SDimitry Andric           &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));
36594994d37SDimitry Andric       if (!error.Success()) {
36694994d37SDimitry Andric         result.AppendError(error.AsCString());
36794994d37SDimitry Andric       }
36894994d37SDimitry Andric     }
36994994d37SDimitry Andric   }
37094994d37SDimitry Andric 
37194994d37SDimitry Andric private:
37294994d37SDimitry Andric   CommandOptions m_options;
37394994d37SDimitry Andric };
37494994d37SDimitry Andric 
37594994d37SDimitry Andric // CommandObjectSettingsRead -- Read settings from file
3765f29bb8aSDimitry Andric #define LLDB_OPTIONS_settings_read
3775f29bb8aSDimitry Andric #include "CommandOptions.inc"
37894994d37SDimitry Andric 
37994994d37SDimitry Andric class CommandObjectSettingsRead : public CommandObjectParsed {
38094994d37SDimitry Andric public:
CommandObjectSettingsRead(CommandInterpreter & interpreter)38194994d37SDimitry Andric   CommandObjectSettingsRead(CommandInterpreter &interpreter)
38294994d37SDimitry Andric       : CommandObjectParsed(
38394994d37SDimitry Andric             interpreter, "settings read",
38494994d37SDimitry Andric             "Read settings previously saved to a file with \"settings write\".",
3856f8fc217SDimitry Andric             nullptr) {}
38694994d37SDimitry Andric 
38794994d37SDimitry Andric   ~CommandObjectSettingsRead() override = default;
38894994d37SDimitry Andric 
GetOptions()38994994d37SDimitry Andric   Options *GetOptions() override { return &m_options; }
39094994d37SDimitry Andric 
39194994d37SDimitry Andric   class CommandOptions : public Options {
39294994d37SDimitry Andric   public:
393145449b1SDimitry Andric     CommandOptions() = default;
39494994d37SDimitry Andric 
39594994d37SDimitry Andric     ~CommandOptions() override = default;
39694994d37SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)39794994d37SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
39894994d37SDimitry Andric                           ExecutionContext *execution_context) override {
39994994d37SDimitry Andric       Status error;
40094994d37SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
40194994d37SDimitry Andric 
40294994d37SDimitry Andric       switch (short_option) {
40394994d37SDimitry Andric       case 'f':
404cfca06d7SDimitry Andric         m_filename.assign(std::string(option_arg));
40594994d37SDimitry Andric         break;
40694994d37SDimitry Andric       default:
407ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
40894994d37SDimitry Andric       }
40994994d37SDimitry Andric 
41094994d37SDimitry Andric       return error;
41194994d37SDimitry Andric     }
41294994d37SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)41394994d37SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
41494994d37SDimitry Andric       m_filename.clear();
41594994d37SDimitry Andric     }
41694994d37SDimitry Andric 
GetDefinitions()41794994d37SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
418e3b55780SDimitry Andric       return llvm::ArrayRef(g_settings_read_options);
41994994d37SDimitry Andric     }
42094994d37SDimitry Andric 
42194994d37SDimitry Andric     // Instance variables to hold the values for command options.
42294994d37SDimitry Andric     std::string m_filename;
42394994d37SDimitry Andric   };
42494994d37SDimitry Andric 
42594994d37SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)426b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
42794994d37SDimitry Andric     FileSpec file(m_options.m_filename);
42894994d37SDimitry Andric     FileSystem::Instance().Resolve(file);
42994994d37SDimitry Andric     CommandInterpreterRunOptions options;
43094994d37SDimitry Andric     options.SetAddToHistory(false);
43194994d37SDimitry Andric     options.SetEchoCommands(false);
43294994d37SDimitry Andric     options.SetPrintResults(true);
4335f29bb8aSDimitry Andric     options.SetPrintErrors(true);
43494994d37SDimitry Andric     options.SetStopOnError(false);
435344a3780SDimitry Andric     m_interpreter.HandleCommandsFromFile(file, options, result);
43694994d37SDimitry Andric   }
43794994d37SDimitry Andric 
43894994d37SDimitry Andric private:
43994994d37SDimitry Andric   CommandOptions m_options;
44094994d37SDimitry Andric };
44194994d37SDimitry Andric 
442f034231aSEd Maste // CommandObjectSettingsList -- List settable variables
443f034231aSEd Maste 
44414f1b3e8SDimitry Andric class CommandObjectSettingsList : public CommandObjectParsed {
445f034231aSEd Maste public:
CommandObjectSettingsList(CommandInterpreter & interpreter)446f3fbd1c0SDimitry Andric   CommandObjectSettingsList(CommandInterpreter &interpreter)
447f3fbd1c0SDimitry Andric       : CommandObjectParsed(interpreter, "settings list",
44814f1b3e8SDimitry Andric                             "List and describe matching debugger settings.  "
44914f1b3e8SDimitry Andric                             "Defaults to all listing all settings.",
45014f1b3e8SDimitry Andric                             nullptr) {
451f034231aSEd Maste     CommandArgumentEntry arg;
452f034231aSEd Maste     CommandArgumentData var_name_arg;
453f034231aSEd Maste     CommandArgumentData prefix_name_arg;
454f034231aSEd Maste 
455f034231aSEd Maste     // Define the first variant of this arg.
456f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
457f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatOptional;
458f034231aSEd Maste 
459f034231aSEd Maste     // Define the second variant of this arg.
460f034231aSEd Maste     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
461f034231aSEd Maste     prefix_name_arg.arg_repetition = eArgRepeatOptional;
462f034231aSEd Maste 
463f034231aSEd Maste     arg.push_back(var_name_arg);
464f034231aSEd Maste     arg.push_back(prefix_name_arg);
465f034231aSEd Maste 
466f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
467f034231aSEd Maste     m_arguments.push_back(arg);
468f034231aSEd Maste   }
469f034231aSEd Maste 
470f3fbd1c0SDimitry Andric   ~CommandObjectSettingsList() override = default;
471f034231aSEd Maste 
472ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)473ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
474f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
4757fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
4767fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
4777fa27ce4SDimitry Andric         nullptr);
478f034231aSEd Maste   }
479f034231aSEd Maste 
480f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)481b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
482f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
483f034231aSEd Maste 
484f034231aSEd Maste     const size_t argc = args.GetArgumentCount();
48514f1b3e8SDimitry Andric     if (argc > 0) {
486f034231aSEd Maste       const bool dump_qualified_name = true;
487f034231aSEd Maste 
488cfca06d7SDimitry Andric       for (const Args::ArgEntry &arg : args) {
489cfca06d7SDimitry Andric         const char *property_path = arg.c_str();
490f034231aSEd Maste 
49114f1b3e8SDimitry Andric         const Property *property =
4925f29bb8aSDimitry Andric             GetDebugger().GetValueProperties()->GetPropertyAtPath(
4937fa27ce4SDimitry Andric                 &m_exe_ctx, property_path);
494f034231aSEd Maste 
49514f1b3e8SDimitry Andric         if (property) {
49614f1b3e8SDimitry Andric           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
49714f1b3e8SDimitry Andric                                     dump_qualified_name);
49814f1b3e8SDimitry Andric         } else {
49914f1b3e8SDimitry Andric           result.AppendErrorWithFormat("invalid property path '%s'",
50014f1b3e8SDimitry Andric                                        property_path);
501f034231aSEd Maste         }
502f034231aSEd Maste       }
50314f1b3e8SDimitry Andric     } else {
5045f29bb8aSDimitry Andric       GetDebugger().DumpAllDescriptions(m_interpreter,
50514f1b3e8SDimitry Andric                                         result.GetOutputStream());
506f034231aSEd Maste     }
507f034231aSEd Maste   }
508f034231aSEd Maste };
509f034231aSEd Maste 
510f034231aSEd Maste // CommandObjectSettingsRemove
511f034231aSEd Maste 
51214f1b3e8SDimitry Andric class CommandObjectSettingsRemove : public CommandObjectRaw {
513f034231aSEd Maste public:
CommandObjectSettingsRemove(CommandInterpreter & interpreter)514f3fbd1c0SDimitry Andric   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
515f3fbd1c0SDimitry Andric       : CommandObjectRaw(interpreter, "settings remove",
51614f1b3e8SDimitry Andric                          "Remove a value from a setting, specified by array "
51714f1b3e8SDimitry Andric                          "index or dictionary key.") {
518f034231aSEd Maste     CommandArgumentEntry arg1;
519f034231aSEd Maste     CommandArgumentEntry arg2;
520f034231aSEd Maste     CommandArgumentData var_name_arg;
521f034231aSEd Maste     CommandArgumentData index_arg;
522f034231aSEd Maste     CommandArgumentData key_arg;
523f034231aSEd Maste 
524f034231aSEd Maste     // Define the first (and only) variant of this arg.
525f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
526f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
527f034231aSEd Maste 
52814f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
52914f1b3e8SDimitry Andric     // argument entry.
530f034231aSEd Maste     arg1.push_back(var_name_arg);
531f034231aSEd Maste 
532f034231aSEd Maste     // Define the first variant of this arg.
533f034231aSEd Maste     index_arg.arg_type = eArgTypeSettingIndex;
534f034231aSEd Maste     index_arg.arg_repetition = eArgRepeatPlain;
535f034231aSEd Maste 
536f034231aSEd Maste     // Define the second variant of this arg.
537f034231aSEd Maste     key_arg.arg_type = eArgTypeSettingKey;
538f034231aSEd Maste     key_arg.arg_repetition = eArgRepeatPlain;
539f034231aSEd Maste 
540f034231aSEd Maste     // Push both variants into this arg
541f034231aSEd Maste     arg2.push_back(index_arg);
542f034231aSEd Maste     arg2.push_back(key_arg);
543f034231aSEd Maste 
544f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
545f034231aSEd Maste     m_arguments.push_back(arg1);
546f034231aSEd Maste     m_arguments.push_back(arg2);
547f034231aSEd Maste   }
548f034231aSEd Maste 
549f3fbd1c0SDimitry Andric   ~CommandObjectSettingsRemove() override = default;
550f034231aSEd Maste 
WantsCompletion()551ead24645SDimitry Andric   bool WantsCompletion() override { return true; }
552ead24645SDimitry Andric 
553ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)554ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
555f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
556f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
5577fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
5587fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
5597fa27ce4SDimitry Andric           nullptr);
560f034231aSEd Maste   }
561f034231aSEd Maste 
562f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)563b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
564f73363f1SDimitry Andric                  CommandReturnObject &result) override {
565f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
566f034231aSEd Maste 
567f034231aSEd Maste     Args cmd_args(command);
568f034231aSEd Maste 
569f034231aSEd Maste     // Process possible options.
570f034231aSEd Maste     if (!ParseOptions(cmd_args, result))
571b1c73532SDimitry Andric       return;
572f034231aSEd Maste 
573f034231aSEd Maste     const size_t argc = cmd_args.GetArgumentCount();
57414f1b3e8SDimitry Andric     if (argc == 0) {
575ead24645SDimitry Andric       result.AppendError("'settings remove' takes an array or dictionary item, "
576ead24645SDimitry Andric                          "or an array followed by one or more indexes, or a "
57714f1b3e8SDimitry Andric                          "dictionary followed by one or more key names to "
57814f1b3e8SDimitry Andric                          "remove");
579b1c73532SDimitry Andric       return;
580f034231aSEd Maste     }
581f034231aSEd Maste 
582f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
58314f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
58414f1b3e8SDimitry Andric       result.AppendError(
585ead24645SDimitry Andric           "'settings remove' command requires a valid variable name");
586b1c73532SDimitry Andric       return;
587f034231aSEd Maste     }
588f034231aSEd Maste 
589f034231aSEd Maste     // Split the raw command into var_name and value pair.
590ead24645SDimitry Andric     llvm::StringRef var_value(command);
591ead24645SDimitry Andric     var_value = var_value.split(var_name).second.trim();
592f034231aSEd Maste 
5935f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
594ead24645SDimitry Andric         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
59514f1b3e8SDimitry Andric     if (error.Fail()) {
596f034231aSEd Maste       result.AppendError(error.AsCString());
597f034231aSEd Maste     }
598f034231aSEd Maste   }
599f034231aSEd Maste };
600f034231aSEd Maste 
601f034231aSEd Maste // CommandObjectSettingsReplace
602f034231aSEd Maste 
60314f1b3e8SDimitry Andric class CommandObjectSettingsReplace : public CommandObjectRaw {
604f034231aSEd Maste public:
CommandObjectSettingsReplace(CommandInterpreter & interpreter)605f3fbd1c0SDimitry Andric   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
606f3fbd1c0SDimitry Andric       : CommandObjectRaw(interpreter, "settings replace",
60714f1b3e8SDimitry Andric                          "Replace the debugger setting value specified by "
60814f1b3e8SDimitry Andric                          "array index or dictionary key.") {
609f034231aSEd Maste     CommandArgumentEntry arg1;
610f034231aSEd Maste     CommandArgumentEntry arg2;
611f034231aSEd Maste     CommandArgumentEntry arg3;
612f034231aSEd Maste     CommandArgumentData var_name_arg;
613f034231aSEd Maste     CommandArgumentData index_arg;
614f034231aSEd Maste     CommandArgumentData key_arg;
615f034231aSEd Maste     CommandArgumentData value_arg;
616f034231aSEd Maste 
617f034231aSEd Maste     // Define the first (and only) variant of this arg.
618f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
619f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
620f034231aSEd Maste 
62114f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
62214f1b3e8SDimitry Andric     // argument entry.
623f034231aSEd Maste     arg1.push_back(var_name_arg);
624f034231aSEd Maste 
625f034231aSEd Maste     // Define the first (variant of this arg.
626f034231aSEd Maste     index_arg.arg_type = eArgTypeSettingIndex;
627f034231aSEd Maste     index_arg.arg_repetition = eArgRepeatPlain;
628f034231aSEd Maste 
629f034231aSEd Maste     // Define the second (variant of this arg.
630f034231aSEd Maste     key_arg.arg_type = eArgTypeSettingKey;
631f034231aSEd Maste     key_arg.arg_repetition = eArgRepeatPlain;
632f034231aSEd Maste 
633f034231aSEd Maste     // Put both variants into this arg
634f034231aSEd Maste     arg2.push_back(index_arg);
635f034231aSEd Maste     arg2.push_back(key_arg);
636f034231aSEd Maste 
637f034231aSEd Maste     // Define the first (and only) variant of this arg.
638f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
639f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
640f034231aSEd Maste 
64114f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
64214f1b3e8SDimitry Andric     // argument entry.
643f034231aSEd Maste     arg3.push_back(value_arg);
644f034231aSEd Maste 
645f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
646f034231aSEd Maste     m_arguments.push_back(arg1);
647f034231aSEd Maste     m_arguments.push_back(arg2);
648f034231aSEd Maste     m_arguments.push_back(arg3);
649f034231aSEd Maste   }
650f034231aSEd Maste 
651f3fbd1c0SDimitry Andric   ~CommandObjectSettingsReplace() override = default;
652f034231aSEd Maste 
65314f1b3e8SDimitry Andric   // Overrides base class's behavior where WantsCompletion =
65414f1b3e8SDimitry Andric   // !WantsRawCommandString.
WantsCompletion()65514f1b3e8SDimitry Andric   bool WantsCompletion() override { return true; }
656f034231aSEd Maste 
657ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)658ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
659f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
660f034231aSEd Maste     // Attempting to complete variable name
661f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
6627fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
6637fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
6647fa27ce4SDimitry Andric           nullptr);
665f034231aSEd Maste   }
666f034231aSEd Maste 
667f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)668b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
669f73363f1SDimitry Andric                  CommandReturnObject &result) override {
670f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
671f034231aSEd Maste 
672f034231aSEd Maste     Args cmd_args(command);
673f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
67414f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
67514f1b3e8SDimitry Andric       result.AppendError("'settings replace' command requires a valid variable "
67614f1b3e8SDimitry Andric                          "name; No value supplied");
677b1c73532SDimitry Andric       return;
678f034231aSEd Maste     }
679f034231aSEd Maste 
680f034231aSEd Maste     // Split the raw command into var_name, index_value, and value triple.
681ead24645SDimitry Andric     llvm::StringRef var_value(command);
682ead24645SDimitry Andric     var_value = var_value.split(var_name).second.trim();
683f034231aSEd Maste 
6845f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
685ead24645SDimitry Andric         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
68614f1b3e8SDimitry Andric     if (error.Fail()) {
687f034231aSEd Maste       result.AppendError(error.AsCString());
68814f1b3e8SDimitry Andric     } else {
689f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
690f034231aSEd Maste     }
691f034231aSEd Maste   }
692f034231aSEd Maste };
693f034231aSEd Maste 
694f034231aSEd Maste // CommandObjectSettingsInsertBefore
695f034231aSEd Maste 
69614f1b3e8SDimitry Andric class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
697f034231aSEd Maste public:
CommandObjectSettingsInsertBefore(CommandInterpreter & interpreter)698f3fbd1c0SDimitry Andric   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
69914f1b3e8SDimitry Andric       : CommandObjectRaw(interpreter, "settings insert-before",
70014f1b3e8SDimitry Andric                          "Insert one or more values into an debugger array "
701f3fbd1c0SDimitry Andric                          "setting immediately before the specified element "
70214f1b3e8SDimitry Andric                          "index.") {
703f034231aSEd Maste     CommandArgumentEntry arg1;
704f034231aSEd Maste     CommandArgumentEntry arg2;
705f034231aSEd Maste     CommandArgumentEntry arg3;
706f034231aSEd Maste     CommandArgumentData var_name_arg;
707f034231aSEd Maste     CommandArgumentData index_arg;
708f034231aSEd Maste     CommandArgumentData value_arg;
709f034231aSEd Maste 
710f034231aSEd Maste     // Define the first (and only) variant of this arg.
711f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
712f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
713f034231aSEd Maste 
71414f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
71514f1b3e8SDimitry Andric     // argument entry.
716f034231aSEd Maste     arg1.push_back(var_name_arg);
717f034231aSEd Maste 
718f034231aSEd Maste     // Define the first (variant of this arg.
719f034231aSEd Maste     index_arg.arg_type = eArgTypeSettingIndex;
720f034231aSEd Maste     index_arg.arg_repetition = eArgRepeatPlain;
721f034231aSEd Maste 
72214f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
72314f1b3e8SDimitry Andric     // argument entry.
724f034231aSEd Maste     arg2.push_back(index_arg);
725f034231aSEd Maste 
726f034231aSEd Maste     // Define the first (and only) variant of this arg.
727f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
728f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
729f034231aSEd Maste 
73014f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
73114f1b3e8SDimitry Andric     // argument entry.
732f034231aSEd Maste     arg3.push_back(value_arg);
733f034231aSEd Maste 
734f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
735f034231aSEd Maste     m_arguments.push_back(arg1);
736f034231aSEd Maste     m_arguments.push_back(arg2);
737f034231aSEd Maste     m_arguments.push_back(arg3);
738f034231aSEd Maste   }
739f034231aSEd Maste 
740f3fbd1c0SDimitry Andric   ~CommandObjectSettingsInsertBefore() override = default;
741f034231aSEd Maste 
74214f1b3e8SDimitry Andric   // Overrides base class's behavior where WantsCompletion =
74314f1b3e8SDimitry Andric   // !WantsRawCommandString.
WantsCompletion()74414f1b3e8SDimitry Andric   bool WantsCompletion() override { return true; }
745f034231aSEd Maste 
746ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)747ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
748f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
749f034231aSEd Maste     // Attempting to complete variable name
750f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
7517fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
7527fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
7537fa27ce4SDimitry Andric           nullptr);
754f034231aSEd Maste   }
755f034231aSEd Maste 
756f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)757b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
758f73363f1SDimitry Andric                  CommandReturnObject &result) override {
759f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
760f034231aSEd Maste 
761f034231aSEd Maste     Args cmd_args(command);
762f034231aSEd Maste     const size_t argc = cmd_args.GetArgumentCount();
763f034231aSEd Maste 
76414f1b3e8SDimitry Andric     if (argc < 3) {
765f034231aSEd Maste       result.AppendError("'settings insert-before' takes more arguments");
766b1c73532SDimitry Andric       return;
767f034231aSEd Maste     }
768f034231aSEd Maste 
769f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
77014f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
77114f1b3e8SDimitry Andric       result.AppendError("'settings insert-before' command requires a valid "
77214f1b3e8SDimitry Andric                          "variable name; No value supplied");
773b1c73532SDimitry Andric       return;
774f034231aSEd Maste     }
775f034231aSEd Maste 
776f034231aSEd Maste     // Split the raw command into var_name, index_value, and value triple.
777ead24645SDimitry Andric     llvm::StringRef var_value(command);
778ead24645SDimitry Andric     var_value = var_value.split(var_name).second.trim();
779f034231aSEd Maste 
7805f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
781ead24645SDimitry Andric         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
78214f1b3e8SDimitry Andric     if (error.Fail()) {
783f034231aSEd Maste       result.AppendError(error.AsCString());
784f034231aSEd Maste     }
785f034231aSEd Maste   }
786f034231aSEd Maste };
787f034231aSEd Maste 
788f034231aSEd Maste // CommandObjectSettingInsertAfter
789f034231aSEd Maste 
79014f1b3e8SDimitry Andric class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
791f034231aSEd Maste public:
CommandObjectSettingsInsertAfter(CommandInterpreter & interpreter)792f3fbd1c0SDimitry Andric   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
79314f1b3e8SDimitry Andric       : CommandObjectRaw(interpreter, "settings insert-after",
79414f1b3e8SDimitry Andric                          "Insert one or more values into a debugger array "
79514f1b3e8SDimitry Andric                          "settings after the specified element index.") {
796f034231aSEd Maste     CommandArgumentEntry arg1;
797f034231aSEd Maste     CommandArgumentEntry arg2;
798f034231aSEd Maste     CommandArgumentEntry arg3;
799f034231aSEd Maste     CommandArgumentData var_name_arg;
800f034231aSEd Maste     CommandArgumentData index_arg;
801f034231aSEd Maste     CommandArgumentData value_arg;
802f034231aSEd Maste 
803f034231aSEd Maste     // Define the first (and only) variant of this arg.
804f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
805f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
806f034231aSEd Maste 
80714f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
80814f1b3e8SDimitry Andric     // argument entry.
809f034231aSEd Maste     arg1.push_back(var_name_arg);
810f034231aSEd Maste 
811f034231aSEd Maste     // Define the first (variant of this arg.
812f034231aSEd Maste     index_arg.arg_type = eArgTypeSettingIndex;
813f034231aSEd Maste     index_arg.arg_repetition = eArgRepeatPlain;
814f034231aSEd Maste 
81514f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
81614f1b3e8SDimitry Andric     // argument entry.
817f034231aSEd Maste     arg2.push_back(index_arg);
818f034231aSEd Maste 
819f034231aSEd Maste     // Define the first (and only) variant of this arg.
820f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
821f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
822f034231aSEd Maste 
82314f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
82414f1b3e8SDimitry Andric     // argument entry.
825f034231aSEd Maste     arg3.push_back(value_arg);
826f034231aSEd Maste 
827f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
828f034231aSEd Maste     m_arguments.push_back(arg1);
829f034231aSEd Maste     m_arguments.push_back(arg2);
830f034231aSEd Maste     m_arguments.push_back(arg3);
831f034231aSEd Maste   }
832f034231aSEd Maste 
833f3fbd1c0SDimitry Andric   ~CommandObjectSettingsInsertAfter() override = default;
834f034231aSEd Maste 
83514f1b3e8SDimitry Andric   // Overrides base class's behavior where WantsCompletion =
83614f1b3e8SDimitry Andric   // !WantsRawCommandString.
WantsCompletion()83714f1b3e8SDimitry Andric   bool WantsCompletion() override { return true; }
838f034231aSEd Maste 
839ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)840ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
841f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
842f034231aSEd Maste     // Attempting to complete variable name
843f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
8447fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
8457fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
8467fa27ce4SDimitry Andric           nullptr);
847f034231aSEd Maste   }
848f034231aSEd Maste 
849f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)850b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
851f73363f1SDimitry Andric                  CommandReturnObject &result) override {
852f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
853f034231aSEd Maste 
854f034231aSEd Maste     Args cmd_args(command);
855f034231aSEd Maste     const size_t argc = cmd_args.GetArgumentCount();
856f034231aSEd Maste 
85714f1b3e8SDimitry Andric     if (argc < 3) {
858f034231aSEd Maste       result.AppendError("'settings insert-after' takes more arguments");
859b1c73532SDimitry Andric       return;
860f034231aSEd Maste     }
861f034231aSEd Maste 
862f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
86314f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
86414f1b3e8SDimitry Andric       result.AppendError("'settings insert-after' command requires a valid "
86514f1b3e8SDimitry Andric                          "variable name; No value supplied");
866b1c73532SDimitry Andric       return;
867f034231aSEd Maste     }
868f034231aSEd Maste 
869f034231aSEd Maste     // Split the raw command into var_name, index_value, and value triple.
870ead24645SDimitry Andric     llvm::StringRef var_value(command);
871ead24645SDimitry Andric     var_value = var_value.split(var_name).second.trim();
872f034231aSEd Maste 
8735f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
874ead24645SDimitry Andric         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
87514f1b3e8SDimitry Andric     if (error.Fail()) {
876f034231aSEd Maste       result.AppendError(error.AsCString());
877f034231aSEd Maste     }
878f034231aSEd Maste   }
879f034231aSEd Maste };
880f034231aSEd Maste 
881f034231aSEd Maste // CommandObjectSettingsAppend
882f034231aSEd Maste 
88314f1b3e8SDimitry Andric class CommandObjectSettingsAppend : public CommandObjectRaw {
884f034231aSEd Maste public:
CommandObjectSettingsAppend(CommandInterpreter & interpreter)885f3fbd1c0SDimitry Andric   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
886f3fbd1c0SDimitry Andric       : CommandObjectRaw(interpreter, "settings append",
88714f1b3e8SDimitry Andric                          "Append one or more values to a debugger array, "
88814f1b3e8SDimitry Andric                          "dictionary, or string setting.") {
889f034231aSEd Maste     CommandArgumentEntry arg1;
890f034231aSEd Maste     CommandArgumentEntry arg2;
891f034231aSEd Maste     CommandArgumentData var_name_arg;
892f034231aSEd Maste     CommandArgumentData value_arg;
893f034231aSEd Maste 
894f034231aSEd Maste     // Define the first (and only) variant of this arg.
895f034231aSEd Maste     var_name_arg.arg_type = eArgTypeSettingVariableName;
896f034231aSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlain;
897f034231aSEd Maste 
89814f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
89914f1b3e8SDimitry Andric     // argument entry.
900f034231aSEd Maste     arg1.push_back(var_name_arg);
901f034231aSEd Maste 
902f034231aSEd Maste     // Define the first (and only) variant of this arg.
903f034231aSEd Maste     value_arg.arg_type = eArgTypeValue;
904f034231aSEd Maste     value_arg.arg_repetition = eArgRepeatPlain;
905f034231aSEd Maste 
90614f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
90714f1b3e8SDimitry Andric     // argument entry.
908f034231aSEd Maste     arg2.push_back(value_arg);
909f034231aSEd Maste 
910f034231aSEd Maste     // Push the data for the first argument into the m_arguments vector.
911f034231aSEd Maste     m_arguments.push_back(arg1);
912f034231aSEd Maste     m_arguments.push_back(arg2);
913f034231aSEd Maste   }
914f034231aSEd Maste 
915f3fbd1c0SDimitry Andric   ~CommandObjectSettingsAppend() override = default;
916f034231aSEd Maste 
91714f1b3e8SDimitry Andric   // Overrides base class's behavior where WantsCompletion =
91814f1b3e8SDimitry Andric   // !WantsRawCommandString.
WantsCompletion()91914f1b3e8SDimitry Andric   bool WantsCompletion() override { return true; }
920f034231aSEd Maste 
921ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)922ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
923f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
924f034231aSEd Maste     // Attempting to complete variable name
925f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
9267fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
9277fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
9287fa27ce4SDimitry Andric           nullptr);
929f034231aSEd Maste   }
930f034231aSEd Maste 
931f034231aSEd Maste protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)932b1c73532SDimitry Andric   void DoExecute(llvm::StringRef command,
933f73363f1SDimitry Andric                  CommandReturnObject &result) override {
934f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
935f034231aSEd Maste     Args cmd_args(command);
936f034231aSEd Maste     const size_t argc = cmd_args.GetArgumentCount();
937f034231aSEd Maste 
93814f1b3e8SDimitry Andric     if (argc < 2) {
939f034231aSEd Maste       result.AppendError("'settings append' takes more arguments");
940b1c73532SDimitry Andric       return;
941f034231aSEd Maste     }
942f034231aSEd Maste 
943f034231aSEd Maste     const char *var_name = cmd_args.GetArgumentAtIndex(0);
94414f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
94514f1b3e8SDimitry Andric       result.AppendError("'settings append' command requires a valid variable "
94614f1b3e8SDimitry Andric                          "name; No value supplied");
947b1c73532SDimitry Andric       return;
948f034231aSEd Maste     }
949f034231aSEd Maste 
950f73363f1SDimitry Andric     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
951f73363f1SDimitry Andric     // character string later on.
952f034231aSEd Maste 
953f034231aSEd Maste     // Split the raw command into var_name and value pair.
954ead24645SDimitry Andric     llvm::StringRef var_value(command);
955ead24645SDimitry Andric     var_value = var_value.split(var_name).second.trim();
956f034231aSEd Maste 
9575f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
958ead24645SDimitry Andric         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
95914f1b3e8SDimitry Andric     if (error.Fail()) {
960f034231aSEd Maste       result.AppendError(error.AsCString());
961f034231aSEd Maste     }
962f034231aSEd Maste   }
963f034231aSEd Maste };
964f034231aSEd Maste 
965f034231aSEd Maste // CommandObjectSettingsClear
966cfca06d7SDimitry Andric #define LLDB_OPTIONS_settings_clear
967cfca06d7SDimitry Andric #include "CommandOptions.inc"
968f034231aSEd Maste 
96914f1b3e8SDimitry Andric class CommandObjectSettingsClear : public CommandObjectParsed {
970f034231aSEd Maste public:
CommandObjectSettingsClear(CommandInterpreter & interpreter)971f3fbd1c0SDimitry Andric   CommandObjectSettingsClear(CommandInterpreter &interpreter)
97214f1b3e8SDimitry Andric       : CommandObjectParsed(
97314f1b3e8SDimitry Andric             interpreter, "settings clear",
974cfca06d7SDimitry Andric             "Clear a debugger setting array, dictionary, or string. "
975cfca06d7SDimitry Andric             "If '-a' option is specified, it clears all settings.", nullptr) {
976ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeSettingVariableName);
977f034231aSEd Maste   }
978f034231aSEd Maste 
979f3fbd1c0SDimitry Andric   ~CommandObjectSettingsClear() override = default;
980f034231aSEd Maste 
981ead24645SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)982ead24645SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
983f73363f1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
984f034231aSEd Maste     // Attempting to complete variable name
985f73363f1SDimitry Andric     if (request.GetCursorIndex() < 2)
9867fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
9877fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,
9887fa27ce4SDimitry Andric           nullptr);
989f034231aSEd Maste   }
990f034231aSEd Maste 
GetOptions()991cfca06d7SDimitry Andric    Options *GetOptions() override { return &m_options; }
992cfca06d7SDimitry Andric 
993cfca06d7SDimitry Andric   class CommandOptions : public Options {
994cfca06d7SDimitry Andric   public:
995cfca06d7SDimitry Andric     CommandOptions() = default;
996cfca06d7SDimitry Andric 
997cfca06d7SDimitry Andric     ~CommandOptions() override = default;
998cfca06d7SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)999cfca06d7SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1000cfca06d7SDimitry Andric                           ExecutionContext *execution_context) override {
1001cfca06d7SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
1002cfca06d7SDimitry Andric       switch (short_option) {
1003cfca06d7SDimitry Andric       case 'a':
1004cfca06d7SDimitry Andric         m_clear_all = true;
1005cfca06d7SDimitry Andric         break;
1006cfca06d7SDimitry Andric       default:
1007cfca06d7SDimitry Andric         llvm_unreachable("Unimplemented option");
1008cfca06d7SDimitry Andric       }
1009cfca06d7SDimitry Andric       return Status();
1010cfca06d7SDimitry Andric     }
1011cfca06d7SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1012cfca06d7SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1013cfca06d7SDimitry Andric       m_clear_all = false;
1014cfca06d7SDimitry Andric     }
1015cfca06d7SDimitry Andric 
GetDefinitions()1016cfca06d7SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1017e3b55780SDimitry Andric       return llvm::ArrayRef(g_settings_clear_options);
1018cfca06d7SDimitry Andric     }
1019cfca06d7SDimitry Andric 
1020cfca06d7SDimitry Andric     bool m_clear_all = false;
1021cfca06d7SDimitry Andric   };
1022cfca06d7SDimitry Andric 
1023f034231aSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1024b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
1025f034231aSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1026f034231aSEd Maste     const size_t argc = command.GetArgumentCount();
1027f034231aSEd Maste 
1028cfca06d7SDimitry Andric     if (m_options.m_clear_all) {
1029cfca06d7SDimitry Andric       if (argc != 0) {
1030cfca06d7SDimitry Andric         result.AppendError("'settings clear --all' doesn't take any arguments");
1031b1c73532SDimitry Andric         return;
1032cfca06d7SDimitry Andric       }
1033cfca06d7SDimitry Andric       GetDebugger().GetValueProperties()->Clear();
1034b1c73532SDimitry Andric       return;
1035cfca06d7SDimitry Andric     }
1036cfca06d7SDimitry Andric 
103714f1b3e8SDimitry Andric     if (argc != 1) {
10380cac4ca3SEd Maste       result.AppendError("'settings clear' takes exactly one argument");
1039b1c73532SDimitry Andric       return;
1040f034231aSEd Maste     }
1041f034231aSEd Maste 
1042f034231aSEd Maste     const char *var_name = command.GetArgumentAtIndex(0);
104314f1b3e8SDimitry Andric     if ((var_name == nullptr) || (var_name[0] == '\0')) {
104414f1b3e8SDimitry Andric       result.AppendError("'settings clear' command requires a valid variable "
104514f1b3e8SDimitry Andric                          "name; No value supplied");
1046b1c73532SDimitry Andric       return;
1047f034231aSEd Maste     }
1048f034231aSEd Maste 
10495f29bb8aSDimitry Andric     Status error(GetDebugger().SetPropertyValue(
105014f1b3e8SDimitry Andric         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
105114f1b3e8SDimitry Andric     if (error.Fail()) {
1052f034231aSEd Maste       result.AppendError(error.AsCString());
1053f034231aSEd Maste     }
1054f034231aSEd Maste   }
1055cfca06d7SDimitry Andric 
1056cfca06d7SDimitry Andric   private:
1057cfca06d7SDimitry Andric     CommandOptions m_options;
1058f034231aSEd Maste };
1059f034231aSEd Maste 
1060f034231aSEd Maste // CommandObjectMultiwordSettings
1061f034231aSEd Maste 
CommandObjectMultiwordSettings(CommandInterpreter & interpreter)106214f1b3e8SDimitry Andric CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
106314f1b3e8SDimitry Andric     CommandInterpreter &interpreter)
106414f1b3e8SDimitry Andric     : CommandObjectMultiword(interpreter, "settings",
106514f1b3e8SDimitry Andric                              "Commands for managing LLDB settings.",
106614f1b3e8SDimitry Andric                              "settings <subcommand> [<command-options>]") {
106714f1b3e8SDimitry Andric   LoadSubCommand("set",
106814f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
106914f1b3e8SDimitry Andric   LoadSubCommand("show",
107014f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
107114f1b3e8SDimitry Andric   LoadSubCommand("list",
107214f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
107314f1b3e8SDimitry Andric   LoadSubCommand("remove",
107414f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
107514f1b3e8SDimitry Andric   LoadSubCommand("replace", CommandObjectSP(
107614f1b3e8SDimitry Andric                                 new CommandObjectSettingsReplace(interpreter)));
107714f1b3e8SDimitry Andric   LoadSubCommand(
107814f1b3e8SDimitry Andric       "insert-before",
107914f1b3e8SDimitry Andric       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
108014f1b3e8SDimitry Andric   LoadSubCommand(
108114f1b3e8SDimitry Andric       "insert-after",
108214f1b3e8SDimitry Andric       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
108314f1b3e8SDimitry Andric   LoadSubCommand("append",
108414f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
108514f1b3e8SDimitry Andric   LoadSubCommand("clear",
108614f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
108794994d37SDimitry Andric   LoadSubCommand("write",
108894994d37SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
108994994d37SDimitry Andric   LoadSubCommand("read",
109094994d37SDimitry Andric                  CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1091f034231aSEd Maste }
1092f034231aSEd Maste 
1093f3fbd1c0SDimitry Andric CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1094