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