1dda28197Spatrick //===-- CommandObjectSettings.cpp -----------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "CommandObjectSettings.h"
10061da546Spatrick 
11061da546Spatrick #include "llvm/ADT/StringRef.h"
12061da546Spatrick 
13061da546Spatrick #include "lldb/Host/OptionParser.h"
14061da546Spatrick #include "lldb/Interpreter/CommandCompletions.h"
15061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
16*f6aab3d8Srobert #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
18061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
19061da546Spatrick 
20061da546Spatrick using namespace lldb;
21061da546Spatrick using namespace lldb_private;
22061da546Spatrick 
23061da546Spatrick // CommandObjectSettingsSet
24061da546Spatrick #define LLDB_OPTIONS_settings_set
25061da546Spatrick #include "CommandOptions.inc"
26061da546Spatrick 
27061da546Spatrick class CommandObjectSettingsSet : public CommandObjectRaw {
28061da546Spatrick public:
CommandObjectSettingsSet(CommandInterpreter & interpreter)29061da546Spatrick   CommandObjectSettingsSet(CommandInterpreter &interpreter)
30061da546Spatrick       : CommandObjectRaw(interpreter, "settings set",
31*f6aab3d8Srobert                          "Set the value of the specified debugger setting.") {
32061da546Spatrick     CommandArgumentEntry arg1;
33061da546Spatrick     CommandArgumentEntry arg2;
34061da546Spatrick     CommandArgumentData var_name_arg;
35061da546Spatrick     CommandArgumentData value_arg;
36061da546Spatrick 
37061da546Spatrick     // Define the first (and only) variant of this arg.
38061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
39061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
40061da546Spatrick 
41061da546Spatrick     // There is only one variant this argument could be; put it into the
42061da546Spatrick     // argument entry.
43061da546Spatrick     arg1.push_back(var_name_arg);
44061da546Spatrick 
45061da546Spatrick     // Define the first (and only) variant of this arg.
46061da546Spatrick     value_arg.arg_type = eArgTypeValue;
47061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
48061da546Spatrick 
49061da546Spatrick     // There is only one variant this argument could be; put it into the
50061da546Spatrick     // argument entry.
51061da546Spatrick     arg2.push_back(value_arg);
52061da546Spatrick 
53061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
54061da546Spatrick     m_arguments.push_back(arg1);
55061da546Spatrick     m_arguments.push_back(arg2);
56061da546Spatrick 
57061da546Spatrick     SetHelpLong(
58061da546Spatrick         "\nWhen setting a dictionary or array variable, you can set multiple entries \
59061da546Spatrick at once by giving the values to the set command.  For example:"
60061da546Spatrick         R"(
61061da546Spatrick 
62061da546Spatrick (lldb) settings set target.run-args value1 value2 value3
63061da546Spatrick (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin  SOME_ENV_VAR=12345
64061da546Spatrick 
65061da546Spatrick (lldb) settings show target.run-args
66061da546Spatrick   [0]: 'value1'
67061da546Spatrick   [1]: 'value2'
68061da546Spatrick   [3]: 'value3'
69061da546Spatrick (lldb) settings show target.env-vars
70061da546Spatrick   'MYPATH=~/.:/usr/bin'
71061da546Spatrick   'SOME_ENV_VAR=12345'
72061da546Spatrick 
73061da546Spatrick )"
74061da546Spatrick         "Warning:  The 'set' command re-sets the entire array or dictionary.  If you \
75061da546Spatrick just want to add, remove or update individual values (or add something to \
76061da546Spatrick the end), use one of the other settings sub-commands: append, replace, \
77061da546Spatrick insert-before or insert-after.");
78061da546Spatrick   }
79061da546Spatrick 
80061da546Spatrick   ~CommandObjectSettingsSet() override = default;
81061da546Spatrick 
82061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
83061da546Spatrick   // !WantsRawCommandString.
WantsCompletion()84061da546Spatrick   bool WantsCompletion() override { return true; }
85061da546Spatrick 
GetOptions()86061da546Spatrick   Options *GetOptions() override { return &m_options; }
87061da546Spatrick 
88061da546Spatrick   class CommandOptions : public Options {
89061da546Spatrick   public:
90*f6aab3d8Srobert     CommandOptions() = default;
91061da546Spatrick 
92061da546Spatrick     ~CommandOptions() override = default;
93061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)94061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
95061da546Spatrick                           ExecutionContext *execution_context) override {
96061da546Spatrick       Status error;
97061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
98061da546Spatrick 
99061da546Spatrick       switch (short_option) {
100061da546Spatrick       case 'f':
101061da546Spatrick         m_force = true;
102061da546Spatrick         break;
103061da546Spatrick       case 'g':
104061da546Spatrick         m_global = true;
105061da546Spatrick         break;
106*f6aab3d8Srobert       case 'e':
107*f6aab3d8Srobert         m_exists = true;
108*f6aab3d8Srobert         break;
109061da546Spatrick       default:
110061da546Spatrick         llvm_unreachable("Unimplemented option");
111061da546Spatrick       }
112061da546Spatrick 
113061da546Spatrick       return error;
114061da546Spatrick     }
115061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)116061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
117061da546Spatrick       m_global = false;
118061da546Spatrick       m_force = false;
119*f6aab3d8Srobert       m_exists = false;
120061da546Spatrick     }
121061da546Spatrick 
GetDefinitions()122061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
123*f6aab3d8Srobert       return llvm::ArrayRef(g_settings_set_options);
124061da546Spatrick     }
125061da546Spatrick 
126061da546Spatrick     // Instance variables to hold the values for command options.
127be691f3bSpatrick     bool m_global = false;
128*f6aab3d8Srobert     bool m_force = false;
129*f6aab3d8Srobert     bool m_exists = false;
130061da546Spatrick   };
131061da546Spatrick 
132061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)133061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
134061da546Spatrick                            OptionElementVector &opt_element_vector) override {
135061da546Spatrick 
136061da546Spatrick     const size_t argc = request.GetParsedLine().GetArgumentCount();
137061da546Spatrick     const char *arg = nullptr;
138061da546Spatrick     size_t setting_var_idx;
139061da546Spatrick     for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {
140061da546Spatrick       arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
141061da546Spatrick       if (arg && arg[0] != '-')
142061da546Spatrick         break; // We found our setting variable name index
143061da546Spatrick     }
144061da546Spatrick     if (request.GetCursorIndex() == setting_var_idx) {
145061da546Spatrick       // Attempting to complete setting variable name
146061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
147061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
148061da546Spatrick           request, nullptr);
149061da546Spatrick       return;
150061da546Spatrick     }
151061da546Spatrick     arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
152061da546Spatrick 
153061da546Spatrick     if (!arg)
154061da546Spatrick       return;
155061da546Spatrick 
156061da546Spatrick     // Complete option name
157*f6aab3d8Srobert     if (arg[0] == '-')
158061da546Spatrick       return;
159061da546Spatrick 
160061da546Spatrick     // Complete setting value
161061da546Spatrick     const char *setting_var_name =
162061da546Spatrick         request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
163061da546Spatrick     Status error;
164061da546Spatrick     lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue(
165061da546Spatrick         &m_exe_ctx, setting_var_name, false, error));
166061da546Spatrick     if (!value_sp)
167061da546Spatrick       return;
168061da546Spatrick     value_sp->AutoComplete(m_interpreter, request);
169061da546Spatrick   }
170061da546Spatrick 
171061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)172061da546Spatrick   bool DoExecute(llvm::StringRef command,
173061da546Spatrick                  CommandReturnObject &result) override {
174061da546Spatrick     Args cmd_args(command);
175061da546Spatrick 
176061da546Spatrick     // Process possible options.
177061da546Spatrick     if (!ParseOptions(cmd_args, result))
178061da546Spatrick       return false;
179061da546Spatrick 
180061da546Spatrick     const size_t min_argc = m_options.m_force ? 1 : 2;
181061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
182061da546Spatrick 
183061da546Spatrick     if ((argc < min_argc) && (!m_options.m_global)) {
184061da546Spatrick       result.AppendError("'settings set' takes more arguments");
185061da546Spatrick       return false;
186061da546Spatrick     }
187061da546Spatrick 
188061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
189061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
190061da546Spatrick       result.AppendError(
191061da546Spatrick           "'settings set' command requires a valid variable name");
192061da546Spatrick       return false;
193061da546Spatrick     }
194061da546Spatrick 
195061da546Spatrick     // A missing value corresponds to clearing the setting when "force" is
196061da546Spatrick     // specified.
197061da546Spatrick     if (argc == 1 && m_options.m_force) {
198061da546Spatrick       Status error(GetDebugger().SetPropertyValue(
199061da546Spatrick           &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
200061da546Spatrick       if (error.Fail()) {
201061da546Spatrick         result.AppendError(error.AsCString());
202061da546Spatrick         return false;
203061da546Spatrick       }
204061da546Spatrick       return result.Succeeded();
205061da546Spatrick     }
206061da546Spatrick 
207061da546Spatrick     // Split the raw command into var_name and value pair.
208061da546Spatrick     llvm::StringRef var_value(command);
209061da546Spatrick     var_value = var_value.split(var_name).second.ltrim();
210061da546Spatrick 
211061da546Spatrick     Status error;
212061da546Spatrick     if (m_options.m_global)
213061da546Spatrick       error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,
214061da546Spatrick                                              var_name, var_value);
215061da546Spatrick 
216061da546Spatrick     if (error.Success()) {
217061da546Spatrick       // FIXME this is the same issue as the one in commands script import
218061da546Spatrick       // we could be setting target.load-script-from-symbol-file which would
219061da546Spatrick       // cause Python scripts to be loaded, which could run LLDB commands (e.g.
220061da546Spatrick       // settings set target.process.python-os-plugin-path) and cause a crash
221061da546Spatrick       // if we did not clear the command's exe_ctx first
222061da546Spatrick       ExecutionContext exe_ctx(m_exe_ctx);
223061da546Spatrick       m_exe_ctx.Clear();
224061da546Spatrick       error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
225061da546Spatrick                                              var_name, var_value);
226061da546Spatrick     }
227061da546Spatrick 
228*f6aab3d8Srobert     if (error.Fail() && !m_options.m_exists) {
229061da546Spatrick       result.AppendError(error.AsCString());
230061da546Spatrick       return false;
231061da546Spatrick     }
232061da546Spatrick 
233*f6aab3d8Srobert     result.SetStatus(eReturnStatusSuccessFinishResult);
234061da546Spatrick     return result.Succeeded();
235061da546Spatrick   }
236061da546Spatrick 
237061da546Spatrick private:
238061da546Spatrick   CommandOptions m_options;
239061da546Spatrick };
240061da546Spatrick 
241061da546Spatrick // CommandObjectSettingsShow -- Show current values
242061da546Spatrick 
243061da546Spatrick class CommandObjectSettingsShow : public CommandObjectParsed {
244061da546Spatrick public:
CommandObjectSettingsShow(CommandInterpreter & interpreter)245061da546Spatrick   CommandObjectSettingsShow(CommandInterpreter &interpreter)
246061da546Spatrick       : CommandObjectParsed(interpreter, "settings show",
247061da546Spatrick                             "Show matching debugger settings and their current "
248061da546Spatrick                             "values.  Defaults to showing all settings.",
249061da546Spatrick                             nullptr) {
250061da546Spatrick     CommandArgumentEntry arg1;
251061da546Spatrick     CommandArgumentData var_name_arg;
252061da546Spatrick 
253061da546Spatrick     // Define the first (and only) variant of this arg.
254061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
255061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatOptional;
256061da546Spatrick 
257061da546Spatrick     // There is only one variant this argument could be; put it into the
258061da546Spatrick     // argument entry.
259061da546Spatrick     arg1.push_back(var_name_arg);
260061da546Spatrick 
261061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
262061da546Spatrick     m_arguments.push_back(arg1);
263061da546Spatrick   }
264061da546Spatrick 
265061da546Spatrick   ~CommandObjectSettingsShow() override = default;
266061da546Spatrick 
267061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)268061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
269061da546Spatrick                            OptionElementVector &opt_element_vector) override {
270061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
271061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
272061da546Spatrick         request, nullptr);
273061da546Spatrick   }
274061da546Spatrick 
275061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)276061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
277061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
278061da546Spatrick 
279061da546Spatrick     if (!args.empty()) {
280061da546Spatrick       for (const auto &arg : args) {
281061da546Spatrick         Status error(GetDebugger().DumpPropertyValue(
282061da546Spatrick             &m_exe_ctx, result.GetOutputStream(), arg.ref(),
283061da546Spatrick             OptionValue::eDumpGroupValue));
284061da546Spatrick         if (error.Success()) {
285061da546Spatrick           result.GetOutputStream().EOL();
286061da546Spatrick         } else {
287061da546Spatrick           result.AppendError(error.AsCString());
288061da546Spatrick         }
289061da546Spatrick       }
290061da546Spatrick     } else {
291061da546Spatrick       GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),
292061da546Spatrick                                           OptionValue::eDumpGroupValue);
293061da546Spatrick     }
294061da546Spatrick 
295061da546Spatrick     return result.Succeeded();
296061da546Spatrick   }
297061da546Spatrick };
298061da546Spatrick 
299061da546Spatrick // CommandObjectSettingsWrite -- Write settings to file
300061da546Spatrick #define LLDB_OPTIONS_settings_write
301061da546Spatrick #include "CommandOptions.inc"
302061da546Spatrick 
303061da546Spatrick class CommandObjectSettingsWrite : public CommandObjectParsed {
304061da546Spatrick public:
CommandObjectSettingsWrite(CommandInterpreter & interpreter)305061da546Spatrick   CommandObjectSettingsWrite(CommandInterpreter &interpreter)
306061da546Spatrick       : CommandObjectParsed(
307061da546Spatrick             interpreter, "settings export",
308061da546Spatrick             "Write matching debugger settings and their "
309061da546Spatrick             "current values to a file that can be read in with "
310061da546Spatrick             "\"settings read\". Defaults to writing all settings.",
311*f6aab3d8Srobert             nullptr) {
312061da546Spatrick     CommandArgumentEntry arg1;
313061da546Spatrick     CommandArgumentData var_name_arg;
314061da546Spatrick 
315061da546Spatrick     // Define the first (and only) variant of this arg.
316061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
317061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatOptional;
318061da546Spatrick 
319061da546Spatrick     // There is only one variant this argument could be; put it into the
320061da546Spatrick     // argument entry.
321061da546Spatrick     arg1.push_back(var_name_arg);
322061da546Spatrick 
323061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
324061da546Spatrick     m_arguments.push_back(arg1);
325061da546Spatrick   }
326061da546Spatrick 
327061da546Spatrick   ~CommandObjectSettingsWrite() override = default;
328061da546Spatrick 
GetOptions()329061da546Spatrick   Options *GetOptions() override { return &m_options; }
330061da546Spatrick 
331061da546Spatrick   class CommandOptions : public Options {
332061da546Spatrick   public:
333*f6aab3d8Srobert     CommandOptions() = default;
334061da546Spatrick 
335061da546Spatrick     ~CommandOptions() override = default;
336061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)337061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
338061da546Spatrick                           ExecutionContext *execution_context) override {
339061da546Spatrick       Status error;
340061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
341061da546Spatrick 
342061da546Spatrick       switch (short_option) {
343061da546Spatrick       case 'f':
344dda28197Spatrick         m_filename.assign(std::string(option_arg));
345061da546Spatrick         break;
346061da546Spatrick       case 'a':
347061da546Spatrick         m_append = true;
348061da546Spatrick         break;
349061da546Spatrick       default:
350061da546Spatrick         llvm_unreachable("Unimplemented option");
351061da546Spatrick       }
352061da546Spatrick 
353061da546Spatrick       return error;
354061da546Spatrick     }
355061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)356061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
357061da546Spatrick       m_filename.clear();
358061da546Spatrick       m_append = false;
359061da546Spatrick     }
360061da546Spatrick 
GetDefinitions()361061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
362*f6aab3d8Srobert       return llvm::ArrayRef(g_settings_write_options);
363061da546Spatrick     }
364061da546Spatrick 
365061da546Spatrick     // Instance variables to hold the values for command options.
366061da546Spatrick     std::string m_filename;
367061da546Spatrick     bool m_append = false;
368061da546Spatrick   };
369061da546Spatrick 
370061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)371061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
372061da546Spatrick     FileSpec file_spec(m_options.m_filename);
373061da546Spatrick     FileSystem::Instance().Resolve(file_spec);
374061da546Spatrick     std::string path(file_spec.GetPath());
375*f6aab3d8Srobert     auto options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
376061da546Spatrick     if (m_options.m_append)
377061da546Spatrick       options |= File::eOpenOptionAppend;
378061da546Spatrick     else
379061da546Spatrick       options |= File::eOpenOptionTruncate;
380061da546Spatrick 
381061da546Spatrick     StreamFile out_file(path.c_str(), options,
382061da546Spatrick                         lldb::eFilePermissionsFileDefault);
383061da546Spatrick 
384061da546Spatrick     if (!out_file.GetFile().IsValid()) {
385061da546Spatrick       result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
386061da546Spatrick       return false;
387061da546Spatrick     }
388061da546Spatrick 
389061da546Spatrick     // Exporting should not be context sensitive.
390061da546Spatrick     ExecutionContext clean_ctx;
391061da546Spatrick 
392061da546Spatrick     if (args.empty()) {
393061da546Spatrick       GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,
394061da546Spatrick                                           OptionValue::eDumpGroupExport);
395061da546Spatrick       return result.Succeeded();
396061da546Spatrick     }
397061da546Spatrick 
398061da546Spatrick     for (const auto &arg : args) {
399061da546Spatrick       Status error(GetDebugger().DumpPropertyValue(
400061da546Spatrick           &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));
401061da546Spatrick       if (!error.Success()) {
402061da546Spatrick         result.AppendError(error.AsCString());
403061da546Spatrick       }
404061da546Spatrick     }
405061da546Spatrick 
406061da546Spatrick     return result.Succeeded();
407061da546Spatrick   }
408061da546Spatrick 
409061da546Spatrick private:
410061da546Spatrick   CommandOptions m_options;
411061da546Spatrick };
412061da546Spatrick 
413061da546Spatrick // CommandObjectSettingsRead -- Read settings from file
414061da546Spatrick #define LLDB_OPTIONS_settings_read
415061da546Spatrick #include "CommandOptions.inc"
416061da546Spatrick 
417061da546Spatrick class CommandObjectSettingsRead : public CommandObjectParsed {
418061da546Spatrick public:
CommandObjectSettingsRead(CommandInterpreter & interpreter)419061da546Spatrick   CommandObjectSettingsRead(CommandInterpreter &interpreter)
420061da546Spatrick       : CommandObjectParsed(
421061da546Spatrick             interpreter, "settings read",
422061da546Spatrick             "Read settings previously saved to a file with \"settings write\".",
423*f6aab3d8Srobert             nullptr) {}
424061da546Spatrick 
425061da546Spatrick   ~CommandObjectSettingsRead() override = default;
426061da546Spatrick 
GetOptions()427061da546Spatrick   Options *GetOptions() override { return &m_options; }
428061da546Spatrick 
429061da546Spatrick   class CommandOptions : public Options {
430061da546Spatrick   public:
431*f6aab3d8Srobert     CommandOptions() = default;
432061da546Spatrick 
433061da546Spatrick     ~CommandOptions() override = default;
434061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)435061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
436061da546Spatrick                           ExecutionContext *execution_context) override {
437061da546Spatrick       Status error;
438061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
439061da546Spatrick 
440061da546Spatrick       switch (short_option) {
441061da546Spatrick       case 'f':
442dda28197Spatrick         m_filename.assign(std::string(option_arg));
443061da546Spatrick         break;
444061da546Spatrick       default:
445061da546Spatrick         llvm_unreachable("Unimplemented option");
446061da546Spatrick       }
447061da546Spatrick 
448061da546Spatrick       return error;
449061da546Spatrick     }
450061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)451061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
452061da546Spatrick       m_filename.clear();
453061da546Spatrick     }
454061da546Spatrick 
GetDefinitions()455061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
456*f6aab3d8Srobert       return llvm::ArrayRef(g_settings_read_options);
457061da546Spatrick     }
458061da546Spatrick 
459061da546Spatrick     // Instance variables to hold the values for command options.
460061da546Spatrick     std::string m_filename;
461061da546Spatrick   };
462061da546Spatrick 
463061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)464061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
465061da546Spatrick     FileSpec file(m_options.m_filename);
466061da546Spatrick     FileSystem::Instance().Resolve(file);
467061da546Spatrick     CommandInterpreterRunOptions options;
468061da546Spatrick     options.SetAddToHistory(false);
469061da546Spatrick     options.SetEchoCommands(false);
470061da546Spatrick     options.SetPrintResults(true);
471061da546Spatrick     options.SetPrintErrors(true);
472061da546Spatrick     options.SetStopOnError(false);
473be691f3bSpatrick     m_interpreter.HandleCommandsFromFile(file, options, result);
474061da546Spatrick     return result.Succeeded();
475061da546Spatrick   }
476061da546Spatrick 
477061da546Spatrick private:
478061da546Spatrick   CommandOptions m_options;
479061da546Spatrick };
480061da546Spatrick 
481061da546Spatrick // CommandObjectSettingsList -- List settable variables
482061da546Spatrick 
483061da546Spatrick class CommandObjectSettingsList : public CommandObjectParsed {
484061da546Spatrick public:
CommandObjectSettingsList(CommandInterpreter & interpreter)485061da546Spatrick   CommandObjectSettingsList(CommandInterpreter &interpreter)
486061da546Spatrick       : CommandObjectParsed(interpreter, "settings list",
487061da546Spatrick                             "List and describe matching debugger settings.  "
488061da546Spatrick                             "Defaults to all listing all settings.",
489061da546Spatrick                             nullptr) {
490061da546Spatrick     CommandArgumentEntry arg;
491061da546Spatrick     CommandArgumentData var_name_arg;
492061da546Spatrick     CommandArgumentData prefix_name_arg;
493061da546Spatrick 
494061da546Spatrick     // Define the first variant of this arg.
495061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
496061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatOptional;
497061da546Spatrick 
498061da546Spatrick     // Define the second variant of this arg.
499061da546Spatrick     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
500061da546Spatrick     prefix_name_arg.arg_repetition = eArgRepeatOptional;
501061da546Spatrick 
502061da546Spatrick     arg.push_back(var_name_arg);
503061da546Spatrick     arg.push_back(prefix_name_arg);
504061da546Spatrick 
505061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
506061da546Spatrick     m_arguments.push_back(arg);
507061da546Spatrick   }
508061da546Spatrick 
509061da546Spatrick   ~CommandObjectSettingsList() override = default;
510061da546Spatrick 
511061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)512061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
513061da546Spatrick                            OptionElementVector &opt_element_vector) override {
514061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
515061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
516061da546Spatrick         request, nullptr);
517061da546Spatrick   }
518061da546Spatrick 
519061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)520061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
521061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
522061da546Spatrick 
523061da546Spatrick     const bool will_modify = false;
524061da546Spatrick     const size_t argc = args.GetArgumentCount();
525061da546Spatrick     if (argc > 0) {
526061da546Spatrick       const bool dump_qualified_name = true;
527061da546Spatrick 
528dda28197Spatrick       for (const Args::ArgEntry &arg : args) {
529dda28197Spatrick         const char *property_path = arg.c_str();
530061da546Spatrick 
531061da546Spatrick         const Property *property =
532061da546Spatrick             GetDebugger().GetValueProperties()->GetPropertyAtPath(
533061da546Spatrick                 &m_exe_ctx, will_modify, property_path);
534061da546Spatrick 
535061da546Spatrick         if (property) {
536061da546Spatrick           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
537061da546Spatrick                                     dump_qualified_name);
538061da546Spatrick         } else {
539061da546Spatrick           result.AppendErrorWithFormat("invalid property path '%s'",
540061da546Spatrick                                        property_path);
541061da546Spatrick         }
542061da546Spatrick       }
543061da546Spatrick     } else {
544061da546Spatrick       GetDebugger().DumpAllDescriptions(m_interpreter,
545061da546Spatrick                                         result.GetOutputStream());
546061da546Spatrick     }
547061da546Spatrick 
548061da546Spatrick     return result.Succeeded();
549061da546Spatrick   }
550061da546Spatrick };
551061da546Spatrick 
552061da546Spatrick // CommandObjectSettingsRemove
553061da546Spatrick 
554061da546Spatrick class CommandObjectSettingsRemove : public CommandObjectRaw {
555061da546Spatrick public:
CommandObjectSettingsRemove(CommandInterpreter & interpreter)556061da546Spatrick   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
557061da546Spatrick       : CommandObjectRaw(interpreter, "settings remove",
558061da546Spatrick                          "Remove a value from a setting, specified by array "
559061da546Spatrick                          "index or dictionary key.") {
560061da546Spatrick     CommandArgumentEntry arg1;
561061da546Spatrick     CommandArgumentEntry arg2;
562061da546Spatrick     CommandArgumentData var_name_arg;
563061da546Spatrick     CommandArgumentData index_arg;
564061da546Spatrick     CommandArgumentData key_arg;
565061da546Spatrick 
566061da546Spatrick     // Define the first (and only) variant of this arg.
567061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
568061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
569061da546Spatrick 
570061da546Spatrick     // There is only one variant this argument could be; put it into the
571061da546Spatrick     // argument entry.
572061da546Spatrick     arg1.push_back(var_name_arg);
573061da546Spatrick 
574061da546Spatrick     // Define the first variant of this arg.
575061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
576061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
577061da546Spatrick 
578061da546Spatrick     // Define the second variant of this arg.
579061da546Spatrick     key_arg.arg_type = eArgTypeSettingKey;
580061da546Spatrick     key_arg.arg_repetition = eArgRepeatPlain;
581061da546Spatrick 
582061da546Spatrick     // Push both variants into this arg
583061da546Spatrick     arg2.push_back(index_arg);
584061da546Spatrick     arg2.push_back(key_arg);
585061da546Spatrick 
586061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
587061da546Spatrick     m_arguments.push_back(arg1);
588061da546Spatrick     m_arguments.push_back(arg2);
589061da546Spatrick   }
590061da546Spatrick 
591061da546Spatrick   ~CommandObjectSettingsRemove() override = default;
592061da546Spatrick 
WantsCompletion()593061da546Spatrick   bool WantsCompletion() override { return true; }
594061da546Spatrick 
595061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)596061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
597061da546Spatrick                            OptionElementVector &opt_element_vector) override {
598061da546Spatrick     if (request.GetCursorIndex() < 2)
599061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
600061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
601061da546Spatrick           request, nullptr);
602061da546Spatrick   }
603061da546Spatrick 
604061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)605061da546Spatrick   bool DoExecute(llvm::StringRef command,
606061da546Spatrick                  CommandReturnObject &result) override {
607061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
608061da546Spatrick 
609061da546Spatrick     Args cmd_args(command);
610061da546Spatrick 
611061da546Spatrick     // Process possible options.
612061da546Spatrick     if (!ParseOptions(cmd_args, result))
613061da546Spatrick       return false;
614061da546Spatrick 
615061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
616061da546Spatrick     if (argc == 0) {
617061da546Spatrick       result.AppendError("'settings remove' takes an array or dictionary item, "
618061da546Spatrick                          "or an array followed by one or more indexes, or a "
619061da546Spatrick                          "dictionary followed by one or more key names to "
620061da546Spatrick                          "remove");
621061da546Spatrick       return false;
622061da546Spatrick     }
623061da546Spatrick 
624061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
625061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
626061da546Spatrick       result.AppendError(
627061da546Spatrick           "'settings remove' command requires a valid variable name");
628061da546Spatrick       return false;
629061da546Spatrick     }
630061da546Spatrick 
631061da546Spatrick     // Split the raw command into var_name and value pair.
632061da546Spatrick     llvm::StringRef var_value(command);
633061da546Spatrick     var_value = var_value.split(var_name).second.trim();
634061da546Spatrick 
635061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
636061da546Spatrick         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
637061da546Spatrick     if (error.Fail()) {
638061da546Spatrick       result.AppendError(error.AsCString());
639061da546Spatrick       return false;
640061da546Spatrick     }
641061da546Spatrick 
642061da546Spatrick     return result.Succeeded();
643061da546Spatrick   }
644061da546Spatrick };
645061da546Spatrick 
646061da546Spatrick // CommandObjectSettingsReplace
647061da546Spatrick 
648061da546Spatrick class CommandObjectSettingsReplace : public CommandObjectRaw {
649061da546Spatrick public:
CommandObjectSettingsReplace(CommandInterpreter & interpreter)650061da546Spatrick   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
651061da546Spatrick       : CommandObjectRaw(interpreter, "settings replace",
652061da546Spatrick                          "Replace the debugger setting value specified by "
653061da546Spatrick                          "array index or dictionary key.") {
654061da546Spatrick     CommandArgumentEntry arg1;
655061da546Spatrick     CommandArgumentEntry arg2;
656061da546Spatrick     CommandArgumentEntry arg3;
657061da546Spatrick     CommandArgumentData var_name_arg;
658061da546Spatrick     CommandArgumentData index_arg;
659061da546Spatrick     CommandArgumentData key_arg;
660061da546Spatrick     CommandArgumentData value_arg;
661061da546Spatrick 
662061da546Spatrick     // Define the first (and only) variant of this arg.
663061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
664061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
665061da546Spatrick 
666061da546Spatrick     // There is only one variant this argument could be; put it into the
667061da546Spatrick     // argument entry.
668061da546Spatrick     arg1.push_back(var_name_arg);
669061da546Spatrick 
670061da546Spatrick     // Define the first (variant of this arg.
671061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
672061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
673061da546Spatrick 
674061da546Spatrick     // Define the second (variant of this arg.
675061da546Spatrick     key_arg.arg_type = eArgTypeSettingKey;
676061da546Spatrick     key_arg.arg_repetition = eArgRepeatPlain;
677061da546Spatrick 
678061da546Spatrick     // Put both variants into this arg
679061da546Spatrick     arg2.push_back(index_arg);
680061da546Spatrick     arg2.push_back(key_arg);
681061da546Spatrick 
682061da546Spatrick     // Define the first (and only) variant of this arg.
683061da546Spatrick     value_arg.arg_type = eArgTypeValue;
684061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
685061da546Spatrick 
686061da546Spatrick     // There is only one variant this argument could be; put it into the
687061da546Spatrick     // argument entry.
688061da546Spatrick     arg3.push_back(value_arg);
689061da546Spatrick 
690061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
691061da546Spatrick     m_arguments.push_back(arg1);
692061da546Spatrick     m_arguments.push_back(arg2);
693061da546Spatrick     m_arguments.push_back(arg3);
694061da546Spatrick   }
695061da546Spatrick 
696061da546Spatrick   ~CommandObjectSettingsReplace() override = default;
697061da546Spatrick 
698061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
699061da546Spatrick   // !WantsRawCommandString.
WantsCompletion()700061da546Spatrick   bool WantsCompletion() override { return true; }
701061da546Spatrick 
702061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)703061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
704061da546Spatrick                            OptionElementVector &opt_element_vector) override {
705061da546Spatrick     // Attempting to complete variable name
706061da546Spatrick     if (request.GetCursorIndex() < 2)
707061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
708061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
709061da546Spatrick           request, nullptr);
710061da546Spatrick   }
711061da546Spatrick 
712061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)713061da546Spatrick   bool DoExecute(llvm::StringRef command,
714061da546Spatrick                  CommandReturnObject &result) override {
715061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
716061da546Spatrick 
717061da546Spatrick     Args cmd_args(command);
718061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
719061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
720061da546Spatrick       result.AppendError("'settings replace' command requires a valid variable "
721061da546Spatrick                          "name; No value supplied");
722061da546Spatrick       return false;
723061da546Spatrick     }
724061da546Spatrick 
725061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
726061da546Spatrick     llvm::StringRef var_value(command);
727061da546Spatrick     var_value = var_value.split(var_name).second.trim();
728061da546Spatrick 
729061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
730061da546Spatrick         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
731061da546Spatrick     if (error.Fail()) {
732061da546Spatrick       result.AppendError(error.AsCString());
733061da546Spatrick       return false;
734061da546Spatrick     } else {
735061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishNoResult);
736061da546Spatrick     }
737061da546Spatrick 
738061da546Spatrick     return result.Succeeded();
739061da546Spatrick   }
740061da546Spatrick };
741061da546Spatrick 
742061da546Spatrick // CommandObjectSettingsInsertBefore
743061da546Spatrick 
744061da546Spatrick class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
745061da546Spatrick public:
CommandObjectSettingsInsertBefore(CommandInterpreter & interpreter)746061da546Spatrick   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
747061da546Spatrick       : CommandObjectRaw(interpreter, "settings insert-before",
748061da546Spatrick                          "Insert one or more values into an debugger array "
749061da546Spatrick                          "setting immediately before the specified element "
750061da546Spatrick                          "index.") {
751061da546Spatrick     CommandArgumentEntry arg1;
752061da546Spatrick     CommandArgumentEntry arg2;
753061da546Spatrick     CommandArgumentEntry arg3;
754061da546Spatrick     CommandArgumentData var_name_arg;
755061da546Spatrick     CommandArgumentData index_arg;
756061da546Spatrick     CommandArgumentData value_arg;
757061da546Spatrick 
758061da546Spatrick     // Define the first (and only) variant of this arg.
759061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
760061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
761061da546Spatrick 
762061da546Spatrick     // There is only one variant this argument could be; put it into the
763061da546Spatrick     // argument entry.
764061da546Spatrick     arg1.push_back(var_name_arg);
765061da546Spatrick 
766061da546Spatrick     // Define the first (variant of this arg.
767061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
768061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
769061da546Spatrick 
770061da546Spatrick     // There is only one variant this argument could be; put it into the
771061da546Spatrick     // argument entry.
772061da546Spatrick     arg2.push_back(index_arg);
773061da546Spatrick 
774061da546Spatrick     // Define the first (and only) variant of this arg.
775061da546Spatrick     value_arg.arg_type = eArgTypeValue;
776061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
777061da546Spatrick 
778061da546Spatrick     // There is only one variant this argument could be; put it into the
779061da546Spatrick     // argument entry.
780061da546Spatrick     arg3.push_back(value_arg);
781061da546Spatrick 
782061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
783061da546Spatrick     m_arguments.push_back(arg1);
784061da546Spatrick     m_arguments.push_back(arg2);
785061da546Spatrick     m_arguments.push_back(arg3);
786061da546Spatrick   }
787061da546Spatrick 
788061da546Spatrick   ~CommandObjectSettingsInsertBefore() override = default;
789061da546Spatrick 
790061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
791061da546Spatrick   // !WantsRawCommandString.
WantsCompletion()792061da546Spatrick   bool WantsCompletion() override { return true; }
793061da546Spatrick 
794061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)795061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
796061da546Spatrick                            OptionElementVector &opt_element_vector) override {
797061da546Spatrick     // Attempting to complete variable name
798061da546Spatrick     if (request.GetCursorIndex() < 2)
799061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
800061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
801061da546Spatrick           request, nullptr);
802061da546Spatrick   }
803061da546Spatrick 
804061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)805061da546Spatrick   bool DoExecute(llvm::StringRef command,
806061da546Spatrick                  CommandReturnObject &result) override {
807061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
808061da546Spatrick 
809061da546Spatrick     Args cmd_args(command);
810061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
811061da546Spatrick 
812061da546Spatrick     if (argc < 3) {
813061da546Spatrick       result.AppendError("'settings insert-before' takes more arguments");
814061da546Spatrick       return false;
815061da546Spatrick     }
816061da546Spatrick 
817061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
818061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
819061da546Spatrick       result.AppendError("'settings insert-before' command requires a valid "
820061da546Spatrick                          "variable name; No value supplied");
821061da546Spatrick       return false;
822061da546Spatrick     }
823061da546Spatrick 
824061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
825061da546Spatrick     llvm::StringRef var_value(command);
826061da546Spatrick     var_value = var_value.split(var_name).second.trim();
827061da546Spatrick 
828061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
829061da546Spatrick         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
830061da546Spatrick     if (error.Fail()) {
831061da546Spatrick       result.AppendError(error.AsCString());
832061da546Spatrick       return false;
833061da546Spatrick     }
834061da546Spatrick 
835061da546Spatrick     return result.Succeeded();
836061da546Spatrick   }
837061da546Spatrick };
838061da546Spatrick 
839061da546Spatrick // CommandObjectSettingInsertAfter
840061da546Spatrick 
841061da546Spatrick class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
842061da546Spatrick public:
CommandObjectSettingsInsertAfter(CommandInterpreter & interpreter)843061da546Spatrick   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
844061da546Spatrick       : CommandObjectRaw(interpreter, "settings insert-after",
845061da546Spatrick                          "Insert one or more values into a debugger array "
846061da546Spatrick                          "settings after the specified element index.") {
847061da546Spatrick     CommandArgumentEntry arg1;
848061da546Spatrick     CommandArgumentEntry arg2;
849061da546Spatrick     CommandArgumentEntry arg3;
850061da546Spatrick     CommandArgumentData var_name_arg;
851061da546Spatrick     CommandArgumentData index_arg;
852061da546Spatrick     CommandArgumentData value_arg;
853061da546Spatrick 
854061da546Spatrick     // Define the first (and only) variant of this arg.
855061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
856061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
857061da546Spatrick 
858061da546Spatrick     // There is only one variant this argument could be; put it into the
859061da546Spatrick     // argument entry.
860061da546Spatrick     arg1.push_back(var_name_arg);
861061da546Spatrick 
862061da546Spatrick     // Define the first (variant of this arg.
863061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
864061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
865061da546Spatrick 
866061da546Spatrick     // There is only one variant this argument could be; put it into the
867061da546Spatrick     // argument entry.
868061da546Spatrick     arg2.push_back(index_arg);
869061da546Spatrick 
870061da546Spatrick     // Define the first (and only) variant of this arg.
871061da546Spatrick     value_arg.arg_type = eArgTypeValue;
872061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
873061da546Spatrick 
874061da546Spatrick     // There is only one variant this argument could be; put it into the
875061da546Spatrick     // argument entry.
876061da546Spatrick     arg3.push_back(value_arg);
877061da546Spatrick 
878061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
879061da546Spatrick     m_arguments.push_back(arg1);
880061da546Spatrick     m_arguments.push_back(arg2);
881061da546Spatrick     m_arguments.push_back(arg3);
882061da546Spatrick   }
883061da546Spatrick 
884061da546Spatrick   ~CommandObjectSettingsInsertAfter() override = default;
885061da546Spatrick 
886061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
887061da546Spatrick   // !WantsRawCommandString.
WantsCompletion()888061da546Spatrick   bool WantsCompletion() override { return true; }
889061da546Spatrick 
890061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)891061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
892061da546Spatrick                            OptionElementVector &opt_element_vector) override {
893061da546Spatrick     // Attempting to complete variable name
894061da546Spatrick     if (request.GetCursorIndex() < 2)
895061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
896061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
897061da546Spatrick           request, nullptr);
898061da546Spatrick   }
899061da546Spatrick 
900061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)901061da546Spatrick   bool DoExecute(llvm::StringRef command,
902061da546Spatrick                  CommandReturnObject &result) override {
903061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
904061da546Spatrick 
905061da546Spatrick     Args cmd_args(command);
906061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
907061da546Spatrick 
908061da546Spatrick     if (argc < 3) {
909061da546Spatrick       result.AppendError("'settings insert-after' takes more arguments");
910061da546Spatrick       return false;
911061da546Spatrick     }
912061da546Spatrick 
913061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
914061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
915061da546Spatrick       result.AppendError("'settings insert-after' command requires a valid "
916061da546Spatrick                          "variable name; No value supplied");
917061da546Spatrick       return false;
918061da546Spatrick     }
919061da546Spatrick 
920061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
921061da546Spatrick     llvm::StringRef var_value(command);
922061da546Spatrick     var_value = var_value.split(var_name).second.trim();
923061da546Spatrick 
924061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
925061da546Spatrick         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
926061da546Spatrick     if (error.Fail()) {
927061da546Spatrick       result.AppendError(error.AsCString());
928061da546Spatrick       return false;
929061da546Spatrick     }
930061da546Spatrick 
931061da546Spatrick     return result.Succeeded();
932061da546Spatrick   }
933061da546Spatrick };
934061da546Spatrick 
935061da546Spatrick // CommandObjectSettingsAppend
936061da546Spatrick 
937061da546Spatrick class CommandObjectSettingsAppend : public CommandObjectRaw {
938061da546Spatrick public:
CommandObjectSettingsAppend(CommandInterpreter & interpreter)939061da546Spatrick   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
940061da546Spatrick       : CommandObjectRaw(interpreter, "settings append",
941061da546Spatrick                          "Append one or more values to a debugger array, "
942061da546Spatrick                          "dictionary, or string setting.") {
943061da546Spatrick     CommandArgumentEntry arg1;
944061da546Spatrick     CommandArgumentEntry arg2;
945061da546Spatrick     CommandArgumentData var_name_arg;
946061da546Spatrick     CommandArgumentData value_arg;
947061da546Spatrick 
948061da546Spatrick     // Define the first (and only) variant of this arg.
949061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
950061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
951061da546Spatrick 
952061da546Spatrick     // There is only one variant this argument could be; put it into the
953061da546Spatrick     // argument entry.
954061da546Spatrick     arg1.push_back(var_name_arg);
955061da546Spatrick 
956061da546Spatrick     // Define the first (and only) variant of this arg.
957061da546Spatrick     value_arg.arg_type = eArgTypeValue;
958061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
959061da546Spatrick 
960061da546Spatrick     // There is only one variant this argument could be; put it into the
961061da546Spatrick     // argument entry.
962061da546Spatrick     arg2.push_back(value_arg);
963061da546Spatrick 
964061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
965061da546Spatrick     m_arguments.push_back(arg1);
966061da546Spatrick     m_arguments.push_back(arg2);
967061da546Spatrick   }
968061da546Spatrick 
969061da546Spatrick   ~CommandObjectSettingsAppend() override = default;
970061da546Spatrick 
971061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
972061da546Spatrick   // !WantsRawCommandString.
WantsCompletion()973061da546Spatrick   bool WantsCompletion() override { return true; }
974061da546Spatrick 
975061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)976061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
977061da546Spatrick                            OptionElementVector &opt_element_vector) override {
978061da546Spatrick     // Attempting to complete variable name
979061da546Spatrick     if (request.GetCursorIndex() < 2)
980061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
981061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
982061da546Spatrick           request, nullptr);
983061da546Spatrick   }
984061da546Spatrick 
985061da546Spatrick protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)986061da546Spatrick   bool DoExecute(llvm::StringRef command,
987061da546Spatrick                  CommandReturnObject &result) override {
988061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
989061da546Spatrick     Args cmd_args(command);
990061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
991061da546Spatrick 
992061da546Spatrick     if (argc < 2) {
993061da546Spatrick       result.AppendError("'settings append' takes more arguments");
994061da546Spatrick       return false;
995061da546Spatrick     }
996061da546Spatrick 
997061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
998061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
999061da546Spatrick       result.AppendError("'settings append' command requires a valid variable "
1000061da546Spatrick                          "name; No value supplied");
1001061da546Spatrick       return false;
1002061da546Spatrick     }
1003061da546Spatrick 
1004061da546Spatrick     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
1005061da546Spatrick     // character string later on.
1006061da546Spatrick 
1007061da546Spatrick     // Split the raw command into var_name and value pair.
1008061da546Spatrick     llvm::StringRef var_value(command);
1009061da546Spatrick     var_value = var_value.split(var_name).second.trim();
1010061da546Spatrick 
1011061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
1012061da546Spatrick         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
1013061da546Spatrick     if (error.Fail()) {
1014061da546Spatrick       result.AppendError(error.AsCString());
1015061da546Spatrick       return false;
1016061da546Spatrick     }
1017061da546Spatrick 
1018061da546Spatrick     return result.Succeeded();
1019061da546Spatrick   }
1020061da546Spatrick };
1021061da546Spatrick 
1022061da546Spatrick // CommandObjectSettingsClear
1023dda28197Spatrick #define LLDB_OPTIONS_settings_clear
1024dda28197Spatrick #include "CommandOptions.inc"
1025061da546Spatrick 
1026061da546Spatrick class CommandObjectSettingsClear : public CommandObjectParsed {
1027061da546Spatrick public:
CommandObjectSettingsClear(CommandInterpreter & interpreter)1028061da546Spatrick   CommandObjectSettingsClear(CommandInterpreter &interpreter)
1029061da546Spatrick       : CommandObjectParsed(
1030061da546Spatrick             interpreter, "settings clear",
1031dda28197Spatrick             "Clear a debugger setting array, dictionary, or string. "
1032dda28197Spatrick             "If '-a' option is specified, it clears all settings.", nullptr) {
1033061da546Spatrick     CommandArgumentEntry arg;
1034061da546Spatrick     CommandArgumentData var_name_arg;
1035061da546Spatrick 
1036061da546Spatrick     // Define the first (and only) variant of this arg.
1037061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
1038061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
1039061da546Spatrick 
1040061da546Spatrick     // There is only one variant this argument could be; put it into the
1041061da546Spatrick     // argument entry.
1042061da546Spatrick     arg.push_back(var_name_arg);
1043061da546Spatrick 
1044061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1045061da546Spatrick     m_arguments.push_back(arg);
1046061da546Spatrick   }
1047061da546Spatrick 
1048061da546Spatrick   ~CommandObjectSettingsClear() override = default;
1049061da546Spatrick 
1050061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1051061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
1052061da546Spatrick                            OptionElementVector &opt_element_vector) override {
1053061da546Spatrick     // Attempting to complete variable name
1054061da546Spatrick     if (request.GetCursorIndex() < 2)
1055061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
1056061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1057061da546Spatrick           request, nullptr);
1058061da546Spatrick   }
1059061da546Spatrick 
GetOptions()1060dda28197Spatrick    Options *GetOptions() override { return &m_options; }
1061dda28197Spatrick 
1062dda28197Spatrick   class CommandOptions : public Options {
1063dda28197Spatrick   public:
1064dda28197Spatrick     CommandOptions() = default;
1065dda28197Spatrick 
1066dda28197Spatrick     ~CommandOptions() override = default;
1067dda28197Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1068dda28197Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1069dda28197Spatrick                           ExecutionContext *execution_context) override {
1070dda28197Spatrick       const int short_option = m_getopt_table[option_idx].val;
1071dda28197Spatrick       switch (short_option) {
1072dda28197Spatrick       case 'a':
1073dda28197Spatrick         m_clear_all = true;
1074dda28197Spatrick         break;
1075dda28197Spatrick       default:
1076dda28197Spatrick         llvm_unreachable("Unimplemented option");
1077dda28197Spatrick       }
1078dda28197Spatrick       return Status();
1079dda28197Spatrick     }
1080dda28197Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)1081dda28197Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1082dda28197Spatrick       m_clear_all = false;
1083dda28197Spatrick     }
1084dda28197Spatrick 
GetDefinitions()1085dda28197Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1086*f6aab3d8Srobert       return llvm::ArrayRef(g_settings_clear_options);
1087dda28197Spatrick     }
1088dda28197Spatrick 
1089dda28197Spatrick     bool m_clear_all = false;
1090dda28197Spatrick   };
1091dda28197Spatrick 
1092061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1093061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1094061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1095061da546Spatrick     const size_t argc = command.GetArgumentCount();
1096061da546Spatrick 
1097dda28197Spatrick     if (m_options.m_clear_all) {
1098dda28197Spatrick       if (argc != 0) {
1099dda28197Spatrick         result.AppendError("'settings clear --all' doesn't take any arguments");
1100dda28197Spatrick         return false;
1101dda28197Spatrick       }
1102dda28197Spatrick       GetDebugger().GetValueProperties()->Clear();
1103dda28197Spatrick       return result.Succeeded();
1104dda28197Spatrick     }
1105dda28197Spatrick 
1106061da546Spatrick     if (argc != 1) {
1107061da546Spatrick       result.AppendError("'settings clear' takes exactly one argument");
1108061da546Spatrick       return false;
1109061da546Spatrick     }
1110061da546Spatrick 
1111061da546Spatrick     const char *var_name = command.GetArgumentAtIndex(0);
1112061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1113061da546Spatrick       result.AppendError("'settings clear' command requires a valid variable "
1114061da546Spatrick                          "name; No value supplied");
1115061da546Spatrick       return false;
1116061da546Spatrick     }
1117061da546Spatrick 
1118061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
1119061da546Spatrick         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1120061da546Spatrick     if (error.Fail()) {
1121061da546Spatrick       result.AppendError(error.AsCString());
1122061da546Spatrick       return false;
1123061da546Spatrick     }
1124061da546Spatrick 
1125061da546Spatrick     return result.Succeeded();
1126061da546Spatrick   }
1127dda28197Spatrick 
1128dda28197Spatrick   private:
1129dda28197Spatrick     CommandOptions m_options;
1130061da546Spatrick };
1131061da546Spatrick 
1132061da546Spatrick // CommandObjectMultiwordSettings
1133061da546Spatrick 
CommandObjectMultiwordSettings(CommandInterpreter & interpreter)1134061da546Spatrick CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1135061da546Spatrick     CommandInterpreter &interpreter)
1136061da546Spatrick     : CommandObjectMultiword(interpreter, "settings",
1137061da546Spatrick                              "Commands for managing LLDB settings.",
1138061da546Spatrick                              "settings <subcommand> [<command-options>]") {
1139061da546Spatrick   LoadSubCommand("set",
1140061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1141061da546Spatrick   LoadSubCommand("show",
1142061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1143061da546Spatrick   LoadSubCommand("list",
1144061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1145061da546Spatrick   LoadSubCommand("remove",
1146061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1147061da546Spatrick   LoadSubCommand("replace", CommandObjectSP(
1148061da546Spatrick                                 new CommandObjectSettingsReplace(interpreter)));
1149061da546Spatrick   LoadSubCommand(
1150061da546Spatrick       "insert-before",
1151061da546Spatrick       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1152061da546Spatrick   LoadSubCommand(
1153061da546Spatrick       "insert-after",
1154061da546Spatrick       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1155061da546Spatrick   LoadSubCommand("append",
1156061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1157061da546Spatrick   LoadSubCommand("clear",
1158061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1159061da546Spatrick   LoadSubCommand("write",
1160061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
1161061da546Spatrick   LoadSubCommand("read",
1162061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1163061da546Spatrick }
1164061da546Spatrick 
1165061da546Spatrick CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1166