1*dda28197Spatrick //===-- 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"
16061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
17061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
18061da546Spatrick 
19061da546Spatrick using namespace lldb;
20061da546Spatrick using namespace lldb_private;
21061da546Spatrick 
22061da546Spatrick // CommandObjectSettingsSet
23061da546Spatrick #define LLDB_OPTIONS_settings_set
24061da546Spatrick #include "CommandOptions.inc"
25061da546Spatrick 
26061da546Spatrick class CommandObjectSettingsSet : public CommandObjectRaw {
27061da546Spatrick public:
28061da546Spatrick   CommandObjectSettingsSet(CommandInterpreter &interpreter)
29061da546Spatrick       : CommandObjectRaw(interpreter, "settings set",
30061da546Spatrick                          "Set the value of the specified debugger setting."),
31061da546Spatrick         m_options() {
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.
84061da546Spatrick   bool WantsCompletion() override { return true; }
85061da546Spatrick 
86061da546Spatrick   Options *GetOptions() override { return &m_options; }
87061da546Spatrick 
88061da546Spatrick   class CommandOptions : public Options {
89061da546Spatrick   public:
90061da546Spatrick     CommandOptions() : Options(), m_global(false) {}
91061da546Spatrick 
92061da546Spatrick     ~CommandOptions() override = default;
93061da546Spatrick 
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;
106061da546Spatrick       default:
107061da546Spatrick         llvm_unreachable("Unimplemented option");
108061da546Spatrick       }
109061da546Spatrick 
110061da546Spatrick       return error;
111061da546Spatrick     }
112061da546Spatrick 
113061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
114061da546Spatrick       m_global = false;
115061da546Spatrick       m_force = false;
116061da546Spatrick     }
117061da546Spatrick 
118061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
119061da546Spatrick       return llvm::makeArrayRef(g_settings_set_options);
120061da546Spatrick     }
121061da546Spatrick 
122061da546Spatrick     // Instance variables to hold the values for command options.
123061da546Spatrick     bool m_global;
124061da546Spatrick     bool m_force;
125061da546Spatrick   };
126061da546Spatrick 
127061da546Spatrick   void
128061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
129061da546Spatrick                            OptionElementVector &opt_element_vector) override {
130061da546Spatrick 
131061da546Spatrick     const size_t argc = request.GetParsedLine().GetArgumentCount();
132061da546Spatrick     const char *arg = nullptr;
133061da546Spatrick     size_t setting_var_idx;
134061da546Spatrick     for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {
135061da546Spatrick       arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
136061da546Spatrick       if (arg && arg[0] != '-')
137061da546Spatrick         break; // We found our setting variable name index
138061da546Spatrick     }
139061da546Spatrick     if (request.GetCursorIndex() == setting_var_idx) {
140061da546Spatrick       // Attempting to complete setting variable name
141061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
142061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
143061da546Spatrick           request, nullptr);
144061da546Spatrick       return;
145061da546Spatrick     }
146061da546Spatrick     arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
147061da546Spatrick 
148061da546Spatrick     if (!arg)
149061da546Spatrick       return;
150061da546Spatrick 
151061da546Spatrick     // Complete option name
152061da546Spatrick     if (arg[0] != '-')
153061da546Spatrick       return;
154061da546Spatrick 
155061da546Spatrick     // Complete setting value
156061da546Spatrick     const char *setting_var_name =
157061da546Spatrick         request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
158061da546Spatrick     Status error;
159061da546Spatrick     lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue(
160061da546Spatrick         &m_exe_ctx, setting_var_name, false, error));
161061da546Spatrick     if (!value_sp)
162061da546Spatrick       return;
163061da546Spatrick     value_sp->AutoComplete(m_interpreter, request);
164061da546Spatrick   }
165061da546Spatrick 
166061da546Spatrick protected:
167061da546Spatrick   bool DoExecute(llvm::StringRef command,
168061da546Spatrick                  CommandReturnObject &result) override {
169061da546Spatrick     Args cmd_args(command);
170061da546Spatrick 
171061da546Spatrick     // Process possible options.
172061da546Spatrick     if (!ParseOptions(cmd_args, result))
173061da546Spatrick       return false;
174061da546Spatrick 
175061da546Spatrick     const size_t min_argc = m_options.m_force ? 1 : 2;
176061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
177061da546Spatrick 
178061da546Spatrick     if ((argc < min_argc) && (!m_options.m_global)) {
179061da546Spatrick       result.AppendError("'settings set' takes more arguments");
180061da546Spatrick       result.SetStatus(eReturnStatusFailed);
181061da546Spatrick       return false;
182061da546Spatrick     }
183061da546Spatrick 
184061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
185061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
186061da546Spatrick       result.AppendError(
187061da546Spatrick           "'settings set' command requires a valid variable name");
188061da546Spatrick       result.SetStatus(eReturnStatusFailed);
189061da546Spatrick       return false;
190061da546Spatrick     }
191061da546Spatrick 
192061da546Spatrick     // A missing value corresponds to clearing the setting when "force" is
193061da546Spatrick     // specified.
194061da546Spatrick     if (argc == 1 && m_options.m_force) {
195061da546Spatrick       Status error(GetDebugger().SetPropertyValue(
196061da546Spatrick           &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
197061da546Spatrick       if (error.Fail()) {
198061da546Spatrick         result.AppendError(error.AsCString());
199061da546Spatrick         result.SetStatus(eReturnStatusFailed);
200061da546Spatrick         return false;
201061da546Spatrick       }
202061da546Spatrick       return result.Succeeded();
203061da546Spatrick     }
204061da546Spatrick 
205061da546Spatrick     // Split the raw command into var_name and value pair.
206061da546Spatrick     llvm::StringRef var_value(command);
207061da546Spatrick     var_value = var_value.split(var_name).second.ltrim();
208061da546Spatrick 
209061da546Spatrick     Status error;
210061da546Spatrick     if (m_options.m_global)
211061da546Spatrick       error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,
212061da546Spatrick                                              var_name, var_value);
213061da546Spatrick 
214061da546Spatrick     if (error.Success()) {
215061da546Spatrick       // FIXME this is the same issue as the one in commands script import
216061da546Spatrick       // we could be setting target.load-script-from-symbol-file which would
217061da546Spatrick       // cause Python scripts to be loaded, which could run LLDB commands (e.g.
218061da546Spatrick       // settings set target.process.python-os-plugin-path) and cause a crash
219061da546Spatrick       // if we did not clear the command's exe_ctx first
220061da546Spatrick       ExecutionContext exe_ctx(m_exe_ctx);
221061da546Spatrick       m_exe_ctx.Clear();
222061da546Spatrick       error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
223061da546Spatrick                                              var_name, var_value);
224061da546Spatrick     }
225061da546Spatrick 
226061da546Spatrick     if (error.Fail()) {
227061da546Spatrick       result.AppendError(error.AsCString());
228061da546Spatrick       result.SetStatus(eReturnStatusFailed);
229061da546Spatrick       return false;
230061da546Spatrick     } else {
231061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
232061da546Spatrick     }
233061da546Spatrick 
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:
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
268061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
269061da546Spatrick                            OptionElementVector &opt_element_vector) override {
270061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
271061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
272061da546Spatrick         request, nullptr);
273061da546Spatrick   }
274061da546Spatrick 
275061da546Spatrick protected:
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           result.SetStatus(eReturnStatusFailed);
289061da546Spatrick         }
290061da546Spatrick       }
291061da546Spatrick     } else {
292061da546Spatrick       GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),
293061da546Spatrick                                           OptionValue::eDumpGroupValue);
294061da546Spatrick     }
295061da546Spatrick 
296061da546Spatrick     return result.Succeeded();
297061da546Spatrick   }
298061da546Spatrick };
299061da546Spatrick 
300061da546Spatrick // CommandObjectSettingsWrite -- Write settings to file
301061da546Spatrick #define LLDB_OPTIONS_settings_write
302061da546Spatrick #include "CommandOptions.inc"
303061da546Spatrick 
304061da546Spatrick class CommandObjectSettingsWrite : public CommandObjectParsed {
305061da546Spatrick public:
306061da546Spatrick   CommandObjectSettingsWrite(CommandInterpreter &interpreter)
307061da546Spatrick       : CommandObjectParsed(
308061da546Spatrick             interpreter, "settings export",
309061da546Spatrick             "Write matching debugger settings and their "
310061da546Spatrick             "current values to a file that can be read in with "
311061da546Spatrick             "\"settings read\". Defaults to writing all settings.",
312061da546Spatrick             nullptr),
313061da546Spatrick         m_options() {
314061da546Spatrick     CommandArgumentEntry arg1;
315061da546Spatrick     CommandArgumentData var_name_arg;
316061da546Spatrick 
317061da546Spatrick     // Define the first (and only) variant of this arg.
318061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
319061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatOptional;
320061da546Spatrick 
321061da546Spatrick     // There is only one variant this argument could be; put it into the
322061da546Spatrick     // argument entry.
323061da546Spatrick     arg1.push_back(var_name_arg);
324061da546Spatrick 
325061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
326061da546Spatrick     m_arguments.push_back(arg1);
327061da546Spatrick   }
328061da546Spatrick 
329061da546Spatrick   ~CommandObjectSettingsWrite() override = default;
330061da546Spatrick 
331061da546Spatrick   Options *GetOptions() override { return &m_options; }
332061da546Spatrick 
333061da546Spatrick   class CommandOptions : public Options {
334061da546Spatrick   public:
335061da546Spatrick     CommandOptions() : Options() {}
336061da546Spatrick 
337061da546Spatrick     ~CommandOptions() override = default;
338061da546Spatrick 
339061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
340061da546Spatrick                           ExecutionContext *execution_context) override {
341061da546Spatrick       Status error;
342061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
343061da546Spatrick 
344061da546Spatrick       switch (short_option) {
345061da546Spatrick       case 'f':
346*dda28197Spatrick         m_filename.assign(std::string(option_arg));
347061da546Spatrick         break;
348061da546Spatrick       case 'a':
349061da546Spatrick         m_append = true;
350061da546Spatrick         break;
351061da546Spatrick       default:
352061da546Spatrick         llvm_unreachable("Unimplemented option");
353061da546Spatrick       }
354061da546Spatrick 
355061da546Spatrick       return error;
356061da546Spatrick     }
357061da546Spatrick 
358061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
359061da546Spatrick       m_filename.clear();
360061da546Spatrick       m_append = false;
361061da546Spatrick     }
362061da546Spatrick 
363061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
364061da546Spatrick       return llvm::makeArrayRef(g_settings_write_options);
365061da546Spatrick     }
366061da546Spatrick 
367061da546Spatrick     // Instance variables to hold the values for command options.
368061da546Spatrick     std::string m_filename;
369061da546Spatrick     bool m_append = false;
370061da546Spatrick   };
371061da546Spatrick 
372061da546Spatrick protected:
373061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
374061da546Spatrick     FileSpec file_spec(m_options.m_filename);
375061da546Spatrick     FileSystem::Instance().Resolve(file_spec);
376061da546Spatrick     std::string path(file_spec.GetPath());
377061da546Spatrick     auto options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
378061da546Spatrick     if (m_options.m_append)
379061da546Spatrick       options |= File::eOpenOptionAppend;
380061da546Spatrick     else
381061da546Spatrick       options |= File::eOpenOptionTruncate;
382061da546Spatrick 
383061da546Spatrick     StreamFile out_file(path.c_str(), options,
384061da546Spatrick                         lldb::eFilePermissionsFileDefault);
385061da546Spatrick 
386061da546Spatrick     if (!out_file.GetFile().IsValid()) {
387061da546Spatrick       result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
388061da546Spatrick       result.SetStatus(eReturnStatusFailed);
389061da546Spatrick       return false;
390061da546Spatrick     }
391061da546Spatrick 
392061da546Spatrick     // Exporting should not be context sensitive.
393061da546Spatrick     ExecutionContext clean_ctx;
394061da546Spatrick 
395061da546Spatrick     if (args.empty()) {
396061da546Spatrick       GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,
397061da546Spatrick                                           OptionValue::eDumpGroupExport);
398061da546Spatrick       return result.Succeeded();
399061da546Spatrick     }
400061da546Spatrick 
401061da546Spatrick     for (const auto &arg : args) {
402061da546Spatrick       Status error(GetDebugger().DumpPropertyValue(
403061da546Spatrick           &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));
404061da546Spatrick       if (!error.Success()) {
405061da546Spatrick         result.AppendError(error.AsCString());
406061da546Spatrick         result.SetStatus(eReturnStatusFailed);
407061da546Spatrick       }
408061da546Spatrick     }
409061da546Spatrick 
410061da546Spatrick     return result.Succeeded();
411061da546Spatrick   }
412061da546Spatrick 
413061da546Spatrick private:
414061da546Spatrick   CommandOptions m_options;
415061da546Spatrick };
416061da546Spatrick 
417061da546Spatrick // CommandObjectSettingsRead -- Read settings from file
418061da546Spatrick #define LLDB_OPTIONS_settings_read
419061da546Spatrick #include "CommandOptions.inc"
420061da546Spatrick 
421061da546Spatrick class CommandObjectSettingsRead : public CommandObjectParsed {
422061da546Spatrick public:
423061da546Spatrick   CommandObjectSettingsRead(CommandInterpreter &interpreter)
424061da546Spatrick       : CommandObjectParsed(
425061da546Spatrick             interpreter, "settings read",
426061da546Spatrick             "Read settings previously saved to a file with \"settings write\".",
427061da546Spatrick             nullptr),
428061da546Spatrick         m_options() {}
429061da546Spatrick 
430061da546Spatrick   ~CommandObjectSettingsRead() override = default;
431061da546Spatrick 
432061da546Spatrick   Options *GetOptions() override { return &m_options; }
433061da546Spatrick 
434061da546Spatrick   class CommandOptions : public Options {
435061da546Spatrick   public:
436061da546Spatrick     CommandOptions() : Options() {}
437061da546Spatrick 
438061da546Spatrick     ~CommandOptions() override = default;
439061da546Spatrick 
440061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
441061da546Spatrick                           ExecutionContext *execution_context) override {
442061da546Spatrick       Status error;
443061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
444061da546Spatrick 
445061da546Spatrick       switch (short_option) {
446061da546Spatrick       case 'f':
447*dda28197Spatrick         m_filename.assign(std::string(option_arg));
448061da546Spatrick         break;
449061da546Spatrick       default:
450061da546Spatrick         llvm_unreachable("Unimplemented option");
451061da546Spatrick       }
452061da546Spatrick 
453061da546Spatrick       return error;
454061da546Spatrick     }
455061da546Spatrick 
456061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
457061da546Spatrick       m_filename.clear();
458061da546Spatrick     }
459061da546Spatrick 
460061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
461061da546Spatrick       return llvm::makeArrayRef(g_settings_read_options);
462061da546Spatrick     }
463061da546Spatrick 
464061da546Spatrick     // Instance variables to hold the values for command options.
465061da546Spatrick     std::string m_filename;
466061da546Spatrick   };
467061da546Spatrick 
468061da546Spatrick protected:
469061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
470061da546Spatrick     FileSpec file(m_options.m_filename);
471061da546Spatrick     FileSystem::Instance().Resolve(file);
472061da546Spatrick     ExecutionContext clean_ctx;
473061da546Spatrick     CommandInterpreterRunOptions options;
474061da546Spatrick     options.SetAddToHistory(false);
475061da546Spatrick     options.SetEchoCommands(false);
476061da546Spatrick     options.SetPrintResults(true);
477061da546Spatrick     options.SetPrintErrors(true);
478061da546Spatrick     options.SetStopOnError(false);
479061da546Spatrick     m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result);
480061da546Spatrick     return result.Succeeded();
481061da546Spatrick   }
482061da546Spatrick 
483061da546Spatrick private:
484061da546Spatrick   CommandOptions m_options;
485061da546Spatrick };
486061da546Spatrick 
487061da546Spatrick // CommandObjectSettingsList -- List settable variables
488061da546Spatrick 
489061da546Spatrick class CommandObjectSettingsList : public CommandObjectParsed {
490061da546Spatrick public:
491061da546Spatrick   CommandObjectSettingsList(CommandInterpreter &interpreter)
492061da546Spatrick       : CommandObjectParsed(interpreter, "settings list",
493061da546Spatrick                             "List and describe matching debugger settings.  "
494061da546Spatrick                             "Defaults to all listing all settings.",
495061da546Spatrick                             nullptr) {
496061da546Spatrick     CommandArgumentEntry arg;
497061da546Spatrick     CommandArgumentData var_name_arg;
498061da546Spatrick     CommandArgumentData prefix_name_arg;
499061da546Spatrick 
500061da546Spatrick     // Define the first variant of this arg.
501061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
502061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatOptional;
503061da546Spatrick 
504061da546Spatrick     // Define the second variant of this arg.
505061da546Spatrick     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
506061da546Spatrick     prefix_name_arg.arg_repetition = eArgRepeatOptional;
507061da546Spatrick 
508061da546Spatrick     arg.push_back(var_name_arg);
509061da546Spatrick     arg.push_back(prefix_name_arg);
510061da546Spatrick 
511061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
512061da546Spatrick     m_arguments.push_back(arg);
513061da546Spatrick   }
514061da546Spatrick 
515061da546Spatrick   ~CommandObjectSettingsList() override = default;
516061da546Spatrick 
517061da546Spatrick   void
518061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
519061da546Spatrick                            OptionElementVector &opt_element_vector) override {
520061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
521061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
522061da546Spatrick         request, nullptr);
523061da546Spatrick   }
524061da546Spatrick 
525061da546Spatrick protected:
526061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
527061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
528061da546Spatrick 
529061da546Spatrick     const bool will_modify = false;
530061da546Spatrick     const size_t argc = args.GetArgumentCount();
531061da546Spatrick     if (argc > 0) {
532061da546Spatrick       const bool dump_qualified_name = true;
533061da546Spatrick 
534*dda28197Spatrick       for (const Args::ArgEntry &arg : args) {
535*dda28197Spatrick         const char *property_path = arg.c_str();
536061da546Spatrick 
537061da546Spatrick         const Property *property =
538061da546Spatrick             GetDebugger().GetValueProperties()->GetPropertyAtPath(
539061da546Spatrick                 &m_exe_ctx, will_modify, property_path);
540061da546Spatrick 
541061da546Spatrick         if (property) {
542061da546Spatrick           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
543061da546Spatrick                                     dump_qualified_name);
544061da546Spatrick         } else {
545061da546Spatrick           result.AppendErrorWithFormat("invalid property path '%s'",
546061da546Spatrick                                        property_path);
547061da546Spatrick           result.SetStatus(eReturnStatusFailed);
548061da546Spatrick         }
549061da546Spatrick       }
550061da546Spatrick     } else {
551061da546Spatrick       GetDebugger().DumpAllDescriptions(m_interpreter,
552061da546Spatrick                                         result.GetOutputStream());
553061da546Spatrick     }
554061da546Spatrick 
555061da546Spatrick     return result.Succeeded();
556061da546Spatrick   }
557061da546Spatrick };
558061da546Spatrick 
559061da546Spatrick // CommandObjectSettingsRemove
560061da546Spatrick 
561061da546Spatrick class CommandObjectSettingsRemove : public CommandObjectRaw {
562061da546Spatrick public:
563061da546Spatrick   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
564061da546Spatrick       : CommandObjectRaw(interpreter, "settings remove",
565061da546Spatrick                          "Remove a value from a setting, specified by array "
566061da546Spatrick                          "index or dictionary key.") {
567061da546Spatrick     CommandArgumentEntry arg1;
568061da546Spatrick     CommandArgumentEntry arg2;
569061da546Spatrick     CommandArgumentData var_name_arg;
570061da546Spatrick     CommandArgumentData index_arg;
571061da546Spatrick     CommandArgumentData key_arg;
572061da546Spatrick 
573061da546Spatrick     // Define the first (and only) variant of this arg.
574061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
575061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
576061da546Spatrick 
577061da546Spatrick     // There is only one variant this argument could be; put it into the
578061da546Spatrick     // argument entry.
579061da546Spatrick     arg1.push_back(var_name_arg);
580061da546Spatrick 
581061da546Spatrick     // Define the first variant of this arg.
582061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
583061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
584061da546Spatrick 
585061da546Spatrick     // Define the second variant of this arg.
586061da546Spatrick     key_arg.arg_type = eArgTypeSettingKey;
587061da546Spatrick     key_arg.arg_repetition = eArgRepeatPlain;
588061da546Spatrick 
589061da546Spatrick     // Push both variants into this arg
590061da546Spatrick     arg2.push_back(index_arg);
591061da546Spatrick     arg2.push_back(key_arg);
592061da546Spatrick 
593061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
594061da546Spatrick     m_arguments.push_back(arg1);
595061da546Spatrick     m_arguments.push_back(arg2);
596061da546Spatrick   }
597061da546Spatrick 
598061da546Spatrick   ~CommandObjectSettingsRemove() override = default;
599061da546Spatrick 
600061da546Spatrick   bool WantsCompletion() override { return true; }
601061da546Spatrick 
602061da546Spatrick   void
603061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
604061da546Spatrick                            OptionElementVector &opt_element_vector) override {
605061da546Spatrick     if (request.GetCursorIndex() < 2)
606061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
607061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
608061da546Spatrick           request, nullptr);
609061da546Spatrick   }
610061da546Spatrick 
611061da546Spatrick protected:
612061da546Spatrick   bool DoExecute(llvm::StringRef command,
613061da546Spatrick                  CommandReturnObject &result) override {
614061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
615061da546Spatrick 
616061da546Spatrick     Args cmd_args(command);
617061da546Spatrick 
618061da546Spatrick     // Process possible options.
619061da546Spatrick     if (!ParseOptions(cmd_args, result))
620061da546Spatrick       return false;
621061da546Spatrick 
622061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
623061da546Spatrick     if (argc == 0) {
624061da546Spatrick       result.AppendError("'settings remove' takes an array or dictionary item, "
625061da546Spatrick                          "or an array followed by one or more indexes, or a "
626061da546Spatrick                          "dictionary followed by one or more key names to "
627061da546Spatrick                          "remove");
628061da546Spatrick       result.SetStatus(eReturnStatusFailed);
629061da546Spatrick       return false;
630061da546Spatrick     }
631061da546Spatrick 
632061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
633061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
634061da546Spatrick       result.AppendError(
635061da546Spatrick           "'settings remove' command requires a valid variable name");
636061da546Spatrick       result.SetStatus(eReturnStatusFailed);
637061da546Spatrick       return false;
638061da546Spatrick     }
639061da546Spatrick 
640061da546Spatrick     // Split the raw command into var_name and value pair.
641061da546Spatrick     llvm::StringRef var_value(command);
642061da546Spatrick     var_value = var_value.split(var_name).second.trim();
643061da546Spatrick 
644061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
645061da546Spatrick         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
646061da546Spatrick     if (error.Fail()) {
647061da546Spatrick       result.AppendError(error.AsCString());
648061da546Spatrick       result.SetStatus(eReturnStatusFailed);
649061da546Spatrick       return false;
650061da546Spatrick     }
651061da546Spatrick 
652061da546Spatrick     return result.Succeeded();
653061da546Spatrick   }
654061da546Spatrick };
655061da546Spatrick 
656061da546Spatrick // CommandObjectSettingsReplace
657061da546Spatrick 
658061da546Spatrick class CommandObjectSettingsReplace : public CommandObjectRaw {
659061da546Spatrick public:
660061da546Spatrick   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
661061da546Spatrick       : CommandObjectRaw(interpreter, "settings replace",
662061da546Spatrick                          "Replace the debugger setting value specified by "
663061da546Spatrick                          "array index or dictionary key.") {
664061da546Spatrick     CommandArgumentEntry arg1;
665061da546Spatrick     CommandArgumentEntry arg2;
666061da546Spatrick     CommandArgumentEntry arg3;
667061da546Spatrick     CommandArgumentData var_name_arg;
668061da546Spatrick     CommandArgumentData index_arg;
669061da546Spatrick     CommandArgumentData key_arg;
670061da546Spatrick     CommandArgumentData value_arg;
671061da546Spatrick 
672061da546Spatrick     // Define the first (and only) variant of this arg.
673061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
674061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
675061da546Spatrick 
676061da546Spatrick     // There is only one variant this argument could be; put it into the
677061da546Spatrick     // argument entry.
678061da546Spatrick     arg1.push_back(var_name_arg);
679061da546Spatrick 
680061da546Spatrick     // Define the first (variant of this arg.
681061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
682061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
683061da546Spatrick 
684061da546Spatrick     // Define the second (variant of this arg.
685061da546Spatrick     key_arg.arg_type = eArgTypeSettingKey;
686061da546Spatrick     key_arg.arg_repetition = eArgRepeatPlain;
687061da546Spatrick 
688061da546Spatrick     // Put both variants into this arg
689061da546Spatrick     arg2.push_back(index_arg);
690061da546Spatrick     arg2.push_back(key_arg);
691061da546Spatrick 
692061da546Spatrick     // Define the first (and only) variant of this arg.
693061da546Spatrick     value_arg.arg_type = eArgTypeValue;
694061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
695061da546Spatrick 
696061da546Spatrick     // There is only one variant this argument could be; put it into the
697061da546Spatrick     // argument entry.
698061da546Spatrick     arg3.push_back(value_arg);
699061da546Spatrick 
700061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
701061da546Spatrick     m_arguments.push_back(arg1);
702061da546Spatrick     m_arguments.push_back(arg2);
703061da546Spatrick     m_arguments.push_back(arg3);
704061da546Spatrick   }
705061da546Spatrick 
706061da546Spatrick   ~CommandObjectSettingsReplace() override = default;
707061da546Spatrick 
708061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
709061da546Spatrick   // !WantsRawCommandString.
710061da546Spatrick   bool WantsCompletion() override { return true; }
711061da546Spatrick 
712061da546Spatrick   void
713061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
714061da546Spatrick                            OptionElementVector &opt_element_vector) override {
715061da546Spatrick     // Attempting to complete variable name
716061da546Spatrick     if (request.GetCursorIndex() < 2)
717061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
718061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
719061da546Spatrick           request, nullptr);
720061da546Spatrick   }
721061da546Spatrick 
722061da546Spatrick protected:
723061da546Spatrick   bool DoExecute(llvm::StringRef command,
724061da546Spatrick                  CommandReturnObject &result) override {
725061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
726061da546Spatrick 
727061da546Spatrick     Args cmd_args(command);
728061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
729061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
730061da546Spatrick       result.AppendError("'settings replace' command requires a valid variable "
731061da546Spatrick                          "name; No value supplied");
732061da546Spatrick       result.SetStatus(eReturnStatusFailed);
733061da546Spatrick       return false;
734061da546Spatrick     }
735061da546Spatrick 
736061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
737061da546Spatrick     llvm::StringRef var_value(command);
738061da546Spatrick     var_value = var_value.split(var_name).second.trim();
739061da546Spatrick 
740061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
741061da546Spatrick         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
742061da546Spatrick     if (error.Fail()) {
743061da546Spatrick       result.AppendError(error.AsCString());
744061da546Spatrick       result.SetStatus(eReturnStatusFailed);
745061da546Spatrick       return false;
746061da546Spatrick     } else {
747061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishNoResult);
748061da546Spatrick     }
749061da546Spatrick 
750061da546Spatrick     return result.Succeeded();
751061da546Spatrick   }
752061da546Spatrick };
753061da546Spatrick 
754061da546Spatrick // CommandObjectSettingsInsertBefore
755061da546Spatrick 
756061da546Spatrick class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
757061da546Spatrick public:
758061da546Spatrick   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
759061da546Spatrick       : CommandObjectRaw(interpreter, "settings insert-before",
760061da546Spatrick                          "Insert one or more values into an debugger array "
761061da546Spatrick                          "setting immediately before the specified element "
762061da546Spatrick                          "index.") {
763061da546Spatrick     CommandArgumentEntry arg1;
764061da546Spatrick     CommandArgumentEntry arg2;
765061da546Spatrick     CommandArgumentEntry arg3;
766061da546Spatrick     CommandArgumentData var_name_arg;
767061da546Spatrick     CommandArgumentData index_arg;
768061da546Spatrick     CommandArgumentData value_arg;
769061da546Spatrick 
770061da546Spatrick     // Define the first (and only) variant of this arg.
771061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
772061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
773061da546Spatrick 
774061da546Spatrick     // There is only one variant this argument could be; put it into the
775061da546Spatrick     // argument entry.
776061da546Spatrick     arg1.push_back(var_name_arg);
777061da546Spatrick 
778061da546Spatrick     // Define the first (variant of this arg.
779061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
780061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
781061da546Spatrick 
782061da546Spatrick     // There is only one variant this argument could be; put it into the
783061da546Spatrick     // argument entry.
784061da546Spatrick     arg2.push_back(index_arg);
785061da546Spatrick 
786061da546Spatrick     // Define the first (and only) variant of this arg.
787061da546Spatrick     value_arg.arg_type = eArgTypeValue;
788061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
789061da546Spatrick 
790061da546Spatrick     // There is only one variant this argument could be; put it into the
791061da546Spatrick     // argument entry.
792061da546Spatrick     arg3.push_back(value_arg);
793061da546Spatrick 
794061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
795061da546Spatrick     m_arguments.push_back(arg1);
796061da546Spatrick     m_arguments.push_back(arg2);
797061da546Spatrick     m_arguments.push_back(arg3);
798061da546Spatrick   }
799061da546Spatrick 
800061da546Spatrick   ~CommandObjectSettingsInsertBefore() override = default;
801061da546Spatrick 
802061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
803061da546Spatrick   // !WantsRawCommandString.
804061da546Spatrick   bool WantsCompletion() override { return true; }
805061da546Spatrick 
806061da546Spatrick   void
807061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
808061da546Spatrick                            OptionElementVector &opt_element_vector) override {
809061da546Spatrick     // Attempting to complete variable name
810061da546Spatrick     if (request.GetCursorIndex() < 2)
811061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
812061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
813061da546Spatrick           request, nullptr);
814061da546Spatrick   }
815061da546Spatrick 
816061da546Spatrick protected:
817061da546Spatrick   bool DoExecute(llvm::StringRef command,
818061da546Spatrick                  CommandReturnObject &result) override {
819061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
820061da546Spatrick 
821061da546Spatrick     Args cmd_args(command);
822061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
823061da546Spatrick 
824061da546Spatrick     if (argc < 3) {
825061da546Spatrick       result.AppendError("'settings insert-before' takes more arguments");
826061da546Spatrick       result.SetStatus(eReturnStatusFailed);
827061da546Spatrick       return false;
828061da546Spatrick     }
829061da546Spatrick 
830061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
831061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
832061da546Spatrick       result.AppendError("'settings insert-before' command requires a valid "
833061da546Spatrick                          "variable name; No value supplied");
834061da546Spatrick       result.SetStatus(eReturnStatusFailed);
835061da546Spatrick       return false;
836061da546Spatrick     }
837061da546Spatrick 
838061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
839061da546Spatrick     llvm::StringRef var_value(command);
840061da546Spatrick     var_value = var_value.split(var_name).second.trim();
841061da546Spatrick 
842061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
843061da546Spatrick         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
844061da546Spatrick     if (error.Fail()) {
845061da546Spatrick       result.AppendError(error.AsCString());
846061da546Spatrick       result.SetStatus(eReturnStatusFailed);
847061da546Spatrick       return false;
848061da546Spatrick     }
849061da546Spatrick 
850061da546Spatrick     return result.Succeeded();
851061da546Spatrick   }
852061da546Spatrick };
853061da546Spatrick 
854061da546Spatrick // CommandObjectSettingInsertAfter
855061da546Spatrick 
856061da546Spatrick class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
857061da546Spatrick public:
858061da546Spatrick   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
859061da546Spatrick       : CommandObjectRaw(interpreter, "settings insert-after",
860061da546Spatrick                          "Insert one or more values into a debugger array "
861061da546Spatrick                          "settings after the specified element index.") {
862061da546Spatrick     CommandArgumentEntry arg1;
863061da546Spatrick     CommandArgumentEntry arg2;
864061da546Spatrick     CommandArgumentEntry arg3;
865061da546Spatrick     CommandArgumentData var_name_arg;
866061da546Spatrick     CommandArgumentData index_arg;
867061da546Spatrick     CommandArgumentData value_arg;
868061da546Spatrick 
869061da546Spatrick     // Define the first (and only) variant of this arg.
870061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
871061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
872061da546Spatrick 
873061da546Spatrick     // There is only one variant this argument could be; put it into the
874061da546Spatrick     // argument entry.
875061da546Spatrick     arg1.push_back(var_name_arg);
876061da546Spatrick 
877061da546Spatrick     // Define the first (variant of this arg.
878061da546Spatrick     index_arg.arg_type = eArgTypeSettingIndex;
879061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
880061da546Spatrick 
881061da546Spatrick     // There is only one variant this argument could be; put it into the
882061da546Spatrick     // argument entry.
883061da546Spatrick     arg2.push_back(index_arg);
884061da546Spatrick 
885061da546Spatrick     // Define the first (and only) variant of this arg.
886061da546Spatrick     value_arg.arg_type = eArgTypeValue;
887061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
888061da546Spatrick 
889061da546Spatrick     // There is only one variant this argument could be; put it into the
890061da546Spatrick     // argument entry.
891061da546Spatrick     arg3.push_back(value_arg);
892061da546Spatrick 
893061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
894061da546Spatrick     m_arguments.push_back(arg1);
895061da546Spatrick     m_arguments.push_back(arg2);
896061da546Spatrick     m_arguments.push_back(arg3);
897061da546Spatrick   }
898061da546Spatrick 
899061da546Spatrick   ~CommandObjectSettingsInsertAfter() override = default;
900061da546Spatrick 
901061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
902061da546Spatrick   // !WantsRawCommandString.
903061da546Spatrick   bool WantsCompletion() override { return true; }
904061da546Spatrick 
905061da546Spatrick   void
906061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
907061da546Spatrick                            OptionElementVector &opt_element_vector) override {
908061da546Spatrick     // Attempting to complete variable name
909061da546Spatrick     if (request.GetCursorIndex() < 2)
910061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
911061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
912061da546Spatrick           request, nullptr);
913061da546Spatrick   }
914061da546Spatrick 
915061da546Spatrick protected:
916061da546Spatrick   bool DoExecute(llvm::StringRef command,
917061da546Spatrick                  CommandReturnObject &result) override {
918061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
919061da546Spatrick 
920061da546Spatrick     Args cmd_args(command);
921061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
922061da546Spatrick 
923061da546Spatrick     if (argc < 3) {
924061da546Spatrick       result.AppendError("'settings insert-after' takes more arguments");
925061da546Spatrick       result.SetStatus(eReturnStatusFailed);
926061da546Spatrick       return false;
927061da546Spatrick     }
928061da546Spatrick 
929061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
930061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
931061da546Spatrick       result.AppendError("'settings insert-after' command requires a valid "
932061da546Spatrick                          "variable name; No value supplied");
933061da546Spatrick       result.SetStatus(eReturnStatusFailed);
934061da546Spatrick       return false;
935061da546Spatrick     }
936061da546Spatrick 
937061da546Spatrick     // Split the raw command into var_name, index_value, and value triple.
938061da546Spatrick     llvm::StringRef var_value(command);
939061da546Spatrick     var_value = var_value.split(var_name).second.trim();
940061da546Spatrick 
941061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
942061da546Spatrick         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
943061da546Spatrick     if (error.Fail()) {
944061da546Spatrick       result.AppendError(error.AsCString());
945061da546Spatrick       result.SetStatus(eReturnStatusFailed);
946061da546Spatrick       return false;
947061da546Spatrick     }
948061da546Spatrick 
949061da546Spatrick     return result.Succeeded();
950061da546Spatrick   }
951061da546Spatrick };
952061da546Spatrick 
953061da546Spatrick // CommandObjectSettingsAppend
954061da546Spatrick 
955061da546Spatrick class CommandObjectSettingsAppend : public CommandObjectRaw {
956061da546Spatrick public:
957061da546Spatrick   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
958061da546Spatrick       : CommandObjectRaw(interpreter, "settings append",
959061da546Spatrick                          "Append one or more values to a debugger array, "
960061da546Spatrick                          "dictionary, or string setting.") {
961061da546Spatrick     CommandArgumentEntry arg1;
962061da546Spatrick     CommandArgumentEntry arg2;
963061da546Spatrick     CommandArgumentData var_name_arg;
964061da546Spatrick     CommandArgumentData value_arg;
965061da546Spatrick 
966061da546Spatrick     // Define the first (and only) variant of this arg.
967061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
968061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
969061da546Spatrick 
970061da546Spatrick     // There is only one variant this argument could be; put it into the
971061da546Spatrick     // argument entry.
972061da546Spatrick     arg1.push_back(var_name_arg);
973061da546Spatrick 
974061da546Spatrick     // Define the first (and only) variant of this arg.
975061da546Spatrick     value_arg.arg_type = eArgTypeValue;
976061da546Spatrick     value_arg.arg_repetition = eArgRepeatPlain;
977061da546Spatrick 
978061da546Spatrick     // There is only one variant this argument could be; put it into the
979061da546Spatrick     // argument entry.
980061da546Spatrick     arg2.push_back(value_arg);
981061da546Spatrick 
982061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
983061da546Spatrick     m_arguments.push_back(arg1);
984061da546Spatrick     m_arguments.push_back(arg2);
985061da546Spatrick   }
986061da546Spatrick 
987061da546Spatrick   ~CommandObjectSettingsAppend() override = default;
988061da546Spatrick 
989061da546Spatrick   // Overrides base class's behavior where WantsCompletion =
990061da546Spatrick   // !WantsRawCommandString.
991061da546Spatrick   bool WantsCompletion() override { return true; }
992061da546Spatrick 
993061da546Spatrick   void
994061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
995061da546Spatrick                            OptionElementVector &opt_element_vector) override {
996061da546Spatrick     // Attempting to complete variable name
997061da546Spatrick     if (request.GetCursorIndex() < 2)
998061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
999061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1000061da546Spatrick           request, nullptr);
1001061da546Spatrick   }
1002061da546Spatrick 
1003061da546Spatrick protected:
1004061da546Spatrick   bool DoExecute(llvm::StringRef command,
1005061da546Spatrick                  CommandReturnObject &result) override {
1006061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1007061da546Spatrick     Args cmd_args(command);
1008061da546Spatrick     const size_t argc = cmd_args.GetArgumentCount();
1009061da546Spatrick 
1010061da546Spatrick     if (argc < 2) {
1011061da546Spatrick       result.AppendError("'settings append' takes more arguments");
1012061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1013061da546Spatrick       return false;
1014061da546Spatrick     }
1015061da546Spatrick 
1016061da546Spatrick     const char *var_name = cmd_args.GetArgumentAtIndex(0);
1017061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1018061da546Spatrick       result.AppendError("'settings append' command requires a valid variable "
1019061da546Spatrick                          "name; No value supplied");
1020061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1021061da546Spatrick       return false;
1022061da546Spatrick     }
1023061da546Spatrick 
1024061da546Spatrick     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
1025061da546Spatrick     // character string later on.
1026061da546Spatrick 
1027061da546Spatrick     // Split the raw command into var_name and value pair.
1028061da546Spatrick     llvm::StringRef var_value(command);
1029061da546Spatrick     var_value = var_value.split(var_name).second.trim();
1030061da546Spatrick 
1031061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
1032061da546Spatrick         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
1033061da546Spatrick     if (error.Fail()) {
1034061da546Spatrick       result.AppendError(error.AsCString());
1035061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1036061da546Spatrick       return false;
1037061da546Spatrick     }
1038061da546Spatrick 
1039061da546Spatrick     return result.Succeeded();
1040061da546Spatrick   }
1041061da546Spatrick };
1042061da546Spatrick 
1043061da546Spatrick // CommandObjectSettingsClear
1044*dda28197Spatrick #define LLDB_OPTIONS_settings_clear
1045*dda28197Spatrick #include "CommandOptions.inc"
1046061da546Spatrick 
1047061da546Spatrick class CommandObjectSettingsClear : public CommandObjectParsed {
1048061da546Spatrick public:
1049061da546Spatrick   CommandObjectSettingsClear(CommandInterpreter &interpreter)
1050061da546Spatrick       : CommandObjectParsed(
1051061da546Spatrick             interpreter, "settings clear",
1052*dda28197Spatrick             "Clear a debugger setting array, dictionary, or string. "
1053*dda28197Spatrick             "If '-a' option is specified, it clears all settings.", nullptr) {
1054061da546Spatrick     CommandArgumentEntry arg;
1055061da546Spatrick     CommandArgumentData var_name_arg;
1056061da546Spatrick 
1057061da546Spatrick     // Define the first (and only) variant of this arg.
1058061da546Spatrick     var_name_arg.arg_type = eArgTypeSettingVariableName;
1059061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlain;
1060061da546Spatrick 
1061061da546Spatrick     // There is only one variant this argument could be; put it into the
1062061da546Spatrick     // argument entry.
1063061da546Spatrick     arg.push_back(var_name_arg);
1064061da546Spatrick 
1065061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1066061da546Spatrick     m_arguments.push_back(arg);
1067061da546Spatrick   }
1068061da546Spatrick 
1069061da546Spatrick   ~CommandObjectSettingsClear() override = default;
1070061da546Spatrick 
1071061da546Spatrick   void
1072061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
1073061da546Spatrick                            OptionElementVector &opt_element_vector) override {
1074061da546Spatrick     // Attempting to complete variable name
1075061da546Spatrick     if (request.GetCursorIndex() < 2)
1076061da546Spatrick       CommandCompletions::InvokeCommonCompletionCallbacks(
1077061da546Spatrick           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1078061da546Spatrick           request, nullptr);
1079061da546Spatrick   }
1080061da546Spatrick 
1081*dda28197Spatrick    Options *GetOptions() override { return &m_options; }
1082*dda28197Spatrick 
1083*dda28197Spatrick   class CommandOptions : public Options {
1084*dda28197Spatrick   public:
1085*dda28197Spatrick     CommandOptions() = default;
1086*dda28197Spatrick 
1087*dda28197Spatrick     ~CommandOptions() override = default;
1088*dda28197Spatrick 
1089*dda28197Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1090*dda28197Spatrick                           ExecutionContext *execution_context) override {
1091*dda28197Spatrick       const int short_option = m_getopt_table[option_idx].val;
1092*dda28197Spatrick       switch (short_option) {
1093*dda28197Spatrick       case 'a':
1094*dda28197Spatrick         m_clear_all = true;
1095*dda28197Spatrick         break;
1096*dda28197Spatrick       default:
1097*dda28197Spatrick         llvm_unreachable("Unimplemented option");
1098*dda28197Spatrick       }
1099*dda28197Spatrick       return Status();
1100*dda28197Spatrick     }
1101*dda28197Spatrick 
1102*dda28197Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1103*dda28197Spatrick       m_clear_all = false;
1104*dda28197Spatrick     }
1105*dda28197Spatrick 
1106*dda28197Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1107*dda28197Spatrick       return llvm::makeArrayRef(g_settings_clear_options);
1108*dda28197Spatrick     }
1109*dda28197Spatrick 
1110*dda28197Spatrick     bool m_clear_all = false;
1111*dda28197Spatrick   };
1112*dda28197Spatrick 
1113061da546Spatrick protected:
1114061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1115061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1116061da546Spatrick     const size_t argc = command.GetArgumentCount();
1117061da546Spatrick 
1118*dda28197Spatrick     if (m_options.m_clear_all) {
1119*dda28197Spatrick       if (argc != 0) {
1120*dda28197Spatrick         result.AppendError("'settings clear --all' doesn't take any arguments");
1121*dda28197Spatrick         result.SetStatus(eReturnStatusFailed);
1122*dda28197Spatrick         return false;
1123*dda28197Spatrick       }
1124*dda28197Spatrick       GetDebugger().GetValueProperties()->Clear();
1125*dda28197Spatrick       return result.Succeeded();
1126*dda28197Spatrick     }
1127*dda28197Spatrick 
1128061da546Spatrick     if (argc != 1) {
1129061da546Spatrick       result.AppendError("'settings clear' takes exactly one argument");
1130061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1131061da546Spatrick       return false;
1132061da546Spatrick     }
1133061da546Spatrick 
1134061da546Spatrick     const char *var_name = command.GetArgumentAtIndex(0);
1135061da546Spatrick     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1136061da546Spatrick       result.AppendError("'settings clear' command requires a valid variable "
1137061da546Spatrick                          "name; No value supplied");
1138061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1139061da546Spatrick       return false;
1140061da546Spatrick     }
1141061da546Spatrick 
1142061da546Spatrick     Status error(GetDebugger().SetPropertyValue(
1143061da546Spatrick         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1144061da546Spatrick     if (error.Fail()) {
1145061da546Spatrick       result.AppendError(error.AsCString());
1146061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1147061da546Spatrick       return false;
1148061da546Spatrick     }
1149061da546Spatrick 
1150061da546Spatrick     return result.Succeeded();
1151061da546Spatrick   }
1152*dda28197Spatrick 
1153*dda28197Spatrick   private:
1154*dda28197Spatrick     CommandOptions m_options;
1155061da546Spatrick };
1156061da546Spatrick 
1157061da546Spatrick // CommandObjectMultiwordSettings
1158061da546Spatrick 
1159061da546Spatrick CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1160061da546Spatrick     CommandInterpreter &interpreter)
1161061da546Spatrick     : CommandObjectMultiword(interpreter, "settings",
1162061da546Spatrick                              "Commands for managing LLDB settings.",
1163061da546Spatrick                              "settings <subcommand> [<command-options>]") {
1164061da546Spatrick   LoadSubCommand("set",
1165061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1166061da546Spatrick   LoadSubCommand("show",
1167061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1168061da546Spatrick   LoadSubCommand("list",
1169061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1170061da546Spatrick   LoadSubCommand("remove",
1171061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1172061da546Spatrick   LoadSubCommand("replace", CommandObjectSP(
1173061da546Spatrick                                 new CommandObjectSettingsReplace(interpreter)));
1174061da546Spatrick   LoadSubCommand(
1175061da546Spatrick       "insert-before",
1176061da546Spatrick       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1177061da546Spatrick   LoadSubCommand(
1178061da546Spatrick       "insert-after",
1179061da546Spatrick       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1180061da546Spatrick   LoadSubCommand("append",
1181061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1182061da546Spatrick   LoadSubCommand("clear",
1183061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1184061da546Spatrick   LoadSubCommand("write",
1185061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
1186061da546Spatrick   LoadSubCommand("read",
1187061da546Spatrick                  CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1188061da546Spatrick }
1189061da546Spatrick 
1190061da546Spatrick CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1191