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