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

source code of lldb/source/Commands/CommandObjectSettings.cpp