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

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