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