1 //===-- CommandObjectSettings.cpp -------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CommandObjectSettings.h"
10
11 #include "llvm/ADT/StringRef.h"
12
13 #include "lldb/Host/OptionParser.h"
14 #include "lldb/Interpreter/CommandCompletions.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandReturnObject.h"
17 #include "lldb/Interpreter/OptionValueProperties.h"
18
19 using namespace lldb;
20 using namespace lldb_private;
21
22 // CommandObjectSettingsSet
23 #define LLDB_OPTIONS_settings_set
24 #include "CommandOptions.inc"
25
26 class CommandObjectSettingsSet : public CommandObjectRaw {
27 public:
CommandObjectSettingsSet(CommandInterpreter & interpreter)28 CommandObjectSettingsSet(CommandInterpreter &interpreter)
29 : CommandObjectRaw(interpreter, "settings set",
30 "Set the value of the specified debugger setting."),
31 m_options() {
32 CommandArgumentEntry arg1;
33 CommandArgumentEntry arg2;
34 CommandArgumentData var_name_arg;
35 CommandArgumentData value_arg;
36
37 // Define the first (and only) variant of this arg.
38 var_name_arg.arg_type = eArgTypeSettingVariableName;
39 var_name_arg.arg_repetition = eArgRepeatPlain;
40
41 // There is only one variant this argument could be; put it into the
42 // argument entry.
43 arg1.push_back(var_name_arg);
44
45 // Define the first (and only) variant of this arg.
46 value_arg.arg_type = eArgTypeValue;
47 value_arg.arg_repetition = eArgRepeatPlain;
48
49 // There is only one variant this argument could be; put it into the
50 // argument entry.
51 arg2.push_back(value_arg);
52
53 // Push the data for the first argument into the m_arguments vector.
54 m_arguments.push_back(arg1);
55 m_arguments.push_back(arg2);
56
57 SetHelpLong(
58 "\nWhen setting a dictionary or array variable, you can set multiple entries \
59 at once by giving the values to the set command. For example:"
60 R"(
61
62 (lldb) settings set target.run-args value1 value2 value3
63 (lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
64
65 (lldb) settings show target.run-args
66 [0]: 'value1'
67 [1]: 'value2'
68 [3]: 'value3'
69 (lldb) settings show target.env-vars
70 'MYPATH=~/.:/usr/bin'
71 'SOME_ENV_VAR=12345'
72
73 )"
74 "Warning: The 'set' command re-sets the entire array or dictionary. If you \
75 just want to add, remove or update individual values (or add something to \
76 the end), use one of the other settings sub-commands: append, replace, \
77 insert-before or insert-after.");
78 }
79
80 ~CommandObjectSettingsSet() override = default;
81
82 // Overrides base class's behavior where WantsCompletion =
83 // !WantsRawCommandString.
WantsCompletion()84 bool WantsCompletion() override { return true; }
85
GetOptions()86 Options *GetOptions() override { return &m_options; }
87
88 class CommandOptions : public Options {
89 public:
CommandOptions()90 CommandOptions() : Options(), m_global(false) {}
91
92 ~CommandOptions() override = default;
93
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)94 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
95 ExecutionContext *execution_context) override {
96 Status error;
97 const int short_option = m_getopt_table[option_idx].val;
98
99 switch (short_option) {
100 case 'f':
101 m_force = true;
102 break;
103 case 'g':
104 m_global = true;
105 break;
106 default:
107 llvm_unreachable("Unimplemented option");
108 }
109
110 return error;
111 }
112
OptionParsingStarting(ExecutionContext * execution_context)113 void OptionParsingStarting(ExecutionContext *execution_context) override {
114 m_global = false;
115 m_force = false;
116 }
117
GetDefinitions()118 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
119 return llvm::makeArrayRef(g_settings_set_options);
120 }
121
122 // Instance variables to hold the values for command options.
123 bool m_global;
124 bool m_force;
125 };
126
127 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)128 HandleArgumentCompletion(CompletionRequest &request,
129 OptionElementVector &opt_element_vector) override {
130
131 const size_t argc = request.GetParsedLine().GetArgumentCount();
132 const char *arg = nullptr;
133 size_t setting_var_idx;
134 for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {
135 arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
136 if (arg && arg[0] != '-')
137 break; // We found our setting variable name index
138 }
139 if (request.GetCursorIndex() == setting_var_idx) {
140 // Attempting to complete setting variable name
141 CommandCompletions::InvokeCommonCompletionCallbacks(
142 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
143 request, nullptr);
144 return;
145 }
146 arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
147
148 if (!arg)
149 return;
150
151 // Complete option name
152 if (arg[0] != '-')
153 return;
154
155 // Complete setting value
156 const char *setting_var_name =
157 request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
158 Status error;
159 lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue(
160 &m_exe_ctx, setting_var_name, false, error));
161 if (!value_sp)
162 return;
163 value_sp->AutoComplete(m_interpreter, request);
164 }
165
166 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)167 bool DoExecute(llvm::StringRef command,
168 CommandReturnObject &result) override {
169 Args cmd_args(command);
170
171 // Process possible options.
172 if (!ParseOptions(cmd_args, result))
173 return false;
174
175 const size_t min_argc = m_options.m_force ? 1 : 2;
176 const size_t argc = cmd_args.GetArgumentCount();
177
178 if ((argc < min_argc) && (!m_options.m_global)) {
179 result.AppendError("'settings set' takes more arguments");
180 result.SetStatus(eReturnStatusFailed);
181 return false;
182 }
183
184 const char *var_name = cmd_args.GetArgumentAtIndex(0);
185 if ((var_name == nullptr) || (var_name[0] == '\0')) {
186 result.AppendError(
187 "'settings set' command requires a valid variable name");
188 result.SetStatus(eReturnStatusFailed);
189 return false;
190 }
191
192 // A missing value corresponds to clearing the setting when "force" is
193 // specified.
194 if (argc == 1 && m_options.m_force) {
195 Status error(GetDebugger().SetPropertyValue(
196 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
197 if (error.Fail()) {
198 result.AppendError(error.AsCString());
199 result.SetStatus(eReturnStatusFailed);
200 return false;
201 }
202 return result.Succeeded();
203 }
204
205 // Split the raw command into var_name and value pair.
206 llvm::StringRef var_value(command);
207 var_value = var_value.split(var_name).second.ltrim();
208
209 Status error;
210 if (m_options.m_global)
211 error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,
212 var_name, var_value);
213
214 if (error.Success()) {
215 // FIXME this is the same issue as the one in commands script import
216 // we could be setting target.load-script-from-symbol-file which would
217 // cause Python scripts to be loaded, which could run LLDB commands (e.g.
218 // settings set target.process.python-os-plugin-path) and cause a crash
219 // if we did not clear the command's exe_ctx first
220 ExecutionContext exe_ctx(m_exe_ctx);
221 m_exe_ctx.Clear();
222 error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,
223 var_name, var_value);
224 }
225
226 if (error.Fail()) {
227 result.AppendError(error.AsCString());
228 result.SetStatus(eReturnStatusFailed);
229 return false;
230 } else {
231 result.SetStatus(eReturnStatusSuccessFinishResult);
232 }
233
234 return result.Succeeded();
235 }
236
237 private:
238 CommandOptions m_options;
239 };
240
241 // CommandObjectSettingsShow -- Show current values
242
243 class CommandObjectSettingsShow : public CommandObjectParsed {
244 public:
CommandObjectSettingsShow(CommandInterpreter & interpreter)245 CommandObjectSettingsShow(CommandInterpreter &interpreter)
246 : CommandObjectParsed(interpreter, "settings show",
247 "Show matching debugger settings and their current "
248 "values. Defaults to showing all settings.",
249 nullptr) {
250 CommandArgumentEntry arg1;
251 CommandArgumentData var_name_arg;
252
253 // Define the first (and only) variant of this arg.
254 var_name_arg.arg_type = eArgTypeSettingVariableName;
255 var_name_arg.arg_repetition = eArgRepeatOptional;
256
257 // There is only one variant this argument could be; put it into the
258 // argument entry.
259 arg1.push_back(var_name_arg);
260
261 // Push the data for the first argument into the m_arguments vector.
262 m_arguments.push_back(arg1);
263 }
264
265 ~CommandObjectSettingsShow() override = default;
266
267 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)268 HandleArgumentCompletion(CompletionRequest &request,
269 OptionElementVector &opt_element_vector) override {
270 CommandCompletions::InvokeCommonCompletionCallbacks(
271 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
272 request, nullptr);
273 }
274
275 protected:
DoExecute(Args & args,CommandReturnObject & result)276 bool DoExecute(Args &args, CommandReturnObject &result) override {
277 result.SetStatus(eReturnStatusSuccessFinishResult);
278
279 if (!args.empty()) {
280 for (const auto &arg : args) {
281 Status error(GetDebugger().DumpPropertyValue(
282 &m_exe_ctx, result.GetOutputStream(), arg.ref(),
283 OptionValue::eDumpGroupValue));
284 if (error.Success()) {
285 result.GetOutputStream().EOL();
286 } else {
287 result.AppendError(error.AsCString());
288 result.SetStatus(eReturnStatusFailed);
289 }
290 }
291 } else {
292 GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),
293 OptionValue::eDumpGroupValue);
294 }
295
296 return result.Succeeded();
297 }
298 };
299
300 // CommandObjectSettingsWrite -- Write settings to file
301 #define LLDB_OPTIONS_settings_write
302 #include "CommandOptions.inc"
303
304 class CommandObjectSettingsWrite : public CommandObjectParsed {
305 public:
CommandObjectSettingsWrite(CommandInterpreter & interpreter)306 CommandObjectSettingsWrite(CommandInterpreter &interpreter)
307 : CommandObjectParsed(
308 interpreter, "settings export",
309 "Write matching debugger settings and their "
310 "current values to a file that can be read in with "
311 "\"settings read\". Defaults to writing all settings.",
312 nullptr),
313 m_options() {
314 CommandArgumentEntry arg1;
315 CommandArgumentData var_name_arg;
316
317 // Define the first (and only) variant of this arg.
318 var_name_arg.arg_type = eArgTypeSettingVariableName;
319 var_name_arg.arg_repetition = eArgRepeatOptional;
320
321 // There is only one variant this argument could be; put it into the
322 // argument entry.
323 arg1.push_back(var_name_arg);
324
325 // Push the data for the first argument into the m_arguments vector.
326 m_arguments.push_back(arg1);
327 }
328
329 ~CommandObjectSettingsWrite() override = default;
330
GetOptions()331 Options *GetOptions() override { return &m_options; }
332
333 class CommandOptions : public Options {
334 public:
CommandOptions()335 CommandOptions() : Options() {}
336
337 ~CommandOptions() override = default;
338
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)339 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
340 ExecutionContext *execution_context) override {
341 Status error;
342 const int short_option = m_getopt_table[option_idx].val;
343
344 switch (short_option) {
345 case 'f':
346 m_filename.assign(option_arg);
347 break;
348 case 'a':
349 m_append = true;
350 break;
351 default:
352 llvm_unreachable("Unimplemented option");
353 }
354
355 return error;
356 }
357
OptionParsingStarting(ExecutionContext * execution_context)358 void OptionParsingStarting(ExecutionContext *execution_context) override {
359 m_filename.clear();
360 m_append = false;
361 }
362
GetDefinitions()363 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
364 return llvm::makeArrayRef(g_settings_write_options);
365 }
366
367 // Instance variables to hold the values for command options.
368 std::string m_filename;
369 bool m_append = false;
370 };
371
372 protected:
DoExecute(Args & args,CommandReturnObject & result)373 bool DoExecute(Args &args, CommandReturnObject &result) override {
374 FileSpec file_spec(m_options.m_filename);
375 FileSystem::Instance().Resolve(file_spec);
376 std::string path(file_spec.GetPath());
377 auto options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
378 if (m_options.m_append)
379 options |= File::eOpenOptionAppend;
380 else
381 options |= File::eOpenOptionTruncate;
382
383 StreamFile out_file(path.c_str(), options,
384 lldb::eFilePermissionsFileDefault);
385
386 if (!out_file.GetFile().IsValid()) {
387 result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
388 result.SetStatus(eReturnStatusFailed);
389 return false;
390 }
391
392 // Exporting should not be context sensitive.
393 ExecutionContext clean_ctx;
394
395 if (args.empty()) {
396 GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,
397 OptionValue::eDumpGroupExport);
398 return result.Succeeded();
399 }
400
401 for (const auto &arg : args) {
402 Status error(GetDebugger().DumpPropertyValue(
403 &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));
404 if (!error.Success()) {
405 result.AppendError(error.AsCString());
406 result.SetStatus(eReturnStatusFailed);
407 }
408 }
409
410 return result.Succeeded();
411 }
412
413 private:
414 CommandOptions m_options;
415 };
416
417 // CommandObjectSettingsRead -- Read settings from file
418 #define LLDB_OPTIONS_settings_read
419 #include "CommandOptions.inc"
420
421 class CommandObjectSettingsRead : public CommandObjectParsed {
422 public:
CommandObjectSettingsRead(CommandInterpreter & interpreter)423 CommandObjectSettingsRead(CommandInterpreter &interpreter)
424 : CommandObjectParsed(
425 interpreter, "settings read",
426 "Read settings previously saved to a file with \"settings write\".",
427 nullptr),
428 m_options() {}
429
430 ~CommandObjectSettingsRead() override = default;
431
GetOptions()432 Options *GetOptions() override { return &m_options; }
433
434 class CommandOptions : public Options {
435 public:
CommandOptions()436 CommandOptions() : Options() {}
437
438 ~CommandOptions() override = default;
439
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)440 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
441 ExecutionContext *execution_context) override {
442 Status error;
443 const int short_option = m_getopt_table[option_idx].val;
444
445 switch (short_option) {
446 case 'f':
447 m_filename.assign(option_arg);
448 break;
449 default:
450 llvm_unreachable("Unimplemented option");
451 }
452
453 return error;
454 }
455
OptionParsingStarting(ExecutionContext * execution_context)456 void OptionParsingStarting(ExecutionContext *execution_context) override {
457 m_filename.clear();
458 }
459
GetDefinitions()460 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
461 return llvm::makeArrayRef(g_settings_read_options);
462 }
463
464 // Instance variables to hold the values for command options.
465 std::string m_filename;
466 };
467
468 protected:
DoExecute(Args & command,CommandReturnObject & result)469 bool DoExecute(Args &command, CommandReturnObject &result) override {
470 FileSpec file(m_options.m_filename);
471 FileSystem::Instance().Resolve(file);
472 ExecutionContext clean_ctx;
473 CommandInterpreterRunOptions options;
474 options.SetAddToHistory(false);
475 options.SetEchoCommands(false);
476 options.SetPrintResults(true);
477 options.SetPrintErrors(true);
478 options.SetStopOnError(false);
479 m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result);
480 return result.Succeeded();
481 }
482
483 private:
484 CommandOptions m_options;
485 };
486
487 // CommandObjectSettingsList -- List settable variables
488
489 class CommandObjectSettingsList : public CommandObjectParsed {
490 public:
CommandObjectSettingsList(CommandInterpreter & interpreter)491 CommandObjectSettingsList(CommandInterpreter &interpreter)
492 : CommandObjectParsed(interpreter, "settings list",
493 "List and describe matching debugger settings. "
494 "Defaults to all listing all settings.",
495 nullptr) {
496 CommandArgumentEntry arg;
497 CommandArgumentData var_name_arg;
498 CommandArgumentData prefix_name_arg;
499
500 // Define the first variant of this arg.
501 var_name_arg.arg_type = eArgTypeSettingVariableName;
502 var_name_arg.arg_repetition = eArgRepeatOptional;
503
504 // Define the second variant of this arg.
505 prefix_name_arg.arg_type = eArgTypeSettingPrefix;
506 prefix_name_arg.arg_repetition = eArgRepeatOptional;
507
508 arg.push_back(var_name_arg);
509 arg.push_back(prefix_name_arg);
510
511 // Push the data for the first argument into the m_arguments vector.
512 m_arguments.push_back(arg);
513 }
514
515 ~CommandObjectSettingsList() override = default;
516
517 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)518 HandleArgumentCompletion(CompletionRequest &request,
519 OptionElementVector &opt_element_vector) override {
520 CommandCompletions::InvokeCommonCompletionCallbacks(
521 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
522 request, nullptr);
523 }
524
525 protected:
DoExecute(Args & args,CommandReturnObject & result)526 bool DoExecute(Args &args, CommandReturnObject &result) override {
527 result.SetStatus(eReturnStatusSuccessFinishResult);
528
529 const bool will_modify = false;
530 const size_t argc = args.GetArgumentCount();
531 if (argc > 0) {
532 const bool dump_qualified_name = true;
533
534 // TODO: Convert to StringRef based enumeration. Requires converting
535 // GetPropertyAtPath first.
536 for (size_t i = 0; i < argc; ++i) {
537 const char *property_path = args.GetArgumentAtIndex(i);
538
539 const Property *property =
540 GetDebugger().GetValueProperties()->GetPropertyAtPath(
541 &m_exe_ctx, will_modify, property_path);
542
543 if (property) {
544 property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
545 dump_qualified_name);
546 } else {
547 result.AppendErrorWithFormat("invalid property path '%s'",
548 property_path);
549 result.SetStatus(eReturnStatusFailed);
550 }
551 }
552 } else {
553 GetDebugger().DumpAllDescriptions(m_interpreter,
554 result.GetOutputStream());
555 }
556
557 return result.Succeeded();
558 }
559 };
560
561 // CommandObjectSettingsRemove
562
563 class CommandObjectSettingsRemove : public CommandObjectRaw {
564 public:
CommandObjectSettingsRemove(CommandInterpreter & interpreter)565 CommandObjectSettingsRemove(CommandInterpreter &interpreter)
566 : CommandObjectRaw(interpreter, "settings remove",
567 "Remove a value from a setting, specified by array "
568 "index or dictionary key.") {
569 CommandArgumentEntry arg1;
570 CommandArgumentEntry arg2;
571 CommandArgumentData var_name_arg;
572 CommandArgumentData index_arg;
573 CommandArgumentData key_arg;
574
575 // Define the first (and only) variant of this arg.
576 var_name_arg.arg_type = eArgTypeSettingVariableName;
577 var_name_arg.arg_repetition = eArgRepeatPlain;
578
579 // There is only one variant this argument could be; put it into the
580 // argument entry.
581 arg1.push_back(var_name_arg);
582
583 // Define the first variant of this arg.
584 index_arg.arg_type = eArgTypeSettingIndex;
585 index_arg.arg_repetition = eArgRepeatPlain;
586
587 // Define the second variant of this arg.
588 key_arg.arg_type = eArgTypeSettingKey;
589 key_arg.arg_repetition = eArgRepeatPlain;
590
591 // Push both variants into this arg
592 arg2.push_back(index_arg);
593 arg2.push_back(key_arg);
594
595 // Push the data for the first argument into the m_arguments vector.
596 m_arguments.push_back(arg1);
597 m_arguments.push_back(arg2);
598 }
599
600 ~CommandObjectSettingsRemove() override = default;
601
WantsCompletion()602 bool WantsCompletion() override { return true; }
603
604 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)605 HandleArgumentCompletion(CompletionRequest &request,
606 OptionElementVector &opt_element_vector) override {
607 if (request.GetCursorIndex() < 2)
608 CommandCompletions::InvokeCommonCompletionCallbacks(
609 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
610 request, nullptr);
611 }
612
613 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)614 bool DoExecute(llvm::StringRef command,
615 CommandReturnObject &result) override {
616 result.SetStatus(eReturnStatusSuccessFinishNoResult);
617
618 Args cmd_args(command);
619
620 // Process possible options.
621 if (!ParseOptions(cmd_args, result))
622 return false;
623
624 const size_t argc = cmd_args.GetArgumentCount();
625 if (argc == 0) {
626 result.AppendError("'settings remove' takes an array or dictionary item, "
627 "or an array followed by one or more indexes, or a "
628 "dictionary followed by one or more key names to "
629 "remove");
630 result.SetStatus(eReturnStatusFailed);
631 return false;
632 }
633
634 const char *var_name = cmd_args.GetArgumentAtIndex(0);
635 if ((var_name == nullptr) || (var_name[0] == '\0')) {
636 result.AppendError(
637 "'settings remove' command requires a valid variable name");
638 result.SetStatus(eReturnStatusFailed);
639 return false;
640 }
641
642 // Split the raw command into var_name and value pair.
643 llvm::StringRef var_value(command);
644 var_value = var_value.split(var_name).second.trim();
645
646 Status error(GetDebugger().SetPropertyValue(
647 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
648 if (error.Fail()) {
649 result.AppendError(error.AsCString());
650 result.SetStatus(eReturnStatusFailed);
651 return false;
652 }
653
654 return result.Succeeded();
655 }
656 };
657
658 // CommandObjectSettingsReplace
659
660 class CommandObjectSettingsReplace : public CommandObjectRaw {
661 public:
CommandObjectSettingsReplace(CommandInterpreter & interpreter)662 CommandObjectSettingsReplace(CommandInterpreter &interpreter)
663 : CommandObjectRaw(interpreter, "settings replace",
664 "Replace the debugger setting value specified by "
665 "array index or dictionary key.") {
666 CommandArgumentEntry arg1;
667 CommandArgumentEntry arg2;
668 CommandArgumentEntry arg3;
669 CommandArgumentData var_name_arg;
670 CommandArgumentData index_arg;
671 CommandArgumentData key_arg;
672 CommandArgumentData value_arg;
673
674 // Define the first (and only) variant of this arg.
675 var_name_arg.arg_type = eArgTypeSettingVariableName;
676 var_name_arg.arg_repetition = eArgRepeatPlain;
677
678 // There is only one variant this argument could be; put it into the
679 // argument entry.
680 arg1.push_back(var_name_arg);
681
682 // Define the first (variant of this arg.
683 index_arg.arg_type = eArgTypeSettingIndex;
684 index_arg.arg_repetition = eArgRepeatPlain;
685
686 // Define the second (variant of this arg.
687 key_arg.arg_type = eArgTypeSettingKey;
688 key_arg.arg_repetition = eArgRepeatPlain;
689
690 // Put both variants into this arg
691 arg2.push_back(index_arg);
692 arg2.push_back(key_arg);
693
694 // Define the first (and only) variant of this arg.
695 value_arg.arg_type = eArgTypeValue;
696 value_arg.arg_repetition = eArgRepeatPlain;
697
698 // There is only one variant this argument could be; put it into the
699 // argument entry.
700 arg3.push_back(value_arg);
701
702 // Push the data for the first argument into the m_arguments vector.
703 m_arguments.push_back(arg1);
704 m_arguments.push_back(arg2);
705 m_arguments.push_back(arg3);
706 }
707
708 ~CommandObjectSettingsReplace() override = default;
709
710 // Overrides base class's behavior where WantsCompletion =
711 // !WantsRawCommandString.
WantsCompletion()712 bool WantsCompletion() override { return true; }
713
714 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)715 HandleArgumentCompletion(CompletionRequest &request,
716 OptionElementVector &opt_element_vector) override {
717 // Attempting to complete variable name
718 if (request.GetCursorIndex() < 2)
719 CommandCompletions::InvokeCommonCompletionCallbacks(
720 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
721 request, nullptr);
722 }
723
724 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)725 bool DoExecute(llvm::StringRef command,
726 CommandReturnObject &result) override {
727 result.SetStatus(eReturnStatusSuccessFinishNoResult);
728
729 Args cmd_args(command);
730 const char *var_name = cmd_args.GetArgumentAtIndex(0);
731 if ((var_name == nullptr) || (var_name[0] == '\0')) {
732 result.AppendError("'settings replace' command requires a valid variable "
733 "name; No value supplied");
734 result.SetStatus(eReturnStatusFailed);
735 return false;
736 }
737
738 // Split the raw command into var_name, index_value, and value triple.
739 llvm::StringRef var_value(command);
740 var_value = var_value.split(var_name).second.trim();
741
742 Status error(GetDebugger().SetPropertyValue(
743 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
744 if (error.Fail()) {
745 result.AppendError(error.AsCString());
746 result.SetStatus(eReturnStatusFailed);
747 return false;
748 } else {
749 result.SetStatus(eReturnStatusSuccessFinishNoResult);
750 }
751
752 return result.Succeeded();
753 }
754 };
755
756 // CommandObjectSettingsInsertBefore
757
758 class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
759 public:
CommandObjectSettingsInsertBefore(CommandInterpreter & interpreter)760 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
761 : CommandObjectRaw(interpreter, "settings insert-before",
762 "Insert one or more values into an debugger array "
763 "setting immediately before the specified element "
764 "index.") {
765 CommandArgumentEntry arg1;
766 CommandArgumentEntry arg2;
767 CommandArgumentEntry arg3;
768 CommandArgumentData var_name_arg;
769 CommandArgumentData index_arg;
770 CommandArgumentData value_arg;
771
772 // Define the first (and only) variant of this arg.
773 var_name_arg.arg_type = eArgTypeSettingVariableName;
774 var_name_arg.arg_repetition = eArgRepeatPlain;
775
776 // There is only one variant this argument could be; put it into the
777 // argument entry.
778 arg1.push_back(var_name_arg);
779
780 // Define the first (variant of this arg.
781 index_arg.arg_type = eArgTypeSettingIndex;
782 index_arg.arg_repetition = eArgRepeatPlain;
783
784 // There is only one variant this argument could be; put it into the
785 // argument entry.
786 arg2.push_back(index_arg);
787
788 // Define the first (and only) variant of this arg.
789 value_arg.arg_type = eArgTypeValue;
790 value_arg.arg_repetition = eArgRepeatPlain;
791
792 // There is only one variant this argument could be; put it into the
793 // argument entry.
794 arg3.push_back(value_arg);
795
796 // Push the data for the first argument into the m_arguments vector.
797 m_arguments.push_back(arg1);
798 m_arguments.push_back(arg2);
799 m_arguments.push_back(arg3);
800 }
801
802 ~CommandObjectSettingsInsertBefore() override = default;
803
804 // Overrides base class's behavior where WantsCompletion =
805 // !WantsRawCommandString.
WantsCompletion()806 bool WantsCompletion() override { return true; }
807
808 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)809 HandleArgumentCompletion(CompletionRequest &request,
810 OptionElementVector &opt_element_vector) override {
811 // Attempting to complete variable name
812 if (request.GetCursorIndex() < 2)
813 CommandCompletions::InvokeCommonCompletionCallbacks(
814 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
815 request, nullptr);
816 }
817
818 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)819 bool DoExecute(llvm::StringRef command,
820 CommandReturnObject &result) override {
821 result.SetStatus(eReturnStatusSuccessFinishNoResult);
822
823 Args cmd_args(command);
824 const size_t argc = cmd_args.GetArgumentCount();
825
826 if (argc < 3) {
827 result.AppendError("'settings insert-before' takes more arguments");
828 result.SetStatus(eReturnStatusFailed);
829 return false;
830 }
831
832 const char *var_name = cmd_args.GetArgumentAtIndex(0);
833 if ((var_name == nullptr) || (var_name[0] == '\0')) {
834 result.AppendError("'settings insert-before' command requires a valid "
835 "variable name; No value supplied");
836 result.SetStatus(eReturnStatusFailed);
837 return false;
838 }
839
840 // Split the raw command into var_name, index_value, and value triple.
841 llvm::StringRef var_value(command);
842 var_value = var_value.split(var_name).second.trim();
843
844 Status error(GetDebugger().SetPropertyValue(
845 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
846 if (error.Fail()) {
847 result.AppendError(error.AsCString());
848 result.SetStatus(eReturnStatusFailed);
849 return false;
850 }
851
852 return result.Succeeded();
853 }
854 };
855
856 // CommandObjectSettingInsertAfter
857
858 class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
859 public:
CommandObjectSettingsInsertAfter(CommandInterpreter & interpreter)860 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
861 : CommandObjectRaw(interpreter, "settings insert-after",
862 "Insert one or more values into a debugger array "
863 "settings after the specified element index.") {
864 CommandArgumentEntry arg1;
865 CommandArgumentEntry arg2;
866 CommandArgumentEntry arg3;
867 CommandArgumentData var_name_arg;
868 CommandArgumentData index_arg;
869 CommandArgumentData value_arg;
870
871 // Define the first (and only) variant of this arg.
872 var_name_arg.arg_type = eArgTypeSettingVariableName;
873 var_name_arg.arg_repetition = eArgRepeatPlain;
874
875 // There is only one variant this argument could be; put it into the
876 // argument entry.
877 arg1.push_back(var_name_arg);
878
879 // Define the first (variant of this arg.
880 index_arg.arg_type = eArgTypeSettingIndex;
881 index_arg.arg_repetition = eArgRepeatPlain;
882
883 // There is only one variant this argument could be; put it into the
884 // argument entry.
885 arg2.push_back(index_arg);
886
887 // Define the first (and only) variant of this arg.
888 value_arg.arg_type = eArgTypeValue;
889 value_arg.arg_repetition = eArgRepeatPlain;
890
891 // There is only one variant this argument could be; put it into the
892 // argument entry.
893 arg3.push_back(value_arg);
894
895 // Push the data for the first argument into the m_arguments vector.
896 m_arguments.push_back(arg1);
897 m_arguments.push_back(arg2);
898 m_arguments.push_back(arg3);
899 }
900
901 ~CommandObjectSettingsInsertAfter() override = default;
902
903 // Overrides base class's behavior where WantsCompletion =
904 // !WantsRawCommandString.
WantsCompletion()905 bool WantsCompletion() override { return true; }
906
907 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)908 HandleArgumentCompletion(CompletionRequest &request,
909 OptionElementVector &opt_element_vector) override {
910 // Attempting to complete variable name
911 if (request.GetCursorIndex() < 2)
912 CommandCompletions::InvokeCommonCompletionCallbacks(
913 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
914 request, nullptr);
915 }
916
917 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)918 bool DoExecute(llvm::StringRef command,
919 CommandReturnObject &result) override {
920 result.SetStatus(eReturnStatusSuccessFinishNoResult);
921
922 Args cmd_args(command);
923 const size_t argc = cmd_args.GetArgumentCount();
924
925 if (argc < 3) {
926 result.AppendError("'settings insert-after' takes more arguments");
927 result.SetStatus(eReturnStatusFailed);
928 return false;
929 }
930
931 const char *var_name = cmd_args.GetArgumentAtIndex(0);
932 if ((var_name == nullptr) || (var_name[0] == '\0')) {
933 result.AppendError("'settings insert-after' command requires a valid "
934 "variable name; No value supplied");
935 result.SetStatus(eReturnStatusFailed);
936 return false;
937 }
938
939 // Split the raw command into var_name, index_value, and value triple.
940 llvm::StringRef var_value(command);
941 var_value = var_value.split(var_name).second.trim();
942
943 Status error(GetDebugger().SetPropertyValue(
944 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
945 if (error.Fail()) {
946 result.AppendError(error.AsCString());
947 result.SetStatus(eReturnStatusFailed);
948 return false;
949 }
950
951 return result.Succeeded();
952 }
953 };
954
955 // CommandObjectSettingsAppend
956
957 class CommandObjectSettingsAppend : public CommandObjectRaw {
958 public:
CommandObjectSettingsAppend(CommandInterpreter & interpreter)959 CommandObjectSettingsAppend(CommandInterpreter &interpreter)
960 : CommandObjectRaw(interpreter, "settings append",
961 "Append one or more values to a debugger array, "
962 "dictionary, or string setting.") {
963 CommandArgumentEntry arg1;
964 CommandArgumentEntry arg2;
965 CommandArgumentData var_name_arg;
966 CommandArgumentData value_arg;
967
968 // Define the first (and only) variant of this arg.
969 var_name_arg.arg_type = eArgTypeSettingVariableName;
970 var_name_arg.arg_repetition = eArgRepeatPlain;
971
972 // There is only one variant this argument could be; put it into the
973 // argument entry.
974 arg1.push_back(var_name_arg);
975
976 // Define the first (and only) variant of this arg.
977 value_arg.arg_type = eArgTypeValue;
978 value_arg.arg_repetition = eArgRepeatPlain;
979
980 // There is only one variant this argument could be; put it into the
981 // argument entry.
982 arg2.push_back(value_arg);
983
984 // Push the data for the first argument into the m_arguments vector.
985 m_arguments.push_back(arg1);
986 m_arguments.push_back(arg2);
987 }
988
989 ~CommandObjectSettingsAppend() override = default;
990
991 // Overrides base class's behavior where WantsCompletion =
992 // !WantsRawCommandString.
WantsCompletion()993 bool WantsCompletion() override { return true; }
994
995 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)996 HandleArgumentCompletion(CompletionRequest &request,
997 OptionElementVector &opt_element_vector) override {
998 // Attempting to complete variable name
999 if (request.GetCursorIndex() < 2)
1000 CommandCompletions::InvokeCommonCompletionCallbacks(
1001 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1002 request, nullptr);
1003 }
1004
1005 protected:
DoExecute(llvm::StringRef command,CommandReturnObject & result)1006 bool DoExecute(llvm::StringRef command,
1007 CommandReturnObject &result) override {
1008 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1009 Args cmd_args(command);
1010 const size_t argc = cmd_args.GetArgumentCount();
1011
1012 if (argc < 2) {
1013 result.AppendError("'settings append' takes more arguments");
1014 result.SetStatus(eReturnStatusFailed);
1015 return false;
1016 }
1017
1018 const char *var_name = cmd_args.GetArgumentAtIndex(0);
1019 if ((var_name == nullptr) || (var_name[0] == '\0')) {
1020 result.AppendError("'settings append' command requires a valid variable "
1021 "name; No value supplied");
1022 result.SetStatus(eReturnStatusFailed);
1023 return false;
1024 }
1025
1026 // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
1027 // character string later on.
1028
1029 // Split the raw command into var_name and value pair.
1030 llvm::StringRef var_value(command);
1031 var_value = var_value.split(var_name).second.trim();
1032
1033 Status error(GetDebugger().SetPropertyValue(
1034 &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
1035 if (error.Fail()) {
1036 result.AppendError(error.AsCString());
1037 result.SetStatus(eReturnStatusFailed);
1038 return false;
1039 }
1040
1041 return result.Succeeded();
1042 }
1043 };
1044
1045 // CommandObjectSettingsClear
1046
1047 class CommandObjectSettingsClear : public CommandObjectParsed {
1048 public:
CommandObjectSettingsClear(CommandInterpreter & interpreter)1049 CommandObjectSettingsClear(CommandInterpreter &interpreter)
1050 : CommandObjectParsed(
1051 interpreter, "settings clear",
1052 "Clear a debugger setting array, dictionary, or string.", nullptr) {
1053 CommandArgumentEntry arg;
1054 CommandArgumentData var_name_arg;
1055
1056 // Define the first (and only) variant of this arg.
1057 var_name_arg.arg_type = eArgTypeSettingVariableName;
1058 var_name_arg.arg_repetition = eArgRepeatPlain;
1059
1060 // There is only one variant this argument could be; put it into the
1061 // argument entry.
1062 arg.push_back(var_name_arg);
1063
1064 // Push the data for the first argument into the m_arguments vector.
1065 m_arguments.push_back(arg);
1066 }
1067
1068 ~CommandObjectSettingsClear() override = default;
1069
1070 void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1071 HandleArgumentCompletion(CompletionRequest &request,
1072 OptionElementVector &opt_element_vector) override {
1073 // Attempting to complete variable name
1074 if (request.GetCursorIndex() < 2)
1075 CommandCompletions::InvokeCommonCompletionCallbacks(
1076 GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1077 request, nullptr);
1078 }
1079
1080 protected:
DoExecute(Args & command,CommandReturnObject & result)1081 bool DoExecute(Args &command, CommandReturnObject &result) override {
1082 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1083 const size_t argc = command.GetArgumentCount();
1084
1085 if (argc != 1) {
1086 result.AppendError("'settings clear' takes exactly one argument");
1087 result.SetStatus(eReturnStatusFailed);
1088 return false;
1089 }
1090
1091 const char *var_name = command.GetArgumentAtIndex(0);
1092 if ((var_name == nullptr) || (var_name[0] == '\0')) {
1093 result.AppendError("'settings clear' command requires a valid variable "
1094 "name; No value supplied");
1095 result.SetStatus(eReturnStatusFailed);
1096 return false;
1097 }
1098
1099 Status error(GetDebugger().SetPropertyValue(
1100 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1101 if (error.Fail()) {
1102 result.AppendError(error.AsCString());
1103 result.SetStatus(eReturnStatusFailed);
1104 return false;
1105 }
1106
1107 return result.Succeeded();
1108 }
1109 };
1110
1111 // CommandObjectMultiwordSettings
1112
CommandObjectMultiwordSettings(CommandInterpreter & interpreter)1113 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1114 CommandInterpreter &interpreter)
1115 : CommandObjectMultiword(interpreter, "settings",
1116 "Commands for managing LLDB settings.",
1117 "settings <subcommand> [<command-options>]") {
1118 LoadSubCommand("set",
1119 CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1120 LoadSubCommand("show",
1121 CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1122 LoadSubCommand("list",
1123 CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1124 LoadSubCommand("remove",
1125 CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1126 LoadSubCommand("replace", CommandObjectSP(
1127 new CommandObjectSettingsReplace(interpreter)));
1128 LoadSubCommand(
1129 "insert-before",
1130 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1131 LoadSubCommand(
1132 "insert-after",
1133 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1134 LoadSubCommand("append",
1135 CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1136 LoadSubCommand("clear",
1137 CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1138 LoadSubCommand("write",
1139 CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
1140 LoadSubCommand("read",
1141 CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1142 }
1143
1144 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1145